feat(react-app): vitest render/test-app fixtures under src/vitest - #5285
feat(react-app): vitest render/test-app fixtures under src/vitest#5285odinr wants to merge 1 commit into
Conversation
🦋 Changeset detectedLatest commit: 1fb0357 The changes in this PR will be included in the next version bump. This PR includes changesets to release 11 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 |
- 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)
7be6827 to
1fb0357
Compare
There was a problem hiding this comment.
Pull request overview
Adds Vitest Browser Mode fixtures for rendering React apps and hooks in a fully configured Fusion test scope, aligned with ffc app test.
Changes:
- Renames the testing subpath to
/vitestand adds app-aware fixtures. - Migrates package tests to Playwright-backed browser rendering.
- Includes supporting context, logging, MSAL, and warning fixes.
Reviewed changes
Copilot reviewed 41 out of 44 changed files in this pull request and generated 16 comments.
Show a summary per file
| File | Description |
|---|---|
pnpm-lock.yaml |
Resolves browser-testing dependencies. |
packages/utils/log/src/static.ts |
Guards browser access to process.env. |
packages/react/framework/src/useFrameworkModule.ts |
Corrects missing-module warning text. |
packages/react/app/vitest.config.ts |
Enables Playwright browser tests. |
packages/react/app/src/vitest/virtual-modules.d.ts |
Types CLI-provided virtual modules. |
packages/react/app/src/vitest/test.tsx |
Adds CLI-seeded test fixture. |
packages/react/app/src/vitest/test-app.tsx |
Adds base Fusion app fixture chain. |
packages/react/app/src/vitest/scope/resolve-fusion.ts |
Resolves mocked parent frameworks. |
packages/react/app/src/vitest/scope/resolve-app-scope.ts |
Resolves app module scopes. |
packages/react/app/src/vitest/scope/index.ts |
Exports scope utilities. |
packages/react/app/src/vitest/scope/default-app-env.ts |
Defines the default test environment. |
packages/react/app/src/vitest/scope/create-app-scope-wrapper.tsx |
Creates the provider wrapper. |
packages/react/app/src/vitest/render.tsx |
Adds CLI-seeded component rendering. |
packages/react/app/src/vitest/render-app-hook.tsx |
Migrates hook rendering to browser mode. |
packages/react/app/src/vitest/render-app-component.tsx |
Migrates component rendering to browser mode. |
packages/react/app/src/vitest/index.ts |
Defines the /vitest public surface. |
packages/react/app/src/testing/index.ts |
Removes the old testing barrel. |
packages/react/app/src/msal/useToken.ts |
Stabilizes token request dependencies. |
packages/react/app/src/__tests__/useTrackFeature.test.tsx |
Migrates helper import. |
packages/react/app/src/__tests__/useToken.test.tsx |
Adapts token tests to browser mode. |
packages/react/app/src/__tests__/useHelpCenter.test.tsx |
Uses Vitest polling. |
packages/react/app/src/__tests__/useFeature.test.tsx |
Migrates feature tests. |
packages/react/app/src/__tests__/useCurrentContext.test.tsx |
Migrates context tests. |
packages/react/app/src/__tests__/useCurrentBookmark.test.tsx |
Migrates bookmark tests. |
packages/react/app/src/__tests__/useCurrentAccount.test.tsx |
Updates fixture import. |
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 |
Adapts access-token tests. |
packages/react/app/src/__tests__/Apploader.test.tsx |
Migrates component tests. |
packages/react/app/README.md |
Renames the testing entry point. |
packages/react/app/package.json |
Exports /vitest and adds browser dependencies. |
packages/react/app/docs/testing.md |
Updates testing API documentation. |
packages/modules/msal/src/versioning/resolve-version.ts |
Removes debug output. |
packages/modules/context/tsconfig.json |
References the telemetry package. |
packages/modules/context/src/utils/resolve-initial-context.ts |
Handles an absent initial context. |
packages/modules/context/src/module.ts |
Adds telemetry for context initialization. |
packages/modules/context/src/ContextProvider.ts |
Removes queue debug output. |
packages/modules/context/src/__tests__/ContextModuleConfigurator.test.ts |
Covers empty initial context behavior. |
packages/modules/context/package.json |
Adds telemetry development dependency. |
.gitignore |
Ignores browser-test artifacts. |
.changeset/react-app_render-app-hook-testing.md |
Updates hook-helper release notes. |
.changeset/react-app_render-app-component-testing.md |
Updates component-helper release notes. |
.changeset/react_fix-usemodule-warning.md |
Records the warning fix. |
.changeset/module-context_fix-empty-context-warning.md |
Records the context fix. |
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
Suppressed comments (1)
packages/react/app/docs/testing.md:147
- This guide still documents
@testing-library/reactoptions, return values, imports, andwaitFor, although the implementation and peer dependency were switched tovitest-browser-react. As written, the examples require an undeclared package and do not describe the public API actually returned; migrate the guide consistently to the browser renderer.
Options are the same shape as `renderAppHook`'s — `configure`, `env`, `fusion` — plus any
other `@testing-library/react` `render` option. The result carries the usual `render` return
values (`getByText`, `container`, `unmount`, ...) plus `fusion` — nested rather than spread
directly onto the result, so `@testing-library/react`'s own return shape stays free to evolve
without ever colliding with it. `fusion.app` is the same application module instance the
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| export { test } from './test'; | ||
| export { render } from './render'; |
| "./vitest": { | ||
| "types": "./dist/types/vitest/index.d.ts", | ||
| "import": "./dist/esm/vitest/index.js" |
| // `process` is unavailable in real browser environments (e.g. Vitest Browser Mode) | ||
| const env = typeof process !== 'undefined' ? process.env : undefined; | ||
| const envLogLevel = env?.FUSION_LOG_LEVEL; |
| export function createAppScopeWrapper<TModules extends Array<AnyModule> | unknown = unknown>({ | ||
| framework, | ||
| app, | ||
| }: AppScope<TModules>) { |
| // `req` is typically a fresh object literal each render; key the effect on its | ||
| // scopes' content instead of identity, so it doesn't re-run (and reset `pending` | ||
| // to `true` forever) every time the caller re-renders. | ||
| const scopesKey = req.scopes.join(','); |
| The result also carries a nested `app` object (`app.modules`, `app.fusion`) — the same instances the hook rendered against, for driving a module the hook itself doesn't return — nested rather than spread directly onto the result so `@testing-library/react`'s own return shape stays free to evolve without ever colliding with it. | ||
|
|
||
| Requires `@testing-library/react` (added as an optional peer dependency). |
| `renderAppComponent` wraps `@testing-library/react`'s `render` with the same `FrameworkProvider` + `ModuleProvider` nesting `renderAppHook` uses, backed by `mockFramework` and `mockAppModules` (`@equinor/fusion-framework-app/mock`), so tests can render a real component tree without hand-wiring those mocks. | ||
|
|
||
| The result also carries a nested `app` object (`app.modules`, `app.fusion`) — nested rather than spread directly onto the result so `@testing-library/react`'s own return shape stays free to evolve without ever colliding with it — so a test can drive a module directly after the initial render and assert the component re-renders, instead of hand-wiring `mockAppModules`/`ModuleProvider` itself to reach the same instance: | ||
|
|
||
| ```tsx | ||
| const { getByText, app } = await renderAppComponent<[ContextModule]>(<App />, { | ||
| configure: (configurator) => enableContextMock(configurator, (mock) => mock.setCurrentContext(projectA)), | ||
| }); | ||
| await act(() => app.modules.context.setCurrentContextByIdAsync(projectB.id)); | ||
| await waitFor(() => expect(getByText(/project-b/)).toBeInTheDocument()); |
| Any other `renderHook` option (e.g. `initialProps`) is forwarded as-is. The result carries the | ||
| usual `renderHook` return values (`result`, `rerender`, `unmount`) plus `modules` and `fusion` — | ||
| the same instances the hook rendered against — for driving a module the hook itself doesn't return. |
| ```tsx | ||
| import { renderAppHook } from '@equinor/fusion-framework-react-app/testing'; | ||
| import { renderAppHook } from '@equinor/fusion-framework-react-app/vitest'; | ||
| import { waitFor } from '@testing-library/react'; | ||
| import { useAccessToken } from '@equinor/fusion-framework-react-app/msal'; |
| | `/framework` | `useFramework`, `useCurrentUser`, `useFrameworkHttpClient` | | ||
| | `/widget` | Widget entry-point | | ||
| | `/testing` | `renderAppHook`, `renderAppComponent` — pre-wrapped `renderHook`/`render` for testing app-scoped hooks and components | | ||
| | `/vitest` | `renderAppHook`, `renderAppComponent` — pre-wrapped `renderHook`/`render` for testing app-scoped hooks and components | |
|
Closing in favor of a new PR — the direction changed after this was opened: instead of renaming Superseded by a new PR from |
Why is this change needed?
@equinor/fusion-framework-react-app's testing utilities lived undersrc/testing, disconnected from the CLI's newffc app testcommand (@equinor/fusion-framework-cli/vitest, added in #5284, now merged). This PR renames the testing surface tosrc/vitestand adds a full fixture chain (test-app.tsx,test.tsx,scope/*) for rendering app components and hooks against a fully wired Fusion test environment, matching the CLI's naming convention.What is the current behavior?
packages/react/app/src/testing/*with onlyrender-app-component.tsxandrender-app-hook.tsx.useFrameworkModule's missing-module warning interpolates the wrong variable (${module}instead of${name}), so the warning message is always broken.@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?
src/testingrenamed tosrc/vitest, with a newtest-app.tsx/test.tsx/scope/*fixture chain providing a ready-to-use Fusion test environment (scope wrapper, default app env, fusion resolver).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.What is the intended behavior or invariant?
Consumers importing app-testing utilities should do so from
@equinor/fusion-framework-react-app/vitest, mirroring@equinor/fusion-framework-cli/vitest. The fixture chain assumes it's only used in a Vitest environment (browser or node).Does this PR introduce a breaking change?
Yes —
@equinor/fusion-framework-react-app'ssrc/testingexport path is renamed tosrc/vitest. Consumers importing from the oldtestingsubpath must update tovitest.Impact assessment:
@equinor/fusion-framework-react-app(new subpath + fixtures), Patch for@equinor/fusion-framework-react,@equinor/fusion-framework-module-context@equinor/fusion-framework-react-app/testingto@equinor/fusion-framework-react-app/vitestpackages/react/appconsumersReview guidance:
Focus on the new
src/vitest/scope/*fixture chain andtest-app.tsx/test.tsx— these are the new surface area. The other fixes (useFrameworkModule,module-context,module-msal,fusion-log) are small, isolated bugfixes bundled in because they were needed for the new fixtures to pass cleanly.Additional context
Part of a larger split of an overloaded
test/cookbooksbranch intocli(#5284, merged) /react-app-vitest(this PR) /cookbooks(upcoming).Related issues
None
Checklist
pnpm build:packages,pnpm exec vitest run,pnpm check,pnpm exec fusion-lint lint)