1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-10-13 11:17:26 +02:00
unleash.unleash/src/lib/middleware/api-token-middleware.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

279 lines
7.1 KiB
TypeScript

import getLogger from '../../test/fixtures/no-logger.js';
import { CLIENT } from '../types/permissions.js';
import { createTestConfig } from '../../test/config/test-config.js';
import ApiUser from '../types/api-user.js';
import { ALL } from '../types/models/api-token.js';
import { ApiTokenType } from '../types/model.js';
import apiTokenMiddleware, {
TOKEN_TYPE_ERROR_MESSAGE,
} from './api-token-middleware.js';
import type { ApiTokenService } from '../services/index.js';
import type { IUnleashConfig } from '../types/index.js';
import { vi } from 'vitest';
let config: IUnleashConfig;
beforeEach(() => {
config = createTestConfig({
getLogger,
authentication: {
enableApiToken: true,
},
});
});
test('should not do anything if request does not contain a authorization', async () => {
const apiTokenService = {
getUserForToken: vi.fn(),
} as unknown as ApiTokenService;
const func = apiTokenMiddleware(config, { apiTokenService });
const cb = vi.fn();
const req = {
header: vi.fn(),
};
await func(req, undefined, cb);
expect(req.header).toHaveBeenCalledTimes(1);
expect(cb).toHaveBeenCalledTimes(1);
});
test('should not add user if unknown token', async () => {
const apiTokenService = {
getUserForToken: vi.fn(),
} as unknown as ApiTokenService;
const func = apiTokenMiddleware(config, { apiTokenService });
const cb = vi.fn();
const req = {
header: vi.fn().mockReturnValue('some-token'),
user: undefined,
};
await func(req, undefined, cb);
expect(cb).toHaveBeenCalled();
expect(req.header).toHaveBeenCalled();
expect(req.user).toBeFalsy();
});
test('should not make database query when provided PAT format', async () => {
const apiTokenService = {
getUserForToken: vi.fn(),
} as unknown as ApiTokenService;
const func = apiTokenMiddleware(config, { apiTokenService });
const cb = vi.fn();
const req = {
header: vi.fn().mockReturnValue('user:asdkjsdhg3'),
user: undefined,
};
await func(req, undefined, cb);
expect(apiTokenService.getUserForToken).not.toHaveBeenCalled();
expect(req.header).toHaveBeenCalled();
expect(cb).toHaveBeenCalled();
expect(req.user).toBeFalsy();
});
test('should add user if known token', async () => {
const apiUser = new ApiUser({
tokenName: 'default',
permissions: [CLIENT],
project: ALL,
environment: ALL,
type: ApiTokenType.CLIENT,
secret: 'a',
});
const apiTokenService = {
getUserForToken: vi.fn().mockReturnValue(apiUser),
} as unknown as ApiTokenService;
const func = apiTokenMiddleware(config, { apiTokenService });
const cb = vi.fn();
const req = {
header: vi.fn().mockReturnValue('some-known-token'),
user: undefined,
path: '/api/client',
};
await func(req, undefined, cb);
expect(cb).toHaveBeenCalled();
expect(req.header).toHaveBeenCalled();
expect(req.user).toBe(apiUser);
});
test('should not add user if not /api/client', async () => {
expect.assertions(5);
const apiUser = new ApiUser({
tokenName: 'default',
permissions: [CLIENT],
project: ALL,
environment: ALL,
type: ApiTokenType.CLIENT,
secret: 'a',
});
const apiTokenService = {
getUserForToken: vi.fn().mockReturnValue(apiUser),
} as unknown as ApiTokenService;
const func = apiTokenMiddleware(config, { apiTokenService });
const cb = vi.fn();
const res = {
status: (code: unknown) => ({
send: (data: unknown) => {
expect(code).toEqual(403);
expect(data).toEqual({ message: TOKEN_TYPE_ERROR_MESSAGE });
},
}),
};
const req = {
header: vi.fn().mockReturnValue('some-known-token'),
user: undefined,
path: '/api/admin',
};
await func(req, res, cb);
expect(cb).not.toHaveBeenCalled();
expect(req.header).toHaveBeenCalled();
expect(req.user).toBeUndefined();
});
test('should not add user if disabled', async () => {
const apiUser = new ApiUser({
tokenName: 'default',
permissions: [CLIENT],
project: ALL,
environment: ALL,
type: ApiTokenType.CLIENT,
secret: 'a',
});
const apiTokenService = {
getUserForToken: vi.fn().mockReturnValue(apiUser),
} as unknown as ApiTokenService;
const disabledConfig = createTestConfig({
getLogger,
authentication: {
enableApiToken: false,
createAdminUser: false,
},
});
const func = apiTokenMiddleware(disabledConfig, { apiTokenService });
const cb = vi.fn();
const req = {
header: vi.fn().mockReturnValue('some-known-token'),
user: undefined,
};
const send = vi.fn();
const res = {
status: () => {
return {
send: send,
};
},
};
await func(req, res, cb);
expect(send).not.toHaveBeenCalled();
expect(cb).toHaveBeenCalled();
expect(req.user).toBeFalsy();
});
test('should call next if apiTokenService throws', async () => {
getLogger.setMuteError(true);
const apiTokenService = {
getUserForToken: () => {
throw new Error('hi there, i am stupid');
},
} as unknown as ApiTokenService;
const func = apiTokenMiddleware(config, { apiTokenService });
const cb = vi.fn();
const req = {
header: vi.fn().mockReturnValue('some-token'),
user: undefined,
};
await func(req, undefined, cb);
expect(cb).toHaveBeenCalled();
getLogger.setMuteError(false);
});
test('should call next if apiTokenService throws x2', async () => {
vi.spyOn(global.console, 'error').mockImplementation(() => vi.fn());
const apiTokenService = {
getUserForToken: () => {
throw new Error('hi there, i am stupid');
},
} as unknown as ApiTokenService;
const func = apiTokenMiddleware(config, { apiTokenService });
const cb = vi.fn();
const req = {
header: vi.fn().mockReturnValue('some-token'),
user: undefined,
};
await func(req, undefined, cb);
expect(cb).toHaveBeenCalled();
});
test('should add user if client token and /edge/metrics', async () => {
const apiUser = new ApiUser({
tokenName: 'default',
permissions: [CLIENT],
project: ALL,
environment: ALL,
type: ApiTokenType.CLIENT,
secret: 'a',
});
const apiTokenService = {
getUserForToken: vi.fn().mockReturnValue(apiUser),
} as unknown as ApiTokenService;
const func = apiTokenMiddleware(config, { apiTokenService });
const cb = vi.fn();
const req = {
header: vi.fn().mockReturnValue('some-known-token'),
user: undefined,
path: '/edge/metrics',
method: 'POST',
};
await func(req, undefined, cb);
expect(cb).toHaveBeenCalled();
expect(req.header).toHaveBeenCalled();
expect(req.user).toBe(apiUser);
});