Skip to content

test: cover three modules that had no unit spec at all - #2464

Merged
hahwul merged 1 commit into
mainfrom
hahwul/test-coverage-uncovered-units
Aug 6, 2026
Merged

test: cover three modules that had no unit spec at all#2464
hahwul merged 1 commit into
mainfrom
hahwul/test-coverage-uncovered-units

Conversation

@hahwul

@hahwul hahwul commented Aug 6, 2026

Copy link
Copy Markdown
Member

Motivation

Mapping spec coverage across the tree turned up three files with no direct unit spec — not one reference anywhere under spec/, despite being pure, deterministic logic sitting under decisions that matter:

File LOC What it decides
src/tagger/framework_taggers/go/group_scope.cr 172 Which URL prefix a Go middleware registration guards
src/miniparsers/js_object_config_extractor.cr 217 Payload CMS / Strapi declarative config decoding
src/ai_context/source_reader.cr 240 The source snippets the AI context is built from

Each was reachable only through functional tests of its callers, so a regression in the shared logic would surface (if at all) as a puzzling endpoint diff several layers away.

What's covered

GoRouteGroupScope (39 examples) — go_auth and go_security both build their guarded-prefix list from this module, so a wrong answer here is a security-tag false positive. The specs pin the behaviours its header comment says it exists for:

  • sibling assignment groups staying independent instead of accumulating (api then admin must not resolve to /api/admin)
  • a non-literal group path (r.Group(cfg.APIBase)) resolving to Unknown rather than collapsing to Global — collapsing would tag every endpoint, including the explicitly public ones, as guarded
  • a line that is both a closure and an assignment group not folding its own prefix in twice
  • closure frames retiring on brace unwind, chained Group(...).Use(...), and Party/Pre router dialects

NoirAIContext::SourceReader (47 examples) — its character budget is load-bearing: a snippet truncated before the suppressing evidence becomes a false positive downstream. Covers the budget (default, caller-supplied, and the exact-fit boundary), the three caches, and the block-boundary walk across all four styles — brace / python / ruby / bare statement — including the decorator lead-in and the indent guard behind the django /public/ false positive.

Noir::JSObjectConfigExtractor (39 examples) — every declaration shape its header comment claims to handle (TS type annotation, satisfies, call argument, module.exports), the value decoder including the statically-unresolvable-but-key-still-recorded case, and both depth guards.

Drive-by fix

src/models/code_locator.cr referenced NoirLogger and any_to_bool without requiring either. It compiled only because every real entry point happens to require logger.cr first — require-ing source_reader.cr on its own failed to compile. Requiring a file's own dependencies is what makes anything downstream of it unit-testable in isolation.

Verification

  • 125 new examples, all passing
  • crystal spec spec/unit_test — 4619 examples, 0 failures
  • crystal spec spec/functional_test — 22647 examples, 0 failures
  • just check — 1842 files inspected, 0 failures

No production behaviour changes; the only src/ edit is two require lines.

`GoRouteGroupScope`, `JSObjectConfigExtractor` and
`NoirAIContext::SourceReader` had no direct unit spec — not one
reference anywhere under `spec/`. All three are pure, deterministic
logic sitting under decisions that matter:

* `GoRouteGroupScope` resolves which URL prefix a Go middleware
  registration guards. `go_auth` and `go_security` both build their
  guarded-prefix list from it, so a wrong answer is a security-tag
  false positive. The specs pin the behaviours the module's header
  comment says it exists for: sibling assignment groups staying
  independent rather than accumulating into `/api/admin`, a
  non-literal group path resolving to `Unknown` rather than
  collapsing to `Global`, and a line that is both a closure and an
  assignment group not folding its prefix in twice.

* `SourceReader` extracts the snippets the AI context is built from.
  Its character budget is load-bearing — a snippet truncated before
  the suppressing evidence turns into a false positive downstream —
  so the specs cover the budget and the block-boundary walk across
  all four styles (brace / python / ruby / bare statement), including
  the decorator lead-in and the indent guard behind the django
  `/public/` false positive.

* `JSObjectConfigExtractor` decodes Payload CMS and Strapi configs.
  The specs cover each declaration shape its header comment claims
  to handle, the value decoder, and the depth guards.

`code_locator.cr` referenced `NoirLogger` and `any_to_bool` without
requiring either; it compiled only because every real entry point
happens to require `logger.cr` first. Requiring a file's own
dependencies is what makes anything downstream of it unit-testable in
isolation — without it `require`-ing `source_reader.cr` alone fails to
compile.

125 new examples. Full unit + functional suites and `just check` pass.
@github-actions github-actions Bot added the 💊 spec Issue for test codes label Aug 6, 2026
@hahwul
hahwul merged commit e82d4a8 into main Aug 6, 2026
9 checks passed
@hahwul
hahwul deleted the hahwul/test-coverage-uncovered-units branch August 6, 2026 14:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💊 spec Issue for test codes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant