@@ -7,14 +7,16 @@ import {
77 setupDynamoDBContainer ,
88} from "./db" ;
99import LetterQueueRepository from "../letter-queue-repository" ;
10- import { InsertPendingLetter } from "../types" ;
10+ import { PendingLetterBase } from "../types" ;
1111import { LetterAlreadyExistsError } from "../letter-already-exists-error" ;
1212import { createTestLogger } from "./logs" ;
1313import { LetterDoesNotExistError } from "../letter-does-not-exist-error" ;
1414
15+ type PendingLetterWithPriority = PendingLetterBase & { priority : number } ;
16+
1517function createLetter (
16- overrides : Partial < InsertPendingLetter > = { } ,
17- ) : InsertPendingLetter {
18+ overrides : Partial < PendingLetterWithPriority > = { } ,
19+ ) : PendingLetterBase {
1820 return {
1921 letterId : "letter1" ,
2022 supplierId : "supplier1" ,
@@ -51,6 +53,7 @@ describe("LetterQueueRepository", () => {
5153 afterEach ( async ( ) => {
5254 await deleteTables ( db ) ;
5355 jest . useRealTimers ( ) ;
56+ jest . restoreAllMocks ( ) ;
5457 } ) ;
5558
5659 afterAll ( async ( ) => {
@@ -149,6 +152,116 @@ describe("LetterQueueRepository", () => {
149152 ) . rejects . toThrow ( "Cannot do operations on a non-existent table" ) ;
150153 } ) ;
151154 } ) ;
155+
156+ describe ( "getLetters" , ( ) => {
157+ it ( "filters by supplierId" , async ( ) => {
158+ await letterQueueRepository . putLetter ( createLetter ( ) ) ;
159+
160+ const letters = await letterQueueRepository . getLetters ( "supplier2" , 1 ) ;
161+
162+ expect ( letters ) . toHaveLength ( 0 ) ;
163+ } ) ;
164+
165+ it ( "filters by visibilityTimestamp" , async ( ) => {
166+ const pendingLetter = createLetter ( ) ;
167+ await letterQueueRepository . putLetter ( createLetter ( ) ) ;
168+ await letterQueueRepository . updateVisibilityTimestamp (
169+ pendingLetter ,
170+ new Date ( Date . now ( ) + 600_000 ) ,
171+ ) ;
172+
173+ const letters = await letterQueueRepository . getLetters ( "supplier1" , 1 ) ;
174+
175+ expect ( letters ) . toHaveLength ( 0 ) ;
176+ } ) ;
177+
178+ it ( "returns letters in timestamp order" , async ( ) => {
179+ await letterQueueRepository . putLetter (
180+ createLetter ( { letterId : "first-letter" } ) ,
181+ ) ;
182+ await letterQueueRepository . putLetter (
183+ createLetter ( { letterId : "second-letter" } ) ,
184+ ) ;
185+ await letterQueueRepository . putLetter (
186+ createLetter ( { letterId : "third-letter" } ) ,
187+ ) ;
188+ await letterQueueRepository . putLetter (
189+ createLetter ( { letterId : "fourth-letter" } ) ,
190+ ) ;
191+ await letterQueueRepository . putLetter (
192+ createLetter ( { letterId : "fifth-letter" } ) ,
193+ ) ;
194+
195+ const letters = await letterQueueRepository . getLetters ( "supplier1" , 5 ) ;
196+
197+ expect ( letters [ 0 ] . letterId ) . toBe ( "first-letter" ) ;
198+ expect ( letters [ 1 ] . letterId ) . toBe ( "second-letter" ) ;
199+ expect ( letters [ 2 ] . letterId ) . toBe ( "third-letter" ) ;
200+ expect ( letters [ 3 ] . letterId ) . toBe ( "fourth-letter" ) ;
201+ expect ( letters [ 4 ] . letterId ) . toBe ( "fifth-letter" ) ;
202+ } ) ;
203+
204+ it ( "limits results to the supplied number" , async ( ) => {
205+ await letterQueueRepository . putLetter (
206+ createLetter ( { letterId : "first-letter" } ) ,
207+ ) ;
208+ await letterQueueRepository . putLetter (
209+ createLetter ( { letterId : "second-letter" } ) ,
210+ ) ;
211+ await letterQueueRepository . putLetter (
212+ createLetter ( { letterId : "third-letter" } ) ,
213+ ) ;
214+ await letterQueueRepository . putLetter (
215+ createLetter ( { letterId : "fourth-letter" } ) ,
216+ ) ;
217+
218+ const letters = await letterQueueRepository . getLetters ( "supplier1" , 3 ) ;
219+
220+ expect ( letters ) . toHaveLength ( 3 ) ;
221+ expect ( letters [ 2 ] . letterId ) . toBe ( "third-letter" ) ;
222+ } ) ;
223+ } ) ;
224+
225+ describe ( "updateVisibilityTimestamp" , ( ) => {
226+ it ( "updates the visibilityTimestamp on an existing letter" , async ( ) => {
227+ const pendingLetter =
228+ await letterQueueRepository . putLetter ( createLetter ( ) ) ;
229+
230+ await letterQueueRepository . updateVisibilityTimestamp (
231+ pendingLetter ,
232+ new Date ( "2026-03-04T13:15:45.000Z" ) ,
233+ ) ;
234+
235+ const letter = await getLetter ( db , "supplier1" , "letter1" ) ;
236+ expect ( letter ?. visibilityTimestamp ) . toBe ( "2026-03-04T13:15:45.000Z" ) ;
237+ } ) ;
238+
239+ it ( "does nothing when the letter does not exist" , async ( ) => {
240+ await letterQueueRepository . updateVisibilityTimestamp (
241+ createLetter ( ) ,
242+ new Date ( ) ,
243+ ) ;
244+
245+ expect ( await letterExists ( db , "supplier1" , "letter1" ) ) . toBe ( false ) ;
246+ } ) ;
247+
248+ it ( "rethrows errors from DynamoDB when updating the letter" , async ( ) => {
249+ const misconfiguredRepository = new LetterQueueRepository (
250+ db . docClient ,
251+ logger ,
252+ {
253+ ...db . config ,
254+ letterQueueTableName : "nonexistent-table" ,
255+ } ,
256+ ) ;
257+ await expect (
258+ misconfiguredRepository . updateVisibilityTimestamp (
259+ createLetter ( ) ,
260+ new Date ( ) ,
261+ ) ,
262+ ) . rejects . toThrow ( "Cannot do operations on a non-existent table" ) ;
263+ } ) ;
264+ } ) ;
152265} ) ;
153266
154267async function getLetter ( db : DBContext , supplierId : string , letterId : string ) {
0 commit comments