Skip to content

Commit ca58f3b

Browse files
Fix unit test timestamps, add source
1 parent 64d0fe2 commit ca58f3b

File tree

10 files changed

+89
-40
lines changed

10 files changed

+89
-40
lines changed

internal/datastore/src/__test__/letter-repository.test.ts

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ function createLetter(
1414
supplierId: string,
1515
letterId: string,
1616
status: Letter["status"] = "PENDING",
17+
date: string = new Date().toISOString(),
1718
): InsertLetter {
1819
return {
1920
id: letterId,
@@ -22,8 +23,9 @@ function createLetter(
2223
groupId: "group1",
2324
url: `s3://bucket/${letterId}.pdf`,
2425
status,
25-
createdAt: new Date().toISOString(),
26-
updatedAt: new Date().toISOString(),
26+
createdAt: date,
27+
updatedAt: date,
28+
source: "/data-plane/letter-rendering/pdf"
2729
};
2830
}
2931

@@ -65,16 +67,31 @@ describe("LetterRepository", () => {
6567
expect(letter.status).toBe(status);
6668
}
6769

70+
function assertTtl(ttl: number, before: number, after: number) {
71+
const expectedLower = Math.floor(before / 1000 + 60 * 60 * db.config.lettersTtlHours);
72+
const expectedUpper = Math.floor(after / 1000 + 60 * 60 * db.config.lettersTtlHours);
73+
expect(ttl).toBeGreaterThanOrEqual(expectedLower);
74+
expect(ttl).toBeLessThanOrEqual(expectedUpper);
75+
}
76+
6877
test("adds a letter to the database", async () => {
6978
const supplierId = "supplier1";
7079
const letterId = "letter1";
80+
const date = new Date().toISOString();
7181

72-
await letterRepository.putLetter(createLetter(supplierId, letterId));
82+
await letterRepository.putLetter(createLetter(supplierId, letterId, "PENDING", date));
7383

7484
const letter = await letterRepository.getLetterById(supplierId, letterId);
7585
expect(letter).toBeDefined();
7686
expect(letter.id).toBe(letterId);
7787
expect(letter.supplierId).toBe(supplierId);
88+
expect(letter.createdAt).toBe(date);
89+
expect(letter.updatedAt).toBe(date);
90+
expect(letter.supplierStatusSk).toBe(date);
91+
expect(letter.supplierStatus).toBe("supplier1#PENDING");
92+
expect(letter.url).toBe("s3://bucket/letter1.pdf");
93+
expect(letter.specificationId).toBe("specification1");
94+
expect(letter.groupId).toBe("group1");
7895
expect(letter.reasonCode).toBeUndefined();
7996
expect(letter.reasonText).toBeUndefined();
8097
});
@@ -312,7 +329,7 @@ describe("LetterRepository", () => {
312329
url: "s3://bucket/invalid-letter.pdf",
313330
status: "PENDING",
314331
supplierStatus: "supplier1#PENDING",
315-
supplierStatusSk: Date.now().toString(),
332+
supplierStatusSk: new Date().toISOString(),
316333
createdAt: new Date().toISOString(),
317334
updatedAt: new Date().toISOString(),
318335
},
@@ -458,9 +475,7 @@ describe("LetterRepository", () => {
458475
});
459476

460477
test("successful upsert (update status) returns updated letter", async () => {
461-
jest.useFakeTimers();
462-
jest.setSystemTime(new Date(2020, 0, 1));
463-
const letter: InsertLetter = createLetter("supplier1", "letter1");
478+
const letter: InsertLetter = createLetter("supplier1", "letter1", "PENDING", new Date(2020, 0, 1).toISOString());
464479
const existingLetter: Letter = await letterRepository.putLetter(letter);
465480

466481
const updateLetterStatus: UpsertLetter = {
@@ -469,12 +484,16 @@ describe("LetterRepository", () => {
469484
status: "REJECTED",
470485
reasonCode: "R01",
471486
reasonText: "R01 text",
487+
source: "/data-plane/letter-rendering/pdf",
472488
};
473489

474-
jest.setSystemTime(new Date(2020, 0, 2));
490+
const before = Date.now();
491+
475492
const result: Letter =
476493
await letterRepository.upsertLetter(updateLetterStatus);
477494

495+
const after = Date.now();
496+
478497
expect(result).toEqual(
479498
expect.objectContaining({
480499
id: "letter1",
@@ -486,14 +505,15 @@ describe("LetterRepository", () => {
486505
supplierId: "supplier1",
487506
url: "s3://bucket/letter1.pdf",
488507
supplierStatus: "supplier1#REJECTED",
508+
source: "/data-plane/letter-rendering/pdf",
489509
}),
490510
);
491511
expect(Date.parse(result.updatedAt)).toBeGreaterThan(
492512
Date.parse(existingLetter.updatedAt),
493513
);
494514
expect(result.createdAt).toBe(existingLetter.createdAt);
495515
expect(result.createdAt).toBe(result.supplierStatusSk);
496-
expect(result.ttl).toBeGreaterThan(existingLetter.ttl);
516+
assertTtl(result.ttl, before, after);
497517
});
498518

499519
test("successful upsert (insert letter) returns created letter", async () => {
@@ -504,14 +524,15 @@ describe("LetterRepository", () => {
504524
groupId: "group1",
505525
supplierId: "supplier1",
506526
url: "s3://bucket/letter1.pdf",
527+
source: "/data-plane/letter-rendering/pdf",
507528
};
508529

509-
const nowTest: Date = new Date(2020, 0, 1);
510-
jest.useFakeTimers();
511-
jest.setSystemTime(nowTest);
530+
const before = Date.now();
512531

513532
const result: Letter = await letterRepository.upsertLetter(insertLetter);
514533

534+
const after = Date.now();
535+
515536
expect(result).toEqual(
516537
expect.objectContaining({
517538
id: "letter1",
@@ -523,25 +544,27 @@ describe("LetterRepository", () => {
523544
}),
524545
);
525546

526-
expect(Date.parse(result.updatedAt)).toBe(nowTest.valueOf());
527-
expect(result.createdAt).toBe(result.updatedAt);
547+
expect(Date.parse(result.createdAt)).toBeGreaterThanOrEqual(before);
548+
expect(Date.parse(result.createdAt)).toBeLessThanOrEqual(after);
549+
expect(result.updatedAt).toBe(result.createdAt);
528550
expect(result.supplierStatusSk).toBe(result.createdAt);
529-
expect(result.ttl).toBe(new Date(2020, 0, 1, 1).valueOf() / 1000);
551+
assertTtl(result.ttl, before, after);
530552
});
531553

532554
test("successful upsert without status change (update url)", async () => {
533-
jest.useFakeTimers();
534-
jest.setSystemTime(new Date(2020, 0, 1));
535-
const insertLetter: InsertLetter = createLetter("supplier1", "letter1");
555+
const insertLetter: InsertLetter = createLetter("supplier1", "letter1", "PENDING", new Date(2020, 0, 1).toISOString());
536556
const existingLetter = await letterRepository.putLetter(insertLetter);
537557

538-
jest.setSystemTime(new Date(2020, 0, 2));
558+
const before = Date.now();
559+
539560
const result = await letterRepository.upsertLetter({
540561
id: "letter1",
541562
supplierId: "supplier1",
542563
url: "s3://updateToPdf",
543564
});
544565

566+
const after = Date.now();
567+
545568
expect(result).toEqual(
546569
expect.objectContaining({
547570
id: "letter1",
@@ -558,7 +581,7 @@ describe("LetterRepository", () => {
558581
);
559582
expect(result.createdAt).toBe(existingLetter.createdAt);
560583
expect(result.createdAt).toBe(result.supplierStatusSk);
561-
expect(result.ttl).toBeGreaterThan(existingLetter.ttl);
584+
assertTtl(result.ttl, before, after);
562585
});
563586

564587
test("unsuccessful upsert should throw error", async () => {

internal/datastore/src/letter-repository.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export class LetterRepository {
4444
const letterDb: Letter = {
4545
...letter,
4646
supplierStatus: `${letter.supplierId}#${letter.status}`,
47-
supplierStatusSk: new Date().toISOString(),
47+
supplierStatusSk: letter.createdAt, // needs to be an ISO timestamp
4848
ttl: Math.floor(
4949
Date.now() / 1000 + 60 * 60 * this.config.lettersTtlHours,
5050
),
@@ -80,7 +80,7 @@ export class LetterRepository {
8080
lettersDb.push({
8181
...letter,
8282
supplierStatus: `${letter.supplierId}#${letter.status}`,
83-
supplierStatusSk: Date.now().toString(),
83+
supplierStatusSk: letter.createdAt,
8484
ttl: Math.floor(
8585
Date.now() / 1000 + 60 * 60 * this.config.lettersTtlHours,
8686
),
@@ -318,6 +318,12 @@ export class LetterRepository {
318318
exprAttrValues[":reasonText"] = upsert.reasonText;
319319
}
320320

321+
if (upsert.source !== undefined) {
322+
setParts.push("#source = :source");
323+
exprAttrNames["#source"] = "source";
324+
exprAttrValues[":source"] = upsert.source;
325+
}
326+
321327
const updateExpression = `SET ${setParts.join(", ")}`;
322328

323329
const command = new UpdateCommand({

internal/datastore/src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export const LetterSchema = LetterSchemaBase.extend({
4848
supplierStatus: z.string().describe("Secondary index PK"),
4949
supplierStatusSk: z.string().describe("Secondary index SK"),
5050
ttl: z.int(),
51+
source: z.string()
5152
}).describe("Letter");
5253

5354
/**
@@ -79,6 +80,7 @@ export type UpsertLetter = {
7980
url?: string;
8081
reasonCode?: string;
8182
reasonText?: string;
83+
source?: string;
8284
};
8385

8486
export const MISchemaBase = z.object({

lambdas/api-handler/src/mappers/__tests__/letter-mapper.test.ts

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,20 @@ import {
1212

1313
describe("letter-mapper", () => {
1414
it("maps an internal Letter to a PatchLetterResponse", () => {
15+
const date = new Date().toISOString();
1516
const letter: Letter = {
1617
id: "abc123",
1718
status: "PENDING",
1819
supplierId: "supplier1",
1920
specificationId: "spec123",
2021
groupId: "group123",
2122
url: "https://example.com/letter/abc123",
22-
createdAt: new Date().toISOString(),
23-
updatedAt: new Date().toISOString(),
23+
createdAt: date,
24+
updatedAt: date,
2425
supplierStatus: "supplier1#PENDING",
25-
supplierStatusSk: Date.now().toString(),
26+
supplierStatusSk: date,
2627
ttl: 123,
28+
source: "/data-plane/letter-rendering/pdf",
2729
};
2830

2931
const result: PatchLetterResponse = mapToPatchLetterResponse(letter);
@@ -42,20 +44,22 @@ describe("letter-mapper", () => {
4244
});
4345

4446
it("maps an internal Letter to a PatchLetterResponse with reasonCode and reasonText when present", () => {
47+
const date = new Date().toISOString();
4548
const letter: Letter = {
4649
id: "abc123",
4750
status: "PENDING",
4851
supplierId: "supplier1",
4952
specificationId: "spec123",
5053
groupId: "group123",
5154
url: "https://example.com/letter/abc123",
52-
createdAt: new Date().toISOString(),
53-
updatedAt: new Date().toISOString(),
55+
createdAt: date,
56+
updatedAt: date,
5457
supplierStatus: "supplier1#PENDING",
55-
supplierStatusSk: Date.now().toString(),
58+
supplierStatusSk: date,
5659
ttl: 123,
5760
reasonCode: "R01",
5861
reasonText: "Reason text",
62+
source: "/data-plane/letter-rendering/pdf",
5963
};
6064

6165
const result: PatchLetterResponse = mapToPatchLetterResponse(letter);
@@ -76,18 +80,20 @@ describe("letter-mapper", () => {
7680
});
7781

7882
it("maps an internal Letter to a GetLetterResponse", () => {
83+
const date = new Date().toISOString();
7984
const letter: Letter = {
8085
id: "abc123",
8186
status: "PENDING",
8287
supplierId: "supplier1",
8388
specificationId: "spec123",
8489
groupId: "group123",
8590
url: "https://example.com/letter/abc123",
86-
createdAt: new Date().toISOString(),
87-
updatedAt: new Date().toISOString(),
91+
createdAt: date,
92+
updatedAt: date,
8893
supplierStatus: "supplier1#PENDING",
89-
supplierStatusSk: Date.now().toString(),
94+
supplierStatusSk: date,
9095
ttl: 123,
96+
source: "/data-plane/letter-rendering/pdf",
9197
};
9298

9399
const result: GetLetterResponse = mapToGetLetterResponse(letter);
@@ -106,20 +112,22 @@ describe("letter-mapper", () => {
106112
});
107113

108114
it("maps an internal Letter to a GetLetterResponse with reasonCode and reasonText when present", () => {
115+
const date = new Date().toISOString();
109116
const letter: Letter = {
110117
id: "abc123",
111118
status: "PENDING",
112119
supplierId: "supplier1",
113120
specificationId: "spec123",
114121
groupId: "group123",
115122
url: "https://example.com/letter/abc123",
116-
createdAt: new Date().toISOString(),
117-
updatedAt: new Date().toISOString(),
123+
createdAt: date,
124+
updatedAt: date,
118125
supplierStatus: "supplier1#PENDING",
119-
supplierStatusSk: Date.now().toString(),
126+
supplierStatusSk: date,
120127
ttl: 123,
121128
reasonCode: "R01",
122129
reasonText: "Reason text",
130+
source: "/data-plane/letter-rendering/pdf",
123131
};
124132

125133
const result: GetLetterResponse = mapToGetLetterResponse(letter);
@@ -140,20 +148,22 @@ describe("letter-mapper", () => {
140148
});
141149

142150
it("maps an internal Letter collection to a GetLettersResponse", () => {
151+
const date = new Date().toISOString();
143152
const letter: Letter = {
144153
id: "abc123",
145154
status: "PENDING",
146155
supplierId: "supplier1",
147156
specificationId: "spec123",
148157
groupId: "group123",
149158
url: "https://example.com/letter/abc123",
150-
createdAt: new Date().toISOString(),
151-
updatedAt: new Date().toISOString(),
159+
createdAt: date,
160+
updatedAt: date,
152161
supplierStatus: "supplier1#PENDING",
153-
supplierStatusSk: Date.now().toString(),
162+
supplierStatusSk: date,
154163
ttl: 123,
155164
reasonCode: "R01",
156165
reasonText: "Reason text",
166+
source: "/data-plane/letter-rendering/pdf",
157167
};
158168

159169
const result: GetLettersResponse = mapToGetLettersResponse([

lambdas/api-handler/src/services/__tests__/letter-operations.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ function makeLetter(id: string, status: Letter["status"]): Letter {
3838
ttl: 123,
3939
reasonCode: "R01",
4040
reasonText: "Reason text",
41+
source: "/data-plane/letter-rendering/pdf",
4142
};
4243
}
4344

lambdas/upsert-letter/src/handler/__tests__/upsert-handler.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ describe("createUpsertLetterHandler", () => {
132132
expect(firstArg.url).toBe("s3://letterDataBucket/letter1.pdf");
133133
expect(firstArg.status).toBe("PENDING");
134134
expect(firstArg.groupId).toBe("client1campaign1template1");
135+
expect(firstArg.source).toBe("/data-plane/letter-rendering/test");
135136

136137
const secondArg = (mockedDeps.letterRepo.upsertLetter as jest.Mock).mock
137138
.calls[1][0];
@@ -141,6 +142,8 @@ describe("createUpsertLetterHandler", () => {
141142
expect(secondArg.url).toBe("s3://letterDataBucket/letter2.pdf");
142143
expect(secondArg.status).toBe("PENDING");
143144
expect(secondArg.groupId).toBe("client1campaign1template1");
145+
expect(secondArg.groupId).toBe("client1campaign1template1");
146+
expect(firstArg.source).toBe("/data-plane/letter-rendering/test");
144147
});
145148

146149
test("invalid JSON body produces batch failure and logs error", async () => {

lambdas/upsert-letter/src/handler/upsert-handler.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ function mapToUpsertLetter(
2424
upsertRequest.data.campaignId +
2525
upsertRequest.data.templateId,
2626
url: upsertRequest.data.url,
27-
// TODO CCM-12997 source
28-
// TODO CCM-12997 queueVisibility
27+
source: upsertRequest.source,
2928
};
3029
}
3130

scripts/utilities/letter-test-data/src/__test__/helpers/create_letter_helpers.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ describe("Create letter helpers", () => {
5454
supplierId: "supplierId",
5555
updatedAt: "2020-02-01T00:00:00.000Z",
5656
url: "s3://bucketName/supplierId/targetFilename",
57+
source: "/data-plane/letter-rendering/letter-test-data",
5758
});
5859
});
5960

@@ -81,6 +82,7 @@ describe("Create letter helpers", () => {
8182
status: "PENDING",
8283
createdAt: "2020-02-01T00:00:00.000Z",
8384
updatedAt: "2020-02-01T00:00:00.000Z",
85+
source: "/data-plane/letter-rendering/letter-test-data",
8486
});
8587
});
8688
});

0 commit comments

Comments
 (0)