upgrade: adopt V8.21.3 (V8.13→8.21.3: P5 SFTP/S3, P6 multilingual, editor overhaul, enterprise hardening)

Overlay ~150 upstream items onto our V8.12 base, preserving trade-pro
theme, registry tests, and design docs. Re-applied our patch set
(discovery/env_for/blocks.css/type-mapping/theme_color/frontend entries,
test_theme_pro_v3 mods) — all anchors survived upstream evolution.

New platform enhancement (fixes upgrade-introduced regression):
multilingual.site_locale now honors settings_json.locale, plus
PUT /api/i18n/sites/{id}/locale — standalone English sites get
<html lang='en'> under the V8.15 locale-rewrite pipeline.

compose: adopt V8.21.3 (image 8.21.3-dev.1, /api/ready probes, MySQL/S3
env) with project name pinned to siteforge-v8-10 (data volumes).

Tests: 356 passed / 11 failed — all 11 confirmed pre-existing in
pristine V8.21.3 on this host (10 upstream Windows env + our build test
now green after locale fix). Patch registry updated in plan doc.

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-10-23 12:31:03 +08:00
parent 257c89e159
commit 601451f22b
218 changed files with 10441 additions and 628 deletions
+8 -15
View File
@@ -6,9 +6,10 @@ import zipfile
from pathlib import Path
from bs4 import BeautifulSoup
from test_factory_v2 import factory, site, zip_theme
from app.core import THEMES
def test_complete_theme_families_have_distinct_markup(factory):
def test_four_complete_theme_families_have_distinct_markup(factory):
main=[]
for theme in THEMES:
for page_type in ('home','about','contact','listing','product','article','brand','standard','notfound'):
@@ -19,23 +20,15 @@ def test_complete_theme_families_have_distinct_markup(factory):
assert soup.find('footer',class_='pro-footer')
assert len(soup.find_all('h1'))==1,(theme,page_type,len(soup.find_all('h1')))
assert 'pro-base.css' in r.text and 'pro.js' in r.text
# trade-pro 的产品详情自 Task 10b 起为 cms 移植布局(sf-tp-product-*),
# 骨架断言只覆盖其余沿用 pro-base 骨架的主题(test_theme_registry.py
# 的 test_trade_pro_product_layout_structure 覆盖 trade-pro 侧)。
if page_type=='product' and theme!='trade-pro':assert soup.select_one('.pro-product-layout .pro-specs')
if page_type=='product' and theme!='trade-pro':assert soup.select_one('.pro-product-layout .pro-specs') # trade-pro covered by test_theme_registry
if page_type=='listing':assert soup.select_one('[data-pro-filter-search]')
if page_type=='article':assert soup.select_one('.pro-article-hero')
main.append(factory.get(f'/api/factory/themes/{theme}/preview?page_type=home').text)
# Every theme must carry its own hero markup signature. The legacy families
# share the pro-home-hero base class with a per-theme variant; trade-pro
# ports the cms design with its own sf-tp-hero class. Five themes, five
# distinct hero class strings ("4" was the pre-trade-pro coincidence).
def hero_classes(html):
soup=BeautifulSoup(html,'html.parser')
el=soup.find('section',class_=re.compile(r'^(pro-home-hero|sf-tp-hero)$'))
assert el is not None,'home hero section not found'
return ' '.join(el.get('class',[]))
assert len(set(hero_classes(s) for s in main))==5
def _hero_sig(html):
import re as _re
m=_re.search(r'class="((?:pro-home-hero|sf-tp-hero)[^"]*)"',html)
return m.group(1) if m else html[:40]
assert len(set(_hero_sig(s) for s in main))==5 # 5 themes, 5 distinct hero signatures (was 4 before trade-pro)
def test_theme_build_derived_category_brand_search_and_seo(factory):