michael-s-molina commented on code in PR #39171:
URL: https://github.com/apache/superset/pull/39171#discussion_r3561372837
##########
superset-frontend/src/extensions/ExtensionsLoader.test.ts:
##########
@@ -48,9 +47,53 @@ function createMockExtension(overrides: Partial<Extension> =
{}): Extension {
};
}
+// Simulate what real webpack does when __webpack_init_sharing__ runs: it
+// registers the host's own eagerly-provided @apache-superset/core versions
+// into the share scope.
+function mockWebpackSharing(coreVersions: Record<string, unknown> = {}) {
+ (globalThis as any).__webpack_init_sharing__ = jest
Review Comment:
Fixed — replaced the `any` cast with the project's existing typed globals
(`WebpackSharedScope`/`WebpackSharedScopeModule` from `webpackFederation.d.ts`).
##########
superset-frontend/src/extensions/ExtensionsLoader.test.ts:
##########
@@ -48,9 +47,53 @@ function createMockExtension(overrides: Partial<Extension> =
{}): Extension {
};
}
+// Simulate what real webpack does when __webpack_init_sharing__ runs: it
+// registers the host's own eagerly-provided @apache-superset/core versions
+// into the share scope.
+function mockWebpackSharing(coreVersions: Record<string, unknown> = {}) {
+ (globalThis as any).__webpack_init_sharing__ = jest
+ .fn()
+ .mockImplementation(() => {
+ (globalThis as any).__webpack_share_scopes__.default[
+ '@apache-superset/core'
+ ] = coreVersions;
+ });
+ (globalThis as any).__webpack_share_scopes__ = { default: {} };
Review Comment:
Fixed — replaced the `any` cast with the project's existing typed globals
(`WebpackSharedScope`/`WebpackSharedScopeModule` from `webpackFederation.d.ts`).
##########
superset-frontend/src/extensions/ExtensionsLoader.test.ts:
##########
@@ -48,9 +47,53 @@ function createMockExtension(overrides: Partial<Extension> =
{}): Extension {
};
}
+// Simulate what real webpack does when __webpack_init_sharing__ runs: it
+// registers the host's own eagerly-provided @apache-superset/core versions
+// into the share scope.
+function mockWebpackSharing(coreVersions: Record<string, unknown> = {}) {
+ (globalThis as any).__webpack_init_sharing__ = jest
+ .fn()
+ .mockImplementation(() => {
+ (globalThis as any).__webpack_share_scopes__.default[
+ '@apache-superset/core'
+ ] = coreVersions;
+ });
+ (globalThis as any).__webpack_share_scopes__ = { default: {} };
+}
+
+function cleanupWebpackSharing() {
+ delete (globalThis as any).__webpack_init_sharing__;
+ delete (globalThis as any).__webpack_share_scopes__;
+}
+
+// Intercept script element creation so onload fires synchronously in jsdom.
+function mockRemoteEntryLoad() {
+ return jest
+ .spyOn(document.head, 'appendChild')
+ .mockImplementation((el: Node) => {
+ if (el instanceof HTMLScriptElement && el.onload) {
+ (el as HTMLScriptElement).onload!(new Event('load'));
+ }
+ return el;
+ });
+}
+
beforeEach(() => {
(ExtensionsLoader as any).instance = undefined;
mockApplicationRoot.mockReturnValue('');
+ // Reset window.superset to a base object before each test, including a
+ // shared singleton (commands) to verify identity is preserved across
+ // per-extension scoped copies.
+ (window as any).superset = {
Review Comment:
Fixed — replaced the `any` cast with the existing `Namespaces` type for
`window.superset`.
##########
superset-frontend/src/extensions/ExtensionsLoader.test.ts:
##########
@@ -170,6 +213,212 @@ test('logs success after initializeExtensions completes',
async () => {
infoSpy.mockRestore();
});
+test('logs partial failure count when some extensions fail to initialize',
async () => {
+ const loader = ExtensionsLoader.getInstance();
+ const infoSpy = jest.spyOn(logging, 'info').mockImplementation();
+ jest.spyOn(SupersetClient, 'get').mockResolvedValue({
+ json: {
+ result: [
+ createMockExtension({ id: 'good-ext', remoteEntry: '' }),
+ createMockExtension({
+ id: 'broken-ext',
+ remoteEntry: 'http://broken-url/remoteEntry.js',
+ }),
+ ],
+ },
+ } as any);
+ const appendChildSpy = jest
+ .spyOn(document.head, 'appendChild')
+ .mockImplementation((element: Node) => {
+ if (element instanceof HTMLScriptElement && element.onerror) {
+ setTimeout(() => {
+ (element.onerror as any)('Script load error');
+ }, 0);
+ }
+ return element;
+ });
+
+ await loader.initializeExtensions();
+
+ expect(infoSpy).toHaveBeenCalledWith(
+ expect.stringContaining('1 of 2 extension(s) failing'),
+ );
+ expect(loader.getExtension('good-ext')).toBeDefined();
+ expect(loader.getExtension('broken-ext')).toBeUndefined();
+
+ infoSpy.mockRestore();
+ appendChildSpy.mockRestore();
+});
+
+test('each extension gets an isolated getContext via module federation custom
scope', async () => {
+ const loader = ExtensionsLoader.getInstance();
+
+ // Capture the scoped @apache-superset/core instance each container receives
+ const capturedCoreModules: Array<any> = [];
Review Comment:
Fixed — replaced `Array<any>` with `Array<typeof
import('@apache-superset/core')>`, matching the captured core module shape.
##########
superset-frontend/src/extensions/ExtensionsLoader.test.ts:
##########
@@ -170,6 +213,212 @@ test('logs success after initializeExtensions completes',
async () => {
infoSpy.mockRestore();
});
+test('logs partial failure count when some extensions fail to initialize',
async () => {
+ const loader = ExtensionsLoader.getInstance();
+ const infoSpy = jest.spyOn(logging, 'info').mockImplementation();
+ jest.spyOn(SupersetClient, 'get').mockResolvedValue({
+ json: {
+ result: [
+ createMockExtension({ id: 'good-ext', remoteEntry: '' }),
+ createMockExtension({
+ id: 'broken-ext',
+ remoteEntry: 'http://broken-url/remoteEntry.js',
+ }),
+ ],
+ },
+ } as any);
+ const appendChildSpy = jest
+ .spyOn(document.head, 'appendChild')
+ .mockImplementation((element: Node) => {
+ if (element instanceof HTMLScriptElement && element.onerror) {
+ setTimeout(() => {
+ (element.onerror as any)('Script load error');
+ }, 0);
+ }
+ return element;
+ });
+
+ await loader.initializeExtensions();
+
+ expect(infoSpy).toHaveBeenCalledWith(
+ expect.stringContaining('1 of 2 extension(s) failing'),
+ );
+ expect(loader.getExtension('good-ext')).toBeDefined();
+ expect(loader.getExtension('broken-ext')).toBeUndefined();
+
+ infoSpy.mockRestore();
+ appendChildSpy.mockRestore();
+});
+
+test('each extension gets an isolated getContext via module federation custom
scope', async () => {
+ const loader = ExtensionsLoader.getInstance();
+
+ // Capture the scoped @apache-superset/core instance each container receives
+ const capturedCoreModules: Array<any> = [];
+
+ const makeContainer = () => ({
+ init: jest.fn().mockImplementation(async (scope: any) => {
Review Comment:
Fixed — typed `scope` with the existing `WebpackSharedScope` interface
instead of `any`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]