@servicetitan/web-components 23.0.0 → 23.2.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/dist/__mocks__/index.d.ts +3 -0
- package/dist/__mocks__/index.d.ts.map +1 -0
- package/dist/__mocks__/index.js +3 -0
- package/dist/__mocks__/index.js.map +1 -0
- package/dist/__mocks__/register-component.d.ts +4 -0
- package/dist/__mocks__/register-component.d.ts.map +1 -0
- package/dist/__mocks__/register-component.js +14 -0
- package/dist/__mocks__/register-component.js.map +1 -0
- package/dist/__mocks__/test-component.d.ts +3 -0
- package/dist/__mocks__/test-component.d.ts.map +1 -0
- package/dist/__mocks__/test-component.js +14 -0
- package/dist/__mocks__/test-component.js.map +1 -0
- package/dist/contexts/tests/mfe-data-context.test.js +1 -1
- package/dist/contexts/tests/mfe-data-context.test.js.map +1 -1
- package/dist/contexts/tests/mfe-metadata-context.test.js +1 -1
- package/dist/contexts/tests/mfe-metadata-context.test.js.map +1 -1
- package/dist/loader.d.ts +7 -17
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +74 -224
- package/dist/loader.js.map +1 -1
- package/dist/register.d.ts +4 -1
- package/dist/register.d.ts.map +1 -1
- package/dist/register.js +26 -13
- package/dist/register.js.map +1 -1
- package/dist/render.d.ts +11 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +39 -0
- package/dist/render.js.map +1 -0
- package/dist/utils/get-bundle-info.d.ts +24 -0
- package/dist/utils/get-bundle-info.d.ts.map +1 -0
- package/dist/utils/get-bundle-info.js +98 -0
- package/dist/utils/get-bundle-info.js.map +1 -0
- package/dist/utils/get-entry-points.d.ts +6 -0
- package/dist/utils/get-entry-points.d.ts.map +1 -0
- package/dist/utils/get-entry-points.js +24 -0
- package/dist/utils/get-entry-points.js.map +1 -0
- package/dist/{get-mfe-supports-rerendering.d.ts → utils/get-mfe-supports-rerendering.d.ts} +1 -1
- package/dist/utils/get-mfe-supports-rerendering.d.ts.map +1 -0
- package/dist/utils/get-mfe-supports-rerendering.js.map +1 -0
- package/dist/{utils.d.ts → utils/get-version-mismatches.d.ts} +2 -3
- package/dist/utils/get-version-mismatches.d.ts.map +1 -0
- package/dist/{utils.js → utils/get-version-mismatches.js} +2 -10
- package/dist/utils/get-version-mismatches.js.map +1 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +9 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/is-versioned-url.d.ts +2 -0
- package/dist/utils/is-versioned-url.d.ts.map +1 -0
- package/dist/utils/is-versioned-url.js +9 -0
- package/dist/utils/is-versioned-url.js.map +1 -0
- package/dist/utils/load-scripts.d.ts +3 -0
- package/dist/utils/load-scripts.d.ts.map +1 -0
- package/dist/utils/load-scripts.js +31 -0
- package/dist/utils/load-scripts.js.map +1 -0
- package/dist/utils/validate-bundle-info.d.ts +7 -0
- package/dist/utils/validate-bundle-info.d.ts.map +1 -0
- package/dist/utils/validate-bundle-info.js +10 -0
- package/dist/utils/validate-bundle-info.js.map +1 -0
- package/dist/utils/web-component.d.ts +17 -0
- package/dist/utils/web-component.d.ts.map +1 -0
- package/dist/utils/web-component.js +54 -0
- package/dist/utils/web-component.js.map +1 -0
- package/package.json +17 -18
- package/src/__mocks__/index.ts +2 -0
- package/src/__mocks__/register-component.tsx +20 -0
- package/src/__mocks__/test-component.tsx +30 -0
- package/src/__tests__/event-bus.test.ts +3 -2
- package/src/__tests__/loader.test.tsx +17 -11
- package/src/__tests__/register-legacy-root.test.tsx +36 -0
- package/src/__tests__/register.test.tsx +16 -81
- package/src/contexts/tests/mfe-data-context.test.tsx +4 -4
- package/src/contexts/tests/mfe-metadata-context.test.tsx +4 -4
- package/src/loader.tsx +129 -374
- package/src/register.tsx +25 -14
- package/src/render.ts +62 -0
- package/src/{__tests__ → utils/__tests__}/get-mfe-supports-rerendering.test.ts +1 -1
- package/src/utils/__tests__/get-version-mismatches.test.ts +76 -0
- package/src/utils/__tests__/is-versioned-url.test.ts +18 -0
- package/src/utils/get-bundle-info.ts +121 -0
- package/src/utils/get-entry-points.ts +23 -0
- package/src/{get-mfe-supports-rerendering.ts → utils/get-mfe-supports-rerendering.ts} +1 -1
- package/src/{utils.ts → utils/get-version-mismatches.ts} +1 -12
- package/src/utils/index.ts +8 -0
- package/src/utils/is-versioned-url.ts +11 -0
- package/src/utils/load-scripts.ts +38 -0
- package/src/utils/validate-bundle-info.ts +15 -0
- package/src/utils/web-component.tsx +96 -0
- package/dist/get-mfe-supports-rerendering.d.ts.map +0 -1
- package/dist/get-mfe-supports-rerendering.js.map +0 -1
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js.map +0 -1
- package/src/__tests__/utils.test.ts +0 -95
- /package/dist/{get-mfe-supports-rerendering.js → utils/get-mfe-supports-rerendering.js} +0 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, useMemo, useState } from 'react';
|
|
3
|
+
import { useOptionalDependencies } from '@servicetitan/react-ioc';
|
|
4
|
+
import { HistoryManager } from '../history-manager';
|
|
5
|
+
export function webComponent(props) {
|
|
6
|
+
const { basename, bundleInfo, eventBus, exposedDependencies, logService, LoadingFallback } = props;
|
|
7
|
+
const { WebComponent, disposer, mfeSupportsRerendering } = bundleInfo;
|
|
8
|
+
return (props) => {
|
|
9
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
10
|
+
const [historyManager] = useOptionalDependencies(HistoryManager);
|
|
11
|
+
const handleRef = (webComponent) => {
|
|
12
|
+
webComponent === null || webComponent === void 0 ? void 0 : webComponent.provide({
|
|
13
|
+
logService,
|
|
14
|
+
historyManager,
|
|
15
|
+
exposedDependencies,
|
|
16
|
+
eventBus,
|
|
17
|
+
basename,
|
|
18
|
+
onReady: () => {
|
|
19
|
+
setIsLoading(false);
|
|
20
|
+
},
|
|
21
|
+
onDispose: () => {
|
|
22
|
+
disposer();
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
const stringifiedData = useMemo(() => JSON.stringify(props.data), [props.data]);
|
|
27
|
+
/*
|
|
28
|
+
* Set key for rendering the web component so that if the data from the Host change,
|
|
29
|
+
* and the MFE's version of startup doesn't support watching for data changes, then
|
|
30
|
+
* the web component will be re-mounted whenever the data changes.
|
|
31
|
+
* This is only used as a fallback when the MFE's version is older.
|
|
32
|
+
*/
|
|
33
|
+
const key = mfeSupportsRerendering ? undefined : stringifiedData;
|
|
34
|
+
const dataAttrs = useMemo(() => composeDataAttributes(props.data), [props.data]);
|
|
35
|
+
const styleUrls = getStyleUrls(bundleInfo);
|
|
36
|
+
return (_jsxs(Fragment, { children: [isLoading && _jsx(LoadingFallback, {}), _jsx(WebComponent, Object.assign({ ref: handleRef, class: props.className }, (styleUrls && { 'style-urls': styleUrls }), dataAttrs, { "data-mfe-data": stringifiedData }), key)] }));
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/*
|
|
40
|
+
* Convert camelCase data props to kebab-case data attributes, prepended with data-
|
|
41
|
+
* Ex: fooBar -> data-foo-bar
|
|
42
|
+
*/
|
|
43
|
+
function composeDataAttributes(data = {}) {
|
|
44
|
+
return Object.fromEntries(Object.entries(data).map(([key, value]) => [
|
|
45
|
+
'data-' + key.replace(/[A-Z]/g, letter => '-' + letter.toLowerCase()),
|
|
46
|
+
value,
|
|
47
|
+
]));
|
|
48
|
+
}
|
|
49
|
+
function getStyleUrls({ urls }) {
|
|
50
|
+
if (urls.css.length) {
|
|
51
|
+
return encodeURIComponent(JSON.stringify(urls.css));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=web-component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-component.js","sourceRoot":"","sources":["../../src/utils/web-component.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAMlE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAYpD,MAAM,UAAU,YAAY,CAAC,KAAwB;IACjD,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,mBAAmB,EAAE,UAAU,EAAE,eAAe,EAAE,GACtF,KAAK,CAAC;IACV,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,sBAAsB,EAAE,GAAG,UAAU,CAAC;IAEtE,OAAO,CAAC,KAAsB,EAAE,EAAE;QAC9B,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,CAAC,cAAc,CAAC,GAAG,uBAAuB,CAAC,cAAc,CAAC,CAAC;QAEjE,MAAM,SAAS,GAAG,CAAC,YAAkC,EAAE,EAAE;YACrD,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,OAAO,CAAC;gBAClB,UAAU;gBACV,cAAc;gBACd,mBAAmB;gBACnB,QAAQ;gBACR,QAAQ;gBACR,OAAO,EAAE,GAAG,EAAE;oBACV,YAAY,CAAC,KAAK,CAAC,CAAC;gBACxB,CAAC;gBACD,SAAS,EAAE,GAAG,EAAE;oBACZ,QAAQ,EAAE,CAAC;gBACf,CAAC;aACJ,CAAC,CAAC;QACP,CAAC,CAAC;QAEF,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAEhF;;;;;WAKG;QACH,MAAM,GAAG,GAAG,sBAAsB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC;QACjE,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACjF,MAAM,SAAS,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;QAE3C,OAAO,CACH,MAAC,QAAQ,eACJ,SAAS,IAAI,KAAC,eAAe,KAAG,EACjC,KAAC,YAAY,kBAET,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,KAAK,CAAC,SAAS,IAClB,CAAC,SAAS,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,EAK1C,SAAS,qBAEE,eAAe,KAVzB,GAAG,CAWV,IACK,CACd,CAAC;IACN,CAAC,CAAC;AACN,CAAC;AAED;;;GAGG;AACH,SAAS,qBAAqB,CAAC,OAAuC,EAAE;IACpE,OAAO,MAAM,CAAC,WAAW,CACrB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC;QACvC,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;QACrE,KAAK;KACR,CAAC,CACL,CAAC;AACN,CAAC;AAED,SAAS,YAAY,CAAC,EAAE,IAAI,EAA4B;IACpD,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE;QACjB,OAAO,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;KACvD;AACL,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@servicetitan/web-components",
|
|
3
|
-
"version": "23.
|
|
3
|
+
"version": "23.2.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -15,36 +15,35 @@
|
|
|
15
15
|
"src"
|
|
16
16
|
],
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@servicetitan/error-boundary": "23.
|
|
18
|
+
"@servicetitan/error-boundary": "23.2.0",
|
|
19
19
|
"lodash.get": "~4.4.2",
|
|
20
20
|
"mitt": "~3.0.1",
|
|
21
21
|
"semver": "~7.5.4"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@servicetitan/design-system": "~
|
|
25
|
-
"@servicetitan/log-service": "23.
|
|
26
|
-
"@servicetitan/react-ioc": "23.
|
|
27
|
-
"@testing-library/dom": "^
|
|
24
|
+
"@servicetitan/design-system": "~14.0.0",
|
|
25
|
+
"@servicetitan/log-service": "23.2.0",
|
|
26
|
+
"@servicetitan/react-ioc": "23.2.0",
|
|
27
|
+
"@testing-library/dom": "^9.0.0",
|
|
28
28
|
"@testing-library/jest-dom": "^6.4.2",
|
|
29
|
-
"@testing-library/react": "^
|
|
30
|
-
"@testing-library/react-hooks": "^8.0.1",
|
|
29
|
+
"@testing-library/react": "^14.2.1",
|
|
31
30
|
"@types/history": "~4.7.10",
|
|
32
31
|
"@types/lodash.get": "~4.4.6",
|
|
33
|
-
"@types/react": "~
|
|
34
|
-
"@types/react-dom": "~
|
|
32
|
+
"@types/react": "~18.2.55",
|
|
33
|
+
"@types/react-dom": "~18.2.19",
|
|
35
34
|
"@types/semver": "~7.5.0",
|
|
36
35
|
"history": "~4.10.1",
|
|
37
|
-
"react": "~
|
|
38
|
-
"react-dom": "~
|
|
36
|
+
"react": "~18.2.0",
|
|
37
|
+
"react-dom": "~18.2.0",
|
|
39
38
|
"shadow-dom-testing-library": "^1.11.0"
|
|
40
39
|
},
|
|
41
40
|
"peerDependencies": {
|
|
42
|
-
"@servicetitan/design-system": "
|
|
43
|
-
"@servicetitan/log-service": "23.
|
|
44
|
-
"@servicetitan/react-ioc": "23.
|
|
41
|
+
"@servicetitan/design-system": ">=12.6.2",
|
|
42
|
+
"@servicetitan/log-service": "23.2.0",
|
|
43
|
+
"@servicetitan/react-ioc": "23.2.0",
|
|
45
44
|
"history": "~4.10.1",
|
|
46
|
-
"react": "
|
|
47
|
-
"react-dom": "
|
|
45
|
+
"react": ">=17.0.2",
|
|
46
|
+
"react-dom": ">=17.0.2"
|
|
48
47
|
},
|
|
49
48
|
"publishConfig": {
|
|
50
49
|
"access": "public"
|
|
@@ -52,5 +51,5 @@
|
|
|
52
51
|
"cli": {
|
|
53
52
|
"webpack": false
|
|
54
53
|
},
|
|
55
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "4b72bab5ab6cb52a688d9329c7fbaa702ae6780c"
|
|
56
55
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { FunctionComponent } from 'react';
|
|
2
|
+
import { RegisterOptions } from '../register';
|
|
3
|
+
|
|
4
|
+
export function registerComponent(
|
|
5
|
+
TestComponent: FunctionComponent,
|
|
6
|
+
componentName: string | undefined,
|
|
7
|
+
options?: RegisterOptions
|
|
8
|
+
) {
|
|
9
|
+
/*
|
|
10
|
+
* This register can only happen once, unfortunately. So the TestComponent needs to
|
|
11
|
+
* work for all tests. If ran more than once, window.customElements.define will throw
|
|
12
|
+
* the error: "NotSupportedError: This name has already been registered in the registry."
|
|
13
|
+
*
|
|
14
|
+
* Also note that there is not way to "unregister" a web component, so an afterAll
|
|
15
|
+
* cannot be used.
|
|
16
|
+
*/
|
|
17
|
+
(global as any).WEB_COMPONENT_NAME = componentName;
|
|
18
|
+
const { register } = require('../register');
|
|
19
|
+
register(TestComponent, true, options);
|
|
20
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { FC, useContext } from 'react';
|
|
2
|
+
import { TablePopupPropsContext } from '@servicetitan/design-system';
|
|
3
|
+
import { useMFEDataContext, useMFEMetadataContext } from '../contexts';
|
|
4
|
+
|
|
5
|
+
export const MockComponent: FC<Record<string, any>> = props => {
|
|
6
|
+
const data = useMFEDataContext();
|
|
7
|
+
const metadata = useMFEMetadataContext();
|
|
8
|
+
const popupProps = useContext(TablePopupPropsContext);
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<div>
|
|
12
|
+
{Object.entries(props).map(([name, value]) => (
|
|
13
|
+
<span key={name}>{`Prop: ${name}, Value: ${stringifyValue(value)}`}</span>
|
|
14
|
+
))}
|
|
15
|
+
{Object.entries(data).map(([name, value]) => (
|
|
16
|
+
<span key={name}>{`Data: ${name}, Value: ${stringifyValue(value)}`}</span>
|
|
17
|
+
))}
|
|
18
|
+
{Object.entries(metadata).map(([name, value]) => (
|
|
19
|
+
<span key={name}>{`Metadata: ${name}, Value: ${stringifyValue(value)}`}</span>
|
|
20
|
+
))}
|
|
21
|
+
<span>TablePopupPropsContext appendTo: {String(popupProps({}).appendTo)}</span>
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function stringifyValue(value: any) {
|
|
27
|
+
return JSON.stringify(value, (_key, value) =>
|
|
28
|
+
value instanceof ShadowRoot ? 'ShadowRoot' : value
|
|
29
|
+
);
|
|
30
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as mitt from 'mitt';
|
|
2
|
-
import { renderHook } from '@testing-library/react
|
|
2
|
+
import { renderHook } from '@testing-library/react';
|
|
3
3
|
import { useEventBus, EventBus } from '../event-bus';
|
|
4
4
|
|
|
5
5
|
jest.mock('mitt', () => jest.fn());
|
|
@@ -138,9 +138,10 @@ describe(`[web-components] ${useEventBus.name}`, () => {
|
|
|
138
138
|
test('when the component using useEventBus is re-rendered, useEventBus provides the same event bus instance', () => {
|
|
139
139
|
const { result, rerender } = subject();
|
|
140
140
|
|
|
141
|
+
const firstInstance = result.current;
|
|
141
142
|
rerender();
|
|
142
143
|
|
|
143
|
-
const
|
|
144
|
+
const secondInstance = result.current;
|
|
144
145
|
expect(firstInstance).toBe(secondInstance);
|
|
145
146
|
});
|
|
146
147
|
});
|
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
import { Metadata, Loader, LoaderProps } from '../loader';
|
|
2
|
-
import { act, render, screen, waitFor } from '@testing-library/react';
|
|
3
1
|
import '@testing-library/jest-dom';
|
|
4
|
-
import {
|
|
5
|
-
import * as common from '../common';
|
|
6
|
-
import * as utils from '../utils';
|
|
7
|
-
import { FC } from 'react';
|
|
8
|
-
import { Provider, ProviderProps } from '@servicetitan/react-ioc';
|
|
2
|
+
import { act, render, screen, waitFor } from '@testing-library/react';
|
|
9
3
|
import { Log } from '@servicetitan/log-service';
|
|
10
|
-
import {
|
|
4
|
+
import { Provider, ProviderProps } from '@servicetitan/react-ioc';
|
|
5
|
+
import { FC } from 'react';
|
|
6
|
+
|
|
7
|
+
import * as common from '../common';
|
|
8
|
+
import { Entries, EXPOSED_DEPENDENCIES_TOKEN } from '../common';
|
|
11
9
|
import { EVENT_BUS_TOKEN } from '../event-bus';
|
|
10
|
+
import { HistoryManager } from '../history-manager';
|
|
11
|
+
import { Loader, LoaderProps } from '../loader';
|
|
12
|
+
import { Metadata } from '../utils/get-bundle-info';
|
|
13
|
+
import { getVersionMismatches } from '../utils/get-version-mismatches';
|
|
14
|
+
|
|
15
|
+
jest.mock('../utils/get-version-mismatches', () => ({
|
|
16
|
+
getVersionMismatches: jest.fn(),
|
|
17
|
+
}));
|
|
12
18
|
|
|
13
19
|
describe('[web-components] Loader', () => {
|
|
14
20
|
const baseUrl = 'http://localhost/mfe';
|
|
@@ -108,7 +114,7 @@ describe('[web-components] Loader', () => {
|
|
|
108
114
|
}
|
|
109
115
|
return getJsonMockFns[url]();
|
|
110
116
|
});
|
|
111
|
-
jest.
|
|
117
|
+
jest.mocked(getVersionMismatches).mockReturnValue({});
|
|
112
118
|
});
|
|
113
119
|
|
|
114
120
|
function subject() {
|
|
@@ -249,7 +255,7 @@ describe('[web-components] Loader', () => {
|
|
|
249
255
|
|
|
250
256
|
test('dependencies are pulled from package.json', async () => {
|
|
251
257
|
await scriptLoadedSetup();
|
|
252
|
-
expect(
|
|
258
|
+
expect(getVersionMismatches).toHaveBeenCalledWith(
|
|
253
259
|
expect.anything(),
|
|
254
260
|
dependencies,
|
|
255
261
|
expect.anything()
|
|
@@ -586,7 +592,7 @@ describe('[web-components] Loader', () => {
|
|
|
586
592
|
};
|
|
587
593
|
|
|
588
594
|
beforeEach(() => {
|
|
589
|
-
jest.
|
|
595
|
+
jest.mocked(getVersionMismatches).mockReturnValue(mismatchedDeps);
|
|
590
596
|
});
|
|
591
597
|
|
|
592
598
|
itAddsJsEntrypointToWebComponent(
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import '@testing-library/jest-dom';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
4
|
+
// @ts-ignore because Jest mistakenly complains that "'shadow-dom-testing-library' cannot be imported using this construct".
|
|
5
|
+
import { screen } from 'shadow-dom-testing-library';
|
|
6
|
+
|
|
7
|
+
import { MockComponent, registerComponent } from '../__mocks__';
|
|
8
|
+
|
|
9
|
+
describe('[web-components] register', () => {
|
|
10
|
+
const componentName = 'mock-legacy-root-app';
|
|
11
|
+
|
|
12
|
+
beforeAll(() => {
|
|
13
|
+
registerComponent(MockComponent, componentName, { legacyRoot: true });
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const subject = () => {
|
|
17
|
+
const Component: any = componentName;
|
|
18
|
+
return render(<Component />);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
describe('when the web component data attribute is changed', () => {
|
|
22
|
+
const setup = () => {
|
|
23
|
+
subject();
|
|
24
|
+
|
|
25
|
+
const webComponent = document.getElementsByTagName(componentName);
|
|
26
|
+
webComponent[0]?.setAttribute('data-mfe-data', JSON.stringify({ string: 'baz' }));
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
test('useMFEDataContext provides updated data', () => {
|
|
30
|
+
setup();
|
|
31
|
+
|
|
32
|
+
expect(screen.getByShadowText(`Prop: string, Value: "baz"`)).toBeInTheDocument();
|
|
33
|
+
expect(screen.getByShadowText(`Data: string, Value: "baz"`)).toBeInTheDocument();
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { render } from '@testing-library/react';
|
|
1
|
+
import '@testing-library/jest-dom';
|
|
2
|
+
import { act, render } from '@testing-library/react';
|
|
4
3
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
5
4
|
// @ts-ignore because Jest mistakenly complains that "'shadow-dom-testing-library' cannot be imported using this construct".
|
|
6
5
|
import { screen } from 'shadow-dom-testing-library';
|
|
7
|
-
import '@testing-library/jest-dom';
|
|
8
6
|
|
|
9
7
|
import { IWebComponent } from '../common';
|
|
10
|
-
import {
|
|
8
|
+
import { MockComponent, registerComponent } from '../__mocks__';
|
|
11
9
|
|
|
12
10
|
describe('[web-components] register', () => {
|
|
13
|
-
let onloadRefs: Function[];
|
|
14
11
|
const componentName = 'mock-app';
|
|
15
12
|
const handleRef = (webComponent: IWebComponent | null) => {
|
|
16
13
|
webComponent?.provide({
|
|
@@ -18,31 +15,7 @@ describe('[web-components] register', () => {
|
|
|
18
15
|
onDispose: jest.fn(),
|
|
19
16
|
});
|
|
20
17
|
};
|
|
21
|
-
|
|
22
|
-
return JSON.stringify(value, (_key, value) =>
|
|
23
|
-
value instanceof ShadowRoot ? 'ShadowRoot' : value
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
const TestComponent: FC<Record<string, any>> = props => {
|
|
27
|
-
const data = useMFEDataContext();
|
|
28
|
-
const metadata = useMFEMetadataContext();
|
|
29
|
-
const popupProps = useContext(TablePopupPropsContext);
|
|
30
|
-
|
|
31
|
-
return (
|
|
32
|
-
<div>
|
|
33
|
-
{Object.entries(props).map(([name, value]) => (
|
|
34
|
-
<span key={name}>{`Prop: ${name}, Value: ${stringifyValue(value)}`}</span>
|
|
35
|
-
))}
|
|
36
|
-
{Object.entries(data).map(([name, value]) => (
|
|
37
|
-
<span key={name}>{`Data: ${name}, Value: ${stringifyValue(value)}`}</span>
|
|
38
|
-
))}
|
|
39
|
-
{Object.entries(metadata).map(([name, value]) => (
|
|
40
|
-
<span key={name}>{`Metadata: ${name}, Value: ${stringifyValue(value)}`}</span>
|
|
41
|
-
))}
|
|
42
|
-
<span>TablePopupPropsContext appendTo: {String(popupProps({}).appendTo)}</span>
|
|
43
|
-
</div>
|
|
44
|
-
);
|
|
45
|
-
};
|
|
18
|
+
let onloadRefs: Function[];
|
|
46
19
|
|
|
47
20
|
class Page {
|
|
48
21
|
static get componentShadowRoot() {
|
|
@@ -55,18 +28,7 @@ describe('[web-components] register', () => {
|
|
|
55
28
|
}
|
|
56
29
|
|
|
57
30
|
beforeAll(() => {
|
|
58
|
-
|
|
59
|
-
* This register can only happen once, unfortunately. So the TestComponent needs to
|
|
60
|
-
* work for all tests. If ran more than once, window.customElements.define will throw
|
|
61
|
-
* the error: "NotSupportedError: This name has already been registered in the registry."
|
|
62
|
-
*
|
|
63
|
-
* Also note that there is not way to "unregister" a web component, so an afterAll
|
|
64
|
-
* cannot be used.
|
|
65
|
-
*/
|
|
66
|
-
(global as any).WEB_COMPONENT_NAME = componentName;
|
|
67
|
-
const { register } = require('../register');
|
|
68
|
-
register(TestComponent, true);
|
|
69
|
-
|
|
31
|
+
registerComponent(MockComponent, componentName);
|
|
70
32
|
/*
|
|
71
33
|
* mock <link>'s onload so that we can call it directly from the test,
|
|
72
34
|
* because it won't call itself in the test environment
|
|
@@ -91,9 +53,11 @@ describe('[web-components] register', () => {
|
|
|
91
53
|
const Component: any = componentName;
|
|
92
54
|
const renderResult = render(<Component ref={handleRef} {...data} {...dataAttrs} />);
|
|
93
55
|
|
|
94
|
-
|
|
95
|
-
onload
|
|
96
|
-
|
|
56
|
+
act(() => {
|
|
57
|
+
for (const onload of onloadRefs) {
|
|
58
|
+
onload();
|
|
59
|
+
}
|
|
60
|
+
});
|
|
97
61
|
|
|
98
62
|
return renderResult;
|
|
99
63
|
};
|
|
@@ -200,49 +164,20 @@ describe('[web-components] register', () => {
|
|
|
200
164
|
).toBeInTheDocument()
|
|
201
165
|
);
|
|
202
166
|
});
|
|
203
|
-
|
|
204
|
-
describe('when the web component data attr is changed', () => {
|
|
205
|
-
const setup = () => {
|
|
206
|
-
subject(props);
|
|
207
|
-
|
|
208
|
-
const webComponent = document.getElementsByTagName(componentName);
|
|
209
|
-
webComponent[0]?.setAttribute(
|
|
210
|
-
'data-mfe-data',
|
|
211
|
-
JSON.stringify({ ...props, string: 'baz' })
|
|
212
|
-
);
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
test('useMFEDataContext provides updated data', () => {
|
|
216
|
-
setup();
|
|
217
|
-
|
|
218
|
-
expect(screen.getByShadowText(`Prop: string, Value: "baz"`)).toBeInTheDocument();
|
|
219
|
-
expect(screen.getByShadowText(`Data: string, Value: "baz"`)).toBeInTheDocument();
|
|
220
|
-
});
|
|
221
|
-
});
|
|
222
167
|
});
|
|
223
168
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
jest.isolateModules(() => {
|
|
229
|
-
(global as any).WEB_COMPONENT_NAME = undefined;
|
|
230
|
-
register = require('../register').register;
|
|
231
|
-
});
|
|
232
|
-
jest.spyOn(console, 'error').mockImplementation(jest.fn());
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
test('logs an error', () => {
|
|
236
|
-
register(TestComponent, true);
|
|
237
|
-
// eslint-disable-next-line no-console
|
|
238
|
-
expect(console.error).toHaveBeenCalledWith('"WEB_COMPONENT_NAME" is not defined!');
|
|
169
|
+
test('logs an error when WEB_COMPONENT_NAME is not set', () => {
|
|
170
|
+
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn());
|
|
171
|
+
jest.isolateModules(() => {
|
|
172
|
+
registerComponent(MockComponent, undefined);
|
|
239
173
|
});
|
|
174
|
+
expect(consoleSpy).toHaveBeenCalledWith('"WEB_COMPONENT_NAME" is not defined!');
|
|
240
175
|
});
|
|
241
176
|
|
|
242
177
|
test('configures the shadow root in PopupPropsContext', () => {
|
|
243
178
|
subject();
|
|
244
179
|
expect(screen.getByShadowText(/TablePopupPropsContext appendTo:/)).toHaveTextContent(
|
|
245
|
-
|
|
180
|
+
/\[object ShadowRoot\]/
|
|
246
181
|
);
|
|
247
182
|
});
|
|
248
183
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FC } from 'react';
|
|
2
|
-
import { renderHook } from '@testing-library/react
|
|
1
|
+
import { FC, PropsWithChildren } from 'react';
|
|
2
|
+
import { renderHook } from '@testing-library/react';
|
|
3
3
|
import { MFEDataContext, useMFEDataContext } from '../mfe-data-context';
|
|
4
4
|
|
|
5
5
|
describe(`[web-components] ${useMFEDataContext.name}`, () => {
|
|
@@ -7,7 +7,7 @@ describe(`[web-components] ${useMFEDataContext.name}`, () => {
|
|
|
7
7
|
|
|
8
8
|
describe('when the MFEDataContext is provided by a parent', () => {
|
|
9
9
|
const data = { foo: 'bar' };
|
|
10
|
-
const Wrapper: FC = ({ children }) => {
|
|
10
|
+
const Wrapper: FC<PropsWithChildren<{}>> = ({ children }) => {
|
|
11
11
|
return <MFEDataContext.Provider value={data}>{children}</MFEDataContext.Provider>;
|
|
12
12
|
};
|
|
13
13
|
|
|
@@ -17,7 +17,7 @@ describe(`[web-components] ${useMFEDataContext.name}`, () => {
|
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
describe('when the MFEDataContext is not provided by a parent', () => {
|
|
20
|
-
const Wrapper: FC = ({ children }) => {
|
|
20
|
+
const Wrapper: FC<PropsWithChildren<{}>> = ({ children }) => {
|
|
21
21
|
return <div>{children}</div>;
|
|
22
22
|
};
|
|
23
23
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FC } from 'react';
|
|
2
|
-
import { renderHook } from '@testing-library/react
|
|
1
|
+
import { FC, PropsWithChildren } from 'react';
|
|
2
|
+
import { renderHook } from '@testing-library/react';
|
|
3
3
|
import { MFEMetadataContext, useMFEMetadataContext } from '../mfe-metadata-context';
|
|
4
4
|
|
|
5
5
|
describe(`[web-components] ${useMFEMetadataContext.name}`, () => {
|
|
@@ -9,7 +9,7 @@ describe(`[web-components] ${useMFEMetadataContext.name}`, () => {
|
|
|
9
9
|
const shadowRoot = document.createElement('div').attachShadow({ mode: 'open' });
|
|
10
10
|
const portalShadowRoot = document.createElement('span').attachShadow({ mode: 'open' });
|
|
11
11
|
const metadata = { shadowRoot, portalShadowRoot };
|
|
12
|
-
const Wrapper: FC = ({ children }) => {
|
|
12
|
+
const Wrapper: FC<PropsWithChildren<{}>> = ({ children }) => {
|
|
13
13
|
return (
|
|
14
14
|
<MFEMetadataContext.Provider value={metadata}>
|
|
15
15
|
{children}
|
|
@@ -23,7 +23,7 @@ describe(`[web-components] ${useMFEMetadataContext.name}`, () => {
|
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
describe('when the MFEMetadataContext is not provided by a parent', () => {
|
|
26
|
-
const Wrapper: FC = ({ children }) => {
|
|
26
|
+
const Wrapper: FC<PropsWithChildren<{}>> = ({ children }) => {
|
|
27
27
|
return <div>{children}</div>;
|
|
28
28
|
};
|
|
29
29
|
|