mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-09 16:32:21 +02:00
fix(publication): restore project-origin branding and demo assets (#6561)
* chore(publication): restore cleared first-party assets * fix(branding): restore publication asset integrations * fix(publication): tighten restoration provenance
This commit is contained in:
@@ -14,23 +14,57 @@ const { extractThemeBootstrap } = require('./helpers/theme_bootstrap.cjs');
|
||||
page.on('request', req => { if (/\.(webm|mp4)(?:$|\?)/.test(req.url())) mediaRequests.push(req.url()); });
|
||||
page.on('pageerror', e => errors.push(e.message));
|
||||
await page.goto(origin + '/website/index.html');
|
||||
assert.equal(await page.locator('video, .preview-panel, .sec-bg-tint').count(), 0);
|
||||
assert.equal(await page.locator('.feature-description').count(), 8);
|
||||
for (const description of await page.locator('.feature-description .desc').allTextContents()) assert(description.trim());
|
||||
// Landing page contains expected preview panels, preview videos, and background video
|
||||
assert.equal(await page.locator('.preview-panel').count(), 8);
|
||||
assert.equal(await page.locator('section#previews video').count(), 7);
|
||||
assert.equal(await page.locator('section#how video.sec-bg').count(), 1);
|
||||
assert.equal(await page.locator('section#how .sec-bg-tint').count(), 1);
|
||||
|
||||
// Expected video source paths exist and return 200
|
||||
const expectedVideos = [
|
||||
'chat.webm',
|
||||
'research.webm',
|
||||
'compare.webm',
|
||||
'document.webm',
|
||||
'notes.webm',
|
||||
'gallery.webm',
|
||||
'theme.webm',
|
||||
'bg.webm',
|
||||
];
|
||||
const videoSources = await page.locator('video source').evaluateAll(els => els.map(s => s.getAttribute('src')));
|
||||
assert.deepEqual(videoSources.sort(), expectedVideos.slice().sort());
|
||||
for (const src of expectedVideos) {
|
||||
const videoRes = await page.request.get(origin + '/website/' + src);
|
||||
assert.equal(videoRes.status(), 200, `Video source ${src} should return 200`);
|
||||
}
|
||||
|
||||
// Feature and video layout does not overflow at desktop or mobile widths
|
||||
for (const width of [1280, 390]) {
|
||||
await page.setViewportSize({ width, height: 900 });
|
||||
assert(await page.locator('.feature-description').first().isVisible());
|
||||
assert(await page.locator('.preview-panel').first().isVisible());
|
||||
assert(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth));
|
||||
}
|
||||
assert.deepEqual(mediaRequests, []);
|
||||
assert.deepEqual(errors, []);
|
||||
|
||||
// Manifest has valid icon entries that return successfully
|
||||
const manifest = await (await page.request.get(origin + '/static/manifest.json')).json();
|
||||
assert.equal(manifest.display, 'standalone');
|
||||
assert(!manifest.icons);
|
||||
assert(Array.isArray(manifest.icons) && manifest.icons.length === 3);
|
||||
for (const icon of manifest.icons) {
|
||||
assert(icon.src, 'Manifest icon entry must have src');
|
||||
const iconUrl = new URL(icon.src, origin + '/static/manifest.json').href;
|
||||
const iconRes = await page.request.get(iconUrl);
|
||||
assert.equal(iconRes.status(), 200, `Manifest icon ${icon.src} should return 200`);
|
||||
}
|
||||
|
||||
// Apple touch icon references in app HTML point to real files
|
||||
for (const filename of ['index.html', 'login.html']) {
|
||||
const html = await (await page.request.get(origin + '/static/' + filename)).text();
|
||||
assert(!/<link[^>]+rel=["']apple-touch-icon/.test(html));
|
||||
const match = html.match(/<link[^>]+rel=["']apple-touch-icon["'][^>]+href=["']([^"']+)["']/);
|
||||
assert(match, `missing apple-touch-icon in ${filename}`);
|
||||
const iconUrl = new URL(match[1], origin + '/').href;
|
||||
const res = await page.request.get(iconUrl);
|
||||
assert.equal(res.status(), 200, `Apple touch icon in ${filename} should return 200`);
|
||||
}
|
||||
|
||||
// A small host DOM runs the actual export function and markdown renderer.
|
||||
|
||||
@@ -30,23 +30,49 @@ def test_retained_artifacts_match_distributed_provenance_and_notices():
|
||||
|
||||
def test_removed_resource_ledger_has_no_runtime_references():
|
||||
ledger = (ROOT / 'PUBLICATION_ASSET_DECISIONS.md').read_text()
|
||||
removed = re.findall(r'^- SAN-\d+: `([^`]+)`$', ledger, re.M)
|
||||
assert len(removed) == 21
|
||||
# Inspect tracked text, including files omitted by parity-audit exclusions.
|
||||
san_entries = re.findall(r'^- SAN-\d+: `([^`]+)`$', ledger, re.M)
|
||||
assert len(san_entries) == 21
|
||||
|
||||
restore_entries = re.findall(r'^- RESTORE-\d+: `([^`]+)` \(SHA-256: `([a-f0-9]{64})`\)', ledger, re.M)
|
||||
assert len(restore_entries) == 14
|
||||
|
||||
restored_paths = {path for path, _ in restore_entries}
|
||||
for path, expected_sha in restore_entries:
|
||||
target = ROOT / path
|
||||
assert target.is_file(), f"restored asset missing on disk: {path}"
|
||||
actual_sha = hashlib.sha256(target.read_bytes()).hexdigest()
|
||||
assert actual_sha == expected_sha, f"sha256 mismatch for {path}"
|
||||
|
||||
still_omitted = [path for path in san_entries if path not in restored_paths]
|
||||
assert len(still_omitted) == 7
|
||||
|
||||
expected_omitted_names = {
|
||||
'GohuFont.ttf',
|
||||
'html2pdf.bundle.min.js',
|
||||
'qrcode.min.js',
|
||||
'ollama-mark.png',
|
||||
'ollama-mark-crop.png',
|
||||
'sglang-logo.png',
|
||||
'sglang-mark.png',
|
||||
}
|
||||
assert {Path(p).name for p in still_omitted} == expected_omitted_names
|
||||
|
||||
# Inspect tracked text for references to still-omitted resources.
|
||||
tracked = subprocess.check_output(['git', 'ls-files', '-z'], cwd=ROOT).decode().split('\0')
|
||||
for path in removed:
|
||||
assert not (ROOT / path).exists()
|
||||
for path in still_omitted:
|
||||
assert not (ROOT / path).exists(), f"omitted asset must not exist: {path}"
|
||||
filename = Path(path).name
|
||||
for name in tracked:
|
||||
if name == "PUBLICATION_ASSET_DECISIONS.md":
|
||||
continue # Historical ledger entries are intentionally non-resource references.
|
||||
if name in {"PUBLICATION_ASSET_DECISIONS.md", "tests/test_publication_plan_b.py"}:
|
||||
continue # Historical ledger and test assertions are intentionally non-resource references.
|
||||
file = ROOT / name
|
||||
if not file.is_file():
|
||||
continue
|
||||
try:
|
||||
content = file.read_text()
|
||||
content = file.read_text(encoding="utf-8")
|
||||
except UnicodeError:
|
||||
continue
|
||||
assert Path(path).name not in content, (path, name)
|
||||
assert filename not in content, (path, name)
|
||||
|
||||
|
||||
def test_cold_catalog_and_refresh_use_mutable_data(monkeypatch, tmp_path):
|
||||
@@ -113,12 +139,20 @@ def test_distribution_paths_include_all_notices():
|
||||
ignore = (ROOT / '.dockerignore').read_text()
|
||||
assert '!ACKNOWLEDGMENTS.md' in ignore
|
||||
manifest = json.loads((ROOT / 'static/manifest.json').read_text())
|
||||
assert not manifest.get('icons')
|
||||
assert manifest.get('icons')
|
||||
assert manifest['display'] == 'standalone'
|
||||
expected_icons = [
|
||||
{"src": "icons/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any maskable"},
|
||||
{"src": "icons/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any maskable"},
|
||||
{"src": "icons/icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable"},
|
||||
]
|
||||
assert manifest['icons'] == expected_icons
|
||||
for icon in manifest['icons']:
|
||||
assert (ROOT / 'static' / icon['src']).is_file()
|
||||
|
||||
|
||||
def test_browser_publication_behaviors():
|
||||
"""Real Chromium DOM: text-only website, saved fonts, escaped print/math."""
|
||||
"""Real Chromium DOM: restored website media, saved fonts, escaped print/math."""
|
||||
if not shutil.which('node'):
|
||||
pytest.skip('Node is required')
|
||||
probe = subprocess.run(['node', '-e', "require.resolve('playwright')"], cwd=ROOT, capture_output=True)
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
"""Regression guard for the README title presentation.
|
||||
|
||||
The original ASCII-art banner needed a code fence to preserve whitespace.
|
||||
Publication now opens with a centered text heading after omitting the wordmark
|
||||
artwork. Keep the title identity and the historical ASCII-fencing guard.
|
||||
Keep the wordmark title identity and the historical ASCII-fencing guard.
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
@@ -19,9 +18,9 @@ def _fenced_segments(text: str):
|
||||
return parts[1::2]
|
||||
|
||||
|
||||
def test_readme_opens_with_text_title():
|
||||
def test_readme_opens_with_wordmark_title():
|
||||
head = "\n".join(README.read_text(encoding="utf-8").splitlines()[:15])
|
||||
assert head.startswith('<h1 align="center">Odysseus</h1>'), "README must open with the Odysseus text title"
|
||||
assert 'alt="Odysseus"' in head, "README must open with the Odysseus wordmark image"
|
||||
|
||||
|
||||
def test_reintroduced_ascii_banner_stays_fenced():
|
||||
|
||||
Reference in New Issue
Block a user