Private
Public Access
0
0
Files
manual_slop/tests/test_commands_no_top_level_command_palette.py
T
ed 3dd153f718 refactor(gui_2): merge command_palette; split registry->commands + render->gui_2; git rm src/command_palette.py
Per spec FR1 + Phase 1.3 + architecture feedback: src/command_palette.py
split by responsibility:
  - Command/ScoredCommand/CommandRegistry/fuzzy_match/_close_palette/_execute (data/ops)
    -> src/commands.py (which already owns _LazyCommandRegistry pattern)
  - render_palette_modal (view/ImGui) -> src/gui_2.py

GUI is a pure view; the registry/data classes are ops; commands.py owns
the registry because commands.py is where @registry.register decorators live.
gui_2.render_palette_modal imports Command from commands.py to type its
parameters.

Also fixes Phase 1.1 (bg_shader) per architecture feedback:
BackgroundShader no longer owns 'enabled' state - the GUI is pure view.
State is now owned by AppController.bg_shader_enabled (read on load from
config, written from gui_2 checkbox via app's __setattr__ delegation).

Tests:
- tests/test_command_palette.py: imports from src.commands (was src.command_palette)
- tests/test_commands_no_top_level_command_palette.py: rewritten for the
  new architecture (eager registry in commands.py; render in gui_2; no
  circular import between commands.py and gui_2)
2026-06-26 06:54:59 -04:00

100 lines
3.3 KiB
Python

"""Tests for the post-Phase 1.3 architecture.
Per module_taxonomy_refactor_20260627 Phase 1.3, src/command_palette.py was
deleted and its content split by responsibility:
- Command / ScoredCommand / CommandRegistry / fuzzy_match (data/ops) -> src/commands.py
- render_palette_modal (view) -> src/gui_2.py
src/commands.py is a thin data module and can be imported eagerly (no
require_warmed lazy load is needed; the original lazy-load pattern in
startup_speedup_20260606 was specifically to defer the heavy src/command_palette
which pulled in imgui at module load).
These tests run in fresh subprocesses to ensure no warmup state leaks from
the test runner. We assert:
- src/commands imports cleanly and exposes Command + CommandRegistry
- src/gui_2 exposes render_palette_modal
- src/commands does NOT import gui_2 at module level (avoids circular)
- The static audit detects no top-level command_palette import (since the
module no longer exists)
"""
import subprocess
import sys
import textwrap
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
def _run_in_subprocess(snippet: str) -> subprocess.CompletedProcess:
script = textwrap.dedent(snippet)
return subprocess.run(
[sys.executable, "-c", script],
capture_output=True,
text=True,
cwd=str(ROOT),
timeout=30,
)
def test_commands_exposes_command_and_registry() -> None:
res = _run_in_subprocess("""
from src.commands import Command, CommandRegistry, fuzzy_match, ScoredCommand
r = CommandRegistry()
def my_cmd(app): pass
r.register(my_cmd)
print(len(r.all()))
print(r.all()[0].id)
""")
assert res.returncode == 0, f"stderr: {res.stderr}"
lines = res.stdout.strip().splitlines()
assert lines[0] == "1"
assert lines[1] == "my_cmd"
def test_gui_2_exposes_render_palette_modal() -> None:
res = _run_in_subprocess("""
from src.gui_2 import render_palette_modal
print(callable(render_palette_modal))
""")
assert res.returncode == 0, f"stderr: {res.stderr}"
assert res.stdout.strip() == "True"
def test_commands_does_not_import_gui_2_at_module_level() -> None:
"""src/commands is imported by src/commands registration sites and by
gui_2.render_palette_modal. To avoid a circular import, commands.py must
NOT import gui_2 at the top of the file. (TYPE_CHECKING imports are
allowed because they don't execute at runtime.)
"""
res = _run_in_subprocess("""
import ast
from pathlib import Path
commands_path = Path('src') / 'commands.py'
source = commands_path.read_text(encoding='utf-8')
tree = ast.parse(source)
for node in tree.body:
if isinstance(node, (ast.Import, ast.ImportFrom)):
mod = getattr(node, 'module', None) or (node.names[0].name if node.names else '')
if mod and ('gui_2' in mod or mod.endswith('gui_2')):
print('VIOLATION:', mod)
print('OK')
""")
assert res.returncode == 0, f"stderr: {res.stderr}"
assert "VIOLATION" not in res.stdout
assert "OK" in res.stdout
def test_command_palette_module_no_longer_exists() -> None:
"""src/command_palette.py was deleted in Phase 1.3; this is a regression guard."""
res = _run_in_subprocess("""
import importlib
try:
importlib.import_module('src.command_palette')
print('EXISTS')
except ModuleNotFoundError:
print('NOT_FOUND')
""")
assert res.returncode == 0, f"stderr: {res.stderr}"
assert res.stdout.strip() == "NOT_FOUND"