diff --git a/.changeset/three-kiwis-turn.md b/.changeset/three-kiwis-turn.md
new file mode 100644
index 0000000000..eb67cbbbdc
--- /dev/null
+++ b/.changeset/three-kiwis-turn.md
@@ -0,0 +1,19 @@
+---
+'@backstage/frontend-test-utils': patch
+---
+
+Deprecate the `.render` method of the `createExtensionTester` in favour of using `renderInTestApp` directly.
+
+```tsx
+import {
+ renderInTestApp,
+ createExtensionTester,
+} from '@backstage/frontend-test-utils';
+
+const tester = createExtensionTester(extension);
+
+const { getByTestId } = renderInTestApp(tester.reactElement());
+
+// or if you're not using `coreExtensionData.reactElement` as the output ref
+const { getByTestId } = renderInTestApp(tester.get(myComponentRef));
+```
diff --git a/packages/frontend-plugin-api/src/blueprints/NavItemBlueprint.test.tsx b/packages/frontend-plugin-api/src/blueprints/NavItemBlueprint.test.tsx
index 94b9e7b8e6..daa21f88bb 100644
--- a/packages/frontend-plugin-api/src/blueprints/NavItemBlueprint.test.tsx
+++ b/packages/frontend-plugin-api/src/blueprints/NavItemBlueprint.test.tsx
@@ -77,7 +77,7 @@ describe('NavItemBlueprint', () => {
const tester = createExtensionTester(extension);
- expect(tester.data(NavItemBlueprint.dataRefs.target)).toEqual({
+ expect(tester.get(NavItemBlueprint.dataRefs.target)).toEqual({
title: 'TEST',
icon: MockIcon,
routeRef: mockRouteRef,
@@ -97,7 +97,7 @@ describe('NavItemBlueprint', () => {
config: { title: 'OVERRIDDEN' },
});
- expect(tester.data(NavItemBlueprint.dataRefs.target)).toEqual({
+ expect(tester.get(NavItemBlueprint.dataRefs.target)).toEqual({
title: 'OVERRIDDEN',
icon: MockIcon,
routeRef: mockRouteRef,
diff --git a/packages/frontend-plugin-api/src/blueprints/NavLogoBlueprint.test.tsx b/packages/frontend-plugin-api/src/blueprints/NavLogoBlueprint.test.tsx
index 4a96475cf5..b976196080 100644
--- a/packages/frontend-plugin-api/src/blueprints/NavLogoBlueprint.test.tsx
+++ b/packages/frontend-plugin-api/src/blueprints/NavLogoBlueprint.test.tsx
@@ -64,7 +64,7 @@ describe('NavLogoBlueprint', () => {
const tester = createExtensionTester(extension);
- expect(tester.data(NavLogoBlueprint.dataRefs.logoElements)).toEqual({
+ expect(tester.get(NavLogoBlueprint.dataRefs.logoElements)).toEqual({
logoFull,
logoIcon,
});
diff --git a/packages/frontend-plugin-api/src/blueprints/PageBlueprint.test.tsx b/packages/frontend-plugin-api/src/blueprints/PageBlueprint.test.tsx
index c4bcb4b467..dedc5454bd 100644
--- a/packages/frontend-plugin-api/src/blueprints/PageBlueprint.test.tsx
+++ b/packages/frontend-plugin-api/src/blueprints/PageBlueprint.test.tsx
@@ -16,7 +16,10 @@
import React from 'react';
import { createRouteRef } from '../routing';
import { PageBlueprint } from './PageBlueprint';
-import { createExtensionTester } from '@backstage/frontend-test-utils';
+import {
+ createExtensionTester,
+ renderInTestApp,
+} from '@backstage/frontend-test-utils';
import {
coreExtensionData,
createExtensionBlueprint,
@@ -98,7 +101,7 @@ describe('PageBlueprint', () => {
// TODO(blam): test for the routePath output doesn't work, due to the the way the test harness works
// expect(tester.data(coreExtensionData.routePath)).toBe('/test');
- expect(tester.data(coreExtensionData.routeRef)).toBe(mockRouteRef);
+ expect(tester.get(coreExtensionData.routeRef)).toBe(mockRouteRef);
const { getByTestId } = tester.render();
@@ -144,7 +147,7 @@ describe('PageBlueprint', () => {
CardBlueprint.make({ name: 'card', params: {} }),
);
- const { getByTestId, getByText } = tester.render();
+ const { getByTestId, getByText } = renderInTestApp(tester.reactElement());
await waitFor(() => expect(getByTestId('card')).toBeInTheDocument());
await waitFor(() =>
diff --git a/packages/frontend-plugin-api/src/blueprints/SignInPageBlueprint.test.tsx b/packages/frontend-plugin-api/src/blueprints/SignInPageBlueprint.test.tsx
index f97798a64c..e6389da574 100644
--- a/packages/frontend-plugin-api/src/blueprints/SignInPageBlueprint.test.tsx
+++ b/packages/frontend-plugin-api/src/blueprints/SignInPageBlueprint.test.tsx
@@ -16,9 +16,11 @@
import React from 'react';
import { SignInPageBlueprint } from './SignInPageBlueprint';
-import { createExtensionTester } from '@backstage/frontend-test-utils';
+import {
+ createExtensionTester,
+ renderInTestApp,
+} from '@backstage/frontend-test-utils';
import { screen, waitFor } from '@testing-library/react';
-import { coreExtensionData, createExtension } from '../wiring';
describe('SignInPageBlueprint', () => {
it('should create an extension with sensible defaults', () => {
@@ -60,20 +62,9 @@ describe('SignInPageBlueprint', () => {
const tester = createExtensionTester(extension);
- expect(tester.data(SignInPageBlueprint.dataRefs.component)).toBeDefined();
+ const Component = tester.get(SignInPageBlueprint.dataRefs.component);
- createExtensionTester(
- createExtension({
- name: 'dummy',
- attachTo: { id: 'ignored', input: 'ignored' },
- output: {
- element: coreExtensionData.reactElement,
- },
- factory: () => ({ element:
}),
- }),
- )
- .add(extension)
- .render();
+ renderInTestApp( {}} />);
await waitFor(() => {
expect(screen.getByTestId('mock-sign-in')).toBeInTheDocument();
diff --git a/packages/frontend-plugin-api/src/blueprints/ThemeBlueprint.test.ts b/packages/frontend-plugin-api/src/blueprints/ThemeBlueprint.test.ts
index 40323b6a31..e6daf510eb 100644
--- a/packages/frontend-plugin-api/src/blueprints/ThemeBlueprint.test.ts
+++ b/packages/frontend-plugin-api/src/blueprints/ThemeBlueprint.test.ts
@@ -56,7 +56,7 @@ describe('ThemeBlueprint', () => {
const extension = ThemeBlueprint.make({ params: { theme } });
expect(
- createExtensionTester(extension).data(ThemeBlueprint.dataRefs.theme),
+ createExtensionTester(extension).get(ThemeBlueprint.dataRefs.theme),
).toEqual(theme);
});
});
diff --git a/packages/frontend-plugin-api/src/blueprints/TranslationBlueprint.test.ts b/packages/frontend-plugin-api/src/blueprints/TranslationBlueprint.test.ts
index dfb918053a..3c7b271322 100644
--- a/packages/frontend-plugin-api/src/blueprints/TranslationBlueprint.test.ts
+++ b/packages/frontend-plugin-api/src/blueprints/TranslationBlueprint.test.ts
@@ -76,7 +76,7 @@ describe('TranslationBlueprint', () => {
});
expect(
- createExtensionTester(extension).data(
+ createExtensionTester(extension).get(
TranslationBlueprint.dataRefs.translation,
),
).toBe(messages);
diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.test.ts b/packages/frontend-plugin-api/src/wiring/createExtension.test.ts
index e33bdcb9a1..5902c5c3e7 100644
--- a/packages/frontend-plugin-api/src/wiring/createExtension.test.ts
+++ b/packages/frontend-plugin-api/src/wiring/createExtension.test.ts
@@ -688,7 +688,7 @@ describe('createExtension', () => {
const tester = createExtensionTester(overridden);
- expect(tester.data(numberDataRef)).toBe(43);
+ expect(tester.get(numberDataRef)).toBe(43);
});
it('should work functionally with overrides', () => {
@@ -722,14 +722,14 @@ describe('createExtension', () => {
},
});
- expect(createExtensionTester(overriden).data(stringDataRef)).toBe(
+ expect(createExtensionTester(overriden).get(stringDataRef)).toBe(
'foo-boom-override-hello',
);
expect(
createExtensionTester(overriden, {
config: { foo: 'hello', bar: 'world' },
- }).data(stringDataRef),
+ }).get(stringDataRef),
).toBe('foo-hello-override-world');
});
@@ -809,7 +809,7 @@ describe('createExtension', () => {
.add(singleExt)
.add(multi1Ext)
.add(multi2Ext)
- .data(outputRef),
+ .get(outputRef),
).toEqual({
opt: 'orig-opt',
single: 'orig-single',
@@ -836,7 +836,7 @@ describe('createExtension', () => {
.add(singleExt)
.add(multi1Ext)
.add(multi2Ext)
- .data(outputRef),
+ .get(outputRef),
).toEqual({
opt: 'opt',
single: 'single',
@@ -862,7 +862,7 @@ describe('createExtension', () => {
.add(singleExt)
.add(multi1Ext)
.add(multi2Ext)
- .data(outputRef),
+ .get(outputRef),
).toEqual({
opt: 'none',
single: 'single',
@@ -885,7 +885,7 @@ describe('createExtension', () => {
.add(singleExt)
.add(multi1Ext)
.add(multi2Ext)
- .data(outputRef),
+ .get(outputRef),
).toEqual({
opt: 'orig-opt',
single: 'orig-single',
@@ -912,7 +912,7 @@ describe('createExtension', () => {
.add(singleExt)
.add(multi1Ext)
.add(multi2Ext)
- .data(outputRef),
+ .get(outputRef),
).toEqual({
opt: 'orig-opt',
single: 'orig-single',
@@ -939,7 +939,7 @@ describe('createExtension', () => {
.add(singleExt)
.add(multi1Ext)
.add(multi2Ext)
- .data(outputRef),
+ .get(outputRef),
).toEqual({
opt: 'orig-opt',
single: 'orig-single',
@@ -966,7 +966,7 @@ describe('createExtension', () => {
.add(singleExt)
.add(multi1Ext)
.add(multi2Ext)
- .data(outputRef),
+ .get(outputRef),
).toEqual({
opt: 'orig-opt',
single: 'orig-single',
@@ -997,7 +997,7 @@ describe('createExtension', () => {
.add(singleExt)
.add(multi1Ext)
.add(multi2Ext)
- .data(outputRef),
+ .get(outputRef),
).toEqual({
opt: 'none',
single: 'override-orig-single',
@@ -1023,7 +1023,7 @@ describe('createExtension', () => {
.add(singleExt)
.add(multi1Ext)
.add(multi2Ext)
- .data(outputRef),
+ .get(outputRef),
).toThrowErrorMatchingInlineSnapshot(
`"Failed to instantiate extension 'subject', override data provided for input 'multi' must match the length of the original inputs"`,
);
@@ -1046,7 +1046,7 @@ describe('createExtension', () => {
.add(singleExt)
.add(multi1Ext)
.add(multi2Ext)
- .data(outputRef),
+ .get(outputRef),
).toThrowErrorMatchingInlineSnapshot(
`"Failed to instantiate extension 'subject', override data for input 'multi' may not mix forwarded inputs with data overrides"`,
);
@@ -1069,7 +1069,7 @@ describe('createExtension', () => {
.add(singleExt)
.add(multi1Ext)
.add(multi2Ext)
- .data(outputRef),
+ .get(outputRef),
).toThrowErrorMatchingInlineSnapshot(
`"Failed to instantiate extension 'subject', missing required extension data value(s) 'test1'"`,
);
@@ -1098,7 +1098,7 @@ describe('createExtension', () => {
.add(singleExt)
.add(multi1Ext)
.add(multi2Ext)
- .data(outputRef),
+ .get(outputRef),
).toThrowErrorMatchingInlineSnapshot(
`"Failed to instantiate extension 'subject', extension data 'test2' was provided but not declared"`,
);
diff --git a/packages/frontend-test-utils/api-report.md b/packages/frontend-test-utils/api-report.md
index 3aa9069219..164c222d84 100644
--- a/packages/frontend-test-utils/api-report.md
+++ b/packages/frontend-test-utils/api-report.md
@@ -7,6 +7,7 @@
import { AnalyticsApi } from '@backstage/frontend-plugin-api';
import { AnalyticsEvent } from '@backstage/frontend-plugin-api';
+import { AnyExtensionDataRef } from '@backstage/frontend-plugin-api';
import { AppNode } from '@backstage/frontend-plugin-api';
import { AppNodeInstance } from '@backstage/frontend-plugin-api';
import { ErrorWithContext } from '@backstage/test-utils';
@@ -30,20 +31,30 @@ import { TestApiRegistry } from '@backstage/test-utils';
import { withLogCollector } from '@backstage/test-utils';
// @public (undocumented)
-export function createExtensionTester(
- subject: ExtensionDefinition,
+export function createExtensionTester<
+ TConfig,
+ TConfigInput,
+ UOutput extends AnyExtensionDataRef,
+>(
+ subject: ExtensionDefinition,
options?: {
- config?: TConfig;
+ config?: TConfigInput;
},
-): ExtensionTester;
+): ExtensionTester;
export { ErrorWithContext };
// @public (undocumented)
-export class ExtensionQuery {
+export class ExtensionQuery {
constructor(node: AppNode);
// (undocumented)
- data(ref: ExtensionDataRef): T | undefined;
+ get(
+ ref: ExtensionDataRef,
+ ): UOutput extends ExtensionDataRef
+ ? IConfig['optional'] extends true
+ ? IData | undefined
+ : IData
+ : never;
// (undocumented)
get instance(): AppNodeInstance;
// (undocumented)
@@ -51,19 +62,29 @@ export class ExtensionQuery {
}
// @public (undocumented)
-export class ExtensionTester {
+export class ExtensionTester {
// (undocumented)
add(
extension: ExtensionDefinition,
options?: {
config?: TConfigInput;
},
- ): ExtensionTester;
+ ): ExtensionTester;
// (undocumented)
- data(ref: ExtensionDataRef): T | undefined;
+ get(
+ ref: ExtensionDataRef,
+ ): UOutput extends ExtensionDataRef
+ ? IConfig['optional'] extends true
+ ? IData | undefined
+ : IData
+ : never;
// (undocumented)
- query(id: string | ExtensionDefinition): ExtensionQuery;
+ query(
+ extension: ExtensionDefinition,
+ ): ExtensionQuery;
// (undocumented)
+ reactElement(): JSX.Element;
+ // @deprecated (undocumented)
render(options?: { config?: JsonObject }): RenderResult;
}
@@ -117,6 +138,7 @@ export type TestAppOptions = {
mountedRoutes?: {
[path: string]: RouteRef;
};
+ config?: JsonObject;
};
export { withLogCollector };
diff --git a/packages/frontend-test-utils/src/app/createExtensionTester.test.tsx b/packages/frontend-test-utils/src/app/createExtensionTester.test.tsx
index 889c815fc7..73220419b7 100644
--- a/packages/frontend-test-utils/src/app/createExtensionTester.test.tsx
+++ b/packages/frontend-test-utils/src/app/createExtensionTester.test.tsx
@@ -240,13 +240,13 @@ describe('createExtensionTester', () => {
const extension = createExtension({
namespace: 'test',
attachTo: { id: 'ignored', input: 'ignored' },
- output: { text: stringDataRef },
- factory: () => ({ text: 'test-text' }),
+ output: [stringDataRef],
+ factory: () => [stringDataRef('test-text')],
});
const tester = createExtensionTester(extension);
- expect(tester.data(stringDataRef)).toBe('test-text');
+ expect(tester.get(stringDataRef)).toBe('test-text');
});
it('should throw an error if trying to access an instance not provided to the tester', () => {
@@ -297,6 +297,79 @@ describe('createExtensionTester', () => {
);
});
+ it('should not allow getting extension data for an output that was not defined in the extension', () => {
+ const internalRef = createExtensionDataRef().with({
+ id: 'test.internal',
+ });
+
+ const internalRef2 = createExtensionDataRef().with({
+ id: 'test.internal2',
+ });
+
+ const extension = createExtension({
+ namespace: 'test',
+ name: 'e1',
+ attachTo: { id: 'ignored', input: 'ignored' },
+ output: [stringDataRef, internalRef.optional()],
+ factory: () => [stringDataRef('test-text')],
+ });
+
+ const tester = createExtensionTester(extension);
+
+ const test: string = tester.get(stringDataRef);
+
+ // @ts-expect-error - internalRef is optional
+ const test2: number = tester.get(internalRef);
+
+ // @ts-expect-error - internalRef2 is not defined in the extension
+ const test3: number = tester.get(internalRef2);
+
+ expect([test, test2, test3]).toBeDefined();
+ });
+
+ it('should support getting outputs from a query response', () => {
+ const internalRef = createExtensionDataRef().with({
+ id: 'test.internal',
+ });
+
+ const internalRef2 = createExtensionDataRef().with({
+ id: 'test.internal2',
+ });
+
+ const extension = createExtension({
+ namespace: 'test',
+ name: 'e1',
+ inputs: {
+ ignored: createExtensionInput([stringDataRef]),
+ },
+ attachTo: { id: 'ignored', input: 'ignored' },
+ output: [coreExtensionData.reactElement],
+ factory: () => [coreExtensionData.reactElement(bob
)],
+ });
+
+ const extraExtension = createExtension({
+ namespace: 'test',
+ name: 'e2',
+ attachTo: { id: 'test/e1', input: 'ignored' },
+ output: [stringDataRef, internalRef.optional()],
+ factory: () => [stringDataRef('test-text')],
+ });
+
+ const tester = createExtensionTester(extension)
+ .add(extraExtension)
+ .query(extraExtension);
+
+ const test: string = tester.get(stringDataRef);
+
+ // @ts-expect-error - internalRef is optional
+ const test2: number = tester.get(internalRef);
+
+ // @ts-expect-error - internalRef2 is not defined in the extension
+ const test3: number = tester.get(internalRef2);
+
+ expect([test, test2, test3]).toBeDefined();
+ });
+
// TODO: this should be implemented
// eslint-disable-next-line jest/no-disabled-tests
it.skip('should allow querying an extension and getting outputs', () => {
@@ -328,8 +401,10 @@ describe('createExtensionTester', () => {
const tester = createExtensionTester(extension).add(extension2);
- expect(tester.query(extension).data(stringDataRef)).toBe('nest-test-text');
- expect(tester.query(extension2).data(stringDataRef)).toBe('test-text');
+ // @ts-expect-error
+ expect(tester.query(extension).get(stringDataRef)).toBe('nest-test-text');
+ // @ts-expect-error
+ expect(tester.query(extension2).get(stringDataRef)).toBe('test-text');
// @ts-expect-error
expect(tester.query(extension).input('input').data(stringDataRef)).toBe(
'nest-test-text',
@@ -362,6 +437,7 @@ describe('createExtensionTester', () => {
inputs: { input: 'test-text' },
});
- expect(tester.query(extension).data(stringDataRef)).toBe('nest-test-text');
+ // @ts-expect-error
+ expect(tester.query(extension).get(stringDataRef)).toBe('nest-test-text');
});
});
diff --git a/packages/frontend-test-utils/src/app/createExtensionTester.tsx b/packages/frontend-test-utils/src/app/createExtensionTester.tsx
index 4bfc8392cb..b3c1b385e3 100644
--- a/packages/frontend-test-utils/src/app/createExtensionTester.tsx
+++ b/packages/frontend-test-utils/src/app/createExtensionTester.tsx
@@ -19,6 +19,7 @@ import { MemoryRouter, Link } from 'react-router-dom';
import { RenderResult, render } from '@testing-library/react';
import { createSpecializedApp } from '@backstage/frontend-app-api';
import {
+ AnyExtensionDataRef,
AppNode,
AppTree,
Extension,
@@ -101,7 +102,7 @@ const TestAppNavExtension = createExtension({
});
/** @public */
-export class ExtensionQuery {
+export class ExtensionQuery {
#node: AppNode;
constructor(node: AppNode) {
@@ -124,18 +125,24 @@ export class ExtensionQuery {
return instance;
}
- data(ref: ExtensionDataRef): T | undefined {
+ get(
+ ref: ExtensionDataRef,
+ ): UOutput extends ExtensionDataRef
+ ? IConfig['optional'] extends true
+ ? IData | undefined
+ : IData
+ : never {
return this.instance.getData(ref);
}
}
/** @public */
-export class ExtensionTester {
+export class ExtensionTester {
/** @internal */
- static forSubject(
+ static forSubject(
subject: ExtensionDefinition,
options?: { config?: TConfigInput },
- ): ExtensionTester {
+ ): ExtensionTester {
const tester = new ExtensionTester();
const internal = toInternalExtensionDefinition(subject);
@@ -192,7 +199,7 @@ export class ExtensionTester {
add(
extension: ExtensionDefinition,
options?: { config?: TConfigInput },
- ): ExtensionTester {
+ ): ExtensionTester {
if (this.#tree) {
throw new Error(
'Cannot add more extensions accessing the extension tree',
@@ -219,17 +226,24 @@ export class ExtensionTester {
return this;
}
- data(ref: ExtensionDataRef): T | undefined {
+ get(
+ ref: ExtensionDataRef,
+ ): UOutput extends ExtensionDataRef
+ ? IConfig['optional'] extends true
+ ? IData | undefined
+ : IData
+ : never {
const tree = this.#resolveTree();
- return new ExtensionQuery(tree.root).data(ref);
+ return new ExtensionQuery(tree.root).get(ref);
}
- query(id: string | ExtensionDefinition): ExtensionQuery {
+ query(
+ extension: ExtensionDefinition,
+ ): ExtensionQuery {
const tree = this.#resolveTree();
- const actualId =
- typeof id === 'string' ? id : resolveExtensionDefinition(id).id;
+ const actualId = resolveExtensionDefinition(extension).id;
const node = tree.nodes.get(actualId);
@@ -245,6 +259,25 @@ export class ExtensionTester {
return new ExtensionQuery(node);
}
+ reactElement(): JSX.Element {
+ const tree = this.#resolveTree();
+
+ const element = new ExtensionQuery(tree.root).get(
+ coreExtensionData.reactElement,
+ );
+
+ if (!element) {
+ throw new Error(
+ 'No element found. Make sure the extension has a `coreExtensionData.reactElement` output, or use the `.get(...)` to access output data directly instead',
+ );
+ }
+
+ return element;
+ }
+
+ /**
+ * @deprecated Switch to using `renderInTestApp` directly and using `.reactElement()` or `.get(...)` to get the component you w
+ */
render(options?: { config?: JsonObject }): RenderResult {
const { config = {} } = options ?? {};
@@ -336,9 +369,13 @@ export class ExtensionTester {
}
/** @public */
-export function createExtensionTester(
- subject: ExtensionDefinition,
- options?: { config?: TConfig },
-): ExtensionTester {
+export function createExtensionTester<
+ TConfig,
+ TConfigInput,
+ UOutput extends AnyExtensionDataRef,
+>(
+ subject: ExtensionDefinition,
+ options?: { config?: TConfigInput },
+): ExtensionTester {
return ExtensionTester.forSubject(subject, options);
}
diff --git a/packages/frontend-test-utils/src/app/renderInTestApp.tsx b/packages/frontend-test-utils/src/app/renderInTestApp.tsx
index e0483f68d8..dd03cdd2a2 100644
--- a/packages/frontend-test-utils/src/app/renderInTestApp.tsx
+++ b/packages/frontend-test-utils/src/app/renderInTestApp.tsx
@@ -15,12 +15,23 @@
*/
import React from 'react';
+import { Link, MemoryRouter } from 'react-router-dom';
+import { createSpecializedApp } from '@backstage/frontend-app-api';
+import { RenderResult, render } from '@testing-library/react';
+import { ConfigReader } from '@backstage/config';
+import { JsonObject } from '@backstage/types';
import {
- RouteRef,
- coreExtensionData,
createExtension,
+ createExtensionOverrides,
+ ExtensionDefinition,
+ coreExtensionData,
+ RouteRef,
+ useRouteRef,
+ createExtensionInput,
+ IconComponent,
+ createNavItemExtension,
+ RouterBlueprint,
} from '@backstage/frontend-plugin-api';
-import { createExtensionTester } from './createExtensionTester';
/**
* Options to customize the behavior of the test app.
@@ -44,8 +55,66 @@ export type TestAppOptions = {
* ```
*/
mountedRoutes?: { [path: string]: RouteRef };
+
+ /**
+ * Additional configuration passed to the app when rendering elements inside it.
+ */
+ config?: JsonObject;
};
+const NavItem = (props: {
+ routeRef: RouteRef;
+ title: string;
+ icon: IconComponent;
+}) => {
+ const { routeRef, title, icon: Icon } = props;
+ const link = useRouteRef(routeRef);
+ if (!link) {
+ return null;
+ }
+ return (
+
+
+ {title}
+
+
+ );
+};
+
+export const TestAppNavExtension = createExtension({
+ namespace: 'app',
+ name: 'nav',
+ attachTo: { id: 'app/layout', input: 'nav' },
+ inputs: {
+ items: createExtensionInput([createNavItemExtension.targetDataRef]),
+ },
+ output: [coreExtensionData.reactElement],
+ factory({ inputs }) {
+ return [
+ coreExtensionData.reactElement(
+ ,
+ ),
+ ];
+ },
+});
+
/**
* @public
* Renders the given element in a test app, for use in unit tests.
@@ -53,21 +122,32 @@ export type TestAppOptions = {
export function renderInTestApp(
element: JSX.Element,
options?: TestAppOptions,
-) {
- const extension = createExtension({
- namespace: 'test',
- attachTo: { id: 'app', input: 'root' },
- output: {
- element: coreExtensionData.reactElement,
- },
- factory: () => ({ element }),
- });
- const tester = createExtensionTester(extension);
+): RenderResult {
+ const extensions: Array> = [
+ createExtension({
+ namespace: 'test',
+ attachTo: { id: 'app/routes', input: 'routes' },
+ output: [coreExtensionData.reactElement, coreExtensionData.routePath],
+ factory: () => {
+ return [
+ coreExtensionData.reactElement(element),
+ coreExtensionData.routePath('/'),
+ ];
+ },
+ }),
+ RouterBlueprint.make({
+ namespace: 'test',
+ params: {
+ Component: ({ children }) => {children},
+ },
+ }),
+ TestAppNavExtension,
+ ];
if (options?.mountedRoutes) {
for (const [path, routeRef] of Object.entries(options.mountedRoutes)) {
// TODO(Rugvip): add support for external route refs
- tester.add(
+ extensions.push(
createExtension({
kind: 'test-route',
name: path,
@@ -84,5 +164,17 @@ export function renderInTestApp(
);
}
}
- return tester.render();
+
+ const app = createSpecializedApp({
+ features: [
+ createExtensionOverrides({
+ extensions,
+ }),
+ ],
+ config: ConfigReader.fromConfigs([
+ { context: 'render-config', data: options?.config ?? {} },
+ ]),
+ });
+
+ return render(app.createRoot());
}
diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.test.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.test.tsx
index db787766fd..0cb7cdead8 100644
--- a/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.test.tsx
+++ b/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.test.tsx
@@ -100,7 +100,7 @@ describe('EntityCardBlueprint', () => {
filter: 'test',
},
}),
- ).data(EntityCardBlueprint.dataRefs.filterExpression),
+ ).get(EntityCardBlueprint.dataRefs.filterExpression),
).toBe('test');
expect(
@@ -112,7 +112,7 @@ describe('EntityCardBlueprint', () => {
},
}),
{ config: { filter: 'test' } },
- ).data(EntityCardBlueprint.dataRefs.filterExpression),
+ ).get(EntityCardBlueprint.dataRefs.filterExpression),
).toBe('test');
expect(
@@ -124,7 +124,7 @@ describe('EntityCardBlueprint', () => {
loader: async () => Test!
,
},
}),
- ).data(EntityCardBlueprint.dataRefs.filterFunction),
+ ).get(EntityCardBlueprint.dataRefs.filterFunction),
).toBe(mockFilter);
});
diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.test.tsx b/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.test.tsx
index dab6013bab..5d91f402de 100644
--- a/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.test.tsx
+++ b/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.test.tsx
@@ -122,10 +122,10 @@ describe('EntityContentBlueprint', () => {
const tester = createExtensionTester(extension);
// todo(blam): route paths are always set to / in the createExtensionTester. This will work eventually.
- // expect(tester.data(coreExtensionData.routePath)).toBe('/test');
+ // expect(tester.get(coreExtensionData.routePath)).toBe('/test');
- expect(tester.data(coreExtensionData.routeRef)).toBe(mockRouteRef);
- expect(tester.data(EntityContentBlueprint.dataRefs.title)).toBe('Test');
+ expect(tester.get(coreExtensionData.routeRef)).toBe(mockRouteRef);
+ expect(tester.get(EntityContentBlueprint.dataRefs.title)).toBe('Test');
});
it('should emit the correct filter output', () => {
@@ -142,7 +142,7 @@ describe('EntityContentBlueprint', () => {
filter: 'test',
},
}),
- ).data(EntityContentBlueprint.dataRefs.filterExpression),
+ ).get(EntityContentBlueprint.dataRefs.filterExpression),
).toBe('test');
expect(
@@ -156,7 +156,7 @@ describe('EntityContentBlueprint', () => {
},
}),
{ config: { filter: 'test' } },
- ).data(EntityContentBlueprint.dataRefs.filterExpression),
+ ).get(EntityContentBlueprint.dataRefs.filterExpression),
).toBe('test');
expect(
@@ -170,7 +170,7 @@ describe('EntityContentBlueprint', () => {
loader: async () => Test!
,
},
}),
- ).data(EntityContentBlueprint.dataRefs.filterFunction),
+ ).get(EntityContentBlueprint.dataRefs.filterFunction),
).toBe(mockFilter);
});