from __future__ import annotations import json from quantum_learning import ( canonical_course_steps, entry_notebook_path, project_root, reference_notebook_path, visible_notebook_root_names, ) def _notebook_text(path): data = json.loads(path.read_text()) return "\n".join("".join(cell.get("source", [])) for cell in data.get("cells", [])) def test_start_here_is_the_only_supported_entrypoint(): assert entry_notebook_path() == project_root() / "notebooks" / "START_HERE.ipynb" app_script = (project_root() / "scripts" / "app.sh").read_text() assert "lab/tree/notebooks/START_HERE.ipynb" in app_script def test_visible_notebook_root_is_curated(): notebook_root = project_root() / "notebooks" visible_names = sorted(path.name for path in notebook_root.iterdir() if not path.name.startswith(".")) assert visible_names == sorted(visible_notebook_root_names()) def test_reference_notebook_is_not_in_root(): assert reference_notebook_path().exists() assert not (project_root() / "notebooks" / "PROFESSIONAL_PATH.ipynb").exists() assert not (project_root() / "notebooks" / "reference").exists() def test_mainline_course_notebooks_have_navigation_guardrails(): steps = canonical_course_steps() for index, step in enumerate(steps): path = project_root() / step.path text = _notebook_text(path) assert "" in text assert "" in text assert "What To Open Next" in text if index == 0: assert "This is the start of the mainline course" in text if index < len(steps) - 1: next_title = steps[index + 1].title assert next_title in text else: assert "This notebook closes the mainline course" in text def test_start_here_does_not_contain_stale_branching_advice(): text = _notebook_text(project_root() / "notebooks" / "START_HERE.ipynb") assert "Read the rest of this notebook, then open `PROFESSIONAL_PATH.ipynb`." not in text assert "Open `PROFESSIONAL_PATH.ipynb` next." not in text assert "`00_circuit_literacy.ipynb`" not in text assert "first-pass learner journey" not in text assert "optional side reference" not in text assert "COURSE_BLUEPRINT.ipynb" in text def test_mainline_route_text_is_single_pass_and_non_branching(): notebook_paths = [ project_root() / "notebooks" / "START_HERE.ipynb", project_root() / "notebooks" / "COURSE_BLUEPRINT.ipynb", project_root() / "notebooks" / "COURSE_COMPLETE.ipynb", ] banned_fragments = [ "PROFESSIONAL_PATH.ipynb", "first-pass", "optional side reference", "Only then return to the later single-notebook materials as transition content", "If this notebook still feels unstable, repeat it before you move on.", ] for path in notebook_paths: text = _notebook_text(path) for fragment in banned_fragments: assert fragment not in text course_complete_text = _notebook_text(project_root() / "notebooks" / "COURSE_COMPLETE.ipynb") assert "This is the end of the guarded mainline route." in course_complete_text