1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-11-10 01:19:53 +01:00
unleash.unleash/src/lib/app.test.ts
Christopher Kolstad b681702b77
task: migrate tests to vitest
Vitest Pros:
* Automated failing test comments on github PRs
* A nice local UI with incremental testing when changing files (`yarn
test:ui`)
* Also nicely supported in all major IDEs, click to run test works (so
we won't miss what we had with jest).
* Works well with ESM

Vitest Cons:
* The ESBuild transformer vitest uses takes a little longer to transform
than our current SWC/jest setup, however, it is possible to setup SWC as
the transformer for vitest as well (though it only does one transform,
so we're paying ~7-10 seconds instead of ~ 2-3 seconds in transform
phase).
* Exposes how slow our tests are (tongue in cheek here)
2025-05-16 11:19:10 +02:00

113 lines
3.5 KiB
TypeScript

import { createTestConfig } from '../test/config/test-config.js';
import { type Mock, vi } from 'vitest';
// This mock setup MUST be at the top-level, before any other code that might trigger imports.
vi.mock('compression', () => ({
default: vi.fn().mockImplementation(() => {
// This is the actual middleware function Express would use
return (req, res, next) => {
next();
};
}),
}));
let getApp: any;
let compression: any;
const openApiService = {
// returns a middleware
validPath: vi.fn().mockReturnValue(() => {}),
useDocs: vi.fn(),
};
const appModule = await import('./app.js');
getApp = appModule.default;
test('should not throw when valid config', async () => {
const config = createTestConfig();
const app = await getApp(config, {}, { openApiService });
expect(typeof app.listen).toBe('function');
});
test('should call preHook', async () => {
let called = 0;
const config = createTestConfig({
preHook: () => {
called++;
},
});
await getApp(config, {}, { openApiService });
expect(called).toBe(1);
});
test('should call preRouterHook', async () => {
let called = 0;
const config = createTestConfig({
preRouterHook: () => {
called++;
},
});
await getApp(config, {}, { openApiService });
expect(called).toBe(1);
});
describe('compression middleware', () => {
beforeAll(async () => {
vi.resetModules(); // Crucial: Clears the module cache.
// Import 'compression' AFTER resetModules. This ensures we get the mock.
const compressionModule = await import('compression');
compression = compressionModule.default; // `compression` is now our vi.fn()
// Import 'app.js' AFTER resetModules and AFTER 'compression' is set to the mock.
// This ensures app.js uses the mocked version of compression.
const appModule = await import('./app.js');
getApp = appModule.default;
});
beforeEach(() => {
// Clear call history for the mock before each test in this describe block
if (
compression &&
typeof (compression as Mock).mockClear === 'function'
) {
(compression as Mock).mockClear();
} else {
// This case might happen if beforeAll failed or types are unexpected
console.warn(
'Compression mock was not available or not a mock function in beforeEach',
);
}
});
test.each([
{
disableCompression: true,
expectCompressionEnabled: false,
},
{
disableCompression: false,
expectCompressionEnabled: true,
},
{
disableCompression: null,
expectCompressionEnabled: true,
},
{
disableCompression: undefined,
expectCompressionEnabled: true,
},
])(
`should expect the compression middleware to be $expectCompressionEnabled when configInput.server.disableCompression is $disableCompression`,
async ({ disableCompression, expectCompressionEnabled }) => {
const config = createTestConfig({
server: {
disableCompression: disableCompression as any,
},
});
await getApp(config, {}, { openApiService });
expect(compression).toHaveBeenCalledTimes(
+expectCompressionEnabled,
);
},
);
});