Skip to content

Commit 858ae53

Browse files
committed
fix(testing): close routing over each chain's own tables for direct-await builders
1 parent d34ca5f commit 858ae53

2 files changed

Lines changed: 24 additions & 11 deletions

File tree

packages/testing/src/mocks/database.mock.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,15 @@ describe('database mock', () => {
7373
await expect(db.select().from(workflowTable)).resolves.toEqual([])
7474
})
7575

76+
it('routes two direct-await builders constructed before either resolves', async () => {
77+
queueTableRows(workflowTable, [{ id: 'w-first' }])
78+
queueTableRows(memberTable, [{ id: 'm-second' }])
79+
const first = db.select().from(workflowTable)
80+
const second = db.select().from(memberTable)
81+
await expect(first).resolves.toEqual([{ id: 'w-first' }])
82+
await expect(second).resolves.toEqual([{ id: 'm-second' }])
83+
})
84+
7685
it('routes rows queued for a table referenced only by a join', async () => {
7786
queueTableRows(memberTable, [{ id: 'joined' }])
7887
await expect(

packages/testing/src/mocks/database.mock.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ export function queueTableRows(table: unknown, rows: unknown[]): void {
9595
else tableRowQueues.set(table, [rows])
9696
}
9797

98-
/** Dequeues the first queued set among the chain's tables (from before joins). */
99-
function dequeueActiveRows(): unknown[] | null {
100-
for (const table of activeTables) {
98+
/** Dequeues the first queued set among the given chain's tables (from before joins). */
99+
function dequeueChainRows(tables: unknown[]): unknown[] | null {
100+
for (const table of tables) {
101101
const queue = tableRowQueues.get(table)
102102
if (queue && queue.length > 0) return queue.shift() ?? null
103103
}
@@ -187,7 +187,7 @@ const onConflictDoNothing = vi.fn(() => ({ returning }) as unknown as Promise<vo
187187
const whereBuilder = () => {
188188
// Dequeue table-routed rows when the where clause materializes; every
189189
// downstream terminal (limit/orderBy/...) then resolves the same rows.
190-
activeRows = dequeueActiveRows()
190+
activeRows = dequeueChainRows(activeTables)
191191
// Some call sites await the where directly (no limit/orderBy), so the
192192
// builder is itself a thenable.
193193
const thenable: any = chainRows()
@@ -201,25 +201,29 @@ const whereBuilder = () => {
201201
const where = vi.fn(whereBuilder)
202202

203203
// The from/join builder is itself a thenable so `await db.select().from(t)`
204-
// (no where clause) also resolves table-routed rows. Dequeue happens lazily at
205-
// await time, so a chain that continues into `.where()` never double-consumes.
206-
const joinBuilder = (): { where: typeof where; innerJoin: any; leftJoin: any; then: any } => ({
204+
// (no where clause) also resolves table-routed rows. Each builder closes over
205+
// ITS chain's tables array, so builders constructed before an earlier one is
206+
// awaited still route to their own chain. Dequeue happens lazily at await
207+
// time, so a chain that continues into `.where()` never double-consumes.
208+
const joinBuilder = (
209+
tables: unknown[]
210+
): { where: typeof where; innerJoin: any; leftJoin: any; then: any } => ({
207211
where,
208212
innerJoin,
209213
leftJoin,
210214
then: (onFulfilled?: (rows: unknown[]) => unknown, onRejected?: (reason: unknown) => unknown) =>
211-
Promise.resolve((dequeueActiveRows() ?? []) as unknown[]).then(onFulfilled, onRejected),
215+
Promise.resolve((dequeueChainRows(tables) ?? []) as unknown[]).then(onFulfilled, onRejected),
212216
})
213217
const joinStep = (table?: unknown) => {
214218
activeTables.push(table)
215-
return joinBuilder()
219+
return joinBuilder(activeTables)
216220
}
217221
const innerJoin: ReturnType<typeof vi.fn> = vi.fn(joinStep)
218222
const leftJoin: ReturnType<typeof vi.fn> = vi.fn(joinStep)
219223
const from = vi.fn((table?: unknown) => {
220224
activeTables = [table]
221225
activeRows = null
222-
return joinBuilder()
226+
return joinBuilder(activeTables)
223227
})
224228

225229
const select = vi.fn(() => ({ from }))
@@ -288,7 +292,7 @@ export function resetDbChainMock(): void {
288292
from.mockImplementation((table?: unknown) => {
289293
activeTables = [table]
290294
activeRows = null
291-
return joinBuilder()
295+
return joinBuilder(activeTables)
292296
})
293297
innerJoin.mockImplementation(joinStep)
294298
leftJoin.mockImplementation(joinStep)

0 commit comments

Comments
 (0)