From 7a48659cae73a3f6b0c63142f511b7165a35d11e Mon Sep 17 00:00:00 2001 From: Lucas Berger Date: Tue, 9 Jun 2026 10:51:10 -0400 Subject: [PATCH] fix(03): update event lookup test mocks for CR-01/CR-02 query-chain changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CR-01 fix appended .orderBy().limit(1) to the edit/delete event lookups and CR-02 added .innerJoin(calendars).limit(1) to the freshest-etag re-read. The existing test doubles terminated the mock chain at .where(), so the new chain calls hit undefined methods → handlers caught the throw and returned 503 (events.test.ts) and the worker skipped the PUT (outboxWorker.test.ts). Extend the mocks to match the corrected production chains. Behaviour-preserving: mockWhereCalEvents stays the awaited terminal so etag override assertions still drive. 8 failing tests now green; full suite: api 103, pwa 141. --- apps/api/tests/broker/outboxWorker.test.ts | 10 +++++- apps/api/tests/routes/events.test.ts | 41 ++++++++++++++++------ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/apps/api/tests/broker/outboxWorker.test.ts b/apps/api/tests/broker/outboxWorker.test.ts index fd30ac3..ca82e51 100644 --- a/apps/api/tests/broker/outboxWorker.test.ts +++ b/apps/api/tests/broker/outboxWorker.test.ts @@ -139,7 +139,15 @@ function wireMockChain() { return { where: vi.fn().mockResolvedValue([FAKE_CRED_ROW]) } } if (tableName === 'calendar_events') { - return { where: mockWhereCalEvents } + // CR-02: the freshest-etag re-read now scopes to the writing member's calendar: + // .from(calendarEvents).innerJoin(calendars, ...).where(...).limit(1) + // mockWhereCalEvents stays the awaited terminal (returned by .limit) so existing + // mockWhereCalEvents.mockResolvedValue([{ etag }]) overrides still drive the etag. + return { + innerJoin: vi.fn().mockReturnValue({ + where: vi.fn().mockReturnValue({ limit: mockWhereCalEvents }), + }), + } } return { where: mockWherePending } }) diff --git a/apps/api/tests/routes/events.test.ts b/apps/api/tests/routes/events.test.ts index 2116943..1d64e3f 100644 --- a/apps/api/tests/routes/events.test.ts +++ b/apps/api/tests/routes/events.test.ts @@ -385,9 +385,14 @@ describe('PATCH /api/events/:uid/edit', () => { userId: 1, }, ] - // After BUG 1 fix, the edit lookup uses .from(calendarEvents).innerJoin(calendars, ...).where(...) - // Wire mockFromFn to expose innerJoin → where so the handler resolves mockDbRows. - const mockInnerJoinWhere = vi.fn().mockImplementation(() => Promise.resolve(mockDbRows)) + // After BUG 1 + CR-01 fix, the edit lookup uses + // .from(calendarEvents).innerJoin(calendars, ...).where(...).orderBy(...).limit(1). + // Wire mockFromFn to expose innerJoin → where → orderBy → limit so the handler resolves mockDbRows. + const mockInnerJoinWhere = vi.fn().mockReturnValue({ + orderBy: vi.fn().mockReturnValue({ + limit: vi.fn().mockImplementation(() => Promise.resolve(mockDbRows)), + }), + }) const mockInnerJoin = vi.fn().mockReturnValue({ where: mockInnerJoinWhere }) mockFromFn.mockReturnValue({ innerJoin: mockInnerJoin }) mockSelectFn.mockReturnValue({ from: mockFromFn }) @@ -426,9 +431,14 @@ describe('DELETE /api/events/:uid', () => { userId: 1, }, ] - // After BUG 1 fix, the delete lookup uses .from(calendarEvents).innerJoin(calendars, ...).where(...) - // Wire mockFromFn to expose innerJoin → where so the handler resolves mockDbRows. - const mockInnerJoinWhere = vi.fn().mockImplementation(() => Promise.resolve(mockDbRows)) + // After BUG 1 + CR-01 fix, the delete lookup uses + // .from(calendarEvents).innerJoin(calendars, ...).where(...).orderBy(...).limit(1). + // Wire mockFromFn to expose innerJoin → where → orderBy → limit so the handler resolves mockDbRows. + const mockInnerJoinWhere = vi.fn().mockReturnValue({ + orderBy: vi.fn().mockReturnValue({ + limit: vi.fn().mockImplementation(() => Promise.resolve(mockDbRows)), + }), + }) const mockInnerJoin = vi.fn().mockReturnValue({ where: mockInnerJoinWhere }) mockFromFn.mockReturnValue({ innerJoin: mockInnerJoin }) mockSelectFn.mockReturnValue({ from: mockFromFn }) @@ -543,8 +553,12 @@ describe('CR-01: canonical client payload (title/start/end) accepted by server', userId: 1, }, ] - // Edit lookup uses innerJoin after BUG 1 fix - const mockInnerJoinWhere = vi.fn().mockImplementation(() => Promise.resolve(mockDbRows)) + // Edit lookup uses innerJoin → where → orderBy → limit after BUG 1 + CR-01 fix + const mockInnerJoinWhere = vi.fn().mockReturnValue({ + orderBy: vi.fn().mockReturnValue({ + limit: vi.fn().mockImplementation(() => Promise.resolve(mockDbRows)), + }), + }) const mockInnerJoin = vi.fn().mockReturnValue({ where: mockInnerJoinWhere }) mockFromFn.mockReturnValue({ innerJoin: mockInnerJoin }) mockSelectFn.mockReturnValue({ from: mockFromFn }) @@ -674,9 +688,14 @@ describe('regression: edit/delete lookups join calendars (BUG 1)', () => { beforeEach(() => { mockDbRows = [seededRow] - // Wire from() → innerJoin() → where(); the innerJoin spy proves the handler - // routes through the join rather than calling .where() directly on from(). - const innerJoinWhere = vi.fn().mockImplementation(() => Promise.resolve(mockDbRows)) + // Wire from() → innerJoin() → where() → orderBy() → limit(); the innerJoin spy + // proves the handler routes through the join rather than calling .where() directly + // on from(). The CR-01 fix appends .orderBy(...).limit(1) after .where(...). + const innerJoinWhere = vi.fn().mockReturnValue({ + orderBy: vi.fn().mockReturnValue({ + limit: vi.fn().mockImplementation(() => Promise.resolve(mockDbRows)), + }), + }) innerJoinSpy = vi.fn().mockReturnValue({ where: innerJoinWhere }) mockFromFn.mockReturnValue({ innerJoin: innerJoinSpy }) mockSelectFn.mockReturnValue({ from: mockFromFn })