frontend-app-api: capture sign-in through identity proxy

Let prepared apps observe sign-in completion through the bootstrap identity proxy instead of overriding the sign-in page component, and surface finalization failures back through the default app root.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
This commit is contained in:
Patrik Oldsberg
2026-03-15 23:20:36 +01:00
parent ab3f15f3b3
commit 756e84eb9a
3 changed files with 24 additions and 356 deletions
@@ -32,7 +32,7 @@ import {
FrontendPluginInfo,
} from '@backstage/frontend-plugin-api';
import { ThemeBlueprint } from '@backstage/plugin-app-react';
import { screen, waitFor } from '@testing-library/react';
import { act, screen, waitFor } from '@testing-library/react';
import { createApp } from './createApp';
import { mockApis, renderWithEffects } from '@backstage/test-utils';
import {
@@ -229,6 +229,7 @@ describe('createApp', () => {
getRegisteredFlags: () => [],
save: jest.fn(),
} as unknown as typeof featureFlagsApiRef.T;
let onSignInSuccess: ((identity: IdentityApi) => void) | undefined;
const app = createApp({
advanced: {
@@ -252,9 +253,7 @@ describe('createApp', () => {
function SignInPage(props: {
onSignInSuccess(identity: IdentityApi): void;
}) {
useEffect(() => {
props.onSignInSuccess(identityApi);
}, [props]);
onSignInSuccess = props.onSignInSuccess;
return <div>Custom Sign In</div>;
}
@@ -281,6 +280,16 @@ describe('createApp', () => {
});
await renderWithEffects(app.createRoot());
await expect(
screen.findByText('Custom Sign In'),
).resolves.toBeInTheDocument();
if (!onSignInSuccess) {
throw new Error('Expected sign-in success callback to be captured');
}
const triggerSignInSuccess = onSignInSuccess;
act(() => {
triggerSignInSuccess(identityApi);
});
await expect(
screen.findByText(/Error in app/),
+11 -1
View File
@@ -152,12 +152,22 @@ function PreparedAppRoot(props: {
const [finalizedApp, setFinalizedApp] = useState<
FinalizedSpecializedApp | undefined
>();
const [bootstrapError, setBootstrapError] = useState<Error | undefined>();
useEffect(
() => props.preparedApp.onFinalized(setFinalizedApp),
() => props.preparedApp.onFinalized(setFinalizedApp, setBootstrapError),
[props.preparedApp],
);
if (bootstrapError) {
return (
<>
<div>{bootstrapError.message}</div>
<h1>Error in app</h1>
</>
);
}
if (!finalizedApp) {
return bootstrapApp.element;
}