Skip to content

feat(nx-plugin): add vitest support for e2e tests - #34041

Merged
AgentEnder merged 4 commits into
masterfrom
copilot/add-vitest-support-e2e
Jul 21, 2026
Merged

feat(nx-plugin): add vitest support for e2e tests#34041
AgentEnder merged 4 commits into
masterfrom
copilot/add-vitest-support-e2e

Conversation

Copilot AI commented Jan 7, 2026

Copy link
Copy Markdown
Contributor

Implementation Plan for Vitest E2E Support

Changes Required:

  • Update plugin generator schema to support "vitest" as an e2eTestRunner option
  • Update e2e-project generator schema to add testRunner option
  • Update e2e-project generator implementation
    • Add new function addVitest() similar to addJest()
    • Update e2eProjectGeneratorInternal to conditionally call addJest or addVitest
    • Handle both .ts and .mts vitest config extensions
    • Address all code review feedback
    • Use ensurePackage for dynamic vitest import
    • Fix syntax errors
  • Update test template files
  • Update plugin generator to pass testRunner to e2e-project generator
  • Add tests for new functionality
    • Add unit tests
    • Add e2e test for vitest-backed plugin
  • Update documentation
  • Code review and refinement
    • Address all review feedback
    • Fix CI/Build failures (add @nx/vitest as optional peer dependency)

Changes

  • Schema updates: Added "vitest" to e2eTestRunner enum in @nx/plugin:plugin generator; added testRunner option to @nx/plugin:e2e-project generator
  • Implementation: Added addVitest() function that configures Vitest with globalSetup/globalTeardown for local registry management, uses fork pool with singleFork for proper isolation
  • Config handling: Detects .mts or .ts vitest config files, extracts existing indentation for consistent formatting when injecting global setup/teardown
  • Dependencies: Uses ensurePackage to dynamically import @nx/vitest only when needed; added as optional peer dependency
  • Testing: Added e2e test to verify vitest-backed plugins work correctly

Usage

# Generate plugin with Vitest e2e tests
nx g @nx/plugin:plugin my-plugin --e2eTestRunner=vitest

# Or generate e2e project separately
nx g @nx/plugin:e2e-project --pluginName my-plugin --testRunner vitest

Jest remains the default when no testRunner is specified.

Original prompt

This section details on the original issue you should resolve

<issue_title>vitest support for @nrwl/nx-plugin:e2e</issue_title>
<issue_description>

Description

I'd like to use Vitest instead of Jest for e2e testing of plugins.

Motivation

I use Vitest for everything else and it makes sense to use it for that as well.

Suggested Implementation

Add option for nx g @nrwl/nx-plugin:plugin to use Vitest

Alternate Implementations

I'm going to skip e2e tests altogether for now as I'm having trouble with Jest and my custom ESM setup.</issue_description>

<agent_instructions>This shouldn't be terribly difficult, you'll need to add a schema option for the e2e test runner to be possible to set it to vitest and scaffold a vitest project instead of a jest project. You'll likely need a separate set of templates for the generated e2e setup, since the current ones are jest tests</agent_instructions>

Comments on the Issue (you are @copilot in this section)

@FrozenPandaz Would someone like to open a PR for this? @AgentEnder Reiterating what @FrozenPandaz said, nothing is technically blocking this feature. It should be as easy as adding a schema option and passing it through to the js generator, but we don't quite have the bandwidth to do this on the core team right now.

It would be a great first issue for a community member.</comment_new>


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@vercel

vercel Bot commented Jan 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
nx-dev Ready Ready Preview Jan 22, 2026 8:31pm

Request Review

@netlify

netlify Bot commented Jan 7, 2026

Copy link
Copy Markdown

Deploy Preview for nx-docs ready!

Name Link
🔨 Latest commit 0504d9f
🔍 Latest deploy log https://app.netlify.com/projects/nx-docs/deploys/6a500e03bb7c6800080480ef
😎 Deploy Preview https://deploy-preview-34041--nx-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copilot AI changed the title [WIP] Add Vitest support for e2e testing of plugins feat(plugin): add vitest support for e2e tests Jan 7, 2026
Copilot AI requested a review from AgentEnder January 7, 2026 20:21
@nx-cloud

nx-cloud Bot commented Jan 7, 2026

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit 0504d9f

Command Status Duration Result
nx affected --targets=lint,test,build,e2e,e2e-c... ✅ Succeeded 10m 46s View ↗
nx run-many -t check-imports check-lock-files c... ✅ Succeeded 3s View ↗
nx-cloud record -- pnpm nx-cloud conformance:check ✅ Succeeded 1m 2s View ↗
nx build workspace-plugin ✅ Succeeded <1s View ↗
nx-cloud record -- nx sync:check ✅ Succeeded 18s View ↗
nx-cloud record -- nx format:check ✅ Succeeded 6s View ↗

