diff --git a/test_phase.py b/test_phase.py deleted file mode 100644 index 534a728..0000000 --- a/test_phase.py +++ /dev/null @@ -1,232 +0,0 @@ -#!/usr/bin/env python3 -""" -MD-CMS v0.4 phase test runner. - -Usage: - python3 test_phase.py [phase] - - phase: 1-7 (default: run all phases sequentially) - -Each phase fetches the corresponding branch, checks out the renderer and -content files for that phase, starts a local HTTP server, and opens the -browser. Press Enter when done to continue to the next phase. -""" - -import functools -import http.server -import subprocess -import sys -import threading -import time -import webbrowser -from pathlib import Path - -PORT = 8800 - -PHASES = { - 1: ("main", "theme.yml and colour system"), - 2: ("v0.4_phase2", "Icon system — local SVGs, no Google Fonts"), - 3: ("v0.4_phase3", "Asset validation in mdcms build"), - 4: ("claude/debug-api-errors-gd730", "Callout tags"), - 5: ("claude/toc-tag-phase5", "Table of contents tag"), - 6: ("claude/fetch-deps-phase6", "Offline / fetch-deps"), - 7: ("claude/pwa-phase7", "PWA — service worker and manifest"), -} - -VERIFY = { - 1: [ - "Existing site renders correctly with theme.yml present", - "Missing theme: key falls back gracefully to hardcoded defaults", - "Accent colour and dark/light mode colours apply from theme.yml", - ], - 2: [ - "All UI icons render correctly from local SVG files (no Google Icons font)", - "Theme toggle, search, hamburger, nav arrows all show icons", - "Broken image displays for a missing icon (test by renaming one SVG)", - "Icon name normalisation: 'arrow-right' and 'Arrow Right' both resolve", - ], - 3: [ - "Run: python3 mdcms.py build --path app/ (NOT the installed mdcms command)", - "Warning printed for assets/images/missing-photo.png (referenced in pages/about.md)", - "No warning for assets/images/logo.png (file exists)", - "Build continues and completes after warnings", - ], - 4: [ - "── Basic types ─────────────────────────────────────────────────", - "callout-info, callout-warning, callout-success, callout-error all render", - "Each has: coloured left border + low-opacity background in the right colour", - "── Title row ───────────────────────────────────────────────────", - "Title row shows: icon (inlined SVG) + bold title text in the accent colour", - "Title text is correct for each type: Information / Warning / Success / Error", - "── No-title callout ────────────────────────────────────────────", - "Callout with no title key: no title row rendered, just the body", - "── Markdown body ───────────────────────────────────────────────", - "Body renders full markdown: bold, italic, lists, inline code, links", - "── Custom icon override ────────────────────────────────────────", - "icon: warning on a callout-info renders the warning SVG, not the info SVG", - "── Config-defined message: key ─────────────────────────────────", - "message: aitranslation resolves title 'PLEASE NOTE:' and body from config.yml", - "── Dark mode ───────────────────────────────────────────────────", - "Toggle dark mode: all four callout types still look correct", - "Colours adapt (border and background tint remain visible on dark background)", - ], - 5: [ - "TOC tag renders a section-grouped page list", - "Only pages visible for active category are listed", - "Draft pages are excluded", - "TOC page itself is excluded from the listing", - "Section headings and sort order are correct", - ], - 6: [ - "mdcms fetch-deps downloads JS/CSS to assets/required/vendors/", - "Patched index.html makes no external network requests", - "Fonts load correctly from local paths", - "Site loads fully offline after fetch-deps", - ], - 7: [ - "service-worker.js and manifest.json generated when pwa: yes", - "Full site accessible offline after one online visit", - "Cache updates correctly on new build deployment", - "Offline message displays when cache evicted", - ], -} - -# Files checked out from the phase branch on every phase switch. -# Renderer + presentational config. Content files (home.md, config.yml) are -# added per phase in EXTRA_FILES so the right test content is loaded. -RENDERER_FILES = [ - "app/index.html", - "app/theme.yml", - "app/assets/icons", - "mdcms.py", -] - -# Per-phase extra files to check out from the phase branch. -# Use this for content or config files that differ between phases. -EXTRA_FILES = { - 4: [ - "app/config.yml", # has callouts: block for message: key test - "app/pages/home.md", # has Phase 4 callout test cases - ], - 5: [ - "app/pages/home.md", # has Phase 5 TOC test case - ], - 7: [ - "app/config.yml", # pwa: yes, sidebar nav, offline-message - "app/pages/home.md", # Phase 7 test instructions - "app/pages/about.md", # sample page to cache and test offline - "app/pages/docs.md", # sample page to cache and test offline - ], -} - - -def checkout_phase(phase: int) -> bool: - branch, _ = PHASES[phase] - repo_root = Path(__file__).parent - - print(f"\n Fetching branch {branch} from origin...") - result = subprocess.run( - ["git", "fetch", "origin", branch], - cwd=repo_root, - capture_output=True, - text=True, - ) - if result.returncode != 0: - print(f" ERROR fetching: {result.stderr.strip()}") - return False - - files = RENDERER_FILES + EXTRA_FILES.get(phase, []) - print(f" Checking out {len(files)} file groups from origin/{branch}...") - result = subprocess.run( - ["git", "checkout", f"origin/{branch}", "--"] + files, - cwd=repo_root, - capture_output=True, - text=True, - ) - if result.returncode != 0: - print(f" ERROR checking out files: {result.stderr.strip()}") - return False - - print(" Rebuilding nav.yml...") - result = subprocess.run( - ["python3", "mdcms.py", "build", "--path", "app/"], - cwd=repo_root, - capture_output=True, - text=True, - ) - if result.returncode != 0: - print(f" WARNING: mdcms build failed: {result.stderr.strip()}") - else: - out = result.stdout.strip() - if out: - print(f" {out}") - - print(" Ready.\n") - return True - - -def serve(app_dir: Path): - handler = functools.partial( - http.server.SimpleHTTPRequestHandler, - directory=str(app_dir), - ) - handler.log_message = lambda *a: None - with http.server.HTTPServer(("", PORT), handler) as httpd: - httpd.serve_forever() - - -def run_phase(phase: int): - branch, description = PHASES[phase] - - print("\n" + "=" * 62) - print(f" Phase {phase}: {description}") - print(f" Branch: {branch}") - print("=" * 62) - - repo_root = Path(__file__).parent - app_dir = repo_root / "app" - - if phase > 1: - if not checkout_phase(phase): - print(" Checkout failed — skipping this phase.") - return - - print(f" Serving app/ at http://localhost:{PORT}\n") - print(" Checklist:") - for item in VERIFY[phase]: - if item.startswith("──"): - print(f"\n {item}") - else: - print(f" [ ] {item}") - - t = threading.Thread(target=serve, args=(app_dir,), daemon=True) - t.start() - time.sleep(0.3) - webbrowser.open(f"http://localhost:{PORT}") - - print("\n Press Enter when done (Ctrl+C to abort)...") - try: - input() - except KeyboardInterrupt: - print("\n Aborted.") - - -def main(): - if len(sys.argv) == 2: - try: - phase = int(sys.argv[1]) - except ValueError: - print("Usage: python3 test_phase.py [1-7]") - sys.exit(1) - if phase not in PHASES: - print(f"Phase must be 1-7, got {phase}") - sys.exit(1) - run_phase(phase) - else: - for phase in sorted(PHASES): - run_phase(phase) - print(f"\n Phase {phase} done.") - - -if __name__ == "__main__": - main()