Commit Graph

12 Commits

Author SHA1 Message Date
Kazuki Yamada b25f4446d8 test(server): Relocate server tests into website/server
intent(test-ownership): move tests into website/server/tests/ so they collocate with the code under test and stop reaching up through three parents; reviewer follow-up wanted dedicated coverage and the root vs. website/server package boundary makes collocation the right long-term layout
decision(vitest-config): give website/server its own vitest.config.ts + `test` script; root's existing tests/**/*.test.ts include no longer catches server tests since they moved outside that tree, so the two test runs stay independent
decision(tsconfig-test): add tsconfig.test.json extending the build config and lift lint-tsc to `-p tsconfig.test.json` — the build tsconfig's rootDir: "./src" excludes tests/, so a single lint command wouldn't have type-checked them
learned(valibot-instanceof): with tests now resolving valibot from the same website/server/node_modules as validateRequest, the cause-check can go back to `instanceof v.ValiError` — the duck-type workaround was only needed when the root harness and server pulled different valibot copies
constraint(ci-website): added a `test-website-server` job that links the local repomix build the same way lint-website-server does; tests don't actually import repomix today, but colocation means they easily could later and the link step keeps parity
2026-04-19 21:47:29 +09:00
Kazuki Yamada 04b9612758 test(server): Add dedicated coverage for validateRequest
intent(server): land validateRequest unit tests alongside this PR's rewrite per reviewer follow-up — previously only exercised indirectly via classifyRejectReason with mocks, so silently dropping `.cause` during a future refactor would not fail any test
learned(valibot-instanceof): website/server resolves valibot from its own node_modules (distinct copy from the root harness), so `instanceof v.ValiError` fails across that boundary even for genuine ValiError instances; duck-type the cause check on `{ name: 'ValiError', issues: [] }` to match classifyRejectReason's own contract

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 16:43:52 +09:00
Kazuki Yamada b7f4a810a0 test(server): Use MESSAGES constant in cause-chain test
fix(drift-guard): swap the hard-coded 'Either URL or file must be provided' literal for MESSAGES.MISSING_INPUT so the cause-chain test honors the classifier drift-guard the file's header comment promises — a future message rewrite now propagates to this assertion too, instead of silently falling back to 'unknown'

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 16:41:30 +09:00
Kazuki Yamada e53502eb46 fix(server): Address PR review feedback
fix(pack-event-test): migrate tests/website/server/packEventSchema.test.ts to the valibot-shaped `{ name, issues: [{ message, path: [{ key }] }] }` fixture so the invalid_format case — which relies on the path fallback — actually exercises the post-migration classifier
decision(path-formatting): replace the hand-rolled `path.map/filter/join` in both packEventSchema.ts and validation.ts with `v.getDotPath(issue)` — the valibot built-in does the same reconstruction and eliminates the two-site drift risk reviewers flagged
fix(validation-error-message): drop the leading `": "` when a valibot issue has no path (top-level checks like MISSING_INPUT / BOTH_PROVIDED), so the rendered AppError message reads cleanly
rejected(cause-walk-depth): coderabbit suggested walking `.cause` recursively up to depth 3 — declined because validateRequest wraps exactly once by contract and no second wrapper exists in the chain; defensive recursion would add surface area for no caller

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 16:23:45 +09:00
Kazuki Yamada 9f6d0b5bdb Merge pull request #1489 from yamadashy/perf/try-valibot
perf(config): Migrate configSchema from zod to valibot (experimental)
2026-04-19 10:39:01 +09:00
Kazuki Yamada 53ddb5ac36 test(website): Extract and cover normalizeObjectNode
intent(test-coverage): normalizeObjectNode is the load-bearing workaround for @valibot/to-json-schema's output gaps (missing additionalProperties:false, noisy empty required arrays). A bug in its tree walk would silently break the published repomix.config.json IntelliSense schema. Extract to its own module and pin the behavior: adding/respecting additionalProperties, stripping empty required, recursing through properties / anyOf / oneOf / items, handling null and primitives
2026-04-18 23:13:43 +09:00
Kazuki Yamada 10846fbf8d refactor(server): Extract validation messages to shared constants
Addresses PR #1493 round 5 follow-up (schema-drift tracking) from claude.

intent(eliminate-drift): prior reviews flagged the string-coupling
  between packRequestSchema (produces zod messages) and
  classifyRejectReason (matches them back to a metric label) as
  fragile — a message rewrite in one place would silently land
  requests in the 'other' bucket, quietly mislabeling the dashboard.
  Extract all 11 messages to a shared MESSAGES module so the
  producer, the consumer, and the test's expected values all
  reference the same constants
