Skip to content

Commit 4fe77db

Browse files
unit tests
1 parent 9db7375 commit 4fe77db

10 files changed

Lines changed: 1913 additions & 152 deletions

File tree

internal/datastore/src/__test__/db.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export async function setupDynamoDBContainer() {
3838
letterQueueTtlHours: 1,
3939
miTtlHours: 1,
4040
supplierConfigTableName: "supplier-config",
41+
supplierQuotasTableName: "supplier-quotas",
4142
};
4243

4344
return {
@@ -184,6 +185,19 @@ const createSupplierConfigTableCommand = new CreateTableCommand({
184185
],
185186
});
186187

188+
const createSupplierQuotasTableCommand = new CreateTableCommand({
189+
TableName: "supplier-quotas",
190+
BillingMode: "PAY_PER_REQUEST",
191+
KeySchema: [
192+
{ AttributeName: "pk", KeyType: "HASH" }, // Partition key
193+
{ AttributeName: "sk", KeyType: "RANGE" }, // Sort key
194+
],
195+
AttributeDefinitions: [
196+
{ AttributeName: "pk", AttributeType: "S" },
197+
{ AttributeName: "sk", AttributeType: "S" },
198+
],
199+
});
200+
187201
export async function createTables(context: DBContext) {
188202
const { ddbClient } = context;
189203

@@ -194,6 +208,7 @@ export async function createTables(context: DBContext) {
194208
await ddbClient.send(createSupplierTableCommand);
195209
await ddbClient.send(createLetterQueueTableCommand);
196210
await ddbClient.send(createSupplierConfigTableCommand);
211+
await ddbClient.send(createSupplierQuotasTableCommand);
197212
}
198213

199214
export async function deleteTables(context: DBContext) {
@@ -205,6 +220,7 @@ export async function deleteTables(context: DBContext) {
205220
"suppliers",
206221
"letter-queue",
207222
"supplier-config",
223+
"supplier-quotas",
208224
]) {
209225
await ddbClient.send(
210226
new DeleteTableCommand({
Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
import { PutCommand } from "@aws-sdk/lib-dynamodb";
2+
import {
3+
DBContext,
4+
createTables,
5+
deleteTables,
6+
setupDynamoDBContainer,
7+
} from "./db";
8+
import { SupplierQuotasRepository } from "../supplier-quotas-repository";
9+
10+
function createOverallAllocationItem(
11+
allocationId: string,
12+
volumeGroupId: string,
13+
allocations: Record<string, number>,
14+
) {
15+
return {
16+
pk: "ENTITY#overall-allocation",
17+
sk: `ID#${allocationId}`,
18+
id: allocationId,
19+
volumeGroup: volumeGroupId,
20+
allocations,
21+
updatedAt: new Date().toISOString(),
22+
};
23+
}
24+
25+
function createDailyAllocationItem(
26+
allocationId: string,
27+
volumeGroupId: string,
28+
date: string,
29+
allocations: Record<string, number>,
30+
) {
31+
return {
32+
pk: "ENTITY#daily-allocation",
33+
sk: `ID#${volumeGroupId}#DATE#${date}`,
34+
id: allocationId,
35+
volumeGroup: volumeGroupId,
36+
date,
37+
allocations,
38+
updatedAt: new Date().toISOString(),
39+
};
40+
}
41+
42+
jest.setTimeout(30_000);
43+
44+
describe("SupplierQuotasRepository", () => {
45+
let dbContext: DBContext;
46+
let repository: SupplierQuotasRepository;
47+
48+
// Database tests can take longer, especially with setup and teardown
49+
beforeAll(async () => {
50+
dbContext = await setupDynamoDBContainer();
51+
});
52+
53+
beforeEach(async () => {
54+
await createTables(dbContext);
55+
repository = new SupplierQuotasRepository(dbContext.docClient, {
56+
supplierQuotasTableName: dbContext.config.supplierQuotasTableName,
57+
});
58+
});
59+
60+
afterEach(async () => {
61+
await deleteTables(dbContext);
62+
jest.useRealTimers();
63+
});
64+
65+
afterAll(async () => {
66+
await dbContext.container.stop();
67+
});
68+
69+
test("getOverallAllocation returns correct allocation for existing group", async () => {
70+
const volumeGroupId = "group-123";
71+
const allocations = { supplier1: 100, supplier2: 200 };
72+
await dbContext.docClient.send(
73+
new PutCommand({
74+
TableName: dbContext.config.supplierQuotasTableName,
75+
Item: createOverallAllocationItem(
76+
volumeGroupId,
77+
volumeGroupId,
78+
allocations,
79+
),
80+
}),
81+
);
82+
83+
const result = await repository.getOverallAllocation(volumeGroupId);
84+
85+
expect(result).toEqual({
86+
id: volumeGroupId,
87+
volumeGroup: volumeGroupId,
88+
allocations,
89+
});
90+
});
91+
92+
test("getOverallAllocation returns undefined for non-existent group", async () => {
93+
const volumeGroupId = "non-existent-group";
94+
95+
const result = await repository.getOverallAllocation(volumeGroupId);
96+
97+
expect(result).toBeUndefined();
98+
});
99+
100+
test("putOverallAllocation stores allocation correctly", async () => {
101+
const allocation = {
102+
id: "group-123",
103+
volumeGroup: "group-123",
104+
allocations: { supplier1: 100, supplier2: 200 },
105+
};
106+
107+
await repository.putOverallAllocation(allocation);
108+
109+
const result = await repository.getOverallAllocation("group-123");
110+
expect(result).toEqual(allocation);
111+
});
112+
113+
test("updateOverallAllocation creates new allocation when none exists", async () => {
114+
const volumeGroupId = "group-123";
115+
const supplierId = "supplier-123";
116+
const newAllocation = 50;
117+
118+
await repository.updateOverallAllocation(
119+
volumeGroupId,
120+
supplierId,
121+
newAllocation,
122+
);
123+
124+
const result = await repository.getOverallAllocation(volumeGroupId);
125+
expect(result).toEqual({
126+
id: volumeGroupId,
127+
volumeGroup: volumeGroupId,
128+
allocations: { [supplierId]: newAllocation },
129+
});
130+
});
131+
132+
test("updateOverallAllocation updates existing allocation", async () => {
133+
const volumeGroupId = "group-123";
134+
const supplierId = "supplier-123";
135+
const initialAllocations = { [supplierId]: 100 };
136+
await dbContext.docClient.send(
137+
new PutCommand({
138+
TableName: dbContext.config.supplierQuotasTableName,
139+
Item: createOverallAllocationItem(
140+
volumeGroupId,
141+
volumeGroupId,
142+
initialAllocations,
143+
),
144+
}),
145+
);
146+
147+
const newAllocation = 50;
148+
await repository.updateOverallAllocation(
149+
volumeGroupId,
150+
supplierId,
151+
newAllocation,
152+
);
153+
154+
const result = await repository.getOverallAllocation(volumeGroupId);
155+
expect(result?.allocations[supplierId]).toBe(150);
156+
});
157+
158+
test("getDailyAllocation returns correct allocation for existing group and date", async () => {
159+
const allocationId = "daily-allocation-123";
160+
const volumeGroupId = "group-123";
161+
const date = "2023-10-01";
162+
const allocations = { supplier1: 50, supplier2: 75 };
163+
await dbContext.docClient.send(
164+
new PutCommand({
165+
TableName: dbContext.config.supplierQuotasTableName,
166+
Item: createDailyAllocationItem(
167+
allocationId,
168+
volumeGroupId,
169+
date,
170+
allocations,
171+
),
172+
}),
173+
);
174+
175+
const result = await repository.getDailyAllocation(volumeGroupId, date);
176+
177+
expect(result).toEqual({
178+
id: allocationId,
179+
volumeGroup: volumeGroupId,
180+
date,
181+
allocations,
182+
});
183+
});
184+
185+
test("getDailyAllocation returns undefined for non-existent group and date", async () => {
186+
const volumeGroupId = "non-existent-group";
187+
const date = "2023-10-01";
188+
189+
const result = await repository.getDailyAllocation(volumeGroupId, date);
190+
191+
expect(result).toBeUndefined();
192+
});
193+
194+
test("putDailyAllocation stores allocation correctly", async () => {
195+
const allocation = {
196+
id: "daily-allocation-123",
197+
volumeGroup: "group-123",
198+
date: "2023-10-01",
199+
allocations: { supplier1: 50, supplier2: 75 },
200+
};
201+
202+
await repository.putDailyAllocation(allocation);
203+
204+
const result = await repository.getDailyAllocation(
205+
"group-123",
206+
"2023-10-01",
207+
);
208+
expect(result).toEqual(allocation);
209+
});
210+
211+
test("updateDailyAllocation creates new allocation when none exists", async () => {
212+
const volumeGroupId = "group-123";
213+
const date = "2023-10-01";
214+
const supplierId = "supplier-123";
215+
const newAllocation = 25;
216+
217+
await repository.updateDailyAllocation(
218+
volumeGroupId,
219+
date,
220+
supplierId,
221+
newAllocation,
222+
);
223+
224+
const result = await repository.getDailyAllocation(volumeGroupId, date);
225+
expect(result).toEqual({
226+
id: `${volumeGroupId}#DATE#${date}`,
227+
volumeGroup: volumeGroupId,
228+
date,
229+
allocations: { [supplierId]: newAllocation },
230+
});
231+
});
232+
233+
test("updateDailyAllocation updates existing allocation", async () => {
234+
const allocationId = "daily-allocation-123";
235+
const volumeGroupId = "group-123";
236+
const date = "2023-10-01";
237+
const supplierId = "supplier-123";
238+
const initialAllocations = { [supplierId]: 50 };
239+
await dbContext.docClient.send(
240+
new PutCommand({
241+
TableName: dbContext.config.supplierQuotasTableName,
242+
Item: createDailyAllocationItem(
243+
allocationId,
244+
volumeGroupId,
245+
date,
246+
initialAllocations,
247+
),
248+
}),
249+
);
250+
251+
const newAllocation = 25;
252+
await repository.updateDailyAllocation(
253+
volumeGroupId,
254+
date,
255+
supplierId,
256+
newAllocation,
257+
);
258+
259+
const result = await repository.getDailyAllocation(volumeGroupId, date);
260+
expect(result?.allocations[supplierId]).toBe(75);
261+
});
262+
});

internal/datastore/src/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ export type DatastoreConfig = {
99
letterQueueTtlHours: number;
1010
miTtlHours: number;
1111
supplierConfigTableName: string;
12+
supplierQuotasTableName: string;
1213
};

0 commit comments

Comments
 (0)