mirror of
https://github.com/logto-io/logto.git
synced 2025-02-03 21:48:55 -05:00
111 lines
3.6 KiB
TypeScript
111 lines
3.6 KiB
TypeScript
import { GlobalValues, UrlSet } from '@logto/shared';
|
|
import { createMockUtils } from '@logto/shared/esm';
|
|
import type { RequestMethod } from 'node-mocks-http';
|
|
|
|
import createMockContext from '#src/test-utils/jest-koa-mocks/create-mock-context.js';
|
|
|
|
const { jest } = import.meta;
|
|
|
|
const { mockEsmWithActual } = createMockUtils(jest);
|
|
|
|
await mockEsmWithActual('#src/env-set/index.js', () => ({
|
|
EnvSet: {
|
|
get values() {
|
|
return new GlobalValues();
|
|
},
|
|
},
|
|
}));
|
|
|
|
const { default: koaCors } = await import('./koa-cors.js');
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
const noop = async () => {};
|
|
|
|
const mockContext = (method: RequestMethod, url: string) => {
|
|
const ctx = createMockContext({ method, headers: { origin: new URL(url).origin } });
|
|
|
|
const setSpy = jest.spyOn(ctx, 'set');
|
|
|
|
return [ctx, setSpy] as const;
|
|
};
|
|
|
|
const expectCorsHeaders = (setSpy: jest.SpyInstance, origin: string) => {
|
|
if (origin) {
|
|
expect(setSpy).toHaveBeenCalledWith('Access-Control-Expose-Headers', '*');
|
|
expect(setSpy).toHaveBeenCalledWith('Access-Control-Allow-Origin', origin);
|
|
} else {
|
|
expect(setSpy).not.toHaveBeenCalledWith(
|
|
'Access-Control-Expose-Headers',
|
|
expect.stringMatching('.*')
|
|
);
|
|
expect(setSpy).not.toHaveBeenCalledWith(
|
|
'Access-Control-Allow-Origin',
|
|
expect.stringMatching('.*')
|
|
);
|
|
}
|
|
};
|
|
|
|
describe('koaCors() middleware', () => {
|
|
const envBackup = Object.freeze({ ...process.env });
|
|
|
|
afterEach(() => {
|
|
process.env = { ...envBackup };
|
|
});
|
|
|
|
it('should set proper CORS response headers for a single URL Set', async () => {
|
|
const endpoint = 'https://logto.io';
|
|
process.env.ENDPOINT = endpoint;
|
|
process.env.NODE_ENV = 'dev';
|
|
const urlSet = new UrlSet(false, 3001);
|
|
const run = koaCors(urlSet);
|
|
|
|
const [ctx1, setSpy1] = mockContext('GET', endpoint + '/api');
|
|
await run(ctx1, noop);
|
|
expectCorsHeaders(setSpy1, endpoint);
|
|
|
|
const [ctx2, setSpy2] = mockContext('GET', 'http://localhost:3001/api');
|
|
await run(ctx2, noop);
|
|
expectCorsHeaders(setSpy2, 'http://localhost:3001');
|
|
});
|
|
|
|
it('should set proper CORS response headers for multiple URL Sets', async () => {
|
|
const endpoint = 'https://logto.io';
|
|
const adminEndpoint = 'https://logto.admin';
|
|
|
|
process.env.ENDPOINT = endpoint;
|
|
process.env.ADMIN_ENDPOINT = adminEndpoint;
|
|
process.env.NODE_ENV = 'dev';
|
|
const run = koaCors(new UrlSet(false, 3001), new UrlSet(true, 3002, 'ADMIN_'));
|
|
|
|
const [ctx1, setSpy1] = mockContext('PUT', 'https://localhost:3002/api');
|
|
await run(ctx1, noop);
|
|
expectCorsHeaders(setSpy1, 'https://localhost:3002');
|
|
|
|
const [ctx2, setSpy2] = mockContext('POST', adminEndpoint + '/api');
|
|
await run(ctx2, noop);
|
|
expectCorsHeaders(setSpy2, adminEndpoint);
|
|
});
|
|
|
|
it('should set CORS response headers for localhost in production when endpoint is unavailable', async () => {
|
|
process.env.ENDPOINT = undefined;
|
|
process.env.NODE_ENV = 'production';
|
|
const urlSet = new UrlSet(true, 3002);
|
|
const run = koaCors(urlSet);
|
|
|
|
const [ctx, setSpy] = mockContext('POST', 'https://localhost:3002/api');
|
|
await run(ctx, noop);
|
|
expectCorsHeaders(setSpy, 'https://localhost:3002');
|
|
});
|
|
|
|
it('should not to set CORS response headers for localhost in production when endpoint is available', async () => {
|
|
const endpoint = 'https://logto.io';
|
|
process.env.ENDPOINT = endpoint;
|
|
process.env.NODE_ENV = 'production';
|
|
const urlSet = new UrlSet(false, 3001);
|
|
const run = koaCors(urlSet);
|
|
|
|
const [ctx, setSpy] = mockContext('DELETE', 'http://localhost:3001/api');
|
|
await run(ctx, noop);
|
|
expectCorsHeaders(setSpy, '');
|
|
});
|
|
});
|