Repository navigation
Populate fields.file_path in the JS reporters - #14
Merged
Merged
Conversation
`fields.file_path` is the key the server joins a requirement's repo_file anchors against (test_link_derive.go). No JS reporter ever set it, so a case reported from playwright or vitest could not be linked to a requirement by file anchor at all -- only the Go CLI and the PHPUnit reporter populated it. commons gains resolveFilePath(), deliberately separate from normalizeSpecPath(): that one returns a path outside the root unchanged, which is right for a signature segment and wrong here. An absolute machine path or a virtual module id can never match a repo-relative anchor, so it would be a field that looks like a join key and silently never joins. Undefined means omit, and the caller warns once per file -- omitting is not fabricating, matching the Go CLI's filemap and the PHPUnit reporter's FilePathResolver. Both reporters resolve against rootDir / TIDEN_ROOT_DIR, and a file_path the test set for itself always wins. Incidental fix: vitest's builder assigned metadata.fields by reference, so writing file_path onto the result would have mutated the accumulator's metadata. It now copies. Note what this cannot detect: a path that resolves cleanly against the wrong root. Playwright run from tests/api with no TIDEN_ROOT_DIR yields `Tests/v1/x.api.spec.ts` -- well-formed, matching no anchor.
The first commit covered playwright and vitest and missed the third reporter in this repo. @tiden/jest-reporter never set fields.file_path either -- its own file_path occurrences are all attachment paths -- so jest-reported cases stayed unlinkable while the other two became linkable, which is a worse state than either doing it or neither. Same rule as the others: resolveFilePath against rootDir / TIDEN_ROOT_DIR, omit rather than report an unmatchable absolute path, warn once per file, and never overwrite a file_path the test set for itself. The builder already had rootDir plumbed in for the signature. applyMetadata aliased metadata.fields the same way vitest's builder did, so it copies now for the same reason.
Addresses the review of #14. 1 (high) resolveFilePath compared raw strings, so three plausible spellings of the same directory silently turned the feature off for a whole run: a relative root (`..`, `.`) matched no absolute test path, an unnormalized file path passed through verbatim, and a symlinked root -- /tmp/x on macOS while the runner emits /private/tmp/x -- mismatched. Relative roots now resolve against cwd, `.`/`..` collapse on both sides, and realpath is consulted only after the plain comparison fails, memoized per root. repos/phpunit's FilePathResolver already did this, naming the same macOS case. NOT applied to normalizeSpecPath/resolveRootDir as the review suggested: those feed the case SIGNATURE, and changing how a root resolves would change the file segment of every signature computed under a relative or symlinked root, forking the history of every case already reported. A join key can be corrected; an identity cannot. 2 (medium) rootDir '' reached rootPrefix('') === '/' and reported the absolute path minus its leading slash -- the "well-formed key that never joins" this function exists to prevent -- while normalizePath fell back to cwd, so signature and file_path measured from different roots. An empty root is now cwd, and the three reporters pass rootDir straight through instead of branching on `=== undefined`. 3 (medium) a test-set file_path was forwarded unchecked, so a stale or copy-pasted value could link a case to the wrong requirement. It is now held to the same standard a derived one is: commons gains isUsableFilePath, and an absolute or escaping value is replaced by the derived path with a warning. The larger question -- whether a test should override file_path at all, which tiden-phpunit-reporter answers no -- is a product decision and is left open. 4 (low) vitest: splitFullName's and specPath's doc comments had stacked above filePath, documenting the wrong contract. Each is back on its own function. 5 (low) CHANGELOG entries for all four packages and a file_path row in the jest/vitest README option tables. The three reporters' near-identical helpers are now one applyFilePath so the rule cannot drift between them.
All four published packages move together -- release.yml refuses a tag whose version any of commons/playwright/vitest/jest is not at. The reporters' dependency on commons goes to ^0.3.0 with them. This is the part that is not bookkeeping: a caret range on a 0.x version is minor-locked, so ^0.2.0 does NOT admit 0.3.0. Published 0.3.0 reporters carrying ^0.2.0 would resolve commons 0.2.x, which has no resolveFilePath or isUsableFilePath export -- every consumer would fail at import time, on the registry, with the local workspace symlink hiding it here. CHANGELOG ## Unreleased sections become ## 0.3.0.
prostoandrei
requested review from
n3r and
nipisarev
and removed request for
nipisarev
September 11, 2026 10:36
nipisarev
approved these changes
Sep 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fields.file_pathis the key the server joins a requirement'srepo_fileanchors against (test_link_derive.go). No JS reporter ever set it — only the Go CLI and the PHPUnit reporter do — so a case reported from Playwright or Vitest could not be linked to a requirement by file anchor at all. Everyfile_pathin this repo today belongs to attachments, not to result fields.Found while asking how the
tests/apiPlaywright suite in qase-tms/app#3883 could reach requirements. It can't, and this is half the reason.What's here
commonsgainsresolveFilePath(), deliberately separate fromnormalizeSpecPath()rather than a reuse of it.normalizeSpecPathreturns a path outside the root unchanged — correct for a signature segment, wrong here. An absolute machine path, or a virtual module id, can never match a repo-relative anchor: reporting one yields a field that looks like a join key and silently never joins.undefinedmeans omit, and the caller warns once per file. Omitting is not fabricating — it is what the Go CLI'sfilemapand the PHPUnit reporter'sFilePathResolveralready do.All three reporters (playwright, vitest, jest) resolve the test's own source file against
rootDir/TIDEN_ROOT_DIR. Afile_paththe test set for itself always wins — it may deliberately point at the source under test rather than at the spec's own location.Incidental fix: the Vitest and Jest builders assigned
metadata.fieldsby reference, so writingfile_pathonto the result would have mutated the accumulator's metadata. They now copy. An existing test caught this by asserting exact field equality; that assertion is updated to the new contract rather than worked around.What this deliberately does not do
tests/apiwith noTIDEN_ROOT_DIRyieldsTests/v1/x.api.spec.ts— well-formed, matching no anchor. Documented on the function; consumers whose cwd is not the repo root must setTIDEN_ROOT_DIR.__tests__convention). Black-box HTTP tests in a separate tree still need spec-file anchors on the requirements, or explicit ingest.Verification
Unit tests cover the resolver and both builders: relative resolution, outside-root omission, virtual module ids, warn-once-per-file, user-set value wins, and no-location/no-module.
Full suites green — commons 505, jest 77, playwright 105, vitest 109. Typecheck at its pre-existing 101-error baseline with zero errors in
src/. Two new lint warnings, both the "unnecessary optional chain" thatspecPathalready carries three lines below; the chain is load-bearing for the test doubles, andeslint .sets no--max-warnings.Unit tests don't exercise the
reporter.ts→ResultBuilderrootDir wiring, so I ran a real Playwright suite through the built reporter inreportmode:TIDEN_ROOT_DIRfile_pathsuite/nested/demo.spec.ts.tmp-fp-e2e/suite/nested/demo.spec.ts/nowhereDogfooded
Reported through
@tiden/jest-reporterinto Tiden run 1413, attached to the intent session onintent/2026-09-11-populate-fields-file_path-in: 794 cases, 794 passed, and every sampled result carries a repo-relativefile_path— including the new cases in all three reporter workspaces. That run is this change verifying itself.Downstream
Packages are published at
0.2.0andqase-tms/app'stests/apipins"0.2.0"exactly, so this needs a version bump and a release tag before it changes anything there.Tiden intent branch: intent/2026-09-11-populate-fields-file_path-in