Skip to content

test(theme): add coverage for v2 scope tree + primitives + compound fonts #3179

Description

@ten9876

Follow-up to #3176 — the container-scoped tokenization refactor merged without new tests covering its newly-introduced semantics. theme_manager_test continues to pass but only exercises the legacy flat-token getter API; the v2 surface area is largely uncovered.

Test gaps to close

JSON loader / writer

  • v1 → v2 migration round-trip: load a v1 bundled-style theme, mutate one token, save, reload, assert values match. Catches schema-version detection bugs and ensures the flat tokens block migrates cleanly into scopes.root.tokens.
  • v2 with primitives + {alias} references: load default-dark, assert color("color.accent") returns the resolved #00b4d8 (not the literal "{color.blue.500}"). This would have caught the cssFragment-returns-empty-for-ThemeFont bug we fixed mid-PR.
  • Gradient + font-compound discriminator: confirm flattenTokens correctly routes objects with typeThemeGradient, objects with familyThemeFont, plain nested → recurse. Discriminator order matters.

Scope tree

  • setColor(path, token, c) at a nested scope: override at applet/tx doesn't change root's value.
  • Inheritance walk: token defined at applet, read from applet/tx resolves to applet's value (no own override at tx).
  • removeOverride() at a nested scope drops the override; reading from that scope falls back to parent.
  • removeOverride() at root is a no-op (defensive guard from 3b833fd1).
  • scopeOrCreate("a/b/c") creates the full chain with parent pointers wired correctly.

Compound font tokens

  • setFontToken(path, "font.family.ui", {family, size, color}) round-trip: read back via fontTokenAt matches.
  • value(token) on a ThemeFont returns the .family field — preserves the ~35 legacy callers.
  • cssFragment("font.size.freq") virtual lookup returns the compound's embedded size.
  • Writing a compound persists to disk in {family, size, color} shape (not as a nested scope).

Editor surface (smoke)

  • Editing a token while a built-in theme is active does NOT mutate the built-in's resource bundle (deferred-commit path, even if save-as is cancelled).
  • Per-theme recent-colors bucket: switch themes, confirm the recents grid swaps.

Why this matters

The refactor merged with several non-obvious bugs caught mid-stream by the operator running the app (cssFragment-empty-for-ThemeFont, size combo not marking dirty, root-scope clear deleting tokens tree-wide, destructor SEGV during scope change). Smoke tests across the new APIs would catch the next regression before it lands in someone's workflow.

The 23 commits in #3176 establish the new surface — this issue is the test-debt invoice.

73, Jeremy KK7GWY & Claude (AI dev partner)

Metadata

Metadata

Assignees

No one assigned

    Labels

    GUIUser interfaceenhancementImprovement to existing featuremaintainer-reviewRequires maintainer review before any action is taken

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions