5c7643fcf2
- Overlay 26 changed files from SiteForge_Enterprise_V8_12 (UI layer only: professional-ui.js/css, workspace/factory-v2/operations/editor templates, +2 test files, compose/ci/scripts/docs) - Re-apply v8_workflows type-mapping fix (类型/分类) lost in upgrade - Pin compose project name to siteforge-v8-10 so existing data volumes (hesupipe site 483295c29ea0, 193 entries) keep attached - Drop stray .s10_* state files; ignore .s10_*/.sf_*/.s87_* patterns - Plan/spec revisions per plan-review round 1 (icons are new design, real test assertions, recorded deviations) Tests: 226 passed / 1 env-only failure (test needs node binary in PATH, absent in python:3.12-slim container; host node v24 --check all 9 JS OK) Co-Authored-By: Claude Code <noreply@anthropic.com>
86 lines
3.5 KiB
Python
86 lines
3.5 KiB
Python
"""V8.11: specialized tools share a single task-oriented UI without changing APIs."""
|
|
from test_factory import client
|
|
|
|
PROFESSIONAL = {
|
|
'/editor/{site}/{entry}': 'editor',
|
|
'/theme-gallery': 'theme',
|
|
'/factory-studio': 'factory',
|
|
'/operations': 'operations',
|
|
'/production-v8': 'production',
|
|
}
|
|
|
|
|
|
def create_site(client):
|
|
response = client.post('/api/sites', json={'name': 'V8.11 UI', 'theme': 'corporate'})
|
|
assert response.status_code == 201, response.text
|
|
sid = response.json()['id']
|
|
entry = client.get(f'/api/sites/{sid}/entries').json()[0]
|
|
return sid, entry['id']
|
|
|
|
|
|
def test_all_professional_pages_load_unified_shell(client):
|
|
site, entry = create_site(client)
|
|
for pattern, page_type in PROFESSIONAL.items():
|
|
uri = pattern.format(site=site, entry=entry)
|
|
response = client.get(uri)
|
|
assert response.status_code == 200, uri
|
|
assert f'data-sf-page="{page_type}"' in response.text, uri
|
|
assert '/ui/professional-ui.js' in response.text
|
|
assert '/ui/professional-ui.css' in response.text
|
|
|
|
|
|
def test_shared_navigation_assets_are_real_routes(client):
|
|
css = client.get('/ui/professional-ui.css')
|
|
js = client.get('/ui/professional-ui.js')
|
|
assert css.status_code == 200 and js.status_code == 200
|
|
assert 'sf-bar-nav' in css.text and '.sf-editor-mobile-tabs' in css.text
|
|
for code in ('siteforge:selected-site', 'sfGlobalSite', 'aria-current', 'MutationObserver'):
|
|
assert code in js.text
|
|
|
|
|
|
def test_site_switcher_avoids_cross_site_editor_paths(client):
|
|
js = client.get('/ui/professional-ui.js').text
|
|
assert "ctx==='editor'" in js
|
|
assert "location.assign(route('design'))" in js
|
|
assert 'items.some(s=>s.id===wanted)' in js # selected ID validated against visible sites
|
|
assert 'siteforge:selected-site' in client.get('/ui/workspace.js').text
|
|
|
|
|
|
def test_professional_forms_keep_validation_and_csrf(client):
|
|
js = client.get('/ui/professional-ui.js').text
|
|
assert "addEventListener('invalid'" in js
|
|
assert "aria-invalid" in js
|
|
assert 'X-SiteForge-CSRF' in client.get('/ui/operations.js').text
|
|
assert 'X-SiteForge-CSRF' in client.get('/ui/workspace.js').text
|
|
|
|
|
|
def test_operations_are_split_into_three_steps(client):
|
|
shell = client.get('/ui/professional-ui.js').text
|
|
assert '② 生成静态网站' in shell
|
|
assert '③ 审批与发布' in shell
|
|
assert "role','tabpanel'" in shell
|
|
page = client.get('/operations').text
|
|
assert all(word in page for word in ('CMS 数据迁移', '生产构建任务', '远程发布'))
|
|
|
|
|
|
def test_editor_preserves_draft_publish_and_mobile_panels(client):
|
|
site, entry = create_site(client)
|
|
html = client.get(f'/editor/{site}/{entry}').text
|
|
assert 'Studio.save()' in html and 'Studio.publishDesign()' in html
|
|
js = client.get('/ui/professional-ui.js').text
|
|
assert all(word in js for word in ('结构', '页面预览', '属性设置', "dataset.mobilePane"))
|
|
assert 'sf-editor-actiongroup' in js
|
|
|
|
|
|
def test_health_and_main_workspace_match_unified_release(client):
|
|
assert client.get('/api/health').json()['version'] == '8.12.0-dev.1'
|
|
assert 'const headings=' in client.get('/ui/workspace.js').text
|
|
assert 'new URLSearchParams(location.search)' in client.get('/ui/workspace.js').text
|
|
|
|
|
|
def test_existing_theme_and_content_apis_unchanged(client):
|
|
sid, _ = create_site(client)
|
|
assert client.get('/api/themes').status_code == 200
|
|
assert client.get(f'/api/sites/{sid}/entries').status_code == 200
|
|
assert client.get(f'/api/sites/{sid}/builds').status_code == 200
|