import { describe, test, expect, beforeAll } from "bun:test"; import { waitForService, baseUrl, doorName, buzzerNumber, key, buzzerUrl } from "./testCommon"; import { DoorStatus } from "../src/types/DoorStatus"; import { StatusResponse } from "../src/functions/api/door/status"; import { sleep } from "bun"; import { ONBOARDING_DOOR_NAME, ONBOARDING_DOOR_PIN } from "../src/schema/DoorConfig"; import { LogCallResponse } from "../src/functions/api/door/logCall"; // these tests should only run locally if (process.env.STAGE === 'staging') { process.exit(0); } beforeAll(async () => { await waitForService(baseUrl); }); describe("info path works", () => { test("info works from UI", async () => { const resp = await fetch(baseUrl + `/api/door/info?door=${doorName}`).then(res => res.json()) as any; expect(resp.id as string).toBe(doorName); expect(resp.buzzer).toBe(buzzerNumber); }); test("unknown info repsonds with a msg", async () => { const resp = await fetch(baseUrl + `/api/door/info?door=baddoor`); expect(resp.status).toBe(404); const body = await resp.json() as any; expect(body.msg).toContain("not registered"); }) test("info works from client", async () => { const resp = await fetch(baseUrl + `/api/door/info?buzzer=${buzzerNumber}`).then(res => res.json()) as any; // TODO: why is this different? expect(resp.door as string).toBe(doorName); expect(resp.buzzer).toBe(buzzerNumber); }); }); describe("unlock path works", () => { test("auth updates info and status relocks auth", async () => { // run status first, to make sure we are closed const statusReset = await fetch(baseUrl + `/api/door/status?door=${doorName}`).then(res => res.json()) as StatusResponse; const resp = await fetch(baseUrl + `/api/door/info?door=${doorName}`).then(res => res.json()) as any; expect(resp.id).toBe(doorName); expect(resp.status).toBe(DoorStatus.CLOSED); // unlock door with wrong code should be 401 const badAuthResp = await fetch(baseUrl + `/api/door/auth?door=${doorName}&key=thisisthewrongkey`); expect(badAuthResp.status).toBe(401); // unlock door with correct code should be 200 const authResp = await fetch(baseUrl + `/api/door/auth?door=${doorName}&key=${key}`); expect(authResp.status).toBe(200); // door should be unlocked on info route const infoOpen = await fetch(baseUrl + `/api/door/info?door=${doorName}`).then(res => res.json()) as any; expect(infoOpen.status).toBe(DoorStatus.OPEN); // calling status should unlock and close the door const statusOpen = await fetch(baseUrl + `/api/door/status?door=${doorName}`).then(res => res.json()) as StatusResponse; expect(statusOpen.status).toBe(DoorStatus.OPEN); const infoClosed = await fetch(baseUrl + `/api/door/info?door=${doorName}`).then(res => res.json()) as any; expect(infoClosed.status).toBe(DoorStatus.CLOSED); }); test("auth works for timeout", async () => { // run status first, to make sure we are closed const statusReset = await fetch(baseUrl + `/api/door/status?door=${doorName}`).then(res => res.json()) as StatusResponse; // run auth with timeout specified const authResp = await fetch(baseUrl + `/api/door/auth?door=${doorName}&key=${key}&timeout=1`); // sleep 1s await sleep(1_000); // we should be closed, because we passed the timeout const infoClosed = await fetch(baseUrl + `/api/door/info?door=${doorName}`).then(res => res.json()) as any; expect(infoClosed.status).toBe(DoorStatus.CLOSED); }); }); describe("call log path works", () => { test("call log returns nothing when onboarding is not enabled", async () => { // run status first, to make sure we are closed const statusReset = await fetch(baseUrl + `/api/door/status?door=${ONBOARDING_DOOR_NAME}`).then(res => res.json()) as StatusResponse; // try to log call const logCallRes = await fetch(baseUrl + `/api/door/logCall?caller=${buzzerNumber}`); expect(logCallRes.status).toBe(400); }); test("call log returns 4 digit OTP when onboarding enabled", async () => { // run status first, to make sure we are closed const statusReset = await fetch(baseUrl + `/api/door/status?door=${ONBOARDING_DOOR_NAME}`).then(res => res.json()) as StatusResponse; // run auth with timeout specified const authResp = await fetch(baseUrl + `/api/door/auth?door=${ONBOARDING_DOOR_NAME}&key=${ONBOARDING_DOOR_PIN}`); // try to log call const logCallRes = await fetch(baseUrl + `/api/door/logCall?caller=${buzzerNumber}`); expect(logCallRes.status).toBe(200); const otp = (await logCallRes.json() as LogCallResponse).otp expect(otp.length).toBe(4) }); test("call log after door closed, should not return OTP", async () => { // run status first, to make sure we are closed const statusReset = await fetch(baseUrl + `/api/door/status?door=${ONBOARDING_DOOR_NAME}`).then(res => res.json()) as StatusResponse; // run auth with timeout specified const authResp = await fetch(baseUrl + `/api/door/auth?door=${ONBOARDING_DOOR_NAME}&key=${ONBOARDING_DOOR_PIN}&timeout=1`); // sleep 1s await sleep(1_000); // try to log call const logCallRes = await fetch(baseUrl + `/api/door/logCall?caller=${buzzerNumber}`); expect(logCallRes.status).toBe(400); }); });