Files
cms-SiteForge/tests/test_v826_global_design.py
浅念 8884e100f9 upgrade: adopt V8.31.1 (theme 1.3/1.4 redesigns, editor deep-canvas, guided launch, component library)
Overlay 190 upstream items (V8.22→8.31) preserving trade-pro theme,
registry tests, and design docs. Re-applied full patch set on identical
anchors (discovery/env_for/blocks.css/type-mapping/locale-override/
theme_color/frontend entries/test_theme_pro_v3 mods) plus compose pins.

Verified: theme suites 35/35; dual-baseline full run 415 passed vs
pristine 386+29 ours, FAILED-set diff EMPTY (same 10 Windows env fails).
Live: container 8.31.1-dev.1 healthy, hesupipe 192 entries intact,
trade-pro build 203 pages 0 errors.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-26 09:43:17 +08:00

105 lines
5.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""V8.26 global chrome review, version snapshots, and safe restoration."""
import copy
import json
from tests.test_factory import client, create
from app import db, site_design_v87
def config(marker='Global HESU Header'):
data=copy.deepcopy(site_design_v87.DEFAULTS)
data['header'].update({'announcement': marker, 'show_announcement': True})
data['footer']['title']='HESU Footer'
data['nav']=[{'title':'Products','route':'/products/','children':[
{'title':'Vehicles','route':'/vehicles/','children':[]}]}]
return data
def test_human_review_and_reviewed_publication_are_build_isolated(client):
site=create(client);url=f'/api/sites/{site}/site-design'
old=db.one('SELECT settings_json FROM sites WHERE id=?',(site,))['settings_json']
assert client.put(url,json={'config':config(), 'expected_revision':0}).status_code==200
proof=client.get(url+'/review');assert proof.status_code==200,proof.text
body=proof.json()
assert {'header','nav','footer'}.issubset(set(body['changed_sections']))
assert body['published_site_unchanged'] is True
assert body['change_count']>=3
assert db.one('SELECT settings_json FROM sites WHERE id=?',(site,))['settings_json']==old
wrong=client.post(url+'/publish-reviewed',json={'expected_revision':1,'plan_token':'1'*64})
assert wrong.status_code==409
good=client.post(url+'/publish-reviewed',json={'expected_revision':1,'plan_token':body['plan_token']})
assert good.status_code==200,good.text
assert 'Global HESU Header' in db.one('SELECT settings_json FROM sites WHERE id=?',(site,))['settings_json']
assert client.get(url+'/review').status_code==409
def test_old_review_token_invalid_after_draft_edit(client):
site=create(client);url=f'/api/sites/{site}/site-design'
assert client.put(url,json={'config':config('First'), 'expected_revision':0}).status_code==200
stale=client.get(url+'/review').json()
assert client.put(url,json={'config':config('Second'), 'expected_revision':1}).status_code==200
assert client.post(url+'/publish-reviewed',json={
'expected_revision':2,'plan_token':stale['plan_token']}).status_code==409
fresh=client.get(url+'/review').json()
assert fresh['plan_token']!=stale['plan_token']
assert client.post(url+'/publish-reviewed',json={
'expected_revision':2,'plan_token':fresh['plan_token']}).status_code==200
def test_restore_history_as_new_draft_does_not_mutate_live(client):
site=create(client);url=f'/api/sites/{site}/site-design'
assert client.put(url,json={'config':config('Release A'),'expected_revision':0}).status_code==200
reviewed=client.get(url+'/review').json()
pub=client.post(url+'/publish-reviewed',json={'expected_revision':1,'plan_token':reviewed['plan_token']}).json()
pid=pub['publication_id']
old_live=db.one('SELECT settings_json FROM sites WHERE id=?',(site,))['settings_json']
history=client.get(url+f'/publications/{pid}');assert history.status_code==200
assert history.json()['after']['header']['announcement']=='Release A'
assert any(x['field']=='header.announcement' for x in history.json()['changes'])
live_hash=client.get(url+'/live-hash').json()['live_hash']
recovered=client.post(url+f'/publications/{pid}/restore',json={
'snapshot':'before','expected_revision':0,'expected_live_hash':live_hash})
assert recovered.status_code==200,recovered.text
assert recovered.json()['published_unchanged']
assert client.get(url).json()['revision']==1
assert db.one('SELECT settings_json FROM sites WHERE id=?',(site,))['settings_json']==old_live
assert client.post(url+f'/publications/{pid}/restore',json={
'snapshot':'before','expected_revision':0,'expected_live_hash':live_hash}).status_code==409
def test_restore_rejects_stale_live_site_and_foreign_history(client):
a=create(client);b=create(client)
ua=f'/api/sites/{a}/site-design';ub=f'/api/sites/{b}/site-design'
assert client.put(ua,json={'config':config(), 'expected_revision':0}).status_code==200
preview=client.get(ua+'/review').json()
pid=client.post(ua+'/publish-reviewed',json={
'expected_revision':1,'plan_token':preview['plan_token']}).json()['publication_id']
old_hash=client.get(ua+'/live-hash').json()['live_hash']
assert client.get(ub+f'/publications/{pid}').status_code==404
assert client.post(ub+f'/publications/{pid}/restore',json={
'snapshot':'after','expected_revision':0,'expected_live_hash':old_hash}).status_code==404
current=db.one('SELECT settings_json FROM sites WHERE id=?',(a,))
changed=json.loads(current['settings_json']);changed['external_setting']='changed'
db.execute('UPDATE sites SET settings_json=? WHERE id=?',(json.dumps(changed),a))
assert client.post(ua+f'/publications/{pid}/restore',json={
'snapshot':'after','expected_revision':0,'expected_live_hash':old_hash}).status_code==409
assert client.post(ua+f'/publications/{pid}/restore',json={
'snapshot':'bad','expected_revision':0,'expected_live_hash':'a'*64}).status_code==400
def test_nav_editor_is_visual_and_review_ui_is_wired(client):
sid=create(client)
entry=next(x for x in client.get(f'/api/sites/{sid}/entries').json() if x['route']=='/')
page=client.get(f'/editor/{sid}/{entry["id"]}').text
assert 'siteNavRows' in page and '+ 添加一级菜单' in page
assert 'siteDesignReviewModal' in page and 'siteDesignHistoryModal' in page
code=client.get('/ui/editor.js').text
assert 'drawSiteNav()' in code and 'publish-reviewed' in code
assert 'showSiteDesignHistory' in code
def test_invalid_navigation_remains_rejected(client):
sid=create(client);url=f'/api/sites/{sid}/site-design'
bad=config();bad['nav'][0]['children'][0]['route']='javascript:alert(1)'
assert client.put(url,json={'config':bad,'expected_revision':0}).status_code==400
assert client.get(url).json()['revision']==0