mirror of
https://github.com/kbenestad/mdcms.git
synced 2026-06-18 15:24:32 +00:00
Delete test_phase.py
This commit is contained in:
parent
59efc20dde
commit
3858307302
1 changed files with 0 additions and 232 deletions
232
test_phase.py
232
test_phase.py
|
|
@ -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()
|
||||
Loading…
Reference in a new issue