Skip to content

Commit b787ba1

Browse files
committed
add unit tests for audit logs
1 parent 2a632e4 commit b787ba1

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed

tests/unit/logs.test.ts

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { afterAll, expect, test, beforeEach, vi } from "vitest";
2+
import init from "../../src/api/index.js";
3+
import { describe } from "node:test";
4+
import { mockClient } from "aws-sdk-client-mock";
5+
import { DynamoDBClient, QueryCommand } from "@aws-sdk/client-dynamodb";
6+
import { secretObject } from "./secret.testdata.js";
7+
import supertest from "supertest";
8+
import { createJwt } from "./auth.test.js";
9+
import { genericConfig } from "../../src/common/config.js";
10+
import { marshall } from "@aws-sdk/util-dynamodb";
11+
import { Modules } from "../../src/common/modules.js";
12+
13+
const ddbMock = mockClient(DynamoDBClient);
14+
const jwt_secret = secretObject["jwt_key"];
15+
vi.stubEnv("JwtSigningKey", jwt_secret);
16+
17+
const app = await init();
18+
describe("Audit Log tests", async () => {
19+
test("Sad path: Not authenticated", async () => {
20+
await app.ready();
21+
const response = await supertest(app.server)
22+
.get("/api/v1/logs/events")
23+
.send();
24+
expect(response.statusCode).toBe(403);
25+
});
26+
test("Sad path: Authenticated but not authorized", async () => {
27+
await app.ready();
28+
const testJwt = createJwt(undefined, ["1"]);
29+
const response = await supertest(app.server)
30+
.get("/api/v1/logs/events?start=0&end=1")
31+
.set("Authorization", `Bearer ${testJwt}`)
32+
.send();
33+
expect(response.statusCode).toBe(401);
34+
});
35+
test("Sad path: No start and end provided", async () => {
36+
await app.ready();
37+
const testJwt = createJwt(undefined, ["0"]);
38+
const response = await supertest(app.server)
39+
.get("/api/v1/logs/events")
40+
.set("Authorization", `Bearer ${testJwt}`)
41+
.send();
42+
expect(response.statusCode).toBe(400);
43+
expect(response.body).toStrictEqual({
44+
error: true,
45+
name: "ValidationError",
46+
id: 104,
47+
message:
48+
"querystring/start Expected number, received nan, querystring/end Expected number, received nan",
49+
});
50+
});
51+
test("Sad path: Items is undefined", async () => {
52+
const logEntry = {
53+
module: Modules.EVENTS,
54+
actor: "me",
55+
target: "you",
56+
requestId: "c03ddefa-11d7-4b7c-a6d5-771460e1b45f",
57+
message: "no!",
58+
};
59+
ddbMock
60+
.on(QueryCommand, {
61+
TableName: genericConfig.AuditLogTable,
62+
KeyConditionExpression: "#pk = :module AND #sk BETWEEN :start AND :end",
63+
ExpressionAttributeNames: {
64+
"#pk": "module",
65+
"#sk": "createdAt",
66+
},
67+
ExpressionAttributeValues: {
68+
":module": { S: "events" },
69+
":start": { N: "1750349770" },
70+
":end": { N: "1750436176" },
71+
},
72+
})
73+
.resolvesOnce({
74+
Items: [marshall(logEntry)],
75+
});
76+
await app.ready();
77+
const testJwt = createJwt(undefined, ["0"]);
78+
const response = await supertest(app.server)
79+
.get("/api/v1/logs/events?start=1750349770&end=1750436176")
80+
.set("Authorization", `Bearer ${testJwt}`)
81+
.send();
82+
expect(response.statusCode).toBe(200);
83+
expect(response.body).toStrictEqual([logEntry]);
84+
});
85+
ddbMock
86+
.on(QueryCommand, {
87+
TableName: genericConfig.AuditLogTable,
88+
KeyConditionExpression: "#pk = :module AND #sk BETWEEN :start AND :end",
89+
ExpressionAttributeNames: {
90+
"#pk": "module",
91+
"#sk": "createdAt",
92+
},
93+
ExpressionAttributeValues: {
94+
":module": { S: "events" },
95+
":start": { N: "1750349770" },
96+
":end": { N: "1750436176" },
97+
},
98+
})
99+
.resolvesOnce({
100+
Items: undefined,
101+
});
102+
await app.ready();
103+
const testJwt = createJwt(undefined, ["0"]);
104+
const response = await supertest(app.server)
105+
.get("/api/v1/logs/events?start=1750349770&end=1750436176")
106+
.set("Authorization", `Bearer ${testJwt}`)
107+
.send();
108+
expect(response.statusCode).toBe(500);
109+
});
110+
afterAll(async () => {
111+
await app.close();
112+
});
113+
beforeEach(() => {
114+
(app as any).nodeCache.flushAll();
115+
(app as any).redisClient.flushdb();
116+
ddbMock.reset();
117+
vi.clearAllMocks();
118+
vi.useFakeTimers();
119+
});

0 commit comments

Comments
 (0)