Add tests for public entry point and rename config to disablePublicEntryPoint

Signed-off-by: benjdlambert <ben@blam.sh>
This commit is contained in:
benjdlambert
2026-05-26 10:43:45 +02:00
parent ca450bec54
commit f2d71d1d48
6 changed files with 115 additions and 12 deletions
@@ -2,4 +2,4 @@
'@backstage/plugin-app-backend': patch
---
Added a new `app.disableExperimentalPublicEntryPoint` config option that allows you to opt out of the automatic public sign-in entry point. When set to `true`, the app backend will skip serving the public entry point to unauthenticated users, even if the app was bundled with an `index-public-experimental` entry point.
Added a new `app.disablePublicEntryPoint` config option that allows you to opt out of the automatic public sign-in entry point. When set to `true`, the app backend will skip serving the public entry point to unauthenticated users, even if the app was bundled with an `index-public-experimental` entry point.
+6 -6
View File
@@ -44,12 +44,12 @@ export interface Config {
disableStaticFallbackCache?: boolean;
/**
* Disables the experimental public entry point used for unauthenticated
* sign-in pages. When the app is bundled with an
* `index-public-experimental` entry point, the app backend will
* automatically serve it to unauthenticated users. Set this to `true` to
* skip that behavior and always serve the main entry point instead.
* Disables the public entry point used for unauthenticated sign-in pages.
* When the app is bundled with an `index-public-experimental` entry point,
* the app backend will automatically serve it to unauthenticated users.
* Set this to `true` to skip that behavior and always serve the main
* entry point instead.
*/
disableExperimentalPublicEntryPoint?: boolean;
disablePublicEntryPoint?: boolean;
};
}
@@ -0,0 +1 @@
this is public index.html
@@ -0,0 +1 @@
this is public main.txt
+103 -1
View File
@@ -21,7 +21,11 @@ import { resolve as resolvePath } from 'node:path';
import request from 'supertest';
import { createRouter } from './router';
import { loadConfigSchema } from '@backstage/config-loader';
import { mockServices, TestDatabases } from '@backstage/backend-test-utils';
import {
mockCredentials,
mockServices,
TestDatabases,
} from '@backstage/backend-test-utils';
jest.mock('../lib/config', () => ({
injectConfig: jest.fn(),
@@ -136,6 +140,104 @@ describe('createRouter with static fallback handler', () => {
});
});
describe('createRouter with public entry point', () => {
let app: express.Express;
beforeAll(async () => {
const router = await createRouter({
logger: mockServices.logger.mock(),
database: mockServices.database.mock(),
auth: mockServices.auth(),
httpAuth: mockServices.httpAuth({
defaultCredentials: mockCredentials.none(),
}),
config: mockServices.rootConfig({
data: {
app: { disableStaticFallbackCache: true },
},
}),
appPackageName: 'example-app',
});
app = express().use(router);
});
beforeEach(() => {
jest.resetAllMocks();
});
it('serves the public entry point to unauthenticated users', async () => {
const response = await request(app).get('/index.html');
expect(response.status).toBe(200);
expect(response.text.trim()).toBe('this is public index.html');
});
it('serves the main entry point to authenticated users', async () => {
const response = await request(app)
.get('/index.html')
.set('Cookie', mockCredentials.limitedUser.cookie());
expect(response.status).toBe(200);
expect(response.text.trim()).toBe('this is index.html');
});
it('handles sign-in and issues a user cookie', async () => {
const response = await request(app)
.post('/')
.set('Content-Type', 'application/x-www-form-urlencoded')
.send(`type=sign-in&token=${mockCredentials.user.token()}`);
expect(response.status).toBe(200);
expect(response.headers['set-cookie']).toBeDefined();
expect(response.text.trim()).toBe('this is index.html');
});
it('rejects POST requests without a sign-in type', async () => {
const response = await request(app)
.post('/')
.set('Content-Type', 'application/x-www-form-urlencoded')
.send('type=something-else');
expect(response.status).toBeGreaterThanOrEqual(400);
});
});
describe('createRouter with disablePublicEntryPoint', () => {
let app: express.Express;
beforeAll(async () => {
const router = await createRouter({
logger: mockServices.logger.mock(),
database: mockServices.database.mock(),
auth: mockServices.auth(),
httpAuth: mockServices.httpAuth({
defaultCredentials: mockCredentials.none(),
}),
config: mockServices.rootConfig({
data: {
app: {
disableStaticFallbackCache: true,
disablePublicEntryPoint: true,
},
},
}),
appPackageName: 'example-app',
});
app = express().use(router);
});
beforeEach(() => {
jest.resetAllMocks();
});
it('serves the main entry point to unauthenticated users', async () => {
const response = await request(app).get('/index.html');
expect(response.status).toBe(200);
expect(response.text.trim()).toBe('this is index.html');
});
});
describe('createRouter config schema test', () => {
const libConfigs = require('../lib/config');
const libConfigsActual = jest.requireActual('../lib/config');
+3 -4
View File
@@ -153,12 +153,11 @@ export async function createRouter(
const publicDistDir = resolvePath(appDistDir, 'public');
const disableExperimentalPublicEntryPoint = config.getOptionalBoolean(
'app.disableExperimentalPublicEntryPoint',
const disablePublicEntryPoint = config.getOptionalBoolean(
'app.disablePublicEntryPoint',
);
const enablePublicEntryPoint =
!disableExperimentalPublicEntryPoint &&
(await fs.pathExists(publicDistDir));
!disablePublicEntryPoint && (await fs.pathExists(publicDistDir));
if (enablePublicEntryPoint) {
logger.info(