Skip to content

Raise the quality bar for pull requests: lint, coverage gate, broader tests - #7

Merged
Torgh merged 1 commit into
cloud-storagefrom
test-quality
Oct 16, 2026
Merged

Torgh merged 1 commit into
cloud-storagefrom
test-quality

Conversation

@Torgh

@Torgh Torgh commented Oct 16, 2026

Copy link
Copy Markdown
Owner

Stacked on #6 (cloud-storage): these tests cover its storage and OAuth code. When #6 is merged, GitHub retargets this PR to main.

Summary

Every pull request now has to pass typecheck, ESLint, tests with a coverage gate, and a production build, and the tests also run on Windows.

CI (.github/workflows/ci.yml)

  • Ubuntu job: runs typecheck → lint → test:coverage → build. A coverage table is shown in the run summary.
  • Windows job: runs the tests again. File paths and OneDrive folder detection behave differently on Windows, and that is where the app is used.
  • Concurrency: a new push to a PR cancels the run for the previous push. permissions: contents: read.
  • PR template: a checklist.

Coverage: ~32 % → ~88 % statements, enforced

  • Thresholds in vitest.config.mts: statements 85, branches 80, functions 78, lines 87. These are just below today's numbers, so a change that removes coverage fails CI.
  • Excluded: browser-only glue and thin wrappers around external APIs (Claude, Google Maps, OSM).
Area What is tested
lib/server/http.ts Localhost-only guard, DNS rebinding (foreign Host), cross-site Origin, JSON content type (blocks form posts), body validation, error mapping that never leaks internals
lib/server/cloudAuth.ts PKCE and scopes in the auth URL, code exchange storing the email and scopes, reuse or refresh of access tokens, "reconnect" on a revoked token, offline errors, revocation on disconnect
API routes Trips CRUD, id mismatch and path traversal; storage switching with copying; /api/config never returning secrets; Google sign-in: start cookies, CSRF state check, declined consent, full callback with migration from the hidden folder; disconnect copying trips to this PC
lib/sync.ts + store Newest version wins in both directions, deletes propagate, storage switch uploads instead of "deleting", one sync at a time, offline and server errors; store actions; trip file import
mcp/server.ts The real server over stdio (Bun), as Claude Code runs it: tool and prompt list, planning a trip end to end including the no-fly warning, tool errors that don't kill the server
Other tripOps (19 % → 100 %), Google → OpenStreetMap fallback in maps, time and place helpers

Server tests run against a temporary TRIPDECK_HOME, with the OneDrive folder replaced by a temporary one, so real trips are never touched.

ESLint (eslint-config-next core-web-vitals + typescript, --max-warnings 0)

Fixes for what it found:

  • OsmMap: wrote a ref during render. It is now updated in an effect.
  • Settings: called setState in an effect to read window.location.origin. It now uses useSyncExternalStore.
  • Splitter: the localStorage read after hydration is intentional. It is kept, and the rule is disabled for that line with the reason in a comment.
  • MCP: removed an unused helper (dayNumberOf).

_name stays the convention for deliberately unused values.

Not included

  • Prettier: a format check would reformat 35 existing files. Better as a separate PR so this one stays reviewable.
  • Required checks: to block merging on red CI, mark the check and windows jobs as required checks in the branch protection rules for main.

Test plan

  • bun run check passes locally: 152 tests, coverage 88.5 % statements / 83.4 % branches
  • A deliberately raised threshold (lines=99) makes the run fail
  • In the browser: clicking a map marker still highlights its card, Settings shows the right redirect URI, no console errors

🤖 Generated with Claude Code

… tests

CI now runs `bun run check` (typecheck, ESLint, tests with coverage, build)
and the tests again on Windows. Coverage goes from ~32 % to ~88 % of
statements, with thresholds that fail the run when it drops.

New tests:
- http: localhost-only guard, DNS rebinding, cross-site origin, JSON body
  validation, error mapping
- cloudAuth: PKCE auth URL and scopes, code exchange, token refresh and
  revocation, offline errors
- API routes: trips CRUD and id checks, storage switching, config never
  returning secrets, Google sign-in (state/CSRF check, hidden-folder
  migration) and disconnect
- browser sync: newest wins, deletes, storage switch, offline; store
  actions; trip import
- MCP server: the real server over stdio, planning a trip end to end
- tripOps, maps fallback to OpenStreetMap, time and place helpers

ESLint (eslint-config-next core-web-vitals + typescript) found and this
fixes: a ref written during render in OsmMap, setState in effects in
Settings and Splitter, and an unused MCP helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Torgh
Torgh merged commit 0f77a88 into cloud-storage Oct 16, 2026
2 checks passed
@Torgh
Torgh deleted the test-quality branch October 16, 2026 20:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant