diff --git a/.changeset/strange-parents-hammer.md b/.changeset/strange-parents-hammer.md
new file mode 100644
index 0000000000..57d5eeb83d
--- /dev/null
+++ b/.changeset/strange-parents-hammer.md
@@ -0,0 +1,5 @@
+---
+'@backstage/test-utils': minor
+---
+
+Added `components` option to `TestAppOptions`, which will be forwarded as the `components` option to `createApp`.
diff --git a/packages/core-components/package.json b/packages/core-components/package.json
index 25d7fe111c..4c635b184c 100644
--- a/packages/core-components/package.json
+++ b/packages/core-components/package.json
@@ -92,6 +92,7 @@
"react-router-dom": "6.0.0-beta.0 || ^6.3.0"
},
"devDependencies": {
+ "@backstage/app-defaults": "workspace:^",
"@backstage/cli": "workspace:^",
"@backstage/core-app-api": "workspace:^",
"@backstage/test-utils": "workspace:^",
diff --git a/packages/core-components/src/layout/ProxiedSignInPage/ProxiedSignInPage.test.tsx b/packages/core-components/src/layout/ProxiedSignInPage/ProxiedSignInPage.test.tsx
new file mode 100644
index 0000000000..3f0c01b56b
--- /dev/null
+++ b/packages/core-components/src/layout/ProxiedSignInPage/ProxiedSignInPage.test.tsx
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import { render, screen } from '@testing-library/react';
+import { rest } from 'msw';
+import { setupServer } from 'msw/node';
+import {
+ TestApiProvider,
+ setupRequestMockHandlers,
+ wrapInTestApp,
+} from '@backstage/test-utils';
+import { ProxiedSignInPage } from './ProxiedSignInPage';
+import { discoveryApiRef } from '@backstage/core-plugin-api';
+
+describe('ProxiedSignInPage', () => {
+ const worker = setupServer();
+ setupRequestMockHandlers(worker);
+
+ const Subject = wrapInTestApp(
authenticated
, {
+ components: {
+ SignInPage: props => (
+ 'http://example.com/api/auth',
+ },
+ ],
+ ]}
+ >
+
+
+ ),
+ },
+ });
+
+ it('should sign in a user', async () => {
+ worker.use(
+ rest.get('http://example.com/api/auth/test/refresh', (_, res, ctx) =>
+ res(
+ ctx.status(200),
+ ctx.set('Content-Type', 'application/json'),
+ ctx.json({
+ profile: {
+ email: 'e',
+ displayName: 'd',
+ picture: 'p',
+ },
+ backstageIdentity: {
+ token: 'a.e30.c',
+ identity: {
+ type: 'user',
+ userEntityRef: 'k:ns/ue',
+ ownershipEntityRefs: ['k:ns/oe'],
+ },
+ },
+ }),
+ ),
+ ),
+ );
+
+ render(Subject);
+
+ await expect(
+ screen.findByText('authenticated'),
+ ).resolves.toBeInTheDocument();
+ });
+
+ it('should forward error', async () => {
+ worker.use(
+ rest.get('http://example.com/api/auth/test/refresh', (_, res, ctx) =>
+ res(
+ ctx.status(401),
+ ctx.set('Content-Type', 'application/json'),
+ ctx.json({
+ error: { name: 'Error', message: 'not-displayed' },
+ }),
+ ),
+ ),
+ );
+
+ render(Subject);
+
+ await expect(
+ screen.findByText('Request failed with 401 Error'),
+ ).resolves.toBeInTheDocument();
+ });
+});
diff --git a/packages/test-utils/api-report.md b/packages/test-utils/api-report.md
index 913413acd1..e31a820a1c 100644
--- a/packages/test-utils/api-report.md
+++ b/packages/test-utils/api-report.md
@@ -7,6 +7,7 @@ import { AnalyticsApi } from '@backstage/core-plugin-api';
import { AnalyticsEvent } from '@backstage/core-plugin-api';
import { ApiHolder } from '@backstage/core-plugin-api';
import { ApiRef } from '@backstage/core-plugin-api';
+import { AppComponents } from '@backstage/core-plugin-api';
import { AuthorizeResult } from '@backstage/plugin-permission-common';
import { ComponentType } from 'react';
import { Config } from '@backstage/config';
@@ -243,6 +244,7 @@ export type TestAppOptions = {
mountedRoutes?: {
[path: string]: RouteRef | ExternalRouteRef;
};
+ components?: Partial;
};
// @public
diff --git a/packages/test-utils/src/testUtils/appWrappers.tsx b/packages/test-utils/src/testUtils/appWrappers.tsx
index 8bc69e184a..f2c1ff592e 100644
--- a/packages/test-utils/src/testUtils/appWrappers.tsx
+++ b/packages/test-utils/src/testUtils/appWrappers.tsx
@@ -25,6 +25,7 @@ import { themes, UnifiedThemeProvider } from '@backstage/theme';
import MockIcon from '@material-ui/icons/AcUnit';
import { createSpecializedApp } from '@backstage/core-app-api';
import {
+ AppComponents,
attachComponentData,
BootErrorPageProps,
createRouteRef,
@@ -101,6 +102,11 @@ export type TestAppOptions = {
* const link = useRouteRef(myRouteRef)
*/
mountedRoutes?: { [path: string]: RouteRef | ExternalRouteRef };
+
+ /**
+ * Components to be forwarded to the `components` option of `createApp`.
+ */
+ components?: Partial;
};
function isExternalRouteRef(
@@ -137,6 +143,7 @@ export function createTestAppWrapper(
Router: ({ children }) => (
),
+ ...options.components,
},
icons: mockIcons,
plugins: [],
diff --git a/yarn.lock b/yarn.lock
index 6be53d3402..ba784c04d7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3921,6 +3921,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@backstage/core-components@workspace:packages/core-components"
dependencies:
+ "@backstage/app-defaults": "workspace:^"
"@backstage/cli": "workspace:^"
"@backstage/config": "workspace:^"
"@backstage/core-app-api": "workspace:^"