summaryrefslogtreecommitdiff
path: root/tst/server_filters_activity.test.ts
diff options
context:
space:
mode:
authorElizabeth Hunt <me@liz.coffee>2025-12-14 22:39:18 -0800
committerElizabeth Hunt <me@liz.coffee>2025-12-14 22:39:18 -0800
commit666674327f009e9b1013218fc384f193b64c6997 (patch)
treeacebae7b425b469584eb0a5bec396899c2739501 /tst/server_filters_activity.test.ts
parent594ce452693a71b501d3aff3f35ef3732c06c341 (diff)
downloadpengueno-666674327f009e9b1013218fc384f193b64c6997.tar.gz
pengueno-666674327f009e9b1013218fc384f193b64c6997.zip
Adds unit tests
Diffstat (limited to 'tst/server_filters_activity.test.ts')
-rw-r--r--tst/server_filters_activity.test.ts96
1 files changed, 96 insertions, 0 deletions
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> = {}): 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<ServerTrace>();
+ 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<ServerTrace>();
+ 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<ServerTrace>();
+ 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<ServerTrace>();
+ 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"}');
+ });
+});