Skip to content

Add unit tests for the robots.txt, sitemap.xml and news getServerSideProps handlers - #270

Merged
dmccoystephenson merged 2 commits into
mainfrom
feature/route-getserversideprops-tests
Aug 7, 2026
Merged

Add unit tests for the robots.txt, sitemap.xml and news getServerSideProps handlers#270
dmccoystephenson merged 2 commits into
mainfrom
feature/route-getserversideprops-tests

Conversation

@dmccoystephenson

Copy link
Copy Markdown
Member

Summary

  • Unit test coverage was added for the three getServerSideProps handlers that had none: pages/robots.txt.ts, pages/sitemap.xml.ts, and pages/news.tsx. The home page and the guide page were already covered.
  • The pure builders behind these routes (utils/sitemap.ts, utils/newsStorage.ts) were already tested; what was untested was the route wiring around them — the Content-Type header, the body actually written to the response, res.end() being called, and the {props: {}} return.
  • The crawler routes are asserted to read NEXT_PUBLIC_BASE_URL per request rather than caching an origin at import time, which is the behaviour the comment in utils/seo.ts claims for them.
  • The sitemap route is asserted to emit a guide URL for every plugin in pages/data/plugins.json (read from the real catalogue, not a fixture), so a regression that stops feeding the catalogue through guideSitemapPaths is caught.
  • The News page is asserted to pass getNewsPosts() through unmodified — same list, same order, empty list preserved — with the storage layer mocked so the shared data/news.json fixture is never touched.
  • No production code was changed. These are characterization tests: they assert current behaviour rather than alter it.

No tracking issue — gap found during triage. This cycle was run as a test-expansion cycle because every open issue in the backlog is feature-sized or blocked (see below).

Test plan

  • npm run lint
  • npm test — the three new files pass alongside the existing suite
  • npm run build

Local verification is UNVERIFIED for this branch: npm is unavailable and node_modules is absent in the environment this branch was authored in, so lint/test/build could not be executed locally. CI on this pull request's head SHA is the anchor, and this pull request is not to be merged until that run is green. Only test files and CHANGELOG.md are touched, both of which CI's npm test / npm run lint jobs execute directly.

Issues deferred this cycle

Recorded here for auditability rather than as individual comments on each issue:

This PR description was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).

dmccoystephenson and others added 2 commits August 7, 2026 01:16
…Props handlers

The crawler-document routes and the News page were the last three
getServerSideProps handlers with no coverage. utils/sitemap.ts and
utils/newsStorage.ts were already tested, but the route wiring around
them - content type, written body, per-request NEXT_PUBLIC_BASE_URL
reads, and feeding the plugin catalogue through guideSitemapPaths - was
not. Characterization tests only; no production code changed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ReturnType<typeof vi.fn> is Mock<any[], any>, which left the spy calls
untyped and forced a String() coercion when reading the written body.
Naming the argument tuples keeps the tests honest about the response
surface the routes actually use.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@dmccoystephenson

Copy link
Copy Markdown
Member Author

Self-review rubric

Scored against the CI run on head SHA 063bd3d (both Build Website (Node.js) and Build & Test API (Java) pass; the Test step log shows all three new files executing — 6 + 5 + 4 tests — with 31 test files passing overall).

  • Scope: PASSgit diff --stat origin/main...HEAD lists four files: the three new test files and a single added CHANGELOG.md line. No production code, no formatting churn, no renames.
  • Tests-new: PASS — this cycle is itself a test-expansion cycle; 15 new tests cover the three getServerSideProps handlers that previously had none.
  • Tests-fix: N/A — no bug is fixed here, so there is nothing to stash-and-revert. Sensitivity was instead argued per assertion rather than demonstrated: the "reads NEXT_PUBLIC_BASE_URL per request" tests import their route before beforeEach stubs the variable, so an implementation that captured the origin at module scope would emit the http://localhost:3000 default and fail the first assertion, not merely the second. The catalogue assertion reads pages/data/plugins.json directly, so dropping guideSitemapPaths from the route would fail it.
  • Sibling structure: PASS — the three files follow the shape of __tests__/guideId.getServerSideProps.test.ts and __tests__/index.getServerSideProps.test.ts: vitest imports first, a typed props/response shape interface, a comment explaining why each collaborator is mocked, then describe/it.
  • Sibling renames: N/A — no identifier was renamed.
  • Docs: PASSCHANGELOG.md gained an [Unreleased] → Added entry. CONFIG.md, README.md and USER_GUIDE.md need no change: no behaviour changed, no environment variable was introduced, and README.md already documents npm test and the __tests__/ location.
  • Issue resolution: N/A — no Closes #N; the gap was found during triage and the deferred backlog is enumerated in the pull request body.
  • no-any: PASSgit diff origin/main...HEAD -- '*.ts' '*.tsx' | grep -cE '^\+.*: *any\b' returns 0. The first push did smuggle any in structurally via ReturnType<typeof vi.fn> (which resolves to Mock<any[], any>); that was corrected in 063bd3d to explicit argument tuples.
  • mui-only: N/A — no component or page markup was touched.
  • env-vars-documented: PASS — no new process.env read was added to production code. The tests stub NEXT_PUBLIC_BASE_URL, which is already documented in CONFIG.md.
  • CI: PASS — both required checks pass on the head SHA.

Findings folded in from reading the diff

  • __tests__/news.getServerSideProps.test.ts:40toEqual compares structurally, so this assertion would still pass if the page returned an equal-but-cloned array rather than the exact list getNewsPosts handed back. Left as is deliberately: referential identity is not part of the page's contract, and the following test pins the property that does matter (order).
  • __tests__/robotsTxt.getServerSideProps.test.ts:11 and __tests__/sitemapXml.getServerSideProps.test.ts:13 — the ResponseSpy interface, createResponseSpy, contextWith and bodyWrittenTo are duplicated across the two crawler-route files. Extraction into a shared helper was considered and rejected: every existing file under __tests__/ is self-contained, and vitest's include is __tests__/**/*.test.ts, so a helper module would be a new and unprecedented kind of file in that directory for roughly fifteen shared lines.
  • __tests__/sitemapXml.getServerSideProps.test.ts:28bodyWrittenTo indexes write.mock.calls[0][0] unguarded, so a regression where the body is never written surfaces as a TypeError rather than a readable assertion failure. Accepted: the test still fails, and guarding it would add noise to every call site.

Verification note

Local npm run lint / npm test / npm run build could not be executed — npm is unavailable and node_modules is absent in the environment this branch was authored in. The CI run on the exact head SHA is therefore the anchor for every item above, and it covers the changed files directly.

This comment was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).

@dmccoystephenson
dmccoystephenson merged commit 21faae7 into main Aug 7, 2026
2 checks passed
@dmccoystephenson
dmccoystephenson deleted the feature/route-getserversideprops-tests branch August 7, 2026 07:22
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