@openmrs/esm-framework 8.0.1-pre.3439 → 8.0.1-pre.3457
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/.turbo/turbo-build.log +1 -1
- package/dist/openmrs-esm-framework.js +2 -2
- package/dist/openmrs-esm-framework.js.map +1 -1
- package/docs/functions/attach.md +1 -1
- package/docs/functions/compile.md +1 -1
- package/docs/functions/defineConfigSchema.md +1 -1
- package/docs/functions/defineExtensionConfigSchema.md +1 -1
- package/docs/functions/detach.md +1 -1
- package/docs/functions/detachAll.md +1 -1
- package/docs/functions/evaluateAsTypeAsync.md +1 -1
- package/docs/functions/getAssignedExtensions.md +1 -1
- package/docs/functions/getConfig.md +1 -1
- package/docs/functions/getExtensionNameFromId.md +1 -1
- package/docs/functions/getExtensionStore.md +1 -1
- package/docs/functions/provide.md +1 -1
- package/docs/functions/setLeftNav.md +1 -1
- package/docs/functions/unsetLeftNav.md +1 -1
- package/docs/interfaces/AssignedExtension.md +9 -9
- package/docs/interfaces/ConnectedExtension.md +6 -6
- package/docs/interfaces/ExtensionRegistration.md +8 -0
- package/docs/interfaces/ExtensionSlotProps.md +264 -264
- package/docs/interfaces/ExtensionSlotState.md +11 -3
- package/docs/interfaces/ExtensionStore.md +2 -2
- package/docs/interfaces/FeatureFlagDefinition.md +4 -4
- package/docs/interfaces/LeftNavStore.md +13 -5
- package/docs/interfaces/OpenmrsAppRoutes.md +13 -13
- package/docs/interfaces/ResourceLoader.md +2 -2
- package/docs/interfaces/SetLeftNavParams.md +13 -5
- package/docs/interfaces/WorkspaceDefinition2.md +4 -4
- package/docs/interfaces/WorkspaceGroupDefinition.md +3 -3
- package/docs/interfaces/WorkspaceGroupDefinition2.md +4 -4
- package/docs/interfaces/WorkspaceWindowDefinition2.md +9 -9
- package/docs/type-aliases/ExtensionDefinition.md +13 -3
- package/docs/type-aliases/ModalDefinition.md +3 -3
- package/docs/type-aliases/NameUse.md +1 -1
- package/docs/type-aliases/OpenmrsRoutes.md +1 -1
- package/docs/type-aliases/WorkspaceDefinition.md +10 -10
- package/docs/type-aliases/WorkspaceWindowState.md +1 -1
- package/package.json +20 -20
- package/setup-tests.ts +23 -2
- package/src/integration-tests/extension-config-expressions.test.tsx +316 -0
- package/src/integration-tests/extension-config.test.tsx +48 -36
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openmrs/esm-framework",
|
|
3
|
-
"version": "8.0.1-pre.
|
|
3
|
+
"version": "8.0.1-pre.3457",
|
|
4
4
|
"license": "MPL-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "dist/openmrs-esm-framework.js",
|
|
@@ -59,24 +59,24 @@
|
|
|
59
59
|
"access": "public"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"@openmrs/esm-api": "8.0.1-pre.
|
|
63
|
-
"@openmrs/esm-config": "8.0.1-pre.
|
|
64
|
-
"@openmrs/esm-context": "8.0.1-pre.
|
|
65
|
-
"@openmrs/esm-dynamic-loading": "8.0.1-pre.
|
|
66
|
-
"@openmrs/esm-emr-api": "8.0.1-pre.
|
|
67
|
-
"@openmrs/esm-error-handling": "8.0.1-pre.
|
|
68
|
-
"@openmrs/esm-expression-evaluator": "8.0.1-pre.
|
|
69
|
-
"@openmrs/esm-extensions": "8.0.1-pre.
|
|
70
|
-
"@openmrs/esm-feature-flags": "8.0.1-pre.
|
|
71
|
-
"@openmrs/esm-globals": "8.0.1-pre.
|
|
72
|
-
"@openmrs/esm-navigation": "8.0.1-pre.
|
|
73
|
-
"@openmrs/esm-offline": "8.0.1-pre.
|
|
74
|
-
"@openmrs/esm-react-utils": "8.0.1-pre.
|
|
75
|
-
"@openmrs/esm-routes": "8.0.1-pre.
|
|
76
|
-
"@openmrs/esm-state": "8.0.1-pre.
|
|
77
|
-
"@openmrs/esm-styleguide": "8.0.1-pre.
|
|
78
|
-
"@openmrs/esm-translations": "8.0.1-pre.
|
|
79
|
-
"@openmrs/esm-utils": "8.0.1-pre.
|
|
62
|
+
"@openmrs/esm-api": "8.0.1-pre.3457",
|
|
63
|
+
"@openmrs/esm-config": "8.0.1-pre.3457",
|
|
64
|
+
"@openmrs/esm-context": "8.0.1-pre.3457",
|
|
65
|
+
"@openmrs/esm-dynamic-loading": "8.0.1-pre.3457",
|
|
66
|
+
"@openmrs/esm-emr-api": "8.0.1-pre.3457",
|
|
67
|
+
"@openmrs/esm-error-handling": "8.0.1-pre.3457",
|
|
68
|
+
"@openmrs/esm-expression-evaluator": "8.0.1-pre.3457",
|
|
69
|
+
"@openmrs/esm-extensions": "8.0.1-pre.3457",
|
|
70
|
+
"@openmrs/esm-feature-flags": "8.0.1-pre.3457",
|
|
71
|
+
"@openmrs/esm-globals": "8.0.1-pre.3457",
|
|
72
|
+
"@openmrs/esm-navigation": "8.0.1-pre.3457",
|
|
73
|
+
"@openmrs/esm-offline": "8.0.1-pre.3457",
|
|
74
|
+
"@openmrs/esm-react-utils": "8.0.1-pre.3457",
|
|
75
|
+
"@openmrs/esm-routes": "8.0.1-pre.3457",
|
|
76
|
+
"@openmrs/esm-state": "8.0.1-pre.3457",
|
|
77
|
+
"@openmrs/esm-styleguide": "8.0.1-pre.3457",
|
|
78
|
+
"@openmrs/esm-translations": "8.0.1-pre.3457",
|
|
79
|
+
"@openmrs/esm-utils": "8.0.1-pre.3457"
|
|
80
80
|
},
|
|
81
81
|
"peerDependencies": {
|
|
82
82
|
"dayjs": "1.x",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"swr": "2.x"
|
|
90
90
|
},
|
|
91
91
|
"devDependencies": {
|
|
92
|
-
"@openmrs/typedoc-plugin-file-categories": "8.0.1-pre.
|
|
92
|
+
"@openmrs/typedoc-plugin-file-categories": "8.0.1-pre.3457",
|
|
93
93
|
"@rspack/cli": "^1.3.11",
|
|
94
94
|
"@rspack/core": "^1.3.11",
|
|
95
95
|
"concurrently": "^9.1.2",
|
package/setup-tests.ts
CHANGED
|
@@ -1,12 +1,33 @@
|
|
|
1
|
-
import { afterEach
|
|
1
|
+
import { afterEach } from 'vitest';
|
|
2
2
|
import type {} from '@openmrs/esm-globals';
|
|
3
3
|
import '@testing-library/jest-dom/vitest';
|
|
4
4
|
import { cleanup } from '@testing-library/react';
|
|
5
5
|
|
|
6
|
+
// Configure React's act() environment for Vitest
|
|
7
|
+
// See: https://github.com/testing-library/react-testing-library/issues/1061
|
|
8
|
+
// Store the actual value in a variable to avoid infinite recursion
|
|
9
|
+
let actEnvironment = true;
|
|
10
|
+
|
|
11
|
+
Object.defineProperty(globalThis, 'IS_REACT_ACT_ENVIRONMENT', {
|
|
12
|
+
get() {
|
|
13
|
+
return actEnvironment;
|
|
14
|
+
},
|
|
15
|
+
set(value) {
|
|
16
|
+
actEnvironment = value;
|
|
17
|
+
if (typeof window !== 'undefined' && globalThis !== window) {
|
|
18
|
+
window.IS_REACT_ACT_ENVIRONMENT = value;
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
globalThis.IS_REACT_ACT_ENVIRONMENT = true;
|
|
24
|
+
|
|
6
25
|
window.openmrsBase = '/openmrs';
|
|
7
26
|
window.spaBase = '/spa';
|
|
8
27
|
window.getOpenmrsSpaBase = () => '/openmrs/spa/';
|
|
9
28
|
const { getComputedStyle } = window;
|
|
10
29
|
window.getComputedStyle = (elt) => getComputedStyle(elt);
|
|
11
30
|
|
|
12
|
-
afterEach(
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
cleanup();
|
|
33
|
+
});
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
4
|
+
import '@testing-library/jest-dom/vitest';
|
|
5
|
+
import { act, cleanup, render, screen, waitFor } from '@testing-library/react';
|
|
6
|
+
import { type Person } from '@openmrs/esm-api';
|
|
7
|
+
import { mockSessionStore } from '@openmrs/esm-api/mock';
|
|
8
|
+
import { attach, registerExtension, updateInternalExtensionStore } from '../../../esm-extensions';
|
|
9
|
+
import { ExtensionSlot, getSyncLifecycle, openmrsComponentDecorator, useConfig } from '../../../esm-react-utils/src';
|
|
10
|
+
import {
|
|
11
|
+
configInternalStore,
|
|
12
|
+
defineConfigSchema,
|
|
13
|
+
getExtensionSlotsConfigStore,
|
|
14
|
+
getExtensionsConfigStore,
|
|
15
|
+
provide,
|
|
16
|
+
registerModuleLoad,
|
|
17
|
+
resetConfigSystem,
|
|
18
|
+
temporaryConfigStore,
|
|
19
|
+
} from '../../../esm-config/src';
|
|
20
|
+
|
|
21
|
+
vi.mock('@openmrs/esm-api', async () => {
|
|
22
|
+
const original = await import('@openmrs/esm-api');
|
|
23
|
+
return {
|
|
24
|
+
...original,
|
|
25
|
+
sessionStore: mockSessionStore,
|
|
26
|
+
refetchCurrentUser: vi.fn(),
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Expression evaluation tests
|
|
32
|
+
*
|
|
33
|
+
* These tests are in a separate file due to test isolation issues. When run with other
|
|
34
|
+
* extension/config tests, there is accumulation of state/subscriptions that causes infinite
|
|
35
|
+
* update loops. The tests pass when run individually or in this isolated file.
|
|
36
|
+
*
|
|
37
|
+
* Root cause: Even with subscription cleanup (resetConfigSystem) and deep equality checks,
|
|
38
|
+
* running these tests alongside other tests that manipulate the config system creates
|
|
39
|
+
* conditions where store updates don't settle. This is a test environment issue, not a
|
|
40
|
+
* production code bug - the functionality works correctly in isolation and in production.
|
|
41
|
+
*/
|
|
42
|
+
describe('Expression evaluation in extension display conditions', () => {
|
|
43
|
+
beforeEach(() => {
|
|
44
|
+
temporaryConfigStore.setState({ config: {} });
|
|
45
|
+
configInternalStore.setState({ providedConfigs: [], schemas: {}, moduleLoaded: {} });
|
|
46
|
+
mockSessionStore.setState({});
|
|
47
|
+
getExtensionSlotsConfigStore().setState({ slots: {} });
|
|
48
|
+
getExtensionsConfigStore().setState({ configs: {} });
|
|
49
|
+
updateInternalExtensionStore(() => ({ slots: {}, extensions: {} }));
|
|
50
|
+
resetConfigSystem();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
afterEach(() => {
|
|
54
|
+
cleanup();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should show extension when the expression evalutes to true', async () => {
|
|
58
|
+
const promise = Promise.resolve();
|
|
59
|
+
|
|
60
|
+
registerSimpleExtension('Schmoo', 'esm-bedrock', true);
|
|
61
|
+
attach('A slot', 'Schmoo');
|
|
62
|
+
defineConfigSchema('esm-bedrock', {});
|
|
63
|
+
registerModuleLoad('esm-bedrock');
|
|
64
|
+
provide({
|
|
65
|
+
'esm-bedrock': {
|
|
66
|
+
'Display conditions': {
|
|
67
|
+
expression: 'true',
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
function RootComponent() {
|
|
73
|
+
return (
|
|
74
|
+
<div>
|
|
75
|
+
<ExtensionSlot data-testid="slot" name="A slot" />
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const App = openmrsComponentDecorator({
|
|
81
|
+
moduleName: 'esm-bedrock',
|
|
82
|
+
featureName: 'Bedrock',
|
|
83
|
+
disableTranslations: true,
|
|
84
|
+
})(RootComponent);
|
|
85
|
+
|
|
86
|
+
await act(async () => await promise);
|
|
87
|
+
|
|
88
|
+
render(<App />);
|
|
89
|
+
|
|
90
|
+
await screen.findByTestId(/slot/);
|
|
91
|
+
expect(screen.getByTestId('slot').firstChild).toHaveAttribute('data-extension-id', 'Schmoo');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('should hide extension when the expression evaluates to false', async () => {
|
|
95
|
+
const promise = Promise.resolve();
|
|
96
|
+
|
|
97
|
+
registerSimpleExtension('Schmoo', 'esm-bedrock', true);
|
|
98
|
+
attach('A slot', 'Schmoo');
|
|
99
|
+
defineConfigSchema('esm-bedrock', {});
|
|
100
|
+
registerModuleLoad('esm-bedrock');
|
|
101
|
+
provide({
|
|
102
|
+
'esm-bedrock': {
|
|
103
|
+
'Display conditions': {
|
|
104
|
+
expression: 'false',
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
function RootComponent() {
|
|
110
|
+
return (
|
|
111
|
+
<div>
|
|
112
|
+
<ExtensionSlot data-testid="slot" name="A slot" />
|
|
113
|
+
</div>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const App = openmrsComponentDecorator({
|
|
118
|
+
moduleName: 'esm-bedrock',
|
|
119
|
+
featureName: 'Bedrock',
|
|
120
|
+
disableTranslations: true,
|
|
121
|
+
})(RootComponent);
|
|
122
|
+
|
|
123
|
+
await act(async () => await promise);
|
|
124
|
+
|
|
125
|
+
render(<App />);
|
|
126
|
+
|
|
127
|
+
await screen.findByTestId(/slot/);
|
|
128
|
+
expect(screen.getByTestId('slot').firstChild).toBeNull();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('should show extension using a complex expression', async () => {
|
|
132
|
+
registerSimpleExtension('Schmoo', 'esm-bedrock', true);
|
|
133
|
+
attach('A slot', 'Schmoo');
|
|
134
|
+
defineConfigSchema('esm-bedrock', {});
|
|
135
|
+
registerModuleLoad('esm-bedrock');
|
|
136
|
+
provide({
|
|
137
|
+
'esm-bedrock': {
|
|
138
|
+
'Display conditions': {
|
|
139
|
+
expression: 'session.user.privileges.some(p => p.display === "YOWTCH!")',
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
function RootComponent() {
|
|
145
|
+
return (
|
|
146
|
+
<div>
|
|
147
|
+
<ExtensionSlot data-testid="slot" name="A slot" />
|
|
148
|
+
</div>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const App = openmrsComponentDecorator({
|
|
153
|
+
moduleName: 'esm-bedrock',
|
|
154
|
+
featureName: 'Bedrock',
|
|
155
|
+
disableTranslations: true,
|
|
156
|
+
})(RootComponent);
|
|
157
|
+
|
|
158
|
+
render(<App />);
|
|
159
|
+
|
|
160
|
+
// Update session state after rendering so the component can react to the change
|
|
161
|
+
await act(async () => {
|
|
162
|
+
mockSessionStore.setState({
|
|
163
|
+
loaded: true,
|
|
164
|
+
session: {
|
|
165
|
+
authenticated: true,
|
|
166
|
+
sessionId: '1',
|
|
167
|
+
user: {
|
|
168
|
+
uuid: '1',
|
|
169
|
+
display: 'Non-Admin',
|
|
170
|
+
username: 'nonadmin',
|
|
171
|
+
systemId: 'nonadmin',
|
|
172
|
+
userProperties: {},
|
|
173
|
+
person: {} as Person,
|
|
174
|
+
privileges: [{ uuid: '1', display: 'YOWTCH!' }],
|
|
175
|
+
roles: [],
|
|
176
|
+
retired: false,
|
|
177
|
+
locale: 'en',
|
|
178
|
+
allowedLocales: ['en'],
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
await waitFor(() => {
|
|
185
|
+
const slot = screen.getByTestId('slot');
|
|
186
|
+
expect(slot.firstChild).toHaveAttribute('data-extension-id', 'Schmoo');
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('should hide extension using a complex expression', async () => {
|
|
191
|
+
registerSimpleExtension('Schmoo', 'esm-bedrock', true);
|
|
192
|
+
attach('A slot', 'Schmoo');
|
|
193
|
+
defineConfigSchema('esm-bedrock', {});
|
|
194
|
+
registerModuleLoad('esm-bedrock');
|
|
195
|
+
provide({
|
|
196
|
+
'esm-bedrock': {
|
|
197
|
+
'Display conditions': {
|
|
198
|
+
expression: 'session.user.privileges.every(p => p.display !== "YOWTCH!")',
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
function RootComponent() {
|
|
204
|
+
return (
|
|
205
|
+
<div>
|
|
206
|
+
<ExtensionSlot data-testid="slot" name="A slot" />
|
|
207
|
+
</div>
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const App = openmrsComponentDecorator({
|
|
212
|
+
moduleName: 'esm-bedrock',
|
|
213
|
+
featureName: 'Bedrock',
|
|
214
|
+
disableTranslations: true,
|
|
215
|
+
})(RootComponent);
|
|
216
|
+
|
|
217
|
+
render(<App />);
|
|
218
|
+
|
|
219
|
+
// Update session state after rendering so the component can react to the change
|
|
220
|
+
await act(async () => {
|
|
221
|
+
mockSessionStore.setState({
|
|
222
|
+
loaded: true,
|
|
223
|
+
session: {
|
|
224
|
+
authenticated: true,
|
|
225
|
+
sessionId: '1',
|
|
226
|
+
user: {
|
|
227
|
+
uuid: '1',
|
|
228
|
+
display: 'Non-Admin',
|
|
229
|
+
username: 'nonadmin',
|
|
230
|
+
systemId: 'nonadmin',
|
|
231
|
+
userProperties: {},
|
|
232
|
+
person: {} as Person,
|
|
233
|
+
privileges: [{ uuid: '1', display: 'YOWTCH!' }],
|
|
234
|
+
roles: [],
|
|
235
|
+
retired: false,
|
|
236
|
+
locale: 'en',
|
|
237
|
+
allowedLocales: ['en'],
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
await waitFor(() => {
|
|
244
|
+
const slot = screen.getByTestId('slot');
|
|
245
|
+
expect(slot.firstChild).toBeNull();
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('should hide extension if expression contains an error', async () => {
|
|
250
|
+
registerSimpleExtension('Schmoo', 'esm-bedrock', true);
|
|
251
|
+
attach('A slot', 'Schmoo');
|
|
252
|
+
defineConfigSchema('esm-bedrock', {});
|
|
253
|
+
registerModuleLoad('esm-bedrock');
|
|
254
|
+
|
|
255
|
+
function RootComponent() {
|
|
256
|
+
return (
|
|
257
|
+
<div>
|
|
258
|
+
<ExtensionSlot data-testid="slot" name="A slot" />
|
|
259
|
+
</div>
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const App = openmrsComponentDecorator({
|
|
264
|
+
moduleName: 'esm-bedrock',
|
|
265
|
+
featureName: 'Bedrock',
|
|
266
|
+
disableTranslations: true,
|
|
267
|
+
})(RootComponent);
|
|
268
|
+
|
|
269
|
+
render(<App />);
|
|
270
|
+
|
|
271
|
+
// Provide config with error expression after rendering so the component can react to the change
|
|
272
|
+
await act(async () => {
|
|
273
|
+
provide({
|
|
274
|
+
'esm-bedrock': {
|
|
275
|
+
'Display conditions': {
|
|
276
|
+
expression: 'NotDefined === true',
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
await waitFor(() => {
|
|
283
|
+
const slot = screen.getByTestId('slot');
|
|
284
|
+
expect(slot.firstChild).toBeNull();
|
|
285
|
+
});
|
|
286
|
+
}, 10000);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
async function registerSimpleExtension(
|
|
290
|
+
name: string,
|
|
291
|
+
moduleName: string,
|
|
292
|
+
takesConfig: boolean = false,
|
|
293
|
+
privileges?: string | string[],
|
|
294
|
+
) {
|
|
295
|
+
const SimpleComponent = () => <div>{name}</div>;
|
|
296
|
+
const ConfigurableComponent = () => {
|
|
297
|
+
const config = useConfig();
|
|
298
|
+
return (
|
|
299
|
+
<div>
|
|
300
|
+
{name}: {JSON.stringify(config)}
|
|
301
|
+
</div>
|
|
302
|
+
);
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
registerExtension({
|
|
306
|
+
name,
|
|
307
|
+
moduleName,
|
|
308
|
+
load: getSyncLifecycle(takesConfig ? ConfigurableComponent : SimpleComponent, {
|
|
309
|
+
moduleName,
|
|
310
|
+
featureName: moduleName,
|
|
311
|
+
disableTranslations: true,
|
|
312
|
+
}),
|
|
313
|
+
meta: {},
|
|
314
|
+
privileges,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
4
4
|
import '@testing-library/jest-dom/vitest';
|
|
5
|
-
import { act, render, screen, waitFor } from '@testing-library/react';
|
|
5
|
+
import { act, cleanup, render, screen, waitFor } from '@testing-library/react';
|
|
6
6
|
import { type Person } from '@openmrs/esm-api';
|
|
7
7
|
import { mockSessionStore } from '@openmrs/esm-api/mock';
|
|
8
8
|
import { attach, registerExtension, updateInternalExtensionStore } from '../../../esm-extensions';
|
|
@@ -14,13 +14,15 @@ import {
|
|
|
14
14
|
useExtensionStore,
|
|
15
15
|
} from '../../../esm-react-utils/src';
|
|
16
16
|
import {
|
|
17
|
+
configInternalStore,
|
|
17
18
|
defineConfigSchema,
|
|
19
|
+
getExtensionSlotsConfigStore,
|
|
20
|
+
getExtensionsConfigStore,
|
|
18
21
|
provide,
|
|
19
|
-
Type,
|
|
20
22
|
registerModuleLoad,
|
|
23
|
+
resetConfigSystem,
|
|
21
24
|
temporaryConfigStore,
|
|
22
|
-
|
|
23
|
-
getExtensionSlotsConfigStore,
|
|
25
|
+
Type,
|
|
24
26
|
} from '../../../esm-config/src';
|
|
25
27
|
|
|
26
28
|
vi.mock('@openmrs/esm-api', async () => {
|
|
@@ -35,9 +37,16 @@ vi.mock('@openmrs/esm-api', async () => {
|
|
|
35
37
|
describe('Interaction between configuration and extension systems', () => {
|
|
36
38
|
beforeEach(() => {
|
|
37
39
|
temporaryConfigStore.setState({ config: {} });
|
|
38
|
-
configInternalStore.setState({ providedConfigs: [], schemas: {} });
|
|
40
|
+
configInternalStore.setState({ providedConfigs: [], schemas: {}, moduleLoaded: {} });
|
|
41
|
+
mockSessionStore.setState({});
|
|
39
42
|
getExtensionSlotsConfigStore().setState({ slots: {} });
|
|
43
|
+
getExtensionsConfigStore().setState({ configs: {} });
|
|
40
44
|
updateInternalExtensionStore(() => ({ slots: {}, extensions: {} }));
|
|
45
|
+
resetConfigSystem();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
afterEach(() => {
|
|
49
|
+
cleanup();
|
|
41
50
|
});
|
|
42
51
|
|
|
43
52
|
it('Config should add, order, and remove extensions within slots', async () => {
|
|
@@ -292,7 +301,7 @@ describe('Interaction between configuration and extension systems', () => {
|
|
|
292
301
|
|
|
293
302
|
render(<App />);
|
|
294
303
|
|
|
295
|
-
screen.findByTestId(/slot/);
|
|
304
|
+
await screen.findByTestId(/slot/);
|
|
296
305
|
expect(screen.getByText(/clothes/)).toHaveTextContent(/leopard/);
|
|
297
306
|
|
|
298
307
|
act(() => {
|
|
@@ -374,9 +383,11 @@ describe('Interaction between configuration and extension systems', () => {
|
|
|
374
383
|
|
|
375
384
|
render(<App />);
|
|
376
385
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
386
|
+
await waitFor(() => {
|
|
387
|
+
const slot = screen.getByTestId('slot');
|
|
388
|
+
expect(slot.firstChild).toHaveAttribute('data-extension-id', 'Wilma');
|
|
389
|
+
expect(screen.queryAllByText(/\bSchmoo\b/)).toHaveLength(0);
|
|
390
|
+
});
|
|
380
391
|
});
|
|
381
392
|
|
|
382
393
|
it('should show extension when user has configured privilege', async () => {
|
|
@@ -436,28 +447,29 @@ describe('Interaction between configuration and extension systems', () => {
|
|
|
436
447
|
expect(screen.getByTestId('slot').firstChild).toHaveAttribute('data-extension-id', 'Schmoo');
|
|
437
448
|
});
|
|
438
449
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
450
|
+
it('should only show extensions users have default privilege for', async () => {
|
|
451
|
+
// Set up initial session state before registering extensions
|
|
452
|
+
await act(async () => {
|
|
453
|
+
mockSessionStore.setState({
|
|
454
|
+
loaded: true,
|
|
455
|
+
session: {
|
|
456
|
+
authenticated: true,
|
|
457
|
+
sessionId: '1',
|
|
458
|
+
user: {
|
|
459
|
+
uuid: '1',
|
|
460
|
+
display: 'Non-Admin',
|
|
461
|
+
username: 'nonadmin',
|
|
462
|
+
systemId: 'nonadmin',
|
|
463
|
+
userProperties: {},
|
|
464
|
+
person: {} as Person,
|
|
465
|
+
privileges: [{ uuid: '1', display: 'YOWTCH!' }],
|
|
466
|
+
roles: [],
|
|
467
|
+
retired: false,
|
|
468
|
+
locale: 'en',
|
|
469
|
+
allowedLocales: ['en'],
|
|
470
|
+
},
|
|
459
471
|
},
|
|
460
|
-
}
|
|
472
|
+
});
|
|
461
473
|
});
|
|
462
474
|
|
|
463
475
|
registerSimpleExtension('Schmoo', 'esm-bedrock', true, 'Yabadabadoo!');
|
|
@@ -485,13 +497,13 @@ describe('Interaction between configuration and extension systems', () => {
|
|
|
485
497
|
disableTranslations: true,
|
|
486
498
|
})(RootComponent);
|
|
487
499
|
|
|
488
|
-
await act(async () => await promise);
|
|
489
|
-
|
|
490
500
|
render(<App />);
|
|
491
501
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
502
|
+
await waitFor(() => {
|
|
503
|
+
const slot = screen.getByTestId('slot');
|
|
504
|
+
expect(slot.firstChild).toHaveAttribute('data-extension-id', 'Wilma');
|
|
505
|
+
expect(screen.queryAllByText(/\bSchmoo\b/)).toHaveLength(0);
|
|
506
|
+
});
|
|
495
507
|
});
|
|
496
508
|
});
|
|
497
509
|
|