@equinor/fusion-framework-vitest-plugin-react-app 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/esm/index.js +9 -4
  2. package/dist/esm/index.js.map +1 -1
  3. package/dist/esm/resolve-app-test-env.js +8 -2
  4. package/dist/esm/resolve-app-test-env.js.map +1 -1
  5. package/dist/esm/scope/resolve-fusion.js +22 -24
  6. package/dist/esm/scope/resolve-fusion.js.map +1 -1
  7. package/dist/esm/test-app.js +5 -8
  8. package/dist/esm/test-app.js.map +1 -1
  9. package/dist/esm/test.js +2 -1
  10. package/dist/esm/test.js.map +1 -1
  11. package/dist/esm/version.js +1 -1
  12. package/dist/tsconfig.tsbuildinfo +1 -1
  13. package/dist/types/index.d.ts +4 -3
  14. package/dist/types/resolve-app-test-env.d.ts +3 -1
  15. package/dist/types/scope/resolve-fusion.d.ts +6 -7
  16. package/dist/types/test-app.d.ts +12 -11
  17. package/dist/types/test.d.ts +20 -9
  18. package/dist/types/version.d.ts +1 -1
  19. package/package.json +17 -19
  20. package/CHANGELOG.md +0 -81
  21. package/docs/advanced.md +0 -209
  22. package/docs/configuration.md +0 -112
  23. package/docs/getting-started.md +0 -66
  24. package/docs/migrating-an-existing-app.md +0 -202
  25. package/docs/module-mocks.md +0 -120
  26. package/docs/overview.md +0 -49
  27. package/docs/troubleshooting.md +0 -67
  28. package/docs/why-browser-mode.md +0 -128
  29. package/src/__tests__/app-test-vite-plugin.test.ts +0 -109
  30. package/src/__tests__/merge-env-config.test.ts +0 -67
  31. package/src/__tests__/resolve-app-test-env.test.ts +0 -83
  32. package/src/app-test.ts +0 -19
  33. package/src/define-project.ts +0 -91
  34. package/src/index.ts +0 -124
  35. package/src/merge-env-config.ts +0 -58
  36. package/src/render-app-component.tsx +0 -116
  37. package/src/render-app-hook.tsx +0 -135
  38. package/src/render.tsx +0 -64
  39. package/src/resolve-app-test-env.ts +0 -132
  40. package/src/scope/create-app-scope-wrapper.tsx +0 -26
  41. package/src/scope/default-app-env.ts +0 -13
  42. package/src/scope/index.ts +0 -4
  43. package/src/scope/resolve-app-scope.ts +0 -46
  44. package/src/scope/resolve-fusion.ts +0 -74
  45. package/src/test-app.tsx +0 -148
  46. package/src/test.tsx +0 -42
  47. package/src/version.ts +0 -2
  48. package/src/virtual-modules.d.ts +0 -12
  49. package/tsconfig.json +0 -26
  50. package/vitest.config.ts +0 -10
@@ -34,9 +34,10 @@ export type AppTestVitePluginOptions = ResolveAppTestEnvOptions & {
34
34
  * // ...your own browser-mode config
35
35
  * });
36
36
  * ```
37
- * Exposes two virtual modules: `virtual:fusion-app-test-env` (`manifest`/`config`, as JSON) and
38
- * `virtual:fusion-app-test-configure` (a re-export of the resolved `configure` module, or
39
- * `undefined` if none exists). Not intended to be imported directly by application code.
37
+ * Exposes two virtual modules: `virtual:fusion-app-test-env`
38
+ * (`manifest`/`config`/`runtimeDependencies`, as JSON) and `virtual:fusion-app-test-configure`
39
+ * (a re-export of the resolved `configure` module, or `undefined` if none exists). Not intended
40
+ * to be imported directly by application code.
40
41
  *
41
42
  * @param options - Resolution options; `entrypoint` defaults to the current working directory.
42
43
  * @returns A Vite plugin instance.
@@ -6,6 +6,8 @@ import { type AppManifestFn, type AppConfigFn, type ApiAppConfig } from '@equino
6
6
  export type AppTestEnv = {
7
7
  manifest: AppManifest;
8
8
  config: ApiAppConfig;
9
+ /** Package names declared by the application as runtime dependencies. */
10
+ runtimeDependencies: Array<string>;
9
11
  };
10
12
  /**
11
13
  * Options for {@link resolveAppTestEnv}.
@@ -38,7 +40,7 @@ export type ResolveAppTestEnvOptions = {
38
40
  * `test.override('appEnv', ...)`.
39
41
  *
40
42
  * @param options - Resolution options; `entrypoint` defaults to the current working directory.
41
- * @returns The resolved application manifest and config.
43
+ * @returns The resolved application manifest, config, and module capabilities.
42
44
  * @throws If no `package.json` can be found from `entrypoint` upward, or an explicitly requested
43
45
  * `manifest`/`config` file does not exist.
44
46
  * @example
@@ -10,17 +10,16 @@ import type { NavigationModule } from '@equinor/fusion-framework-module-navigati
10
10
  *
11
11
  * @template TEnv - The application environment descriptor.
12
12
  * @param options - `env` seeds the built-in app manifest mock; navigation defaults to in-memory
13
- * history, so tests don't leak URL/history state between runs. Feature flags default to the
14
- * in-memory feature-flag mock, with none enabled, when the optional
15
- * `@equinor/fusion-framework-module-feature-flag` peer dependency is installed. `configure`
16
- * runs afterwards on the same configurator — e.g. call `enableNavigation` or
17
- * `enableFeatureFlagMock` again to override either, or register extra modules and service
18
- * discovery entries. `fusion`, an already-built parent instance, is reused as-is and skips
19
- * `configure` entirely.
13
+ * history, so tests don't leak URL/history state between runs. `runtimeDependencies` enables
14
+ * parent module mocks associated with packages declared by the tested app. `configure` runs
15
+ * afterwards on the same configurator — e.g. call `enableNavigation` to override the history
16
+ * or register extra modules and service discovery entries. `fusion`, an already-built parent
17
+ * instance, is reused as-is and skips `configure` entirely.
20
18
  * @returns The given `fusion`, or a fresh mocked parent Fusion instance.
21
19
  */
22
20
  export declare function resolveFusion<TEnv extends AppEnv = AppEnv>(options?: {
23
21
  env?: TEnv;
24
22
  fusion?: Fusion;
25
23
  configure?: FrameworkMockConfigureFn<[AppModule, NavigationModule]>;
24
+ runtimeDependencies?: ReadonlyArray<string>;
26
25
  }): Promise<Fusion>;
@@ -85,16 +85,13 @@ import type { FrameworkMockConfigureFn } from '@equinor/fusion-framework/mock';
85
85
  * });
86
86
  * ```
