ppt-tool/backend/tests/test_pptx_slides_processing.py
Vadym Samoilenko cf21ba4516 Phase 1-2: Foundation + Admin Panel & Client Management
Phase 1 (Foundation):
- Project restructure (presenton-main → backend/ + frontend/)
- Database schema (8 new models, Alembic config, seed script)
- Auth (Azure AD SSO + dev bypass, JWT sessions, AuthMiddleware)
- RBAC (access_service, rbac_middleware, admin routers)
- Audit logging (fire-and-forget, AuditMiddleware, admin router)
- i18n (react-i18next with 5 namespace files)

Phase 2 (Admin Panel & Client Management):
- Admin panel shell (sidebar layout, role guard, 12 pages)
- Redux admin slice with 18 async thunks
- User management (role changes, deactivation)
- Client management (CRUD, brand config, team management)
- Brand config editor (colors, fonts, logos, voice rules)
- Master deck upload & parser (PPTX → HTML → React pipeline)
- Audit log viewer with filters and CSV/JSON export

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 15:37:17 +00:00

140 lines
No EOL
5.4 KiB
Python

import os
import tempfile
import zipfile
from fastapi.testclient import TestClient
from fastapi import UploadFile
import pytest
from api.main import app
client = TestClient(app)
def create_sample_pptx():
"""Create a minimal PPTX file for testing."""
# This creates a very basic PPTX structure for testing
pptx_content = {
'[Content_Types].xml': '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="xml" ContentType="application/xml"/>
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
<Override PartName="/ppt/presentation.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml"/>
<Override PartName="/ppt/slides/slide1.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slide+xml"/>
</Types>''',
'_rels/.rels': '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="ppt/presentation.xml"/>
</Relationships>''',
'ppt/presentation.xml': '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<p:presentation xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">
<p:sldMasterIdLst/>
<p:sldIdLst>
<p:sldId id="256" r:id="rId2"/>
</p:sldIdLst>
<p:sldSz cx="9144000" cy="6858000"/>
</p:presentation>''',
'ppt/_rels/presentation.xml.rels': '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide" Target="slides/slide1.xml"/>
</Relationships>''',
'ppt/slides/slide1.xml': '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<p:sld xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">
<p:cSld>
<p:spTree>
<p:nvGrpSpPr>
<p:cNvPr id="1" name=""/>
<p:cNvGrpSpPr/>
<p:nvPr/>
</p:nvGrpSpPr>
<p:grpSpPr>
<a:xfrm xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
<a:off x="0" y="0"/>
<a:ext cx="0" cy="0"/>
<a:chOff x="0" y="0"/>
<a:chExt cx="0" cy="0"/>
</a:xfrm>
</p:grpSpPr>
</p:spTree>
</p:cSld>
<p:clrMapOvr>
<a:masterClrMapping xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"/>
</p:clrMapOvr>
</p:sld>'''
}
with tempfile.NamedTemporaryFile(suffix='.pptx', delete=False) as temp_file:
with zipfile.ZipFile(temp_file.name, 'w') as zip_file:
for path, content in pptx_content.items():
zip_file.writestr(path, content)
return temp_file.name
def test_pptx_slides_processing():
"""Test the PPTX slides processing endpoint."""
# Create a sample PPTX file
pptx_path = create_sample_pptx()
try:
with open(pptx_path, 'rb') as pptx_file:
files = {'pptx_file': ('test.pptx', pptx_file, 'application/vnd.openxmlformats-officedocument.presentationml.presentation')}
response = client.post("/api/v1/ppt/pptx-slides/process", files=files)
# Check response
assert response.status_code == 200
data = response.json()
assert data['success'] == True
assert 'slides' in data
assert 'total_slides' in data
assert data['total_slides'] > 0
# Check slide data structure
if data['slides']:
slide = data['slides'][0]
assert 'slide_number' in slide
assert 'screenshot_url' in slide
assert 'xml_content' in slide
assert slide['slide_number'] == 1
assert slide['xml_content'] != ''
print(f"✅ Test passed! Processed {data['total_slides']} slides successfully")
finally:
# Clean up
if os.path.exists(pptx_path):
os.unlink(pptx_path)
def test_invalid_file_type():
"""Test that non-PPTX files are rejected."""
# Create a text file and try to upload it
with tempfile.NamedTemporaryFile(suffix='.txt', delete=False) as temp_file:
temp_file.write(b"This is not a PPTX file")
temp_file.flush()
try:
with open(temp_file.name, 'rb') as txt_file:
files = {'pptx_file': ('test.txt', txt_file, 'text/plain')}
response = client.post("/api/v1/ppt/pptx-slides/process", files=files)
# Should return 400 for invalid file type
assert response.status_code == 400
data = response.json()
assert 'Invalid file type' in data['detail']
print("✅ Invalid file type test passed!")
finally:
os.unlink(temp_file.name)
if __name__ == "__main__":
print("Running PPTX slides processing tests...")
test_pptx_slides_processing()
test_invalid_file_type()
print("🎉 All tests completed!")