decision(map-over-switch): classifyRejectReason's 11-case switch
  becomes a MESSAGE_TO_REASON lookup table. Same runtime behavior,
  easier to scan, and the keys are compile-time-typed via the
  shared constants (so a typo in either side is a TS error)
decision(preserve-invalid_format-path): 'invalid_format' is keyed by
  path (`format`), not by message text. Left as path-match so it
  continues to work even if zod's default enum error message changes
improve(test-references-constants): test.each cases now reference
  MESSAGES directly. The test continues to catch classifier-logic
  drift (wrong label for a known key, missing entry in the lookup)
  while schema/classifier drift becomes impossible by construction

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 23:07:25 +09:00
Kazuki Yamada e580284729 fix(test): Drop server-only imports from packEventSchema test
intent(ci-green): CI failed on `Cannot find package 'repomix'` because
  the test imported `packRequestSchema.ts` which has `import from
  'repomix'` — the root vitest harness doesn't install server-only
  packages (repomix is this repo, hono is a server dep). Local runs
  passed by coincidence of self-reference resolution
decision(construct-zoderror-directly): rewrite the test to construct
  `z.ZodError` instances with messages matching the schema rather
  than invoking the schema. Keeps classifier-drift coverage (if the
  switch stops matching a known label, a test fails) at the cost of
  not catching schema-drift (if a zod message in packRequestSchema is
  edited without updating the test, the test still passes but
  dashboards mislabel). Schema-drift catching would need a shared
  constants module — tracked as a follow-up
decision(native-error-cause): use `new Error(msg, { cause })` instead
  of importing `AppError`. AppError pulls `hono/utils/http-status`
  (type-only, but some module resolvers still probe). Native Error
  with cause exercises the same classifier code path
improve(table-driven): restructure the 11 label cases as `test.each`
  so each case is named individually in the test output

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 22:51:50 +09:00
Kazuki Yamada 43eb51cac4 test(server): Add classifyRejectReason tests + document Boolean() intent
Addresses PR #1493 round 3 review from claude.

intent(catch-schema-drift): every previous review round flagged the
  fragile string coupling between classifyRejectReason and the zod
  messages in packRequestSchema. The earlier response was that adding
  tests would require new infrastructure in website/server/ — but
  tests/website/cliCommand.test.ts already tests website/ code under
  the root vitest harness. Extended the same pattern to cover every
  rejection path through the real schema so message edits surface as
  CI failures instead of silent 'other'-bucket dashboard drift
decision(table-driven-through-real-schema): the tests invoke
  validateRequest(packRequestSchema, input) rather than constructing
  synthetic ZodError objects — this catches both classifier drift AND
  schema drift in one assertion. 13 tests covering 11 reject labels
  + cause-chain extraction + non-error input
improve(boolean-intent-comment): claude noted that Boolean() collapses
  `undefined` (user didn't send field) with `false` (user explicitly
  disabled), losing that distinction in the pack_options_usage metric.
  This is intentional — the metric answers "what % of packs had
  compress enabled" where both "off" and "unspecified" correctly mean
  the feature wasn't active. Added a comment so future contributors
  don't "fix" it

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 22:45:43 +09:00
Kazuki Yamada 7ea89f7fd0 fix(website): Remove Vue dependency from cliCommand utility to fix CI
Define CliCommandPackOptions interface locally in cliCommand.ts instead of
importing PackOptions from usePackOptions.ts which depends on Vue module.
This prevents tsc from following the import chain to Vue in CI.
2026-02-03 00:06:09 +09:00
Kazuki Yamada 91c39bb5ee fix(website): Avoid importing Vue-dependent module in test to fix CI lint
Use local interface definition instead of importing PackOptions from
usePackOptions.ts which depends on Vue and fails tsc in CI.
2026-02-03 00:04:13 +09:00
Kazuki Yamada 62280a6870 fix(website): Add shell escaping and ZIP upload handling to CLI command generator
Address PR review comments:
- Add shell escaping for user-controlled values (repositoryUrl, includePatterns, ignorePatterns)
  to prevent command injection when users copy-paste the generated command
- Skip --remote flag for uploaded file names by validating with isValidRemoteValue
- Add unit tests for generateCliCommand covering all option combinations
2026-02-02 00:21:16 +09:00