feat(vitest-plugin): extract react-app testing helpers into vitest-plugin-react-app - #5286
Conversation
- rename src/testing -> src/vitest, add test-app/scope fixture chain (test-app.tsx, test.tsx, scope/*) for rendering app components and hooks with a fully wired Fusion test environment - fix(react): useFrameworkModule warns with the correct module name - fix(module-context): stop warning when there's no initial context to resolve - fix(module-msal): drop stray debug console.log in resolve-version - fix(log): guard process.env access for Vitest Browser Mode - chore: biome format fixes surfaced by pnpm check (unrelated pre-existing drift in cli/linting/event packages)
Move renderAppHook/renderAppComponent/testApp and the app-test Vite plugin out of @equinor/fusion-framework-react-app's ./vitest entry-point and @equinor/fusion-framework-cli's ./vitest entry-point into a new standalone package, @equinor/fusion-framework-vitest-plugin-react-app, built on vitest-browser-react instead of @testing-library/react. - Remove the ffc app test CLI command and cli/src/lib/vitest (superseded by appTestVitePlugin registered directly in a project's vitest.config.ts). - Add packages/vitest-plugin/react-app with README, appTestVitePlugin, renderAppHook, renderAppComponent, testApp, and a /test entry-point exporting pre-seeded test/render fixtures. - Update react-app's README/docs and package.json to drop ./vitest and point at the new package instead. - Fix stray console.log in msal's resolveVersion mismatch warning, and guard fusion-log's process.env access for environments without a Node process global (Vitest Browser Mode). - Install Playwright browsers in CI for the new package's and react-app's Vitest Browser Mode tests. - Add CODEMAP.md entry for the new package. Changesets included for all affected packages.
🦋 Changeset detectedLatest commit: 6ab2c32 The changes in this PR will be included in the next version bump. This PR includes changesets to release 24 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
…epends on it pnpm exec at the repo root only resolves bins from root's own node_modules, and playwright is a devDependency of react-app/vitest-plugin-react-app only, not the workspace root - the previous 'pnpm exec playwright install' failed with ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL / 'Command "playwright" not found'.
There was a problem hiding this comment.
Pull request overview
Extracts React app testing helpers into a dedicated Vitest plugin package, removes the superseded CLI testing interface, and includes supporting fixes.
Changes:
- Adds browser-based render fixtures and app environment resolution.
- Removes React app and CLI testing entry points.
- Improves context telemetry, token stability, logging, documentation, and CI.
Reviewed changes
Copilot reviewed 60 out of 66 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
tsconfig.json |
Adds Vitest plugin path mapping. |
pnpm-lock.yaml |
Updates workspace dependency graph. |
packages/vitest-plugin/react-app/tsconfig.json |
Configures the new package build. |
packages/vitest-plugin/react-app/src/virtual-modules.d.ts |
Declares plugin virtual modules. |
packages/vitest-plugin/react-app/src/test.tsx |
Adds pre-seeded test fixture. |
packages/vitest-plugin/react-app/src/test-app.tsx |
Defines app-scoped Vitest fixtures. |
packages/vitest-plugin/react-app/src/scope/resolve-fusion.ts |
Resolves mocked framework instances. |
packages/vitest-plugin/react-app/src/scope/resolve-app-scope.ts |
Resolves app test scopes. |
packages/vitest-plugin/react-app/src/scope/index.ts |
Exports scope utilities. |
packages/vitest-plugin/react-app/src/scope/default-app-env.ts |
Defines the default test environment. |
packages/vitest-plugin/react-app/src/scope/create-app-scope-wrapper.tsx |
Creates React provider wrappers. |
packages/vitest-plugin/react-app/src/resolve-app-test-env.ts |
Resolves app manifest and configuration. |
packages/vitest-plugin/react-app/src/render.tsx |
Adds plugin-backed component rendering. |
packages/vitest-plugin/react-app/src/render-app-hook.tsx |
Migrates hook rendering to browser mode. |
packages/vitest-plugin/react-app/src/render-app-component.tsx |
Migrates component rendering to browser mode. |
packages/vitest-plugin/react-app/src/index.ts |
Implements the Vite plugin. |
packages/vitest-plugin/react-app/src/app-test.ts |
Defines the /test entry point. |
packages/vitest-plugin/react-app/README.md |
Documents the new package. |
packages/vitest-plugin/react-app/package.json |
Defines package exports and dependencies. |
packages/utils/log/src/static.ts |
Guards browser access to process.env. |
packages/react/framework/src/useFrameworkModule.ts |
Corrects the missing-module warning. |
packages/react/app/vitest.config.ts |
Enables Playwright browser tests. |
packages/react/app/src/testing/index.ts |
Removes the old testing barrel. |
packages/react/app/src/msal/useToken.ts |
Stabilizes token acquisition dependencies. |
packages/react/app/src/__tests__/useTrackFeature.test.tsx |
Migrates the render helper import. |
packages/react/app/src/__tests__/useToken.test.tsx |
Migrates token tests to browser fixtures. |
packages/react/app/src/__tests__/useHelpCenter.test.tsx |
Migrates asynchronous browser assertions. |
packages/react/app/src/__tests__/useFeature.test.tsx |
Migrates feature tests to browser mode. |
packages/react/app/src/__tests__/useCurrentContext.test.tsx |
Migrates context hook tests. |
packages/react/app/src/__tests__/useCurrentBookmark.test.tsx |
Migrates bookmark hook tests. |
packages/react/app/src/__tests__/useCurrentAccount.test.tsx |
Migrates account hook tests. |
packages/react/app/src/__tests__/useAppSettings.test.tsx |
Migrates settings tests. |
packages/react/app/src/__tests__/useAppSetting.test.tsx |
Migrates setting tests. |
packages/react/app/src/__tests__/useAccessToken.test.tsx |
Migrates access-token tests. |
packages/react/app/src/__tests__/testApp.test.tsx |
Tests the app fixture integration. |
packages/react/app/src/__tests__/Apploader.test.tsx |
Migrates component tests to browser mode. |
packages/react/app/README.md |
Redirects testing documentation. |
packages/react/app/package.json |
Removes the testing export and updates test dependencies. |
packages/react/app/docs/testing.md |
Removes obsolete testing documentation. |
packages/modules/msal/src/versioning/resolve-version.ts |
Removes debug output. |
packages/modules/context/tsconfig.json |
Adds the telemetry project reference. |
packages/modules/context/src/utils/resolve-initial-context.ts |
Handles an absent initial context. |
packages/modules/context/src/module.ts |
Adds context telemetry reporting. |
packages/modules/context/src/ContextProvider.ts |
Removes context queue debug output. |
packages/modules/context/src/__tests__/ContextModuleConfigurator.test.ts |
Tests empty and failed context resolution. |
packages/modules/context/package.json |
Adds telemetry development metadata. |
packages/cli/src/lib/vitest/tests/resolve-app-test-env.test.ts |
Removes obsolete CLI resolver tests. |
packages/cli/src/lib/vitest/resolve-app-test-env.ts |
Removes CLI-owned environment resolution. |
packages/cli/src/lib/vitest/index.ts |
Removes the CLI Vitest barrel. |
packages/cli/src/cli/commands/app/test.command.ts |
Removes ffc app test. |
packages/cli/src/cli/commands/app/index.ts |
Unregisters the test command. |
packages/cli/src/bin/test-application.ts |
Removes the test runner wrapper. |
packages/cli/src/bin/index.ts |
Removes the test runner export. |
packages/cli/package.json |
Removes the CLI Vitest entry point. |
CODEMAP.md |
Registers the new package. |
.gitignore |
Ignores browser-test artifacts. |
.github/workflows/pr.yml |
Installs Chromium for browser tests. |
.changeset/vitest-plugin-react-app_initial-release.md |
Describes the new package release. |
.changeset/react-app_render-app-hook-testing.md |
Documents hook-helper migration. |
.changeset/react-app_render-app-component-testing.md |
Documents component-helper migration. |
.changeset/react-app_fix-remaining-vitest-docs.md |
Records documentation cleanup. |
.changeset/react_fix-usemodule-warning.md |
Records the warning fix. |
.changeset/msal_remove-debug-log.md |
Records debug-log removal. |
.changeset/module-context_fix-empty-context-warning.md |
Records empty-context handling. |
.changeset/fusion-log_guard-process-env.md |
Records browser-safe logging. |
.changeset/cli_app-test-command.md |
Removes the superseded CLI feature changeset. |
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
Suppressed comments (1)
packages/vitest-plugin/react-app/src/index.ts:36
- The documentation now promises that the package root supplies the app-testing helpers, but this module exports only
appTestVitePlugin; the README and changeset imports ofrenderAppHook,renderAppComponent, andtestApptherefore fail. Add explicit exports for the plugin-free helper modules (and the documented resolver) without re-exportingapp-test, whose virtual imports require plugin registration.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The package uses vitest's expect/vi APIs at test-authoring time but only listed it as a devDependency, so consumers weren't told to install it themselves.
src/index.ts and src/resolve-app-test-env.ts import @equinor/fusion-imports (utils/imports), but the tsconfig referenced utils/observable, an unrelated package.
…ePlugin The package's own resolution/virtual-module logic had no test coverage and no vitest.config.ts, so it wasn't even picked up as a project by the root Vitest run.
The removal of ffc app test, testApplication, the ./vitest entry-point, and resolveAppTestEnv from @equinor/fusion-framework-cli had no changeset.
The context module only reads telemetry defensively via an injected instance (never imports the package directly), matching the optional pattern already used by modules/msal.
…rding
Add the missing 'import { expect } from vitest' to the quick-start test snippet, and reword the fixture-sharing bullet to clarify only seeded defaults are shared, not fusion/app state between tests.
Match the README wording fix: testApp's JSDoc previously implied one shared mocked scope across tests, when each test actually gets fresh fusion/app instances and only the seeded defaults are shared.
vitest-browser-react was only used by the now-removed ./vitest entry-point; src/ has no remaining references to it, so it stays a devDependency only.
…solution Adds coverage for the resolver-error and successful-resolution telemetry events raised by module.ts's postInitialize, alongside the existing console.warn-fallback test for when no telemetry module is registered.
Asserts acquireToken is not re-invoked when scopes are re-rendered with the same contents (a fresh array literal each time), but is re-invoked when the contents actually change.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 64 out of 70 changed files in this pull request and generated no new comments.
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
Suppressed comments (5)
packages/vitest-plugin/react-app/src/index.ts:36
- The advertised root API is not actually exported:
index.tsonly exportsappTestVitePlugin, so the documented imports ofrenderAppHook,renderAppComponent,testApp, andresolveAppTestEnvfrom the package root fail. Re-export these symbols from modules that do not import the virtual test modules.
packages/react/app/vitest.config.ts:8 - This project is also loaded by the root Vitest workspace, where
process.cwd()is the repository root, soappTestVitePlugin()resolves the root package instead ofpackages/react/app. Pass the config directory explicitly so the/testfixtures always receive react-app's manifest/config regardless of the invocation directory.
packages/react/app/src/msal/useToken.ts:41 - This changes the public
useTokenbehavior so equivalent scope arrays no longer reacquire tokens, but none of the react-app changesets mention this consumer-visible fix; the existing entries only cover the testing extraction and docs. Add a react-app changeset describing the stable-scope acquisition behavior so it appears in the release notes.
packages/vitest-plugin/react-app/package.json:23 - This
typesVersionsmap omits the root"."declaration mapping used by the repository's other multi-entry packages (for example,packages/react/framework/package.json:37-43andpackages/cli/package.json:66-72). TypeScript resolution modes that consulttypesVersionscan consequently resolve/testbut not the package-root declarations; add the root mapping.
packages/vitest-plugin/react-app/README.md:75 - The installation section does not install
@vitest/browser-playwrightorplaywright, but the quick-start config imports both immediately; following the documented steps in a consumer app therefore leaves this example unresolved. Add the provider installation command before the config example (or use a provider already listed as required).
…ontextModuleConfigurator tests
Why is this change needed?
Supersedes #5285. That PR renamed
@equinor/fusion-framework-react-app'ssrc/testingtosrc/vitestto mirror the CLI'sffc app testnaming. Building on that, it became clear the testing helpers don't belong inside the app package at all — they're test-only, addvitest-browser-reactas a hard dependency ofreact-app, and duplicate resolution logic already owned by the CLI (app.manifest.ts/app.config.tsresolution). Extracting them into their own package removes that coupling and gives the helpers a home that can evolve independently ofreact-app's own release cadence.What is the current behavior?
renderAppHook,renderAppComponent,test-app.tsx/test.tsx,scope/*) live underpackages/react/app/src/vitest, exported from@equinor/fusion-framework-react-app/vitest.@equinor/fusion-framework-cli) has its own./vitestentry-point (app-test-vite-plugin.ts,resolve-app-test-env.ts) and affc app testcommand (test.command.ts) that wrapsvitestwith that plugin pre-registered.useFrameworkModule's missing-module warning interpolates the wrong variable (${module}instead of${name}).@equinor/fusion-framework-module-contextwarns even when there's no initial context to resolve.@equinor/fusion-framework-module-msalleaves a stray debugconsole.loginresolve-version.@equinor/fusion-log's static logger unconditionally accessesprocess.env, which throws in Vitest Browser Mode (noprocessglobal).What is the new behavior?
@equinor/fusion-framework-vitest-plugin-react-app(packages/vitest-plugin/react-app) hostsrenderAppHook,renderAppComponent,testApp, andappTestVitePlugin— a Vite plugin resolving an app's manifest/config/module-configurator as virtual modules (the same resolutionffc app build/ffc app devuse), plus a/testentry-point exporting pre-seededtest/renderfixtures once the plugin is registered.@equinor/fusion-framework-react-app's./vitestentry-point is removed entirely, with no compatibility shim; its README and docs point at the new package instead.ffc app testCLI command and@equinor/fusion-framework-cli's./vitestentry-point are removed —appTestVitePluginis registered directly in a project's ownvitest.config.ts, so a dedicated CLI command/wrapper is unnecessary.useFrameworkModulewarns with the correct module name.module-contextno longer warns when there is no initial context to resolve.module-msalno longer logs debug output during version resolution.@equinor/fusion-logguardsprocess.envaccess so it's safe in Vitest Browser Mode.react-app's Vitest Browser Mode tests.What is the intended behavior or invariant?
Consumers testing a Fusion React app install
@equinor/fusion-framework-vitest-plugin-react-appas a devDependency and either: (a) userenderAppHook/renderAppComponent/testAppdirectly with a hand-suppliedenv/configure, or (b) registerappTestVitePlugininvitest.config.tsand use the/testentry-point'stest/render, which resolveenv/configureautomatically from the app's own manifest/config/module-configurator. The package has no runtime dependency on the CLI beyond reusing its manifest/config resolution.Does this PR introduce a breaking change?
Yes.
@equinor/fusion-framework-react-app's./vitestentry-point is removed with no compatibility shim. Migrate by installing@equinor/fusion-framework-vitest-plugin-react-appand importingrenderAppHook/renderAppComponent/testAppfrom it instead.ffc app testCLI command and@equinor/fusion-framework-cli's./vitestentry-point are removed. Migrate by registeringappTestVitePlugin(@equinor/fusion-framework-vitest-plugin-react-app) directly invitest.config.ts.Impact assessment:
@equinor/fusion-framework-react-appand@equinor/fusion-framework-cli(entry-point removal); Minor (initial release) for@equinor/fusion-framework-vitest-plugin-react-app; Patch for@equinor/fusion-framework-module-context,@equinor/fusion-framework-module-msal,@equinor/fusion-log@equinor/fusion-framework-react-app/vitestorffc app testmust migrate to the new packagepackages/react/appandpackages/cliconsumers of the removed entry-pointsReview guidance:
Focus on the new
packages/vitest-plugin/react-apppackage — its README documents the full surface area. The CLI command/entry-point removal and the small bugfixes (useFrameworkModule,module-context,module-msal,fusion-log) are carried over unchanged from #5285.Additional context
Supersedes #5285, which is closed in favor of this PR. Part of a larger split of an overloaded
test/cookbooksbranch intocli(#5284, merged) / this PR /cookbooks(upcoming).Related issues
None
Checklist
pnpm build,pnpm test,pnpm exec biome check,pnpm exec fusion-lint lint,pnpm verify:agent-context)