87
87
  *
88
- * @example Extend the parent framework mock with an application module
88
+ * @example Extend the parent framework mock with service discovery
89
89
  * ```tsx
90
90
  * const test = testApp.extend(
91
91
  * 'configureFusion',
92
92
  * { injected: true },
93
93
  * (): FrameworkMockConfigureFn<[AppModule, NavigationModule]> =>
94
94
  * (configurator) => {
95
- * // seed a specific flag rather than merely enabling the mock — that's already the
96
- * // default when the optional feature-flag peer dependency is installed
97
- * enableFeatureFlagMock(configurator, (mock) => mock.addFeature({ key: 'new-search', enabled: true }));
98
95
  * configurator.serviceDiscovery.addServices([
99
96
  * { key: 'people', uri: baseUrl('people') },
100
97
  * { key: 'context', uri: baseUrl('context') },
@@ -103,33 +100,37 @@ import type { FrameworkMockConfigureFn } from '@equinor/fusion-framework/mock';
103
100
  * );
104
101
  * ```
105
102
  */
106
- export declare const testApp: import("vitest").TestAPI<Omit<Omit<Omit<Omit<Omit<Omit<Omit<object, "$__test"> & Record<"appEnv", AppEnv> & {
103
+ export declare const testApp: import("vitest").TestAPI<Omit<Omit<Omit<Omit<Omit<Omit<Omit<Omit<object, "$__test"> & Record<"appEnv", AppEnv> & {
107
104
  readonly $__worker?: object | undefined;
108
105
  readonly $__file?: object | undefined;
109
106
  readonly $__test?: (object & Record<"appEnv", AppEnv>) | undefined;
107
+ }, "$__test"> & Record<"runtimeDependencies", string[]> & {
108
+ readonly $__worker?: object | undefined;
109
+ readonly $__file?: object | undefined;
110
+ readonly $__test?: (object & Record<"appEnv", AppEnv> & Record<"runtimeDependencies", string[]>) | undefined;
110
111
  }, "$__test"> & Record<"configureApp", AppMockConfigureFn | undefined> & {
111
112
  readonly $__worker?: object | undefined;
112
113
  readonly $__file?: object | undefined;
113
- readonly $__test?: (object & Record<"appEnv", AppEnv> & Record<"configureApp", AppMockConfigureFn | undefined>) | undefined;
114
+ readonly $__test?: (object & Record<"appEnv", AppEnv> & Record<"runtimeDependencies", string[]> & Record<"configureApp", AppMockConfigureFn | undefined>) | undefined;
114
115
  }, "$__test"> & Record<"configureFusion", FrameworkMockConfigureFn<[AppModule, NavigationModule]> | undefined> & {
115
116
  readonly $__worker?: object | undefined;
116
117
  readonly $__file?: object | undefined;
117
- readonly $__test?: (object & Record<"appEnv", AppEnv> & Record<"configureApp", AppMockConfigureFn | undefined> & Record<"configureFusion", FrameworkMockConfigureFn<[AppModule, NavigationModule]> | undefined>) | undefined;
118
+ readonly $__test?: (object & Record<"appEnv", AppEnv> & Record<"runtimeDependencies", string[]> & Record<"configureApp", AppMockConfigureFn | undefined> & Record<"configureFusion", FrameworkMockConfigureFn<[AppModule, NavigationModule]> | undefined>) | undefined;
118
119
  }, "$__test"> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & {
119
120
  readonly $__worker?: object | undefined;
120
121
  readonly $__file?: object | undefined;
121
- readonly $__test?: (object & Record<"appEnv", AppEnv> & Record<"configureApp", AppMockConfigureFn | undefined> & Record<"configureFusion", FrameworkMockConfigureFn<[AppModule, NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>>) | undefined;
122
+ readonly $__test?: (object & Record<"appEnv", AppEnv> & Record<"runtimeDependencies", string[]> & Record<"configureApp", AppMockConfigureFn | undefined> & Record<"configureFusion", FrameworkMockConfigureFn<[AppModule, NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>>) | undefined;
122
123
  }, "$__test"> & Record<"app", import("@equinor/fusion-framework-module-app").AppModulesInstance<unknown>> & {
123
124
  readonly $__worker?: object | undefined;
124
125
  readonly $__file?: object | undefined;
125
- readonly $__test?: (object & Record<"appEnv", AppEnv> & Record<"configureApp", AppMockConfigureFn | undefined> & Record<"configureFusion", FrameworkMockConfigureFn<[AppModule, NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & Record<"app", import("@equinor/fusion-framework-module-app").AppModulesInstance<unknown>>) | undefined;
126
+ readonly $__test?: (object & Record<"appEnv", AppEnv> & Record<"runtimeDependencies", string[]> & Record<"configureApp", AppMockConfigureFn | undefined> & Record<"configureFusion", FrameworkMockConfigureFn<[AppModule, NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & Record<"app", import("@equinor/fusion-framework-module-app").AppModulesInstance<unknown>>) | undefined;
126
127
  }, "$__test"> & Record<"render", (ui: ReactElement, options?: Omit<RenderOptions, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderResult>> & {
127
128
  readonly $__worker?: object | undefined;
128
129
  readonly $__file?: object | undefined;
129
- readonly $__test?: (object & Record<"appEnv", AppEnv> & Record<"configureApp", AppMockConfigureFn | undefined> & Record<"configureFusion", FrameworkMockConfigureFn<[AppModule, NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & Record<"app", import("@equinor/fusion-framework-module-app").AppModulesInstance<unknown>> & Record<"render", (ui: ReactElement, options?: Omit<RenderOptions, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderResult>>) | undefined;
130
+ readonly $__test?: (object & Record<"appEnv", AppEnv> & Record<"runtimeDependencies", string[]> & Record<"configureApp", AppMockConfigureFn | undefined> & Record<"configureFusion", FrameworkMockConfigureFn<[AppModule, NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & Record<"app", import("@equinor/fusion-framework-module-app").AppModulesInstance<unknown>> & Record<"render", (ui: ReactElement, options?: Omit<RenderOptions, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderResult>>) | undefined;
130
131
  }, "$__test"> & Record<"renderHook", <Result, Props = undefined>(cb: (initialProps?: Props) => Result, options?: Omit<RenderHookOptions<Props>, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderHookResult<Result, Props>>> & {
131
132
  readonly $__worker?: object | undefined;
132
133
  readonly $__file?: object | undefined;
133
- readonly $__test?: (object & Record<"appEnv", AppEnv> & Record<"configureApp", AppMockConfigureFn | undefined> & Record<"configureFusion", FrameworkMockConfigureFn<[AppModule, NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & Record<"app", import("@equinor/fusion-framework-module-app").AppModulesInstance<unknown>> & Record<"render", (ui: ReactElement, options?: Omit<RenderOptions, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderResult>> & Record<"renderHook", <Result, Props = undefined>(cb: (initialProps?: Props) => Result, options?: Omit<RenderHookOptions<Props>, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderHookResult<Result, Props>>>) | undefined;
134
+ readonly $__test?: (object & Record<"appEnv", AppEnv> & Record<"runtimeDependencies", string[]> & Record<"configureApp", AppMockConfigureFn | undefined> & Record<"configureFusion", FrameworkMockConfigureFn<[AppModule, NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & Record<"app", import("@equinor/fusion-framework-module-app").AppModulesInstance<unknown>> & Record<"render", (ui: ReactElement, options?: Omit<RenderOptions, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderResult>> & Record<"renderHook", <Result, Props = undefined>(cb: (initialProps?: Props) => Result, options?: Omit<RenderHookOptions<Props>, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderHookResult<Result, Props>>>) | undefined;
134
135
  }>;
135
136
  export default testApp;
@@ -28,48 +28,59 @@
28
28
  * });
29
29
  * ```
30
30
  */
31
- export declare const test: import("vitest").TestAPI<Omit<Omit<Omit<Omit<Omit<Omit<Omit<Omit<Omit<object, "$__test"> & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & {
31
+ export declare const test: import("vitest").TestAPI<Omit<Omit<Omit<Omit<Omit<Omit<Omit<Omit<Omit<Omit<Omit<object, "$__test"> & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & {
32
32
  readonly $__worker?: object | undefined;
33
33
  readonly $__file?: object | undefined;
34
34
  readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv>) | undefined;
35
+ }, "$__test"> & Record<"runtimeDependencies", string[]> & {
36
+ readonly $__worker?: object | undefined;
37
+ readonly $__file?: object | undefined;
38
+ readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & Record<"runtimeDependencies", string[]>) | undefined;
35
39
  }, "$__test"> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined> & {
36
40
  readonly $__worker?: object | undefined;
37
41
  readonly $__file?: object | undefined;
38
- readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined>) | undefined;
42
+ readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & Record<"runtimeDependencies", string[]> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined>) | undefined;
39
43
  }, "$__test"> & Record<"configureFusion", import("node_modules/@equinor/fusion-framework/src/mock/mock-framework").FrameworkMockConfigureFn<[import("node_modules/@equinor/fusion-framework-module-app/src/module").AppModule, import("node_modules/@equinor/fusion-framework-module-navigation/src/module").NavigationModule]> | undefined> & {
40
44
  readonly $__worker?: object | undefined;
41
45
  readonly $__file?: object | undefined;
42
- readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined> & Record<"configureFusion", import("node_modules/@equinor/fusion-framework/src/mock/mock-framework").FrameworkMockConfigureFn<[import("node_modules/@equinor/fusion-framework-module-app/src/module").AppModule, import("node_modules/@equinor/fusion-framework-module-navigation/src/module").NavigationModule]> | undefined>) | undefined;
46
+ readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & Record<"runtimeDependencies", string[]> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined> & Record<"configureFusion", import("node_modules/@equinor/fusion-framework/src/mock/mock-framework").FrameworkMockConfigureFn<[import("node_modules/@equinor/fusion-framework-module-app/src/module").AppModule, import("node_modules/@equinor/fusion-framework-module-navigation/src/module").NavigationModule]> | undefined>) | undefined;
43
47
  }, "$__test"> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & {
44
48
  readonly $__worker?: object | undefined;
45
49
  readonly $__file?: object | undefined;
46
- readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined> & Record<"configureFusion", import("node_modules/@equinor/fusion-framework/src/mock/mock-framework").FrameworkMockConfigureFn<[import("node_modules/@equinor/fusion-framework-module-app/src/module").AppModule, import("node_modules/@equinor/fusion-framework-module-navigation/src/module").NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>>) | undefined;
50
+ readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & Record<"runtimeDependencies", string[]> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined> & Record<"configureFusion", import("node_modules/@equinor/fusion-framework/src/mock/mock-framework").FrameworkMockConfigureFn<[import("node_modules/@equinor/fusion-framework-module-app/src/module").AppModule, import("node_modules/@equinor/fusion-framework-module-navigation/src/module").NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>>) | undefined;
47
51
  }, "$__test"> & Record<"app", import("node_modules/@equinor/fusion-framework-module-app/src/types").AppModulesInstance<unknown>> & {
48
52
  readonly $__worker?: object | undefined;
49
53
  readonly $__file?: object | undefined;
50
- readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined> & Record<"configureFusion", import("node_modules/@equinor/fusion-framework/src/mock/mock-framework").FrameworkMockConfigureFn<[import("node_modules/@equinor/fusion-framework-module-app/src/module").AppModule, import("node_modules/@equinor/fusion-framework-module-navigation/src/module").NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & Record<"app", import("node_modules/@equinor/fusion-framework-module-app/src/types").AppModulesInstance<unknown>>) | undefined;
54
+ readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & Record<"runtimeDependencies", string[]> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined> & Record<"configureFusion", import("node_modules/@equinor/fusion-framework/src/mock/mock-framework").FrameworkMockConfigureFn<[import("node_modules/@equinor/fusion-framework-module-app/src/module").AppModule, import("node_modules/@equinor/fusion-framework-module-navigation/src/module").NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & Record<"app", import("node_modules/@equinor/fusion-framework-module-app/src/types").AppModulesInstance<unknown>>) | undefined;
51
55
  }, "$__test"> & Record<"render", (ui: import("node_modules/@types/react").ReactElement, options?: Omit<import("node_modules/vitest-browser-react/dist").RenderOptions, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderResult>> & {
52
56
  readonly $__worker?: object | undefined;
53
57
  readonly $__file?: object | undefined;
54
- readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined> & Record<"configureFusion", import("node_modules/@equinor/fusion-framework/src/mock/mock-framework").FrameworkMockConfigureFn<[import("node_modules/@equinor/fusion-framework-module-app/src/module").AppModule, import("node_modules/@equinor/fusion-framework-module-navigation/src/module").NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & Record<"app", import("node_modules/@equinor/fusion-framework-module-app/src/types").AppModulesInstance<unknown>> & Record<"render", (ui: import("node_modules/@types/react").ReactElement, options?: Omit<import("node_modules/vitest-browser-react/dist").RenderOptions, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderResult>>) | undefined;
58
+ readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & Record<"runtimeDependencies", string[]> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined> & Record<"configureFusion", import("node_modules/@equinor/fusion-framework/src/mock/mock-framework").FrameworkMockConfigureFn<[import("node_modules/@equinor/fusion-framework-module-app/src/module").AppModule, import("node_modules/@equinor/fusion-framework-module-navigation/src/module").NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & Record<"app", import("node_modules/@equinor/fusion-framework-module-app/src/types").AppModulesInstance<unknown>> & Record<"render", (ui: import("node_modules/@types/react").ReactElement, options?: Omit<import("node_modules/vitest-browser-react/dist").RenderOptions, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderResult>>) | undefined;
55
59
  }, "$__test"> & Record<"renderHook", <Result, Props = undefined>(cb: (initialProps?: Props) => Result, options?: Omit<import("node_modules/vitest-browser-react/dist").RenderHookOptions<Props>, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderHookResult<Result, Props>>> & {
56
60
  readonly $__worker?: object | undefined;
57
61
  readonly $__file?: object | undefined;
58
- readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined> & Record<"configureFusion", import("node_modules/@equinor/fusion-framework/src/mock/mock-framework").FrameworkMockConfigureFn<[import("node_modules/@equinor/fusion-framework-module-app/src/module").AppModule, import("node_modules/@equinor/fusion-framework-module-navigation/src/module").NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & Record<"app", import("node_modules/@equinor/fusion-framework-module-app/src/types").AppModulesInstance<unknown>> & Record<"render", (ui: import("node_modules/@types/react").ReactElement, options?: Omit<import("node_modules/vitest-browser-react/dist").RenderOptions, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderResult>> & Record<"renderHook", <Result, Props = undefined>(cb: (initialProps?: Props) => Result, options?: Omit<import("node_modules/vitest-browser-react/dist").RenderHookOptions<Props>, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderHookResult<Result, Props>>>) | undefined;
62
+ readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & Record<"runtimeDependencies", string[]> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined> & Record<"configureFusion", import("node_modules/@equinor/fusion-framework/src/mock/mock-framework").FrameworkMockConfigureFn<[import("node_modules/@equinor/fusion-framework-module-app/src/module").AppModule, import("node_modules/@equinor/fusion-framework-module-navigation/src/module").NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & Record<"app", import("node_modules/@equinor/fusion-framework-module-app/src/types").AppModulesInstance<unknown>> & Record<"render", (ui: import("node_modules/@types/react").ReactElement, options?: Omit<import("node_modules/vitest-browser-react/dist").RenderOptions, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderResult>> & Record<"renderHook", <Result, Props = undefined>(cb: (initialProps?: Props) => Result, options?: Omit<import("node_modules/vitest-browser-react/dist").RenderHookOptions<Props>, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderHookResult<Result, Props>>>) | undefined;
59
63
  }, "$__test"> & Record<"appEnv", {
60
64
  manifest: import("@equinor/fusion-framework-cli/app").AppManifest;
61
65
  config: import("node_modules/@equinor/fusion-framework-module-app/src/AppConfig").AppConfig<import("node_modules/@equinor/fusion-framework-module-app/src/types").ConfigEnvironment> | undefined;
62
66
  }> & {
63
67
  readonly $__worker?: object | undefined;
64
68
  readonly $__file?: object | undefined;
65
- readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined> & Record<"configureFusion", import("node_modules/@equinor/fusion-framework/src/mock/mock-framework").FrameworkMockConfigureFn<[import("node_modules/@equinor/fusion-framework-module-app/src/module").AppModule, import("node_modules/@equinor/fusion-framework-module-navigation/src/module").NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & Record<"app", import("node_modules/@equinor/fusion-framework-module-app/src/types").AppModulesInstance<unknown>> & Record<"render", (ui: import("node_modules/@types/react").ReactElement, options?: Omit<import("node_modules/vitest-browser-react/dist").RenderOptions, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderResult>> & Record<"renderHook", <Result, Props = undefined>(cb: (initialProps?: Props) => Result, options?: Omit<import("node_modules/vitest-browser-react/dist").RenderHookOptions<Props>, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderHookResult<Result, Props>>> & Record<"appEnv", {
69
+ readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & Record<"runtimeDependencies", string[]> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined> & Record<"configureFusion", import("node_modules/@equinor/fusion-framework/src/mock/mock-framework").FrameworkMockConfigureFn<[import("node_modules/@equinor/fusion-framework-module-app/src/module").AppModule, import("node_modules/@equinor/fusion-framework-module-navigation/src/module").NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & Record<"app", import("node_modules/@equinor/fusion-framework-module-app/src/types").AppModulesInstance<unknown>> & Record<"render", (ui: import("node_modules/@types/react").ReactElement, options?: Omit<import("node_modules/vitest-browser-react/dist").RenderOptions, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderResult>> & Record<"renderHook", <Result, Props = undefined>(cb: (initialProps?: Props) => Result, options?: Omit<import("node_modules/vitest-browser-react/dist").RenderHookOptions<Props>, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderHookResult<Result, Props>>> & Record<"appEnv", {
70
+ manifest: import("@equinor/fusion-framework-cli/app").AppManifest;
71
+ config: import("node_modules/@equinor/fusion-framework-module-app/src/AppConfig").AppConfig<import("node_modules/@equinor/fusion-framework-module-app/src/types").ConfigEnvironment> | undefined;
72
+ }>) | undefined;
73
+ }, "$__test"> & Record<"runtimeDependencies", string[]> & {
74
+ readonly $__worker?: object | undefined;
75
+ readonly $__file?: object | undefined;
76
+ readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & Record<"runtimeDependencies", string[]> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined> & Record<"configureFusion", import("node_modules/@equinor/fusion-framework/src/mock/mock-framework").FrameworkMockConfigureFn<[import("node_modules/@equinor/fusion-framework-module-app/src/module").AppModule, import("node_modules/@equinor/fusion-framework-module-navigation/src/module").NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & Record<"app", import("node_modules/@equinor/fusion-framework-module-app/src/types").AppModulesInstance<unknown>> & Record<"render", (ui: import("node_modules/@types/react").ReactElement, options?: Omit<import("node_modules/vitest-browser-react/dist").RenderOptions, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderResult>> & Record<"renderHook", <Result, Props = undefined>(cb: (initialProps?: Props) => Result, options?: Omit<import("node_modules/vitest-browser-react/dist").RenderHookOptions<Props>, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderHookResult<Result, Props>>> & Record<"appEnv", {
66
77
  manifest: import("@equinor/fusion-framework-cli/app").AppManifest;
67
78
  config: import("node_modules/@equinor/fusion-framework-module-app/src/AppConfig").AppConfig<import("node_modules/@equinor/fusion-framework-module-app/src/types").ConfigEnvironment> | undefined;
68
79
  }>) | undefined;
69
80
  }, "$__test"> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined> & {
70
81
  readonly $__worker?: object | undefined;
71
82
  readonly $__file?: object | undefined;
72
- readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined> & Record<"configureFusion", import("node_modules/@equinor/fusion-framework/src/mock/mock-framework").FrameworkMockConfigureFn<[import("node_modules/@equinor/fusion-framework-module-app/src/module").AppModule, import("node_modules/@equinor/fusion-framework-module-navigation/src/module").NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & Record<"app", import("node_modules/@equinor/fusion-framework-module-app/src/types").AppModulesInstance<unknown>> & Record<"render", (ui: import("node_modules/@types/react").ReactElement, options?: Omit<import("node_modules/vitest-browser-react/dist").RenderOptions, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderResult>> & Record<"renderHook", <Result, Props = undefined>(cb: (initialProps?: Props) => Result, options?: Omit<import("node_modules/vitest-browser-react/dist").RenderHookOptions<Props>, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderHookResult<Result, Props>>> & Record<"appEnv", {
83
+ readonly $__test?: (object & Record<"appEnv", import("node_modules/@equinor/fusion-framework-app/src/types").AppEnv> & Record<"runtimeDependencies", string[]> & Record<"configureApp", import("node_modules/@equinor/fusion-framework-app/src/mock/mock-app-modules").AppMockConfigureFn | undefined> & Record<"configureFusion", import("node_modules/@equinor/fusion-framework/src/mock/mock-framework").FrameworkMockConfigureFn<[import("node_modules/@equinor/fusion-framework-module-app/src/module").AppModule, import("node_modules/@equinor/fusion-framework-module-navigation/src/module").NavigationModule]> | undefined> & Record<"fusion", import("node_modules/@equinor/fusion-framework/src/types").Fusion<unknown>> & Record<"app", import("node_modules/@equinor/fusion-framework-module-app/src/types").AppModulesInstance<unknown>> & Record<"render", (ui: import("node_modules/@types/react").ReactElement, options?: Omit<import("node_modules/vitest-browser-react/dist").RenderOptions, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderResult>> & Record<"renderHook", <Result, Props = undefined>(cb: (initialProps?: Props) => Result, options?: Omit<import("node_modules/vitest-browser-react/dist").RenderHookOptions<Props>, 'wrapper'>) => Promise<import("node_modules/vitest-browser-react/dist").RenderHookResult<Result, Props>>> & Record<"appEnv", {
73
84
  manifest: import("@equinor/fusion-framework-cli/app").AppManifest;
74
85
  config: import("node_modules/@equinor/fusion-framework-module-app/src/AppConfig").AppConfig<import("node_modules/@equinor/fusion-framework-module-app/src/types").ConfigEnvironment> | undefined;
75
86
  }>) | undefined;
@@ -1 +1 @@
1
- export declare const version = "1.0.0";
1
+ export declare const version = "1.0.2";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/fusion-framework-vitest-plugin-react-app",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Vite plugin resolving an application's manifest, config, and module-configurator as virtual modules for testing.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -43,19 +43,24 @@
43
43
  "testing"
44
44
  ],
45
45
  "license": "ISC",
46
+ "files": [
47
+ "dist"
48
+ ],
46
49
  "publishConfig": {
47
50
  "access": "public"
48
51
  },
49
52
  "dependencies": {
50
- "@equinor/fusion-framework-app": "13.1.0",
51
- "@equinor/fusion-framework": "8.1.0",
52
- "@equinor/fusion-framework-cli": "15.3.0",
53
- "@equinor/fusion-framework-module-app": "8.1.0",
54
- "@equinor/fusion-framework-module": "6.1.3",
55
- "@equinor/fusion-framework-react": "9.0.0",
56
- "@equinor/fusion-imports": "2.0.3",
57
- "@equinor/fusion-framework-react-module": "4.0.3",
58
- "@equinor/fusion-framework-module-navigation": "7.0.9"
53
+ "@equinor/fusion-framework": "8.1.2",
54
+ "@equinor/fusion-framework-app": "13.1.2",
55
+ "@equinor/fusion-framework-module-app": "8.1.1",
56
+ "@equinor/fusion-framework-module-feature-flag": "2.1.1",
57
+ "@equinor/fusion-framework-module": "6.1.4",
58
+ "@equinor/fusion-framework-module-navigation": "7.0.10",
59
+ "@equinor/fusion-framework-module-telemetry": "7.1.1",
60
+ "@equinor/fusion-framework-react-module": "4.0.4",
61
+ "@equinor/fusion-framework-react": "9.0.1",
62
+ "@equinor/fusion-imports": "2.0.4",
63
+ "@equinor/fusion-framework-cli": "15.3.2"
59
64
  },
60
65
  "devDependencies": {
61
66
  "@types/react": "^19.2.7",
@@ -68,8 +73,7 @@
68
73
  "typescript": "^7.0.2",
69
74
  "vite": "^8.0.0",
70
75
  "vitest": "^4.1.10",
71
- "vitest-browser-react": "^2.2.0",
72
- "@equinor/fusion-framework-module-feature-flag": "2.1.0"
76
+ "vitest-browser-react": "^2.2.0"
73
77
  },
74
78
  "peerDependencies": {
75
79
  "@types/react": "^18.0.0 || ^19.0.0",
@@ -80,13 +84,7 @@
80
84
  "rxjs": "^7.0.0",
81
85
  "vite": "^8.0.0",
82
86
  "vitest": "^4.0.0",
83
- "vitest-browser-react": "^2.2.0",
84
- "@equinor/fusion-framework-module-feature-flag": "2.1.0"
85
- },
86
- "peerDependenciesMeta": {
87
- "@equinor/fusion-framework-module-feature-flag": {
88
- "optional": true
89
- }
87
+ "vitest-browser-react": "^2.2.0"
90
88
  },
91
89
  "scripts": {
92
90
  "build": "tsc -b",
package/CHANGELOG.md DELETED
@@ -1,81 +0,0 @@
1
- # @equinor/fusion-framework-vitest-plugin-react-app
2
-
3
- ## 1.0.0
4
-
5
- ### Minor Changes
6
-
7
- - f663b46: Add `@equinor/fusion-framework-vitest-plugin-react-app`: Vitest/`vitest-browser-react` helpers for testing a Fusion Framework React application inside a real, mock-backed application module scope — the same `FrameworkProvider` + `ModuleProvider` nesting `renderApp`/`createComponent` wire up in production, backed by `mockFramework` and `mockAppModules` (`@equinor/fusion-framework-app/mock`).
8
-
9
- ```tsx
10
- import { renderAppHook } from '@equinor/fusion-framework-vitest-plugin-react-app';
11
- import { useAccessToken } from '@equinor/fusion-framework-react-app/msal';
12
-
13
- const { result } = await renderAppHook(() => useAccessToken({ scopes: ['User.Read'] }));
14
- await vi.waitFor(() => expect(result.current.pending).toBe(false));
15
- ```
16
-
17
- Highlights:
18
-
19
- - `renderAppHook`/`renderAppComponent` — render a hook or component against the real `event`/`http`/`msal` module pipeline, with only the network boundary faked; the result carries a nested `fusion: { framework, app }` for driving a module directly after the initial render.
20
- - `testApp` — a `vitest` `test` extended with `appEnv`/`configureApp`/`configureFusion`/`app`/`render`/`renderHook` fixtures, for a test file whose cases share one mocked scope. `configureApp` composes with the base app-module mock; `configureFusion` composes with the base parent-framework mock (app manifest and navigation) for extending framework-scope modules such as feature flags, service discovery, or navigation history.
21
- - `appTestVitePlugin` — a Vite plugin resolving an application's own manifest, config, and module-configurator (the same pipeline `ffc app build`/`ffc app dev` use) as virtual modules, with `entrypoint` inferred from the Vitest project's own root (via `configResolved`) when not given explicitly, so each cookbook's `vitest.config.ts` needs no `entrypoint` override when run as part of a multi-project Vitest run.
22
- - A `/test` entry-point exporting `test`/`render`, pre-seeded from the resolved manifest/config/configure once `appTestVitePlugin` is registered — no per-test `env`/`configure` wiring — plus `mergeEnvConfig` for overriding one endpoint's URL (or an `environment` value) on `appEnv` without dropping the rest of the app's `AppConfig`.
23
- - A `/config` entry-point exporting `defineProject`: a drop-in for Vitest's own `defineProject`, pre-wired with `appTestVitePlugin` and the `@vitest/browser-playwright`/`chromium` browser provider, so a consuming app's own `vitest.config.ts` needs no browser-provider boilerplate:
24
-
25
- ```ts
26
- import { defineProject } from '@equinor/fusion-framework-vitest-plugin-react-app/config';
27
- import { name, version } from './package.json' with { type: 'json' };
28
-
29
- export default defineProject({ test: { name: `${name}@${version}` } });
30
- ```
31
-
32
- `defineProject` defaults `test.browser.viewport` to `1024x768` instead of Vitest's own mobile-sized default, matching the low, fixed resolution most Fusion apps see in production through Citrix (pass `test.browser.viewport` to use a different size), sets `server.warmup.clientFiles: ['src/**/*.{ts,tsx}']` so lazily/code-split-imported source (e.g. route components reached only through dynamic `import()`) is transformed up front instead of forcing a page reload mid-test, and excludes `.d.ts` files from the default `server.warmup.clientFiles`/`optimizeDeps.entries` globs so a CJS-style declaration file (e.g. one using `export =`) does not fail the Vite warmup scan. `override` is deep-merged onto the default config via Vite's own `mergeConfig` (a plain object), or applied to the default config outright (a function receiving it) — for changes `mergeConfig` can't express, such as swapping `test.browser.provider` for a different `@vitest/browser-*` provider.
33
- - The mocked framework enables the feature-flag mock by default (no flags enabled) when `@equinor/fusion-framework-module-feature-flag` is installed, so `useFeature` needs no `localStorage`/URL seeding in tests, and defaults navigation to in-memory history rather than browser history (which leaked URL/history state between tests) — `configureFusion`/`enableNavigation` can still opt back into browser history for a test that specifically needs it.
34
-
35
- `@vitest/browser-playwright` and `playwright` are peer dependencies of the package. Package documentation provides task-focused guides for setup, configuration, advanced fixtures, module mocks, and troubleshooting so npm, GitHub, and retrieval clients use the same canonical source as the VuePress site.
36
-
37
- ### Patch Changes
38
-
39
- - f663b46: Document `test.override(...)` for overriding a fixture (`configure`, `fusion`, etc.) within a
40
- single test file or `describe` block, alongside the existing `test.extend(...)` guide, in the
41
- package's "Advanced usage" doc (`docs/advanced.md`).
42
- - f663b46: Add a "Migrate an existing app" guide (`docs/migrating-an-existing-app.md`) covering how to
43
- move a suite from `@testing-library/react`/jsdom/happy-dom onto this package: installing
44
- Browser Mode, replacing hand-rolled `vi.mock`s of Fusion hooks with each module's `enable*Mock`
45
- entry point, porting a hand-written mock HTTP server to `createRouterMiddleware`, composing a
46
- router fixture with a domain-state fixture in one file, and updating renders/assertions to the
47
- async `vitest-browser-react` API. Linked from the package README and from
48
- `docs/overview.md` and `testing-choosing-a-layer.md`.
49
- - f663b46: Add a "Why Browser Mode is the default" guide (`docs/why-browser-mode.md`) explaining
50
- the rationale for defaulting to real Chromium over DOM emulation (the documented React 19 peer
51
- dependency crash in the previous renderer, plus the framework's real-module testing philosophy),
52
- the actual performance tradeoff (a real browser is slower, not faster — this was a fidelity
53
- choice, not a speed optimization), and how to bring your own renderer for a single test file by
54
- composing `mockFramework`/`mockAppModules`/`FrameworkProvider`/`ModuleProvider` directly with a
55
- different render function (e.g. `@testing-library/react` on `happy-dom`). Linked from the
56
- package README and `docs/overview.md`.
57
- - Updated dependencies [f663b46]
58
- - Updated dependencies [f663b46]
59
- - Updated dependencies [f663b46]
60
- - Updated dependencies [f663b46]
61
- - Updated dependencies [f663b46]
62
- - Updated dependencies [f663b46]
63
- - Updated dependencies [f663b46]
64
- - Updated dependencies [f663b46]
65
- - Updated dependencies [f663b46]
66
- - Updated dependencies [f663b46]
67
- - Updated dependencies [f663b46]
68
- - Updated dependencies [f663b46]
69
- - Updated dependencies [f663b46]
70
- - Updated dependencies [f663b46]
71
- - Updated dependencies [f663b46]
72
- - @equinor/fusion-framework-app@13.1.0
73
- - @equinor/fusion-framework-cli@15.3.0
74
- - @equinor/fusion-framework@8.1.0
75
- - @equinor/fusion-framework-module-feature-flag@2.1.0
76
- - @equinor/fusion-imports@2.0.3
77
- - @equinor/fusion-framework-module-app@8.1.0
78
- - @equinor/fusion-framework-module@6.1.3
79
- - @equinor/fusion-framework-module-navigation@7.0.9
80
- - @equinor/fusion-framework-react-module@4.0.3
81
- - @equinor/fusion-framework-react@9.0.0
package/docs/advanced.md DELETED
@@ -1,209 +0,0 @@
1
- # Advanced Fusion app testing
2
-
3
- The `/test` entry point extends Vitest's test context with `appEnv`, `configureApp`, `configureFusion`,
4
- `fusion`, `app`, `render`, and `renderHook`. Fixture declarations are reusable, while each test
5
- receives fresh framework and app module instances.
6
-
7
- This guide covers composing and overriding those Fusion fixture values; see Vitest's own
8
- [Test Context](https://vitest.dev/guide/test-context) documentation for fixture scope, cleanup,
9
- and the general `test.extend`/`test.override` mechanics Fusion builds on.
10
-
11
- ## Choose a rendering API
12
-
13
- | API | Use it when |
14
- | --- | --- |
15
- | `test` from `/test` | The app's manifest, config, and module configurator should resolve automatically |
16
- | `render` from `/test` | A standard `describe` or `it` block needs the automatically resolved app scope |
17
- | `renderAppHook` | A hook needs an app scope with explicitly supplied options |
18
- | `renderAppComponent` | A component needs explicit `env`, `configure`, or parent `fusion` options |
19
- | `testApp` | A reusable fixture should not depend on Vite's automatic app-file resolution |
20
-
21
- All Fusion rendering APIs initialize modules asynchronously and must be awaited. The lower
22
- level helpers return `fusion.framework` and `fusion.app`, allowing a test to drive the exact
23
- module instances consumed by the rendered subject.
24
-
25
- ## Extend app configuration
26
-
27
- Create one reusable extended test when several cases need the same deterministic modules.
28
- This must extend `test` from `/test`, not `testApp` from the main entry point:
29
- `testApp`'s `configureApp` defaults to `undefined` (no Vite dependency, so no way to load the
30
- real `src/config.ts` as live code), while `/test`'s `test` seeds it with the app's real
31
- `configure` export via `appTestVitePlugin`'s virtual modules.
32
-
33
- ```tsx
34
- import { enableContextMock } from '@equinor/fusion-framework-module-context/mock';
35
- import { test as baseTest } from '@equinor/fusion-framework-vitest-plugin-react-app/test';
36
-
37
- const project = {
38
- id: 'project-a',
39
- title: 'Project A',
40
- type: { id: 'ProjectMaster' },
41
- value: {},
42
- };
43
-
44
- export const test = baseTest.extend('configureApp', ({ configureApp }) => (configurator, args) => {
45
- configureApp?.(configurator, args);
46
- enableContextMock(configurator, (mock) => mock.setCurrentContext(project));
47
- });
48
- ```
49
-
50
- Composing the original `configureApp` fixture preserves the application's production module
51
- configuration. See [Module mocks](module-mocks.md) for authentication, context, bookmark,
52
- feature-flag, HTTP, analytics, and telemetry boundaries.
53
-
54
- `.extend(...)` returns a new, separately exported `test` — reach for it when several test
55
- *files* need the same fixture default. Within one file, prefer `test.override(...)` (below):
56
- it replaces a fixture in place, so every test in that file keeps importing the same `test`.
57
-
58
- ## Fake an endpoint URL with `mergeEnvConfig`
59
-
60
- `appEnv`'s `config` is an `AppConfig` instance — its `environment`/`endpoints` live behind
61
- private fields exposed only through getters, so `{ ...appEnv.config, endpoints: {...} }` copies
62
- nothing and silently drops the rest of the config. Use `mergeEnvConfig` to fake one endpoint's
63
- URL (e.g. the app's real backend, resolved from `app.config.ts`) while keeping every other
64
- endpoint and environment variable intact:
65
-
66
- ```tsx
67
- import { mergeEnvConfig, test as baseTest } from '@equinor/fusion-framework-vitest-plugin-react-app/test';
68
-
69
- export const test = baseTest.extend('appEnv', ({ appEnv }) =>
70
- mergeEnvConfig(appEnv, { endpoints: { 'cpr-api': { url: backendBaseUrl } } }),
71
- );
72
- ```
73
-
74
- ## Override a fixture for one test or a `describe` block
75
-
76
- `test.override('name', ...)` replaces a fixture's resolved value without creating a new `test`
77
- export. Called at the top of a `describe` block, the override applies to every test inside it
78
- and does not leak to sibling blocks or other files — each `describe` starts from the file's
79
- base `test` again. Called at the top of the file (outside any `describe`), it applies to every
80
- test in that file.
81
-
82
- **`configureApp`'s default value, from `/test`, *is* the app's real `src/config.ts` `configure`
83
- export.** `test.override('configureApp', ...)` replaces that default outright — an override
84
- that doesn't call the real `configure(configurator, args)` itself, as below, skips the app's
85
- production module setup entirely rather than composing with it.
86
-
87
- ```tsx
88
- import { test } from '@equinor/fusion-framework-vitest-plugin-react-app/test';
89
- import { enableContextMock } from '@equinor/fusion-framework-module-context/mock';
90
- import { describe } from 'vitest';
91
-
92
- import { configure } from '../config'; // the app's own, real module configurator
93
-
94
- const project = { id: 'project-a', title: 'Project A', type: { id: 'ProjectMaster' }, value: {} };
95
-
96
- describe('with an initial project', () => {
97
- test.override('configureApp', { injected: true }, () => (configurator, args) => {
98
- configure(configurator, args); // compose the app's real configure, same as `.extend`
99
- enableContextMock(configurator, (mock) => mock.setCurrentContext(project));
100
- });
101
-
102
- test('displays the initial context the app resolves on startup', async ({ render }) => {
103
- const { getByText } = await render(<App />);
104
- await expect.element(getByText(/project-a/)).toBeInTheDocument();
105
- });
106
- });
107
- ```
108
-
109
- `fusion` itself can be overridden the same way, when a case needs a differently configured
110
- parent framework instance rather than a change to the app's own `configureApp`:
111
-
112
- ```tsx
113
- describe('with a parent framework context', () => {
114
- test.override('fusion', async ({ appEnv }) =>
115
- mockFramework<[AppModule, ContextModule]>((configurator) => {
116
- enableAppManifestMock(configurator, appEnv);
117
- enableContextMock(configurator, (mock) => mock.setCurrentContext(project));
118
- }),
119
- );
120
-
121
- test('mirrors the context the parent sets', async ({ render, fusion }) => {
122
- /* ... */
123
- });
124
- });
125
- ```
126
-
127
- The `{ injected: true }` option matches the fixture's original declaration (see
128
- `test-app.tsx`/`test.tsx`); it is not required for `.override(...)` itself, but keeping it
129
- consistent avoids re-deriving whether the base fixture accepts a config-injected value. See
130
- the [React context cookbook](../../../../cookbooks/app-react-context/src/App.test.tsx) and
131
- [feature-flag cookbook](../../../../cookbooks/app-react-feature-flag/src/components/FeatureFlags.test.tsx)
132
- for full working examples, and Vitest's own
133
- [Test Context](https://vitest.dev/guide/test-context) guide for fixture scope and cleanup
134
- mechanics beyond what Fusion adds.
135
-
136
- ## Supply a custom parent framework
137
-
138
- Override or explicitly pass `fusion` when the scenario depends on portal-level context,
139
- service discovery, authentication, or app manifests. Build the parent with `mockFramework`,
140
- then initialize the app beneath it. This exercises parent-to-app propagation without a
141
- running portal.
142
-
143
- Use [`enableAppManifestMock`](../../../app/docs/testing.md#enableappmanifestmockconfigurator-env)
144
- when the custom parent must serve the app's manifest and config. Use
145
- [`mockFramework`](../../../framework/docs/testing.md) to seed the parent modules.
146
-
147
- ## Extend the parent framework mock with `configureFusion`
148
-
149
- `fusion` (built by [`resolveFusion`](../src/scope/resolve-fusion.ts)) always carries a mocked
150
- `app` module (serving this app's manifest) and a `navigation` module with in-memory history, so
151
- tests don't leak URL/history state between runs. It also mocks the `featureFlag` module — with
152
- no flags enabled, so `useFeature` needs no `localStorage` or URL seeding — but only when
153
- `@equinor/fusion-framework-module-feature-flag` (an optional peer dependency) is actually
154
- installed; apps that don't use feature flags aren't forced to add it. `configureFusion` runs on
155
- the same configurator afterwards, so a test can register extra framework-level modules or
156
- override that setup, without reimplementing it:
157
-
158
- ```tsx
159
- import { enableFeatureFlagMock } from '@equinor/fusion-framework-module-feature-flag/mock';
160
-
161
- const test = baseTest.extend('configureFusion', { injected: true }, () => (configurator) => {
162
- // seed a specific flag rather than merely enabling the mock — that's already the default
163
- enableFeatureFlagMock(configurator, (mock) => mock.addFeature({ key: 'new-search', enabled: true }));
164
- configurator.serviceDiscovery.addServices([{ key: 'people', uri: baseUrl('people') }]);
165
- });
166
- ```
167
-
168
- Note this is a **framework-scope** module set, distinct from the app-scope one `configureApp`
169
- seeds. A typical app registers its own `navigation` module independently, inside its own
170
- `config.ts`'s `configure` callback (what `configureApp` composes with) — so overriding history
171
- through `configureFusion` only affects framework-scope consumers, such as
172
- `useFramework<[NavigationModule]>().modules.navigation` or `useBookmarkNavigate`, not a
173
- rendered app's own router:
174
-
175
- ```tsx
176
- import { enableNavigation, createHistory } from '@equinor/fusion-framework-module-navigation';
177
-
178
- test.override('configureFusion', { injected: true }, () => (configurator) =>
179
- enableNavigation(configurator, {
180
- configure: (config) => config.setHistory(createHistory('browser')),
181
- }),
182
- );
183
- ```
184
-
185
- **`.override('fusion', ...)` bypasses `configureFusion` entirely** — it replaces the resolver
186
- that calls it, so a `configureFusion` override on the same test/suite is silently never called.
187
- Reach for `configureFusion` to extend the base mock; reach for `fusion` only to replace it
188
- outright (e.g. with a fully custom or non-mocked instance) — see
189
- [Supply a custom parent framework](#supply-a-custom-parent-framework) above.
190
-
191
- ## Test routes and app lifecycle
192
-
193
- Render the complete `App` when assertions depend on route loaders, navigation, app
194
- configuration, or several modules working together. Set the initial browser URL before
195
- rendering, interact through visible controls or `app.navigation`, and assert the rendered
196
- result.
197
-
198
- The [React router cookbook](../../../../cookbooks/app-react-router/README.md) demonstrates
199
- route-unit tests, complete application navigation, and HTTP-backed loaders.
200
-
201
- ## Runner-level advanced behavior
202
-
203
- Fusion does not wrap these Vitest capabilities:
204
-
205
- - [Browser interactions and assertions](https://vitest.dev/guide/browser/)
206
- - [Asynchronous tests](https://vitest.dev/guide/learn/async)
207
- - [Test projects](https://vitest.dev/guide/projects)
208
- - [Coverage](https://vitest.dev/guide/coverage)
209
- - [Debugging](https://vitest.dev/guide/debugging)