Skip to content

test: stop tests from reaching into other packages' folders - #144

Merged
botandbang merged 5 commits into
mainfrom
bnb/fetchindex-own-deps
Nov 10, 2026
Merged

botandbang merged 5 commits into
mainfrom
bnb/fetchindex-own-deps

Conversation

@botandbang

Copy link
Copy Markdown
Contributor

Four commits: one per part, then the lint rule.

fetchindex no longer loads core's optionsParser

  • Removes the "versions should work with optionsParser" tests from fetchindex/test/test.js. They passed core's optionsParser output to fetchindex, which repeated the two tests above them with the same options: the global fetch or undici's, and the same index URL. Core doesn't use fetchindex, so nothing else covered them.
  • Removes fetchindex's luxon devDependency. It was only there because optionsParser requires luxon and CI installs just the workspace under test.
  • Removes the fetchindex exception from knip.jsonc.

static's build test stops the clock without core's luxon

  • static/test/test.build.js stubs Date.now in the build's child process instead of setting Settings.now on core's copy of luxon, which it found with require.resolve('luxon', { paths: [core] }). luxon's default clock is () => Date.now(), so core sees the same time.
  • Removes the static exception from knip.jsonc.
  • Removes @types/luxon from the root devDependencies. Once static stopped resolving luxon, knip reported it as unused. Core lists @types/luxon itself, so it's still installed and npm run types produces the same output.

A private fixtures workspace holds what the tests share

Adds fixtures/ as the workspace @nodevu/fixtures, with "private": true so it's never published (release.yml lists the published packages by name, and this isn't one of them). It holds:

  • data/index.json, data/schedule.json and data/now.json, moved from core/test/data/static/.
  • index.js, which exports at(), moved from core/util/dev/fixtures.js. ranges/test/fixtures.js had its own copy that differed only by defaulting the date to 2025-09-01, so at() now takes that default and the copy is gone. ranges/test/fixtures.js keeps versionPattern and passes at through.
  • beforeEachTemplate.js, moved from core/util/dev/, which core's network-mocking tests use.
  • The snapshot refresh scripts, moved from core/util/dev/ to fixtures/util/ along with write.js. npm run test:update -w fixtures replaces npm run test:update -w core, and the scripts write to fixtures/data/.
  • The tests for all of the above, moved from core/test/dev-*.js to fixtures/test/, plus one for the new default date. Its coverage is 100%.

core, newest, oldest, parsefiles, ranges, static and translate list @nodevu/fixtures as a devDependency and require it by name (@nodevu/fixtures, @nodevu/fixtures/beforeEachTemplate, @nodevu/fixtures/data/*.json). No test requires a path in another package's folder now. That includes translate's tests, which used to load ranges/test/fixtures.js.

CI's changed-package filter adds fixtures/** to every package that uses it and gives fixtures its own entry, so its tests run in the coverage matrix. The README says where the shared snapshot lives and how to refresh it.

A lint rule keeps it that way

Adds tools/oxlint/nodevu/, the repo's own oxlint JS plugin, loaded from .oxlintrc.json next to the vendored anti-slop one. Its nodevu/no-cross-package-paths rule reports a require(), require.resolve(), import, export ... from or import() whose path is written out in full and resolves into a different package's folder than the file's own. A package is the nearest folder with a package.json, so the repo root counts as one too. Paths built at runtime, like require(`../build/${name}`), aren't checked. oxlint's own no-restricted-imports only looks at ESM import, so it can't do this for CommonJS. eslint-plugin-import-x's no-relative-packages would need eslint as a peer.

npm run lint:rules tests the rule with oxlint's RuleTester (22 cases, 100% of the plugin's lines and branches under c8) and runs as part of npm run lint. With the rule on, putting back fetchindex's old require('../../core/util/prod/optionsParser') fails oxlint. The rule also found translate/examples/default.js requiring ../../ranges, which now requires @nodevu/ranges (already a translate devDependency). The README mentions the rule.

Checked with npm run lint (oxlint with the new rule, oxfmt, docov, harden, the rule's tests, knip), npm run types (committed types unchanged), npm run coverage (100% in all 10 packages with coverage) and npm run docs. Each package's CI test job (npm ci -w <package> then npm run coverage -w <package>) also passes on its own in a clean copy, fixtures included.

…dency

The two tests passed core's optionsParser output to fetchindex, which repeated the two tests above them with the same options. They required core's optionsParser by relative path, and fetchindex listed luxon only so that file could load. knip.jsonc no longer needs its fetchindex exception.
…re's luxon

luxon reads the time through Date.now, so stubbing it in the build's child process stops core's clock without resolving core's own copy of luxon. That drops static's luxon exception from knip.jsonc, and the root's @types/luxon, which knip then reported as unused. core still lists @types/luxon, so npm run types is unchanged.
core's index.json, schedule.json and now.json snapshots, the at() and beforeEachTemplate helpers, and the scripts that refresh the snapshots move into fixtures/, published nowhere (private: true). core, newest, oldest, parsefiles, ranges, static and translate list @nodevu/fixtures as a devDependency and require it by name, so no test reaches into another package's folder. ranges' at() was core's with a default date, so the two are now one at() with that default.
…kages

tools/oxlint/nodevu/ is the repo's own oxlint JS plugin. Its no-cross-package-paths rule reports require(), require.resolve(), import and export paths, written out in full, that resolve into a different package's folder than the file's own. oxlint's no-restricted-imports only checks ESM imports, so it can't do this for CommonJS. npm run lint:rules tests the rule with oxlint's RuleTester and runs as part of npm run lint. The rule found translate/examples/default.js requiring ../../ranges, which now requires @nodevu/ranges.
@socket-security

socket-security Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​nodevu/​fixtures@​0.0.0N/AN/AN/AN/AN/A

View full report

Brings in #143. Its type-checked tests now load the shared snapshot and helpers from @nodevu/fixtures, and the fixtures workspace is added to everything #143 checks lists every workspace in: the TypeScript project references (with its own tsconfig and committed types), Dependabot's directories, release.yml's package lists (as !fixtures, which uppt skips), a LICENSE, and CI's path filters. The docs check in test/workspaces.test.mjs no longer asks private workspaces for a docs page. package-lock.json is regenerated with npm.
@botandbang
botandbang merged commit db239ee into main Nov 10, 2026
37 checks passed
@botandbang
botandbang deleted the bnb/fetchindex-own-deps branch November 10, 2026 21:27
@nodevu-ci nodevu-ci Bot mentioned this pull request Nov 10, 2026
botandbang added a commit that referenced this pull request Nov 11, 2026
Brings in #143 and #144's squash. The merge keeps main's tree plus this branch's change: core requires @nodevu/fetchindex, and core/util/prod/versions.js, core/test/versions.js and its generated types stay deleted. #143's new assertion in core/test/versions.js, that the newest release lists npm, v8, uv, zlib, openssl and modules, is already in fetchindex's tests. CI's path filters for core and the packages built on it include fetchindex/**, and package-lock.json is updated with npm.
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