test(downgrader): rewrite checks as end-to-end tests - #30
Conversation
Every test now goes through the public entry points of
@openapi-spec/downgrader instead of the internal engine in src/shared.ts.
The unit tests in src/ are gone; the behaviors they pinned down (cloning,
cycles and sharing, __proto__ keys, alias chains, pointer decoding) are
expressed through real documents and schemas.
Layout:
- tests/v3.2-to-v3.1/{schema,spec}/ and tests/v3.1-to-v3.0/{schema,spec}/,
one file per topic
- tests/chained.test.ts for the documented 3.2 -> 3.1 -> 3.0 composition
Tricky behaviors carry a comment explaining why the output looks the way
it does, with links to the OpenAPI 3.0.4/3.1.2/3.2.0 specs, JSON Schema
2020-12, and the official upgrade guides.
The e2e suite alone keeps coverage at 100% of statements, branches,
functions, and lines, so no source changes were needed. Snapshots of the
official examples are byte-identical to the previous ones.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018z4VMNTUoJPMp24y74NBMo
- Reuse one Validator: a fresh instance per call recompiled the official schema every time. The suite drops from ~14s to ~4.5s. - Move validation helpers into tests/validate.ts, so files that only need `dig` no longer load Ajv, and add `expectValidDowngrade` for the per-document corpus check that was written out three times. - Declare the official corpora once in tests/corpus.ts instead of copying the 3.2 list into two files. - Add a `convertSchema` helper per downgrader folder in place of nine local wrappers and a dozen inline casts. - Share fixtures across v3.1 spec files, drop unused helper parameters and a positional wrapper, merge back-to-back it.each tables, and remove assertions an exact `toEqual` already covers. - Pin that a Path Item hop re-entered by its own chain contributes no fields, which no test checked before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018z4VMNTUoJPMp24y74NBMo
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — a test-only reorganization of the downgrader suite; no src/ changes. I ran the suite (vitest run: 40 files / 540 tests pass), type:check, and eslint — all green.
- Five monoliths removed —
src/shared.test.ts,src/v3.1-to-v3.0.test.ts,src/v3.2-to-v3.1.test.ts,tests/e2e.test.ts, and the oldtests/corpus.test.ts, together with the olde2e/corpussnapshots. - New per-concern suites added —
tests/{v3.1-to-v3.0,v3.2-to-v3.1}/{spec,schema}/split by version pair and spec-vs-schema, plustests/chained.test.tsfor the 3.2→3.1→3.0 chain. - Shared test infrastructure —
tests/corpus.tsnow holds corpus data only;tests/validate.tsaddsexpectValidDowngrade,expectNoNewDanglingRefs, and a sharedValidator;tests/helpers.tskeepsdigand addsexpectAcyclic. - Snapshots regenerated — keyed to the new test paths; committed snapshots are complete (no files written during the run, tree stays clean).
The new tests are a strict improvement in organization and generally in coverage: the old tests are re-expressed end-to-end with clearer intent, and edge cases such as pointer-token ownership (length, 00, -, __proto__), percent/tilde decoding, and cycle/fixpoint behavior are now pinned explicitly.
ℹ️ The src/shared.test.ts unit suite has no direct replacement
The 754-line unit suite for the engine primitives was deleted, and no test now imports shared.ts. Most of its behavior is re-covered through the public converters, but a few engine-level invariants (e.g. convertObject remembering a DROP result, releasing the cycle guard when a converter throws, and the clone/map/list/child/resolve/getRef/allOfItems/removedPrefixes contracts) are only exercised indirectly, if at all. Worth confirming the black-box approach is intended rather than an accidental loss.
Technical details
# Deleted `src/shared.test.ts` has no direct replacement
## Affected sites
- `packages/downgrader/src/shared.test.ts` — deleted in full; no new test imports `../src/shared` or `@openapi-spec/downgrader` internals.
- `packages/downgrader/tests/` — the new suite drives behavior only through `downgradeSpecV31ToV30` / `downgradeSpecV32ToV31` / `downgradeSchemaV*`.
## Required outcome
- Confirm that dropping direct unit coverage of `shared.ts` is intentional.
- If not, port the engine-invariant cases (error-path guard release, DROP memoization, `child` canonical-index rules) into a small `tests/shared.test.ts`; the `clone`/`map`/`list`/`resolve` edge cases that already have end-to-end equivalents can stay end-to-end.
## Open questions for the human
- Is the deliberate move to black-box-only testing of the engine, or should the primitive-level cases be retained?DeepSeek Flash (default — pick a model for stronger reviews) | 𝕏
|
Re the Pullfrog note on
Generated by Claude Code |

Rewrites the
@openapi-spec/downgradertests as end-to-end tests underpackages/downgrader/tests/. Every test goes through the public package (@openapi-spec/downgrader) instead of the internals insrc/shared.ts, and the suite alone keeps coverage at 100%.src/is unchanged, and the snapshots of the official examples are byte-identical to the old ones.Layout
tests/v3.2-to-v3.1/andtests/v3.1-to-v3.0/, one folder per downgrader, each split into:schema/fordowngradeSchema*, one file per topic, such astype,numeric-bounds,loosening, orkeywordsspec/fordowngradeSpec*, one file per topic, such asparameters,form-bodies,removed-parts, orcorpustests/chained.test.tsfor the 3.2 → 3.1 → 3.0 chain the README describes. It sits at the root because it belongs to neither downgrader alone.tests/corpus.tslists the official documents once.tests/validate.tsholds the official-schema checks, includingexpectValidDowngrade.tests/helpers.tsholdsdigandexpectAcyclic.schema/helpers.tsorspec/helpers.tswith its conversion helpers.Changes
src/shared.test.ts,src/v3.1-to-v3.0.test.ts,src/v3.2-to-v3.1.test.ts,tests/e2e.test.ts, andtests/corpus.test.ts.__proto__keys, key order, long alias chains, and pointer decoding.application/octet-streamdefault, whynotandoneOfare removed or relaxed after keywords are dropped, and why only the first inlined copy keeps its$id.$refchain re-entersPerformance
The suite runs in about 5s instead of about 15s. The old helper built a new validator per check, which recompiled the official OpenAPI schema every time. One shared validator now serves the whole file.
Testing
packages/downgrader/src, from these tests alone.CI=true, no snapshots are written or left obsolete.Notes
toEqualinstead of a snapshot. Its chained 3.0 snapshot was dropped; the official corpus, including themegadocuments, still goes through the whole chain.🤖 Generated with Claude Code
https://claude.ai/code/session_018z4VMNTUoJPMp24y74NBMo