Skip to content

test(ui): cover the client-side openapi spec parser and code-sample generators#8440

Merged
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
kai392:test/critical-issue-openapi-lib-coverage-v2
Jul 24, 2026
Merged

test(ui): cover the client-side openapi spec parser and code-sample generators#8440
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
kai392:test/critical-issue-openapi-lib-coverage-v2

Conversation

@kai392

@kai392 kai392 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Summary

apps/loopover-ui/src/lib/openapi.ts had zero tests despite being the module every /api/* docs page runs at request time — it derives the id each /api/$op URL is keyed on, merges declared vs. path-inferred parameters, extracts response examples, groups tags, rewrites the server origin, and generates the curl/fetch/Python samples. Same class of gap already fixed once for the server-side spec writer in #7770; this is the client-side reader.

Adds apps/loopover-ui/src/lib/openapi.test.ts (14 tests, no production changes).

Fixture, not the committed spec. build() isn't exported and runs at module-import time against public/openapi.json, whose contents drift with every API change. So the spec module is mocked with a small hand-built RawOpenApiSpec and openapi.ts is imported dynamically per test (vi.resetModules()); getApiOrigin is mocked too so normalizeServers' rewrite is asserted against a fixed origin. Nothing here depends on the real spec's current shape.

Covered, per the issue's list:

  • slugify (via op.id): GET /v1/repos/{owner}/{repo}get-v1-repos-owner-repo, with braces stripped, runs collapsed, and no leading/trailing/doubled -
  • extractPathParams: an undeclared {param} is auto-added as required: true / in: "path"; a declared one is not duplicated and the author's description wins
  • extractExample: prefers example; falls back to the first examples entry — asserted on the real unwrapping (first?.value, i.e. 1, not the { value: 1 } envelope); undefined with no application/json content, and no response entries at all for an empty responses
  • tag grouping: declared tags keep their description; build()'s fallback loop still surfaces a tag never declared in raw.tags
  • normalizeServers: the first server's url is overwritten with the live origin while later servers are untouched
  • generateCurl / generateFetch / generatePython: both the auth and no-auth arms, both the body and body-less arms (with DELETE asserted body-less alongside GET), the trailing-slash strip, and the inline-token vs $LOOPOVER_TOKEN branch

Replaces #8428, which the bot auto-closed purely because I briefly had 3 PRs open (this repo's configured limit is 2) — not for any problem with the change. Re-filed unchanged on current main, now within the limit.

Closes #8389

Test plan

  • npx vitest run --root apps/loopover-ui src/lib/openapi.test.ts — 14/14 green
  • npm run ui:typecheck clean; prettier --check clean on the new file
  • Test-only addition — no production file changed, so no behavior risk. apps/** is outside Codecov's coverage.include, so this owes no codecov/patch percentage; it exists to close a real assertion gap, not to move a number
  • CI validate

@kai392
kai392 requested a review from JSONbored as a code owner July 24, 2026 13:13
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 24, 2026
@loopover-orb

loopover-orb Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Tip

✅ LoopOver review result - approve/merge recommended

Review updated: 2026-07-24 13:39:18 UTC

1 file · 1 AI reviewer · no blockers · readiness 93/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This is a pure test-only addition (221 lines) for `apps/loopover-ui/src/lib/openapi.ts`, mocking the raw spec fixture and `getApiOrigin` to deterministically exercise slugify/operation-id derivation, path-param inference vs. declared-param precedence, example extraction (both `example` and `examples` envelope unwrapping), tag grouping including the undeclared-tag fallback, server URL normalization, and all three code-sample generators across auth/no-auth and body/no-body branches. The assertions trace real behavior described in the PR body (e.g. asserting the unwrapped `.value` of the first `examples` entry, not the envelope) rather than fabricating unreachable states, and the fixture is deliberately decoupled from the committed `public/openapi.json` so it won't drift. No production code changes are included, so there's no functional regression risk here.

Nits — 4 non-blocking
  • The dynamic `vi.resetModules()` + `await import('./openapi')` per test adds real overhead across 14 tests; if this module has no per-test mutable state, a single import in `beforeAll` would suffice — verify this pattern is necessary before treating it as a repo convention.
  • The fixture path `../../public/openapi.json` in the `vi.mock` call is a relative guess based on repo layout that couldn't be independently verified from the diff alone; confirm this resolves correctly relative to `openapi.test.ts`'s location.
  • Consider hoisting the dynamic import into `beforeAll` if `openapi.ts` truly has no per-test state requiring `resetModules`, to speed up the suite.
  • If a similar fixture-mocking pattern exists from the server-side spec-writer tests in preserveExistingObjectOrder() in write-ui-openapi.ts has zero direct unit tests despite gating every PR touching the API surface #7770, link to it directly for reviewers to compare conventions.

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #8389
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 117 registered-repo PR(s), 62 merged, 4 issue(s).
Contributor context ✅ Confirmed Gittensor contributor kai392; Gittensor profile; 117 PR(s), 4 issue(s).
Improvement ℹ️ Insufficient signal risk: clean · value: insufficient-signal · LLM: significant
Linked issue satisfaction

Addressed
The PR adds apps/loopover-ui/src/lib/openapi.test.ts with a hand-built fixture spec (not the committed openapi.json) covering slugify via op.id, extractPathParams' declared/undeclared branching, extractExample's example/examples/undefined branches, tag grouping including the undeclared-tag fallback, normalizeServers' first-vs-later-server overwrite, findOperation, and auth/no-auth and body/no-body

Review context
  • Author: kai392
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Python, JavaScript, Kotlin, Perl, TypeScript, Vue
  • Official Gittensor activity: 117 PR(s), 4 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Triage stale or unlinked PRs.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask <question> answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat <question> answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@loopover-orb loopover-orb Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoopOver approves — the gate is satisfied and CI is green.

@loopover-orb
loopover-orb Bot merged commit 09b665e into JSONbored:main Jul 24, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

lib/openapi.ts's client-side spec parsing/transform logic has zero test coverage

2 participants