refactor(tests): per-model fakes, FakeMCP and session mocks come from tests/helpers (#2825, milestone 296 area 1, batch 2)
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / integration (push) Successful in 24s
CI & Build / TypeScript typecheck (push) Successful in 33s
CI & Build / Python tests (push) Failing after 36s
CI & Build / Build & push image (push) Skipped
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / integration (push) Successful in 24s
CI & Build / TypeScript typecheck (push) Successful in 33s
CI & Build / Python tests (push) Failing after 36s
CI & Build / Build & push image (push) Skipped
Second pass over the tests/ ledger after bbee0d0. fake_record(**attrs) is the
one MagicMock-with-real-attributes builder (to_dict mirrors them; the
note-2109 hazard documented once); fake_note/fake_task/fake_snippet/
fake_project/fake_milestone/fake_system/fake_rulebook/fake_topic/fake_rule
carry each model's ordinary defaults on top of it, replacing 14 per-file
factories (two rulebook trios in tool-vs-service wordings, _fake_task, _fake_ms,
_fake_project, _plan_note, _fake_snippet, two _snippet adapters now one-liners
over fake_snippet). FakeMCP replaces the five closure-over-a-list registrar
fakes (+ _Recorder); loc() and design_token_stub() replace the paired _loc /
_token / _T stand-ins; every hand-built async_session mock (9 helper defs and
14 inline copies) now starts from make_mock_session(). Call sites rewritten by
AST with each file's former defaults made explicit, so behaviour is unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,13 +17,7 @@ from scribe.services.design_stylesheet import (
|
||||
safe_value,
|
||||
selector_for_mode,
|
||||
)
|
||||
|
||||
|
||||
def _token(name, value_by_mode, group_name=None, purpose=None):
|
||||
return SimpleNamespace(
|
||||
name=name, value_by_mode=value_by_mode,
|
||||
group_name=group_name, purpose=purpose,
|
||||
)
|
||||
from tests.helpers import design_token_stub
|
||||
|
||||
|
||||
# --- safety -----------------------------------------------------------------
|
||||
@@ -66,7 +60,7 @@ def test_a_rejected_value_is_dropped_not_cleaned_up():
|
||||
"""Rejecting beats stripping. A partially-sanitised value is one the operator
|
||||
never wrote, and the sheet's entire claim is that it IS the record — quietly
|
||||
rendering a different colour would break that claim invisibly."""
|
||||
css = render_stylesheet([_token("--fs-x", {"base": "red; } body { color: blue"})])
|
||||
css = render_stylesheet([design_token_stub(name="--fs-x", value_by_mode={"base": "red; } body { color: blue"})])
|
||||
assert "body" not in css
|
||||
assert "value rejected" in css
|
||||
|
||||
@@ -85,7 +79,7 @@ def test_a_malformed_token_name_is_dropped():
|
||||
assert not is_valid_token_name("color: red")
|
||||
assert not is_valid_token_name("fs-obsidian") # no leading --
|
||||
|
||||
css = render_stylesheet([_token("--bad name", {"base": "red"})])
|
||||
css = render_stylesheet([design_token_stub(name="--bad name", value_by_mode={"base": "red"})])
|
||||
assert "bad name" not in css
|
||||
|
||||
|
||||
@@ -100,8 +94,8 @@ def test_the_sheet_declares_properties_and_styles_no_elements():
|
||||
handful of values once per element and grow with the UI. Purpose tokens are
|
||||
stated once and reused; components are snippets that reference them."""
|
||||
css = render_stylesheet([
|
||||
_token("--fs-obsidian", {"base": "#14171a"}, group_name="surface"),
|
||||
_token("--fs-moss", {"base": "#4a5d3f"}, group_name="action"),
|
||||
design_token_stub(name="--fs-obsidian", value_by_mode={"base": "#14171a"}, group_name="surface"),
|
||||
design_token_stub(name="--fs-moss", value_by_mode={"base": "#4a5d3f"}, group_name="action"),
|
||||
])
|
||||
assert "--fs-obsidian: #14171a;" in css
|
||||
# No element or class rules — the sheet has exactly one block here, and
|
||||
@@ -117,7 +111,7 @@ def test_the_sheet_declares_properties_and_styles_no_elements():
|
||||
def test_the_header_says_what_the_sheet_is_for():
|
||||
"""A generated file with no explanation gets hand-edited, and then it has
|
||||
diverged from the record it claims to be."""
|
||||
css = render_stylesheet([_token("--fs-x", {"base": "1px"})], title="FabledSword")
|
||||
css = render_stylesheet([design_token_stub(name="--fs-x", value_by_mode={"base": "1px"})], title="FabledSword")
|
||||
assert "FabledSword" in css
|
||||
assert "Generated" in css
|
||||
assert "snippets" in css
|
||||
@@ -129,7 +123,7 @@ def test_base_goes_on_the_root_selector_and_other_modes_layer_over_it():
|
||||
"""Matches the convention already in the codebase, and the one-way scoping
|
||||
#251 recorded: light on `:root`, dark layered on an attribute selector."""
|
||||
css = render_stylesheet([
|
||||
_token("--fs-bg", {"base": "#f5f1e8", "dark": "#14171a"}),
|
||||
design_token_stub(name="--fs-bg", value_by_mode={"base": "#f5f1e8", "dark": "#14171a"}),
|
||||
])
|
||||
assert ":root {" in css
|
||||
assert '[data-theme="dark"] {' in css
|
||||
@@ -141,8 +135,8 @@ def test_a_mode_block_contains_only_what_that_mode_declares():
|
||||
Repeating every token in every block would make the sheet claim each mode
|
||||
redefines the whole system."""
|
||||
css = render_stylesheet([
|
||||
_token("--fs-bg", {"base": "#f5f1e8", "dark": "#14171a"}),
|
||||
_token("--fs-radius-md", {"base": "8px"}),
|
||||
design_token_stub(name="--fs-bg", value_by_mode={"base": "#f5f1e8", "dark": "#14171a"}),
|
||||
design_token_stub(name="--fs-radius-md", value_by_mode={"base": "8px"}),
|
||||
])
|
||||
dark_block = css.split('[data-theme="dark"] {')[1]
|
||||
assert "--fs-bg" in dark_block
|
||||
@@ -153,7 +147,7 @@ def test_the_root_selector_is_caller_chosen():
|
||||
"""A container-scoped preview cannot use `:root`. A generator that hardcoded
|
||||
it could not serve the preview surface at all."""
|
||||
css = render_stylesheet(
|
||||
[_token("--fs-x", {"base": "1px"})], root_selector="[data-preview]"
|
||||
[design_token_stub(name="--fs-x", value_by_mode={"base": "1px"})], root_selector="[data-preview]"
|
||||
)
|
||||
assert "[data-preview] {" in css
|
||||
assert ":root {" not in css
|
||||
@@ -163,8 +157,8 @@ def test_the_root_selector_is_caller_chosen():
|
||||
|
||||
def test_tokens_are_grouped_by_purpose_with_the_group_named():
|
||||
css = render_stylesheet([
|
||||
_token("--fs-obsidian", {"base": "#14171a"}, group_name="surface"),
|
||||
_token("--fs-radius-md", {"base": "8px"}, group_name="radius"),
|
||||
design_token_stub(name="--fs-obsidian", value_by_mode={"base": "#14171a"}, group_name="surface"),
|
||||
design_token_stub(name="--fs-radius-md", value_by_mode={"base": "8px"}, group_name="radius"),
|
||||
])
|
||||
assert "/* surface */" in css
|
||||
assert "/* radius */" in css
|
||||
@@ -174,8 +168,7 @@ def test_a_purpose_becomes_an_inline_comment_on_the_base_layer_only():
|
||||
"""Repeating the same prose in every mode block is noise: the token means
|
||||
the same thing in dark mode."""
|
||||
css = render_stylesheet([
|
||||
_token("--fs-obsidian", {"base": "#14171a", "dark": "#000000"},
|
||||
purpose="page bg, deepest surface"),
|
||||
design_token_stub(name="--fs-obsidian", value_by_mode={"base": "#14171a", "dark": "#000000"}, purpose="page bg, deepest surface"),
|
||||
])
|
||||
assert css.count("page bg, deepest surface") == 1
|
||||
|
||||
@@ -185,8 +178,8 @@ def test_a_declared_token_with_no_value_appears_as_a_comment_not_a_silence():
|
||||
that finding where the reader is already looking; dropping it would make the
|
||||
sheet look complete."""
|
||||
css = render_stylesheet([
|
||||
_token("--fs-obsidian", {"base": "#14171a"}),
|
||||
_token("--fs-radius-sm", {}),
|
||||
design_token_stub(name="--fs-obsidian", value_by_mode={"base": "#14171a"}),
|
||||
design_token_stub(name="--fs-radius-sm", value_by_mode={}),
|
||||
])
|
||||
assert "--fs-radius-sm" in css
|
||||
assert "no value set yet" in css
|
||||
@@ -210,9 +203,9 @@ def test_two_tokens_sharing_a_value_are_reported_not_refused():
|
||||
purpose — "Success = Moss, by design" — so this reports and lets a human
|
||||
decide which it is."""
|
||||
dupes = duplicate_values([
|
||||
_token("--fs-moss", {"base": "#4A5D3F"}),
|
||||
_token("--fs-success", {"base": "#4a5d3f"}),
|
||||
_token("--fs-obsidian", {"base": "#14171a"}),
|
||||
design_token_stub(name="--fs-moss", value_by_mode={"base": "#4A5D3F"}),
|
||||
design_token_stub(name="--fs-success", value_by_mode={"base": "#4a5d3f"}),
|
||||
design_token_stub(name="--fs-obsidian", value_by_mode={"base": "#14171a"}),
|
||||
])
|
||||
assert dupes == {"#4a5d3f": ["--fs-moss", "--fs-success"]}
|
||||
|
||||
@@ -221,15 +214,15 @@ def test_tokens_that_agree_in_one_mode_but_differ_in_another_are_not_duplicates(
|
||||
"""A near-miss is a different, weaker finding, and calling it a duplicate
|
||||
would send someone to merge two tokens that genuinely diverge."""
|
||||
assert duplicate_values([
|
||||
_token("--fs-a", {"base": "#fff", "dark": "#000"}),
|
||||
_token("--fs-b", {"base": "#fff", "dark": "#111"}),
|
||||
design_token_stub(name="--fs-a", value_by_mode={"base": "#fff", "dark": "#000"}),
|
||||
design_token_stub(name="--fs-b", value_by_mode={"base": "#fff", "dark": "#111"}),
|
||||
]) == {"#fff": ["--fs-a", "--fs-b"]}
|
||||
|
||||
|
||||
def test_valueless_tokens_never_count_as_duplicates_of_each_other():
|
||||
"""Otherwise every unfilled token would collide with every other one and the
|
||||
report would be nothing but noise on a fresh import."""
|
||||
assert duplicate_values([_token("--fs-a", {}), _token("--fs-b", {})]) == {}
|
||||
assert duplicate_values([design_token_stub(name="--fs-a", value_by_mode={}), design_token_stub(name="--fs-b", value_by_mode={})]) == {}
|
||||
|
||||
|
||||
# --- reading the sheet from the other side ----------------------------------
|
||||
|
||||
Reference in New Issue
Block a user