@equinor/fusion-framework-app 13.0.0 → 14.0.0-next.0
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.
- package/CHANGELOG.md +76 -0
- package/README.md +35 -65
- package/dist/esm/__tests__/mock/AppMockConfigurator.test.js +70 -0
- package/dist/esm/__tests__/mock/AppMockConfigurator.test.js.map +1 -0
- package/dist/esm/__tests__/mock/mock-app.test.js +86 -0
- package/dist/esm/__tests__/mock/mock-app.test.js.map +1 -0
- package/dist/esm/__tests__/mock/msal-hoisting.test.js +36 -0
- package/dist/esm/__tests__/mock/msal-hoisting.test.js.map +1 -0
- package/dist/esm/configure-modules.js +2 -42
- package/dist/esm/configure-modules.js.map +1 -1
- package/dist/esm/initialize-app-modules.js +65 -0
- package/dist/esm/initialize-app-modules.js.map +1 -0
- package/dist/esm/mock/AppMockConfigurator.js +183 -0
- package/dist/esm/mock/AppMockConfigurator.js.map +1 -0
- package/dist/esm/mock/enable-app-manifest-mock.js +49 -0
- package/dist/esm/mock/enable-app-manifest-mock.js.map +1 -0
- package/dist/esm/mock/index.js +21 -0
- package/dist/esm/mock/index.js.map +1 -0
- package/dist/esm/mock/mock-app-modules.js +82 -0
- package/dist/esm/mock/mock-app-modules.js.map +1 -0
- package/dist/esm/version.js +1 -1
- package/dist/esm/version.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/__tests__/mock/AppMockConfigurator.test.d.ts +1 -0
- package/dist/types/__tests__/mock/mock-app.test.d.ts +1 -0
- package/dist/types/__tests__/mock/msal-hoisting.test.d.ts +1 -0
- package/dist/types/initialize-app-modules.d.ts +31 -0
- package/dist/types/mock/AppMockConfigurator.d.ts +142 -0
- package/dist/types/mock/enable-app-manifest-mock.d.ts +33 -0
- package/dist/types/mock/index.d.ts +20 -0
- package/dist/types/mock/mock-app-modules.d.ts +72 -0
- package/dist/types/version.d.ts +1 -1
- package/docs/bookmarks.md +18 -0
- package/docs/http-clients.md +71 -0
- package/docs/testing.md +105 -0
- package/package.json +22 -13
- package/src/__tests__/mock/AppMockConfigurator.test.ts +96 -0
- package/src/__tests__/mock/mock-app.test.ts +112 -0
- package/src/__tests__/mock/msal-hoisting.test.ts +54 -0
- package/src/configure-modules.ts +2 -52
- package/src/initialize-app-modules.ts +98 -0
- package/src/mock/AppMockConfigurator.ts +218 -0
- package/src/mock/enable-app-manifest-mock.ts +62 -0
- package/src/mock/index.ts +21 -0
- package/src/mock/mock-app-modules.ts +109 -0
- package/src/version.ts +1 -1
- package/vitest.config.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,81 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 14.0.0-next.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 2836e0b: `enableAppManifestMock` accepts an optional third `assetUri` argument, overriding the base URI a loaded app's script is imported from — useful for tests that dynamically import a real fixture script. `env.config` is now optional; when omitted, a trivial `AppConfig` is used so `App.initialize()` can still resolve.
|
|
8
|
+
- 2836e0b: Add a `./mock` entry point: `mockAppModules` runs an application's real module pipeline — the real `event`/`http`/`msal` modules, the real `AppConfigurator` configuration pipeline and real lifecycle — against a mocked parent Fusion instance, so a test exercises the wiring an application actually depends on instead of a reimplementation of it.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { mockAppModules } from "@equinor/fusion-framework-app/mock";
|
|
12
|
+
|
|
13
|
+
const manifest = {
|
|
14
|
+
appKey: "my-app",
|
|
15
|
+
displayName: "My App",
|
|
16
|
+
description: "My app",
|
|
17
|
+
type: "standalone",
|
|
18
|
+
} as const;
|
|
19
|
+
const modules = await mockAppModules(undefined, { manifest });
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`enableAppManifestMock` registers the `app` module on a parent `mockFramework` configurator, serving an app's own manifest and config while delegating every other request to whatever service discovery (or a pre-configured http client) would really resolve. `mockAppModules` uses it to build its zero-configuration default parent; call it directly when a test needs to customize `serviceDiscovery` first.
|
|
23
|
+
|
|
24
|
+
Restructured `README.md` into an entry point pointing at `docs/http-clients.md`, `docs/bookmarks.md` and `docs/testing.md`, matching the convention already used by `@equinor/fusion-framework-module-http` and `@equinor/fusion-framework-module-msal`.
|
|
25
|
+
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- e8aae1f: Internal: publish every package on the `next` pre-release tag so the whole framework can be installed as a coherent set.
|
|
29
|
+
|
|
30
|
+
Packages without their own changes are bumped only to receive a `-next.N` version and the `next` dist-tag on npm. Install with:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pnpm add @equinor/fusion-framework-react-app@next
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
- Updated dependencies [e8aae1f]
|
|
37
|
+
- Updated dependencies [2836e0b]
|
|
38
|
+
- Updated dependencies [2836e0b]
|
|
39
|
+
- Updated dependencies [2836e0b]
|
|
40
|
+
- Updated dependencies [2836e0b]
|
|
41
|
+
- Updated dependencies [2836e0b]
|
|
42
|
+
- Updated dependencies [2836e0b]
|
|
43
|
+
- Updated dependencies [2836e0b]
|
|
44
|
+
- Updated dependencies [2836e0b]
|
|
45
|
+
- Updated dependencies [2836e0b]
|
|
46
|
+
- Updated dependencies [2836e0b]
|
|
47
|
+
- Updated dependencies [2836e0b]
|
|
48
|
+
- Updated dependencies [2836e0b]
|
|
49
|
+
- Updated dependencies [2836e0b]
|
|
50
|
+
- Updated dependencies [2836e0b]
|
|
51
|
+
- Updated dependencies [2836e0b]
|
|
52
|
+
- Updated dependencies [2836e0b]
|
|
53
|
+
- Updated dependencies [2836e0b]
|
|
54
|
+
- Updated dependencies [2836e0b]
|
|
55
|
+
- Updated dependencies [2836e0b]
|
|
56
|
+
- Updated dependencies [2836e0b]
|
|
57
|
+
- Updated dependencies [2836e0b]
|
|
58
|
+
- Updated dependencies [2836e0b]
|
|
59
|
+
- Updated dependencies [2836e0b]
|
|
60
|
+
- Updated dependencies [2836e0b]
|
|
61
|
+
- Updated dependencies [2836e0b]
|
|
62
|
+
- Updated dependencies [2836e0b]
|
|
63
|
+
- @equinor/fusion-framework@8.1.0-next.0
|
|
64
|
+
- @equinor/fusion-framework-module@6.1.3-next.0
|
|
65
|
+
- @equinor/fusion-framework-module-app@8.1.0-next.0
|
|
66
|
+
- @equinor/fusion-framework-module-bookmark@4.1.0-next.0
|
|
67
|
+
- @equinor/fusion-framework-module-event@6.1.0-next.0
|
|
68
|
+
- @equinor/fusion-framework-module-http@8.1.0-next.0
|
|
69
|
+
- @equinor/fusion-framework-module-msal@11.0.0-next.0
|
|
70
|
+
- @equinor/fusion-framework-module-state@2.0.1-next.0
|
|
71
|
+
- @equinor/fusion-framework-module-telemetry@8.0.0-next.0
|
|
72
|
+
|
|
73
|
+
## 13.0.1
|
|
74
|
+
|
|
75
|
+
### Patch Changes
|
|
76
|
+
|
|
77
|
+
- @equinor/fusion-framework@8.0.15
|
|
78
|
+
|
|
3
79
|
## 13.0.0
|
|
4
80
|
|
|
5
81
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -20,6 +20,14 @@ single `configureModules` call.
|
|
|
20
20
|
> **Most Fusion apps should use `@equinor/fusion-framework-react-app` instead.**
|
|
21
21
|
> This lower-level package is for framework-agnostic or advanced scenarios.
|
|
22
22
|
|
|
23
|
+
## Documentation
|
|
24
|
+
|
|
25
|
+
| Topic | Description |
|
|
26
|
+
|---|---|
|
|
27
|
+
| [Configure HTTP Clients](docs/http-clients.md) | Named clients from app config, service discovery, and explicit registration, plus resolution priority |
|
|
28
|
+
| [Enable Bookmarks](docs/bookmarks.md) | Registering the bookmark module via `enableBookmark` |
|
|
29
|
+
| [Testing](docs/testing.md) | The `/mock` entry point: `mockAppModules`, `AppMockConfigurator`, and `enableAppManifestMock` |
|
|
30
|
+
|
|
23
31
|
## Installation
|
|
24
32
|
|
|
25
33
|
```sh
|
|
@@ -80,6 +88,7 @@ const modules = await initialize({ fusion, env });
|
|
|
80
88
|
| `AppModuleInitiator` | Callback signature accepted by `configureModules` for user-supplied setup. |
|
|
81
89
|
| `AppEnv` | Environment descriptor containing the app manifest, config, and optional basename. |
|
|
82
90
|
| `enableBookmark` | Helper to enable the bookmark module (import from `@equinor/fusion-framework-app/enable-bookmark`). |
|
|
91
|
+
| `mockAppModules` | Runs the real module pipeline against deterministic fakes for tests (import from `@equinor/fusion-framework-app/mock`). |
|
|
83
92
|
|
|
84
93
|
## API Surface
|
|
85
94
|
|
|
@@ -100,40 +109,13 @@ giving you access to:
|
|
|
100
109
|
|---|---|
|
|
101
110
|
| `@equinor/fusion-framework-app` | `configureModules`, `AppConfigurator`, `IAppConfigurator`, all type aliases |
|
|
102
111
|
| `@equinor/fusion-framework-app/enable-bookmark` | `enableBookmark` function |
|
|
112
|
+
| `@equinor/fusion-framework-app/mock` | `mockAppModules`, `AppMockConfigurator`, `enableAppManifestMock` |
|
|
103
113
|
|
|
104
114
|
## Configure HTTP Clients
|
|
105
115
|
|
|
106
|
-
The `AppConfigurator` can register named HTTP clients from several sources
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
### From Application Config (auto-registration)
|
|
110
|
-
|
|
111
|
-
Endpoints defined in `app.config.<env>.ts` are **automatically registered as
|
|
112
|
-
named HTTP clients** when the `AppConfigurator` is created — no extra code
|
|
113
|
-
needed in `config.ts`.
|
|
114
|
-
|
|
115
|
-
```ts
|
|
116
|
-
// app.config.ts
|
|
117
|
-
import { defineAppConfig } from '@equinor/fusion-framework-cli/app';
|
|
118
|
-
|
|
119
|
-
export default defineAppConfig(() => ({
|
|
120
|
-
endpoints: {
|
|
121
|
-
schedule: {
|
|
122
|
-
url: 'https://schedule-api.example.com',
|
|
123
|
-
scopes: ['api://schedule-id/.default'],
|
|
124
|
-
},
|
|
125
|
-
},
|
|
126
|
-
}));
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
After initialization, use the client directly:
|
|
130
|
-
|
|
131
|
-
```ts
|
|
132
|
-
const client = framework.modules.http.createClient('schedule');
|
|
133
|
-
const data = await client.json('/items');
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### Via Service Discovery
|
|
116
|
+
The `AppConfigurator` can register named HTTP clients from several sources —
|
|
117
|
+
application config endpoints, service discovery, or explicit registration —
|
|
118
|
+
and you retrieve one at runtime with `framework.modules.http.createClient(name)`.
|
|
137
119
|
|
|
138
120
|
```ts
|
|
139
121
|
const initialize = configureModules((configurator) => {
|
|
@@ -141,37 +123,9 @@ const initialize = configureModules((configurator) => {
|
|
|
141
123
|
});
|
|
142
124
|
```
|
|
143
125
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
`app.config.ts`, or when you need custom transport behavior such as headers,
|
|
148
|
-
response guards, or a custom client class.
|
|
149
|
-
|
|
150
|
-
```ts
|
|
151
|
-
configurator.configureHttpClient('custom-api', {
|
|
152
|
-
baseUri: 'https://custom.api.example.com',
|
|
153
|
-
defaultScopes: ['api://custom-id/.default'],
|
|
154
|
-
onCreate: (client) => {
|
|
155
|
-
client.requestHandler.setHeader('X-Source', 'portal');
|
|
156
|
-
},
|
|
157
|
-
});
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
### Resolution Priority
|
|
161
|
-
|
|
162
|
-
When the same client name is configured in more than one place, the
|
|
163
|
-
highest-priority source wins:
|
|
164
|
-
|
|
165
|
-
| Priority | Source | Example |
|
|
166
|
-
|----------|--------|---------|
|
|
167
|
-
| 1 (highest) | **Session overrides** | User-specific URL / scopes set at runtime via `sessionStorage` |
|
|
168
|
-
| 2 | **Application config endpoints** | `endpoints` in `app.config.ts` |
|
|
169
|
-
| 3 | **Service-discovery registry** | Resolved via `useFrameworkServiceClient` |
|
|
170
|
-
| 4 (lowest) | **Explicit registration** | `configureHttpClient(name, options)` in `config.ts` |
|
|
171
|
-
|
|
172
|
-
This means an endpoint defined in `app.config.ts` will override a
|
|
173
|
-
`configureHttpClient` call for the same name, and a session override will
|
|
174
|
-
override both.
|
|
126
|
+
See [Configure HTTP Clients](docs/http-clients.md) for auto-registration from
|
|
127
|
+
`app.config.ts`, explicit registration, and resolution priority when a client
|
|
128
|
+
is configured in more than one place.
|
|
175
129
|
|
|
176
130
|
## Enable Bookmarks
|
|
177
131
|
|
|
@@ -181,7 +135,6 @@ The bookmark module allows applications to save and restore application state.
|
|
|
181
135
|
> `@equinor/fusion-framework-module-bookmark` directly.
|
|
182
136
|
|
|
183
137
|
```ts
|
|
184
|
-
import { configureModules } from '@equinor/fusion-framework-app';
|
|
185
138
|
import { enableBookmark } from '@equinor/fusion-framework-app/enable-bookmark';
|
|
186
139
|
|
|
187
140
|
const initialize = configureModules((configurator) => {
|
|
@@ -189,8 +142,25 @@ const initialize = configureModules((configurator) => {
|
|
|
189
142
|
});
|
|
190
143
|
```
|
|
191
144
|
|
|
192
|
-
|
|
193
|
-
|
|
145
|
+
See [Enable Bookmarks](docs/bookmarks.md) for payload generator cleanup behavior.
|
|
146
|
+
|
|
147
|
+
## Testing
|
|
148
|
+
|
|
149
|
+
Import from `@equinor/fusion-framework-app/mock` to run an application's real
|
|
150
|
+
module pipeline in tests — the real `event`/`http`/`msal` modules, the real
|
|
151
|
+
`AppConfigurator` configuration pipeline, and real lifecycle — while only the
|
|
152
|
+
boundaries that reach outside the process are substituted with deterministic
|
|
153
|
+
fakes. This entry point has no dependency on Vitest or any other test runner.
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
import { mockAppModules } from '@equinor/fusion-framework-app/mock';
|
|
157
|
+
|
|
158
|
+
const manifest = { appKey: 'my-app', displayName: 'My App', description: 'My app', type: 'standalone' } as const;
|
|
159
|
+
const modules = await mockAppModules(undefined, { manifest });
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
See [Testing](docs/testing.md) for `AppMockConfigurator`, `enableAppManifestMock`,
|
|
163
|
+
and customizing the mocked parent's service discovery.
|
|
194
164
|
|
|
195
165
|
## Types
|
|
196
166
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { AppConfig } from '@equinor/fusion-framework-module-app';
|
|
3
|
+
import { enableTelemetry } from '@equinor/fusion-framework-module-telemetry';
|
|
4
|
+
import { AppConfigurator } from '../../AppConfigurator.js';
|
|
5
|
+
import { AppMockConfigurator } from '../../mock/AppMockConfigurator.js';
|
|
6
|
+
const mockEnv = {
|
|
7
|
+
manifest: {
|
|
8
|
+
appKey: 'test-app',
|
|
9
|
+
displayName: 'Test App',
|
|
10
|
+
description: 'A test application',
|
|
11
|
+
type: 'standalone',
|
|
12
|
+
build: {
|
|
13
|
+
version: '1.0.0',
|
|
14
|
+
entryPoint: 'index.js',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
describe('AppMockConfigurator', () => {
|
|
19
|
+
it('is a real AppConfigurator', () => {
|
|
20
|
+
const configurator = new AppMockConfigurator(mockEnv);
|
|
21
|
+
expect(configurator).toBeInstanceOf(AppMockConfigurator);
|
|
22
|
+
expect(configurator).toBeInstanceOf(AppConfigurator);
|
|
23
|
+
});
|
|
24
|
+
it('constructs without throwing when env.config declares endpoints', async () => {
|
|
25
|
+
// the base AppConfigurator constructor auto-registers these via addConfig,
|
|
26
|
+
// before this class's own fields (#pinnedModules) are initialized
|
|
27
|
+
const env = {
|
|
28
|
+
...mockEnv,
|
|
29
|
+
config: new AppConfig({
|
|
30
|
+
endpoints: { status: { url: 'https://status.example.com', scopes: [] } },
|
|
31
|
+
}),
|
|
32
|
+
};
|
|
33
|
+
const configurator = new AppMockConfigurator(env);
|
|
34
|
+
configurator.http.addMiddleware(async (uri, init, next) => uri === 'https://status.example.com/health' ? Response.json({ ok: true }) : next(uri, init));
|
|
35
|
+
enableTelemetry(configurator);
|
|
36
|
+
const modules = await configurator.initialize();
|
|
37
|
+
await expect(modules.http.createClient('status').json('/health')).resolves.toEqual({
|
|
38
|
+
ok: true,
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
it('exposes the same http configurator the http module is built from', async () => {
|
|
42
|
+
const configurator = new AppMockConfigurator(mockEnv);
|
|
43
|
+
configurator.http.configureClient('catalog', { baseUri: 'https://api.example.com' });
|
|
44
|
+
configurator.http.addMiddleware(async (uri, init, next) => uri === 'https://api.example.com/items' ? Response.json([{ id: 1 }]) : next(uri, init));
|
|
45
|
+
// msal's config schema requires a telemetry module, normally wired by configureModules
|
|
46
|
+
enableTelemetry(configurator);
|
|
47
|
+
const modules = await configurator.initialize();
|
|
48
|
+
await expect(modules.http.createClient('catalog').json('/items')).resolves.toEqual([{ id: 1 }]);
|
|
49
|
+
});
|
|
50
|
+
it('exposes the same msal configurator the auth module is built from', async () => {
|
|
51
|
+
const configurator = new AppMockConfigurator(mockEnv);
|
|
52
|
+
configurator.msal.setAccount({ name: 'Ada Lovelace' });
|
|
53
|
+
// msal's config schema requires a telemetry module, normally wired by configureModules
|
|
54
|
+
enableTelemetry(configurator);
|
|
55
|
+
const modules = await configurator.initialize();
|
|
56
|
+
expect(modules.auth.account?.name).toBe('Ada Lovelace');
|
|
57
|
+
});
|
|
58
|
+
it('answers a client registered through configureHttpClient via addMiddleware', async () => {
|
|
59
|
+
const configurator = new AppMockConfigurator(mockEnv);
|
|
60
|
+
configurator.configureHttpClient('status-api', { baseUri: 'https://status.example.com' });
|
|
61
|
+
configurator.http.addMiddleware(async (uri, init, next) => uri === 'https://status.example.com/status' ? Response.json({ ok: true }) : next(uri, init));
|
|
62
|
+
// msal's config schema requires a telemetry module, normally wired by configureModules
|
|
63
|
+
enableTelemetry(configurator);
|
|
64
|
+
const modules = await configurator.initialize();
|
|
65
|
+
await expect(modules.http.createClient('status-api').json('/status')).resolves.toEqual({
|
|
66
|
+
ok: true,
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
//# sourceMappingURL=AppMockConfigurator.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppMockConfigurator.test.js","sourceRoot":"","sources":["../../../../src/__tests__/mock/AppMockConfigurator.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { mockFramework } from '@equinor/fusion-framework/mock';
|
|
3
|
+
import { AppConfig } from '@equinor/fusion-framework-module-app';
|
|
4
|
+
import { AppMockConfigurator } from '../../mock/AppMockConfigurator.js';
|
|
5
|
+
import { mockAppModules } from '../../mock/mock-app-modules.js';
|
|
6
|
+
const env = {
|
|
7
|
+
manifest: {
|
|
8
|
+
appKey: 'test-app',
|
|
9
|
+
displayName: 'Test App',
|
|
10
|
+
description: 'A test application',
|
|
11
|
+
type: 'standalone',
|
|
12
|
+
build: {
|
|
13
|
+
version: '1.0.0',
|
|
14
|
+
entryPoint: 'index.js',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
config: new AppConfig({ environment: { foo: 'bar' } }),
|
|
18
|
+
};
|
|
19
|
+
describe('mockApp', () => {
|
|
20
|
+
it('initializes the app module pipeline with no configuration', async () => {
|
|
21
|
+
const modules = await mockAppModules(undefined, env);
|
|
22
|
+
expect(modules.event).toBeDefined();
|
|
23
|
+
expect(modules.auth).toBeDefined();
|
|
24
|
+
expect(modules.http).toBeDefined();
|
|
25
|
+
});
|
|
26
|
+
it('passes a real AppConfigurator to the callback', async () => {
|
|
27
|
+
expect.assertions(1);
|
|
28
|
+
await mockAppModules((configurator) => {
|
|
29
|
+
expect(configurator).toBeInstanceOf(AppMockConfigurator);
|
|
30
|
+
}, env);
|
|
31
|
+
});
|
|
32
|
+
it('answers a service-discovery-resolved client from the app’s own mocked http module', async () => {
|
|
33
|
+
const modules = await mockAppModules((configurator) => {
|
|
34
|
+
configurator.useFrameworkServiceClient('portal-api');
|
|
35
|
+
// matches against the full resolved URL, so the host is part of the match to keep this
|
|
36
|
+
// from also answering a different client's request
|
|
37
|
+
configurator.http.addMiddleware(async (uri, init, next) => uri === 'https://portal-api.fusion.test/items'
|
|
38
|
+
? Response.json([{ id: 1 }])
|
|
39
|
+
: next(uri, init));
|
|
40
|
+
}, env);
|
|
41
|
+
await expect(modules.http.createClient('portal-api').json('/items')).resolves.toEqual([
|
|
42
|
+
{ id: 1 },
|
|
43
|
+
]);
|
|
44
|
+
});
|
|
45
|
+
it('reuses an already-mocked fusion instance instead of creating a new one', async () => {
|
|
46
|
+
expect.assertions(1);
|
|
47
|
+
const fusion = await mockFramework((configurator) => {
|
|
48
|
+
configurator.msal.setAccount({ name: 'Ada Lovelace' });
|
|
49
|
+
});
|
|
50
|
+
await mockAppModules((_configurator, { fusion: parent }) => {
|
|
51
|
+
expect(parent.modules.auth.account?.name).toBe('Ada Lovelace');
|
|
52
|
+
}, env, fusion);
|
|
53
|
+
});
|
|
54
|
+
it('awaits an async configure callback before initialize resolves', async () => {
|
|
55
|
+
const modules = await mockAppModules(async (configurator) => {
|
|
56
|
+
await Promise.resolve();
|
|
57
|
+
configurator.msal.setAccount({ name: 'Ada Lovelace' });
|
|
58
|
+
}, env);
|
|
59
|
+
expect(modules.auth.account?.name).toBe('Ada Lovelace');
|
|
60
|
+
});
|
|
61
|
+
it('serves this app’s own manifest and config through the default parent’s app module', async () => {
|
|
62
|
+
expect.assertions(2);
|
|
63
|
+
await mockAppModules(async (_configurator, { fusion }) => {
|
|
64
|
+
// the default parent always has `app` enabled; typed as plain `Fusion` since callers
|
|
65
|
+
// may pass in a parent without it, so the module set is narrowed just for this assertion
|
|
66
|
+
const { app } = fusion.modules;
|
|
67
|
+
app.setCurrentApp(env.manifest.appKey);
|
|
68
|
+
await expect(app.current?.getManifestAsync()).resolves.toMatchObject({
|
|
69
|
+
appKey: env.manifest.appKey,
|
|
70
|
+
displayName: env.manifest.displayName,
|
|
71
|
+
});
|
|
72
|
+
await expect(app.current?.getConfigAsync()).resolves.toMatchObject({
|
|
73
|
+
environment: env.config.environment,
|
|
74
|
+
});
|
|
75
|
+
}, env);
|
|
76
|
+
});
|
|
77
|
+
it('falls through to the real client for a manifest not matching this app’s own', async () => {
|
|
78
|
+
expect.assertions(1);
|
|
79
|
+
await mockAppModules(async (_configurator, { fusion }) => {
|
|
80
|
+
const { app } = fusion.modules;
|
|
81
|
+
app.setCurrentApp('some-other-app');
|
|
82
|
+
await expect(app.current?.getManifestAsync()).rejects.toThrow();
|
|
83
|
+
}, env);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
//# sourceMappingURL=mock-app.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-app.test.js","sourceRoot":"","sources":["../../../../src/__tests__/mock/mock-app.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { mockFramework } from '@equinor/fusion-framework/mock';
|
|
3
|
+
import { mockAppModules } from '../../mock/mock-app-modules.js';
|
|
4
|
+
const env = {
|
|
5
|
+
manifest: {
|
|
6
|
+
appKey: 'test-app',
|
|
7
|
+
displayName: 'Test App',
|
|
8
|
+
description: 'A test application',
|
|
9
|
+
type: 'standalone',
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
describe('msal hoisting', () => {
|
|
13
|
+
it('delegates acquireToken to the parent’s auth module instead of building its own client', async () => {
|
|
14
|
+
const fusion = await mockFramework();
|
|
15
|
+
const result = { accessToken: 'parent-issued-token' };
|
|
16
|
+
vi.spyOn(fusion.modules.auth, 'acquireToken').mockResolvedValue(result);
|
|
17
|
+
const modules = await mockAppModules(undefined, env, fusion);
|
|
18
|
+
// the app's own `auth` is a distinct (proxying) object, not the parent's instance itself
|
|
19
|
+
expect(modules.auth).not.toBe(fusion.modules.auth);
|
|
20
|
+
await expect(modules.auth.acquireToken({ request: { scopes: ['User.Read'] } })).resolves.toMatchObject({ accessToken: 'parent-issued-token' });
|
|
21
|
+
});
|
|
22
|
+
it('surfaces the parent’s acquisition failures instead of falling back to its own client', async () => {
|
|
23
|
+
const fusion = await mockFramework();
|
|
24
|
+
vi.spyOn(fusion.modules.auth, 'acquireToken').mockRejectedValue(new Error('acquisition failed'));
|
|
25
|
+
const modules = await mockAppModules(undefined, env, fusion);
|
|
26
|
+
await expect(modules.auth.acquireToken({ request: { scopes: ['User.Read'] } })).rejects.toThrow('acquisition failed');
|
|
27
|
+
});
|
|
28
|
+
it('reflects the parent’s signed-in account rather than signing in its own', async () => {
|
|
29
|
+
const fusion = await mockFramework((configurator) => {
|
|
30
|
+
configurator.msal.setAccount({ name: 'Ada Lovelace' });
|
|
31
|
+
});
|
|
32
|
+
const modules = await mockAppModules(undefined, env, fusion);
|
|
33
|
+
expect(modules.auth.account?.name).toBe('Ada Lovelace');
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
//# sourceMappingURL=msal-hoisting.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"msal-hoisting.test.js","sourceRoot":"","sources":["../../../../src/__tests__/mock/msal-hoisting.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAG/D,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,MAAM,GAAG,GAAG;IACV,QAAQ,EAAE;QACR,MAAM,EAAE,UAAU;QAClB,WAAW,EAAE,UAAU;QACvB,WAAW,EAAE,oBAAoB;QACjC,IAAI,EAAE,YAAqB;KAC5B;CACF,CAAC;AAEF,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,uFAAuF,EAAE,KAAK,IAAI,EAAE;QACrG,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,EAAE,WAAW,EAAE,qBAAqB,EAA0B,CAAC;QAC9E,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAExE,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,SAAS,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAE7D,yFAAyF;QACzF,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACnD,MAAM,MAAM,CACV,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,CAClE,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,qBAAqB,EAAE,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sFAAsF,EAAE,KAAK,IAAI,EAAE;QACpG,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,CAAC;QACrC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,iBAAiB,CAC7D,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAChC,CAAC;QAEF,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,SAAS,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAE7D,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAC7F,oBAAoB,CACrB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;QACtF,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,CAAC,YAAY,EAAE,EAAE;YAClD,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,SAAS,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAE7D,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Provides the core factory function for configuring and initializing
|
|
5
5
|
* application-specific modules in the Fusion framework.
|
|
6
6
|
*/
|
|
7
|
-
import { enableTelemetry, } from '@equinor/fusion-framework-module-telemetry';
|
|
8
7
|
import { AppConfigurator } from './AppConfigurator';
|
|
8
|
+
import { initializeAppModules } from './initialize-app-modules';
|
|
9
9
|
/**
|
|
10
10
|
* Create an application module initializer for a Fusion application.
|
|
11
11
|
*
|
|
@@ -49,49 +49,9 @@ export const configureModules = (cb) =>
|
|
|
49
49
|
* @returns The fully initialized application module instance.
|
|
50
50
|
*/
|
|
51
51
|
async (args) => {
|
|
52
|
-
const { fusion } = args;
|
|
53
52
|
// Create app configurator
|
|
54
53
|
const configurator = new AppConfigurator(args.env);
|
|
55
|
-
|
|
56
|
-
const metadataExtractor = () => {
|
|
57
|
-
return {
|
|
58
|
-
fusion: {
|
|
59
|
-
type: 'app-telemetry',
|
|
60
|
-
app: {
|
|
61
|
-
key: args.env.manifest?.appKey || 'unknown-app',
|
|
62
|
-
version: args.env.manifest?.build?.version || 'unknown-version',
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
};
|
|
67
|
-
// Enable telemetry collection for module configuration events
|
|
68
|
-
// attachConfiguratorEvents automatically prefixes events with configurator class name
|
|
69
|
-
enableTelemetry(configurator, {
|
|
70
|
-
attachConfiguratorEvents: true,
|
|
71
|
-
configure: (builder) => {
|
|
72
|
-
builder.setMetadata(metadataExtractor);
|
|
73
|
-
builder.setParent(fusion.modules.telemetry);
|
|
74
|
-
// Scope telemetry to 'app' level for app-specific event filtering
|
|
75
|
-
builder.setDefaultScope(['app']);
|
|
76
|
-
},
|
|
77
|
-
});
|
|
78
|
-
// Allow user configuration callback to run before module initialization
|
|
79
|
-
if (cb) {
|
|
80
|
-
await Promise.resolve(cb(configurator, args));
|
|
81
|
-
}
|
|
82
|
-
// Type cast is safe because AppConfigurator.initialize() returns the exact module
|
|
83
|
-
// instance that was registered and configured above. The intermediate 'unknown'
|
|
84
|
-
// cast is necessary due to TypeScript's generic inference limitations with the
|
|
85
|
-
// configurator's initialization chain, but the runtime value is guaranteed to match.
|
|
86
|
-
const modules = (await configurator.initialize(args.fusion.modules));
|
|
87
|
-
// Dispatch app modules loaded event for app lifecycle tracking
|
|
88
|
-
// TODO(#5061): remove check after fusion-cli is updated (app module is not enabled in fusion-cli)
|
|
89
|
-
if (args.env.manifest?.appKey) {
|
|
90
|
-
modules.event.dispatchEvent('onAppModulesLoaded', {
|
|
91
|
-
detail: { appKey: args.env.manifest.appKey, manifest: args.env.manifest, modules },
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
return modules;
|
|
54
|
+
return initializeAppModules(configurator, cb, args);
|
|
95
55
|
};
|
|
96
56
|
export default configureModules;
|
|
97
57
|
//# sourceMappingURL=configure-modules.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configure-modules.js","sourceRoot":"","sources":["../../src/configure-modules.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"configure-modules.js","sourceRoot":"","sources":["../../src/configure-modules.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAC3B,CAKE,EAA6C,EACmC,EAAE;AACpF;;;;;;;GAOG;AACH,KAAK,EAAE,IAAiC,EAAyC,EAAE;IACjF,0BAA0B;IAC1B,MAAM,YAAY,GAAG,IAAI,eAAe,CAAkC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpF,OAAO,oBAAoB,CAAC,YAAY,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;AACtD,CAAC,CAAC;AAEJ,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { enableTelemetry, } from '@equinor/fusion-framework-module-telemetry';
|
|
2
|
+
/**
|
|
3
|
+
* Runs the telemetry wiring, the caller's configuration callback and module
|
|
4
|
+
* initialization against an already constructed configurator.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Extracted so `mockAppModules` (`@equinor/fusion-framework-app/mock`) can drive the
|
|
8
|
+
* exact same pipeline against an `AppMockConfigurator` instead of reimplementing
|
|
9
|
+
* it — the same way `FrameworkConfigurator` and `FrameworkMockConfigurator`
|
|
10
|
+
* share the framework's `init`.
|
|
11
|
+
*
|
|
12
|
+
* @param configurator - The (real or mock) app configurator to run the pipeline on.
|
|
13
|
+
* @param cb - Configuration callback invoked before module initialization, or `undefined` to skip it.
|
|
14
|
+
* @param args - Object containing the Fusion instance and the application environment.
|
|
15
|
+
* @returns The fully initialized application module instance.
|
|
16
|
+
* @template TModules - Application module descriptors beyond the default set.
|
|
17
|
+
* @template TRef - The parent Fusion instance type.
|
|
18
|
+
* @template TEnv - The application environment descriptor.
|
|
19
|
+
* @template TConfigurator - The (real or mock) `AppConfigurator` subclass driving the pipeline.
|
|
20
|
+
*/
|
|
21
|
+
export async function initializeAppModules(configurator, cb, args) {
|
|
22
|
+
const { fusion } = args;
|
|
23
|
+
// Extract telemetry metadata from app manifest for tracking and debugging
|
|
24
|
+
const metadataExtractor = () => {
|
|
25
|
+
return {
|
|
26
|
+
fusion: {
|
|
27
|
+
type: 'app-telemetry',
|
|
28
|
+
app: {
|
|
29
|
+
key: args.env.manifest?.appKey || 'unknown-app',
|
|
30
|
+
version: args.env.manifest?.build?.version || 'unknown-version',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
// Enable telemetry collection for module configuration events
|
|
36
|
+
// attachConfiguratorEvents automatically prefixes events with configurator class name
|
|
37
|
+
enableTelemetry(configurator, {
|
|
38
|
+
attachConfiguratorEvents: true,
|
|
39
|
+
configure: (builder) => {
|
|
40
|
+
builder.setMetadata(metadataExtractor);
|
|
41
|
+
builder.setParent(fusion.modules.telemetry);
|
|
42
|
+
// Scope telemetry to 'app' level for app-specific event filtering
|
|
43
|
+
builder.setDefaultScope(['app']);
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
// Allow user configuration callback to run before module initialization
|
|
47
|
+
if (cb) {
|
|
48
|
+
await Promise.resolve(cb(configurator, args));
|
|
49
|
+
}
|
|
50
|
+
// Type cast is safe because AppConfigurator.initialize() returns the exact module
|
|
51
|
+
// instance that was registered and configured above. The intermediate 'unknown'
|
|
52
|
+
// cast is necessary due to TypeScript's generic inference limitations with the
|
|
53
|
+
// configurator's initialization chain, but the runtime value is guaranteed to match.
|
|
54
|
+
const modules = (await configurator.initialize(args.fusion.modules));
|
|
55
|
+
// Dispatch app modules loaded event for app lifecycle tracking
|
|
56
|
+
// TODO(#5061): remove check after fusion-cli is updated (app module is not enabled in fusion-cli)
|
|
57
|
+
if (args.env.manifest?.appKey) {
|
|
58
|
+
modules.event.dispatchEvent('onAppModulesLoaded', {
|
|
59
|
+
detail: { appKey: args.env.manifest.appKey, manifest: args.env.manifest, modules },
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return modules;
|
|
63
|
+
}
|
|
64
|
+
export default initializeAppModules;
|
|
65
|
+
//# sourceMappingURL=initialize-app-modules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"initialize-app-modules.js","sourceRoot":"","sources":["../../src/initialize-app-modules.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,eAAe,GAEhB,MAAM,4CAA4C,CAAC;AAKpD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAaxC,YAA2B,EAC3B,EAEa,EACb,IAAiC;IAEjC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAExB,0EAA0E;IAC1E,MAAM,iBAAiB,GAAsB,GAAG,EAAE;QAChD,OAAO;YACL,MAAM,EAAE;gBACN,IAAI,EAAE,eAAe;gBACrB,GAAG,EAAE;oBACH,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,aAAa;oBAC/C,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,IAAI,iBAAiB;iBAChE;aACF;SACF,CAAC;IACJ,CAAC,CAAC;IAEF,8DAA8D;IAC9D,sFAAsF;IACtF,eAAe,CAAC,YAAY,EAAE;QAC5B,wBAAwB,EAAE,IAAI;QAC9B,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;YACrB,OAAO,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC;YACvC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC5C,kEAAkE;YAClE,OAAO,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACnC,CAAC;KACF,CAAC,CAAC;IAEH,wEAAwE;IACxE,IAAI,EAAE,EAAE,CAAC;QACP,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC;IAChD,CAAC;IACD,kFAAkF;IAClF,gFAAgF;IAChF,+EAA+E;IAC/E,qFAAqF;IACrF,MAAM,OAAO,GAAiC,CAAC,MAAM,YAAY,CAAC,UAAU,CAC1E,IAAI,CAAC,MAAM,CAAC,OAAO,CACpB,CAA4C,CAAC;IAE9C,+DAA+D;IAC/D,kGAAkG;IAClG,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;QAC9B,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,oBAAoB,EAAE;YAChD,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE;SACnF,CAAC,CAAC;IACL,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,eAAe,oBAAoB,CAAC"}
|