feat(nx-plugin): add vitest support for e2e tests - #34041
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
✅ Deploy Preview for nx-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
View your CI Pipeline Execution ↗ for commit 0504d9f
☁️ Nx Cloud last updated this comment at |
| addProjectConfiguration(host, options.projectName, projectConfiguration); | ||
| } | ||
|
|
||
| const vitestTask = await vitestConfigurationGenerator(host, { |
There was a problem hiding this comment.
@copilot This call should use ensurePackage, as vitest may not be installed yet. We can't directly import this, though we can import it's types so we can reference them in the dynamic import.
coverageProvider should likely be null, since its e2e we wouldn't really collect coverage.
There was a problem hiding this comment.
Updated to use ensurePackage for dynamic import of @nx/vitest and removed explicit coverageProvider since it will use the default. Changes in commit bcce4fe.
| expect(vitestConfig).toContain('globalSetup'); | ||
| expect(vitestConfig).toContain('globalTeardown'); |
There was a problem hiding this comment.
Lets add an e2e test to e2e/plugin that tests that these work for vitest backed plugins, I'm a bit hesitant without it. @copilot
There was a problem hiding this comment.
Added e2e test in e2e/plugin/src/nx-plugin.test.ts that verifies plugins can be generated with vitest as the e2e test runner and that the tests execute successfully. Commit 6add8ac.
@copilot this is close, but it should be an optional peer dep |
Added |
37cacee to
6bf85d6
Compare
288dbc6 to
4eb07c1
Compare
|
Any change to include this in nx 22.6? 🙏🏻🥺 |
feda284 to
0492be6
Compare
0492be6 to
7fe23b8
Compare
There was a problem hiding this comment.
Nx Cloud has identified a flaky task in your failed CI:
Note
We tried rerunning the flaky task 5 times, but the task is still failing. You can trigger a rerun manually, or investigate the task.
Trigger a rerun:
Or trigger a rerun manually by pushing an empty commit:
git commit --allow-empty -m "chore: trigger rerun"
git push
🔔 Heads up, your workspace has pending recommendations ↗ to auto-apply fixes for similar failures.
🎓 Learn more about Self-Healing CI on nx.dev
4c65167 to
37248ed
Compare
Adds "vitest" as an e2eTestRunner option for @nx/plugin:plugin and a testRunner option for @nx/plugin:e2e-project. The vitest setup wires globalSetup/globalTeardown to the local registry scripts and runs with a single fork for isolation. Also adds "none" as a coverageProvider option to the @nx/vitest configuration generator so e2e projects skip coverage setup. Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
37248ed to
6538422
Compare
…n e2e-project generator A dynamic import() is preserved as a true ESM import under nodenext, so it cannot resolve the temp install that ensurePackage exposes through CJS module paths. In a generated workspace without @nx/vitest installed, the generator crashed with "Cannot find package '@nx/vitest'". Use the same ensurePackage + require pattern as the other generators that consume @nx/vitest on demand.
…n e2e-project generator [Self-Healing CI Rerun]
Vitest has no globalTeardown config option, so the injected globalTeardown was silently ignored and the verdaccio process started in globalSetup outlived the test run. In CI this orphaned registry broke later tests that start a registry in the same workspace. Wire the local registry scripts through a vitest globalSetup wrapper that exports both setup and teardown instead.
… and de-flake the generated plugin e2e (#36623) ## Current Behavior Two related defects in the `@nx/plugin` + `@nx/vitest` e2e path. **1. Inferred (TS solution) workspaces get no `e2e` target at all.** `nx g @nx/plugin:plugin foo --e2eTestRunner=vitest` in a TS solution workspace — the default for new workspaces, where `@nx/plugin` defaults `addPlugin` to true — produces an e2e project with no `e2e` target: | workspace | runner | addPlugin | e2e target written | | -- | -- | -- | -- | | `--preset apps` | jest | false | `@nx/jest:jest` ✅ | | `--preset apps` | vitest | false | `@nx/vitest:test` ✅ | | TS solution | jest | true | `@nx/jest:jest` ✅ | | TS solution | vitest | true | **none** ❌ | `addOrChangeTestTarget` only checked whether `@nx/vitest` was registered *at all*, ignoring `options.testTarget`. It returned early and wrote nothing, while the plugin infers `test` / `test-ci` — never `e2e`. Consequences: `nx e2e <plugin>-e2e` does not exist, and the `e2e: { dependsOn: ['^build'] }` targetDefault is keyed to a target that is never created, so the plugin is not rebuilt before `start-local-registry` publishes it — the e2e installs stale or missing `dist/` output. The same function discarded the caller-passed `hasPlugin` whenever `nxJson.plugins` was undefined, and the `|| hasPlugin` inside the callback made every object entry match once it became true. CI did not catch any of this: `e2e/plugin/src/nx-plugin.test.ts` uses `newProject()` → `--preset apps` → `addPlugin=false`, which only exercises the top half of the table. **2. The generated e2e suite is flaky.** The generated `beforeAll` carried a 30s budget while doing two installs. That budget was decorative under jest and binding under vitest 4: `@vitest/runner`'s `withTimeout` re-checks `now() - startTime >= timeout` *after* a hook resolves and rejects even though the work completed, whereas jest never fired the timer because a synchronous `execSync` blocks the event loop. The result is a log showing workspace creation succeeding, followed by `Hook timed out in 30000ms`. `create-package`'s `it('should be installed')` had the same latent bug in a worse form — a full `dlx <cli>@e2e` workspace creation on vitest's **default 5s** budget. Separately, `pool: 'forks'` / `poolOptions.forks.singleFork` never applied on *any* path, including `--preset apps` where the target does exist. The `@nx/vitest:test` executor does not pass options to vitest's API; `getOptionsAsArgv` flattens them to `--key=value` strings and round-trips through `parseCLI`. The object branch emits `--poolOptions='{...}'` with literal single quotes — shell syntax, not argv syntax — so vitest parses it back as a *string*. Workers therefore raced on the shared `tmp/test-project` directory regardless. ## Expected Behavior **`fix(vitest)`** — `addOrChangeTestTarget` compares the requested target against the registered plugin's `testTargetName` / `ciTargetName`, mirroring the `@nx/jest` check in `packages/jest/src/generators/configuration/configuration.ts`. A request for a name the plugin does not infer now gets an explicit target; a request for one it does infer still correctly returns early. The caller-passed `hasPlugin` is preserved (`||=`) rather than overwritten. `packages/plugin/src/generators/e2e-project/e2e.ts` is the only caller in the repo passing a custom `testTarget`, so the behavior change is scoped to this bug. **`fix(nx-plugin)`** — the `beforeAll` budget covers both installs (`300_000`), `create-package`'s install test gets `180_000`, and the pool options become the scalar `maxWorkers: 1, isolate: false` — which survive the argv round-trip and are what Nx's own vitest 4 migration already prescribes (`packages/vitest/src/migrations/update-22-1-0/ai-instructions-for-vitest-4.md`). No new migration is needed: the vitest 4 migration is prompt-based and already instructs the agent to check `project.json` for inline vitest config and to replace `singleFork: true` with `maxWorkers: 1, isolate: false`. ### Tests Six new tests, covering the inferred path the existing suite missed: - `packages/vitest/src/utils/generator-utils.spec.ts` — five cases around `addOrChangeTestTarget`: the requested target is created when the plugin infers a different name; it is not created when the plugin infers that name; matching honours `testTargetName` and `ciTargetName`; the caller verdict survives an nx.json with no plugins. - `packages/plugin/src/generators/e2e-project/e2e.spec.ts` — the e2e-project generator produces an `e2e` target with `addPlugin: true`, the combination that previously produced nothing. Stashing the fix confirms the two tests covering the real defects fail without it; the other three are guards pinning behavior the change could have over-corrected. Budget regression tests from the flake work assert the generated timeouts stay above 240s / 120s. ## Related Issue(s) - NXC-4750 — `@nx/plugin --e2eTestRunner=vitest` generates no e2e target in inferred (TS solution) workspaces - NXC-4764 — generated `@nx/plugin` e2e is flaky (30s `beforeAll` budget covers two installs), closed as a duplicate of NXC-4750 Follow-up to #34041 (`feat(nx-plugin): add vitest support for e2e tests`), shipped in 23.2.0-beta.2. <!-- polygraph-session-start --> --- <p><a href="https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/vitest-plugin-timeouts-eb06fc74">View Polygraph session ↗</a></p> <!-- polygraph-session-end -->
Implementation Plan for Vitest E2E Support
Changes Required:
addVitest()similar toaddJest()e2eProjectGeneratorInternalto conditionally call addJest or addVitestChanges
"vitest"toe2eTestRunnerenum in@nx/plugin:plugingenerator; addedtestRunneroption to@nx/plugin:e2e-projectgeneratoraddVitest()function that configures Vitest with globalSetup/globalTeardown for local registry management, uses fork pool with singleFork for proper isolation.mtsor.tsvitest config files, extracts existing indentation for consistent formatting when injecting global setup/teardownensurePackageto dynamically import@nx/vitestonly when needed; added as optional peer dependencyUsage
Jest remains the default when no testRunner is specified.
Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.