Fixes#20416 for Oxlint
- Same `VP_VERSION` gating for config discovery, LSP file watchers, and JS config loading
- Refactor JS config loader into `resolveJsConfig` / `resolveVitePlusConfig` with shared `importConfig` + `loadConfigs`
- Split test fixtures into `vite_config_*` (non VP mode) and `vite_plus_*` (VP mode)
- Add `env` field to fixture `options.json` for passing env vars to test runs
- Fix repo `oxlintrc.json` ignore glob (`*/files/**` → `**/files/**`) for nested fixture paths like monorepo usecase
closes https://github.com/oxc-project/oxc/issues/19526
> This PR fixes a bug in the LSP where JavaScript/TypeScript config files were not being reloaded when changed. The fix implements cache-busting by appending a timestamp query parameter to file URLs during import, forcing Node.js to bypass its module cache.
The previous code didn't handle normalization of paths for Windows, and so Vitest tests with snapshots that had paths were failing on Windows.
See https://github.com/oxc-project/oxc/actions/runs/21569650239/job/62146619752 for an example.
AI Disclosure: This change was made with help from Copilot + Raptor mini, and this regex is an abomination. It may be better to handle this via an additional `normalizeSlashes` call but I'm not entirely sure where to add that in this case, and I don't have a windows machine to test on.
I've also added tests with Claude, and confirmed that they work when backported to main, and so confirm the behavior has not changed on macOS (although I did have to find+replace NORMALIZED_REPO_ROOT with REPO_ROOT_PATH in the tests for that to work, but that's expected)
Add a `cwd` option to tests which causes test runner to run Oxlint from within a subfolder inside a fixture dir, instead of root of the fixture dir. This is used for the test added in next PR (#18755).
For a while, we've been skipping the printing of rule runs unless `--disable-nested-config` was passed. This was a result of the nested_configs value including the base config (see #16356). When we were checking whether that value was empty, it would always have at least 1 item (unless nested configs were entirely disabled).
As part of this, I've updated some configs in the fixtures to disable correctness rules, otherwise we will end up with a bunch of fixture snapshots needing updates every time a new default rule is added.
It's probably easiest to review this one commit at a time.
In JS plugins tests, it's sometimes required to ensure that files are linted in deterministic order.
For example, #17207 fixes a bug where some internal global state was not reset correctly after an error is thrown during visiting the AST. This affects what happens when linting the *next* file.
In order to write a test for this, and produces deterministic output in the snapshot file, the order files are linted in needs to be deterministic.
This PR provides this determinism by:
1. Adding a `force_deterministic_order` cargo feature which is enabled in test build.
2. When this feature is enabled *and* Oxlint is run with `--threads 1`, file paths are sorted before linting.
3. Adding an option for test fixtures `singleThread`. When `true`, the fixture is run with `--threads 1`.
Aim is to only enable deterministic ordering in test fixtures which *need* determinism, so that most test fixtures are still testing Oxlint running as it does usually for a user.
Tests in the same file typically run in sequence. we can improve the performance by running these in parallel:
https://vitest.dev/guide/parallelism.html#test-parallelism
- Before (sequential): ~5.2s total, e2e.test.ts ~5000ms
- After (concurrent): ~1.50s total, e2e.test.ts ~1200ms
~3.5x faster
Use `const` where variables are not reassigned instead of `let`. Preparation for enabling ESLint's `prefer-const` rule (running as an Oxlint JS plugin) in our linting setup.
Remove the need to list every fixture in `e2e.test.ts` file by automatically running tests on every fixture in `test/fixtures` directory.
Running Oxlint with `--fix` and running fixtures with ESLint is now controlled by adding an `options.json` file to the fixture directory contining e.g. `{ "fix": true }` or `{ "eslint": true }`.
Now we can add a new fixture just by creating a new directory in `fixtures`.
Follow-on after #15424. Fix the snapshots on Windows. I missed one slash!
Also, convert paths wrapped in quotes e.g. `file path: '/path/to/oxc/apps/oxlint/test/fixtures/blah/files/foo.js'`.
I've had to hack one fixture (`createOnce`) to get diagnostics to be printed in same order on all platforms. Otherwise they get printed out of order on Windows: https://github.com/oxc-project/oxc/actions/runs/19180329507/job/54835252163?pr=15451#step:8:419.
Presumably this is because on Windows the file path `D:\...` is sorted after `Cannot access`, whereas on Mac/Linux, file path `/` is sorted before `Cannot access`. However, I'm unclear why the prefixes `before hook:`, `after hook:` etc aren't included in sorting. If they were, this problem wouldn't arise.
When replacing absolute paths in fixture snapshots, replace paths anywhere in the output, rather than only in certain specified patterns.
Additionally, introduce `<fixtures>` and `<fixture>` replacements to shorten paths in snapshots.
```diff
- File path: <root>/apps/oxlint/test/fixtures/fixture_name/files/1.js
+ File path: <fixture>/files/1.js
- File path: <root>/apps/oxlint/test/fixtures
+ File path: <fixtures>
```
This allows removing the `relativePath` helper function from some test plugins, outputting paths (e.g. `cwd`) anywhere, and generally will avoid problems with snapshots being system-dependent, and dependent on directory layout of fixtures.
Also, amend ESLint `stdout` output in snapshots to align all rule names, to reduce churn in snapshots, and avoid mismatches between local and CI (presumably due to differences in terminal width).
```diff
- filename: <fixture>/files/1.js define-plugin-plugin/create-once
- filename: <fixture>/files/long_filename.js define-plugin-plugin/create-once
- filename: <fixture>/files/very_long_filename.js define-plugin-plugin/create-once
+ filename: <fixture>/files/1.js define-plugin-plugin/create-once
+ filename: <fixture>/files/long_filename.js define-plugin-plugin/create-once
+ filename: <fixture>/files/very_long_filename.js define-plugin-plugin/create-once
```
Include `stderr` output in test snapshots. This makes sure that the "JS plugins are experimental" warning is not output if user doesn't use JS plugins.
Trim leading/trailing line breaks from `stdout` in test snapshots and convert `\r\n` to `\n`. This ensures tests will pass on Windows, and removes extraneous line breaks from snapshots.