feat: amending the test setup in the project - #161
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a Vitest-based unit/integration test layer alongside the existing Playwright E2E suite, and wires those tests into CI and the deploy workflow to prevent publishing a broken build—particularly around the “suggest an edit” automation flow.
Changes:
- Add Vitest configuration plus new unit/integration tests covering the suggest-edit template/client/apply-script contract and
apply-suggestionbehavior. - Refactor
scripts/apply-suggestion.mjsto export pure functions for testability, while retaining the CLI entrypoint. - Gate GitHub Pages deploys on unit + Playwright test jobs, and tighten Playwright’s matcher to
*.spec.tsonly.
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
vitest.config.ts |
Adds Vitest config with a narrow include pattern to avoid Playwright specs. |
tests/unit/suggest-edit-contract.test.ts |
Adds contract tests pinning template/client/workflow/apply-script seams. |
tests/unit/apply-suggestion.test.ts |
Adds unit tests for parsing and patching logic in apply-suggestion. |
tests/integration/process-suggestion.test.ts |
Adds a subprocess-level integration test for the CLI and step outputs. |
scripts/apply-suggestion.mjs |
Exports functions and introduces a pure applySuggestion function used by tests. |
playwright.config.ts |
Restricts Playwright discovery to *.spec.ts so Vitest can own *.test.ts. |
package.json |
Adds Vitest dependency and scripts (test:unit, test:all, etc.). |
package-lock.json |
Locks Vitest and its transitive deps. |
.github/workflows/deploy.yml |
Adds unit + Playwright test jobs and makes deploy depend on them. |
.github/workflows/ci.yml |
Adds a unit-test job and Playwright browser caching in CI. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: sdh100shaun <79883+sdh100shaun@users.noreply.github.com>
Co-authored-by: sdh100shaun <79883+sdh100shaun@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 10 changed files in this pull request and generated no new comments.
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
scripts/apply-suggestion.mjs:119
- The "no meetup file found" error message says the group name must match exactly as shown on the site, but
findMeetupFile()actually matches case-insensitively and trims whitespace. This message is misleading for contributors troubleshooting a failure.
throw new Error(
`No meetup file found with name "${groupName}" — it must match exactly as shown on the site.`,
);
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 10 changed files in this pull request and generated no new comments.
Suppressed comments (1)
scripts/apply-suggestion.mjs:197
- The script-entry guard compares
import.meta.url(a URL-encoded string) toprocess.argv[1](a filesystem path). If the path contains characters that get percent-encoded in a file URL (e.g. spaces),endsWith()will be false andmain()won’t run when invoked as a script. Decoding the URL before the comparison avoids this class of false negatives.
// Only run main() when invoked as a script, not when imported by a test.
const invokedAsScript =
process.argv[1] &&
import.meta.url.endsWith(process.argv[1].replaceAll('\\', '/'));
Every file that touches node builtins — src/pages/index.astro, playwright.config.ts and the three new test files — reported ts(2591) 'Cannot find name node:fs/promises' because @types/node was never installed. tsconfig.json sets no "types" field, so installing the package is enough for TS to pick it up. npm run check: 27 errors -> 3. Pinned to ^22 to match the node-version used by every workflow. Unit/integration (31) and Playwright (30, 1 data-conditional skip) all still pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The guide predated the test/ and suggestion work now on this branch, so it
described a repo that no longer exists in three places:
- Only Playwright was documented. There are now two runners split by
filename (*.spec.ts vs tests/{unit,integration}/**/*.test.ts), which is a
rule a new test file has to obey — so it needs to be written down.
- The "suggest an edit" flow — edit panel to issue form to
apply-suggestion.mjs to PR — was entirely absent, including the label
contract spread across five files that suggest-edit-contract.test.ts
exists to pin.
- CI had drifted: four jobs on PRs, deploy gated on [build, unit, test],
Playwright browser caching. The `npm run check` note also claimed 4 errors
from z.string().url(); it is now 3 errors elsewhere and that one is a
warning.
Verified against the tree rather than the diff: npm run test:unit (31
passing), npm run build, and npm run check for the error count. Both new
example commands were run.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 11 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
.github/workflows/deploy.yml:61
- The new
testjob also inherits workflow-levelpages: write/id-token: writepermissions even though it only needs to read the repo. Consider overriding job permissions tocontents: readto reduce the token scope.
test:
runs-on: ubuntu-latest
steps:
…oy.yml Co-authored-by: sdh100shaun <79883+sdh100shaun@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 11 changed files in this pull request and generated no new comments.
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
scripts/apply-suggestion.mjs:119
- The error message says the group name must "match exactly as shown on the site", but
findMeetupFile()matches case-insensitively and trims whitespace (name.trim().toLowerCase() === groupName.trim().toLowerCase()). This is misleading for users who only differ by case/spacing.
if (!match) {
throw new Error(
`No meetup file found with name "${groupName}" — it must match exactly as shown on the site.`,
);
Amends the testing setup sligthly - builds on the work @thebiggh started
Adds coverage and provides some extra gated assurance prior to deploy
What's on the branch now
Two commits were added after the original description, and the branch was
separated from the dependabot bumps it had been sharing a branch with —
those now live in #171, so this PR is test/tooling work only and contains
no version bumps.
Test setup. A second runner joins Playwright, split by filename so the
two can't collide:
tests/**/*.spec.tsis Playwright (testMatch) andtests/{unit,integration}/**/*.test.tsis vitest (include). Without bothfilters vitest picks up a
.spec.ts, importstestfrom@playwright/test, and fails on it. New scripts:test:unit,test:unit:watch,test:all.Coverage added. 31 tests across three files:
tests/unit/apply-suggestion.test.ts— issue-body parsing, link parsing,and the YAML splicing, including a regression test pinning that editing
one field leaves every other byte of the file identical.
tests/unit/suggest-edit-contract.test.ts— the seam that made thisworth testing. The suggest-an-edit flow restates the same field ids and
labels across the issue template,
EditPanelScript.astroandapply-suggestion.mjs, while the workflow trigger matches the template'stitle prefix. A rename in any one of them breaks the flow silently, at
runtime, for a real contributor. This test reads all of those files and
asserts they still line up.
tests/integration/process-suggestion.test.ts— runsapply-suggestion.mjsas a real subprocess against a temp copy of themeetups, pinning the stdin /
$GITHUB_OUTPUT/MEETUPS_DIRcontract theworkflow depends on.
Deploy gating.
deploy.yml'sdeployjob now needs[build, unit, test], re-running the suites rather than trusting the PRrun, so a direct push, an admin merge or the cron can't republish a broken
build. Both workflows cache
~/.cache/ms-playwrightkeyed on the lockfilehash.
@types/nodewas added as a devDependency because the new test files,playwright.config.tsandsrc/pages/index.astroall reference nodebuiltins and reported
ts(2591)without it. This takesnpm run checkfrom 27 errors to 3.
CLAUDE.mdwas updated to match: it documented only Playwright, nevermentioned the suggest-an-edit pipeline at all, and its
npm run checknoteclaimed 4 errors from a source that is now only a warning.
Verification
npm ci,npm run build,npm run test:unit(31 passing) andnpm run check(the 3 documented errors) all run clean on this branch onits own. The three remaining
checkerrors are implicitanys — one inindex.astro, two in the new unit test — and fixing them is what would letcheckbecome a CI gate.Merge note
This PR and #171 touch
ci.yml,deploy.ymland the manifests indifferent places. Whichever lands second conflicts only in
package-lock.json; resolve withnpm install. The CI jobs added here pinactions/setup-node@v4to matchmain's current convention — #171 moveseverything else to v7, so these will want the same bump once both land.
🤖 Generated with Claude Code
https://claude.ai/code/session_018P7xBafhEuazagBUqaRFo3