From 666674327f009e9b1013218fc384f193b64c6997 Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Sun, 14 Dec 2025 22:39:18 -0800 Subject: Adds unit tests --- tst/server_filters_activity.test.ts | 96 +++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 tst/server_filters_activity.test.ts (limited to 'tst/server_filters_activity.test.ts') diff --git a/tst/server_filters_activity.test.ts b/tst/server_filters_activity.test.ts new file mode 100644 index 0000000..a992e10 --- /dev/null +++ b/tst/server_filters_activity.test.ts @@ -0,0 +1,96 @@ +import { + Either, + HealthCheckActivityImpl, + HealthCheckOutput, + PenguenoError, + PenguenoRequest, + jsonModel, + requireMethod, + type BaseRequest, + type ServerTrace, +} from '../lib/index'; +import { CollectingTrace, TestTraceable } from './test_utils'; + +const makeBaseRequest = (overrides: Partial = {}): BaseRequest => ({ + url: 'https://example.com/hello', + method: 'GET', + header: () => ({}), + formData: async () => new FormData(), + json: async () => ({}), + text: async () => '', + param: () => undefined, + query: () => ({}), + queries: () => ({}), + ...overrides, +}); + +describe('server filters + activities', () => { + beforeEach(() => { + jest.useFakeTimers(); + jest.setSystemTime(new Date('2020-01-01T00:00:00.000Z')); + jest.spyOn(globalThis.crypto, 'randomUUID').mockReturnValue('00000000-0000-0000-0000-000000000000'); + }); + + afterEach(() => { + jest.useRealTimers(); + jest.restoreAllMocks(); + }); + + test('requireMethod rejects unallowed methods', () => { + const trace = new CollectingTrace(); + const req = PenguenoRequest.from(TestTraceable.of(makeBaseRequest({ method: 'GET' }), trace)); + + const res = requireMethod(['POST'])(req); + const err = res.left().get(); + + expect(err).toBeInstanceOf(PenguenoError); + expect(err.status).toBe(405); + }); + + test('jsonModel transforms valid JSON', async () => { + const trace = new CollectingTrace(); + const req = PenguenoRequest.from( + TestTraceable.of( + makeBaseRequest({ + json: async () => ({ hello: 'world' }), + }), + trace, + ), + ); + + const filter = jsonModel((json) => { + const body = json.get() as { hello?: string }; + return body.hello === 'world' ? Either.right('ok') : Either.left(new PenguenoError('bad json', 400)); + }); + + const res = await filter(req); + expect(res.right().get()).toBe('ok'); + }); + + test('jsonModel returns 400 for invalid JSON', async () => { + const trace = new CollectingTrace(); + const req = PenguenoRequest.from( + TestTraceable.of( + makeBaseRequest({ + json: async () => Promise.reject(new Error('nope')), + }), + trace, + ), + ); + + const filter = jsonModel((_json) => Either.right('never')); + const res = await filter(req); + expect(res.left().get().status).toBe(400); + }); + + test('HealthCheckActivityImpl returns 200 on success', async () => { + const trace = new CollectingTrace(); + const req = PenguenoRequest.from(TestTraceable.of(makeBaseRequest(), trace)); + + const activity = new HealthCheckActivityImpl(async () => Either.right(HealthCheckOutput.YAASSSLAYQUEEN)); + const res = await activity.checkHealth(req); + + expect(res.status).toBe(200); + expect(res.body()).toBe('{"ok":"ok"}'); + }); +}); -- cgit v1.2.3-70-g09d2