☁️ Nx Cloud last updated this comment at 2026-07-21 02:59:43 UTC

addProjectConfiguration(host, options.projectName, projectConfiguration);
}

const vitestTask = await vitestConfigurationGenerator(host, {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to use ensurePackage for dynamic import of @nx/vitest and removed explicit coverageProvider since it will use the default. Changes in commit bcce4fe.

Comment on lines +248 to +249
expect(vitestConfig).toContain('globalSetup');
expect(vitestConfig).toContain('globalTeardown');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

@AgentEnder

Copy link
Copy Markdown
Member

Nx Cloud is proposing a fix for your failed CI:

These changes fix the ESLint dependency-checks error by adding @nx/vitest to the dependencies section of packages/plugin/package.json. The PR introduced code that imports from @nx/vitest/generators, creating a runtime dependency that was not declared in the package manifest.

We verified this fix by re-running plugin:lint.

diff --git a/packages/plugin/package.json b/packages/plugin/package.json
index 9c8f175788..279050c071 100644
--- a/packages/plugin/package.json
+++ b/packages/plugin/package.json
@@ -31,7 +31,8 @@
     "@nx/devkit": "workspace:*",
     "@nx/jest": "workspace:*",
     "@nx/js": "workspace:*",
-    "@nx/eslint": "workspace:*"
+    "@nx/eslint": "workspace:*",
+    "@nx/vitest": "workspace:*"
   },
   "devDependencies": {
     "nx": "workspace:*"

[!NOTE]
Auto-apply was skipped. The previous CI pipeline execution was triggered by Nx Cloud

Apply fix via Nx Cloud  Reject fix via Nx Cloud


Or Apply changes locally with:

npx nx-cloud apply-locally J7A3-AuSY

Apply fix locally with your editor ↗   View interactive diff ↗


🎓 Learn more about Self-Healing CI on nx.dev

@copilot this is close, but it should be an optional peer dep

Copilot AI commented Jan 7, 2026

Copy link
Copy Markdown
Contributor Author

Nx Cloud is proposing a fix for your failed CI:

These changes fix the ESLint dependency-checks error by adding @nx/vitest to the dependencies section of packages/plugin/package.json. The PR ...

Added @nx/vitest as an optional peer dependency in package.json following the same pattern as other optional dependencies in the monorepo. Commit 37cacee.

nx-cloud[bot]

This comment was marked as outdated.

@AgentEnder
AgentEnder force-pushed the copilot/add-vitest-support-e2e branch 2 times, most recently from 288dbc6 to 4eb07c1 Compare February 22, 2026 15:29
nx-cloud[bot]

This comment was marked as outdated.

@gperdomor

Copy link
Copy Markdown
Contributor

Any change to include this in nx 22.6? 🙏🏻🥺

@AgentEnder
AgentEnder force-pushed the copilot/add-vitest-support-e2e branch from feda284 to 0492be6 Compare March 13, 2026 19:02
@AgentEnder
AgentEnder force-pushed the copilot/add-vitest-support-e2e branch from 0492be6 to 7fe23b8 Compare April 2, 2026 16:37
nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

@nx-cloud nx-cloud Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

Rerun CI

Or trigger a rerun manually by pushing an empty commit:

git commit --allow-empty -m "chore: trigger rerun"
git push

Nx Cloud View detailed reasoning in Nx Cloud ↗

🔔 Heads up, your workspace has pending recommendations ↗ to auto-apply fixes for similar failures.


🎓 Learn more about Self-Healing CI on nx.dev

@AgentEnder
AgentEnder force-pushed the copilot/add-vitest-support-e2e branch from 4c65167 to 37248ed Compare July 7, 2026 17:54
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>
@AgentEnder
AgentEnder force-pushed the copilot/add-vitest-support-e2e branch from 37248ed to 6538422 Compare July 7, 2026 20:04
AgentEnder and others added 3 commits July 9, 2026 13:21
…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.
@AgentEnder
AgentEnder marked this pull request as ready for review July 21, 2026 03:09
@AgentEnder
AgentEnder requested a review from a team as a code owner July 21, 2026 03:09
@AgentEnder
AgentEnder merged commit beb8600 into master Jul 21, 2026
26 of 27 checks passed
@AgentEnder
AgentEnder deleted the copilot/add-vitest-support-e2e branch July 21, 2026 03:47
FrozenPandaz pushed a commit that referenced this pull request Aug 10, 2026
… 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 -->
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.

vitest support for @nrwl/nx-plugin:e2e

4 participants