Skip to content

Commit d62a1fe

Browse files
committed
move the badly named accumulated data tests
1 parent 7568d92 commit d62a1fe

File tree

5 files changed

+134
-206
lines changed

5 files changed

+134
-206
lines changed

packages/db-collection-e2e/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,3 @@ export { createCollationTestSuite } from "./suites/collation.suite"
2626
export { createMutationsTestSuite } from "./suites/mutations.suite"
2727
export { createLiveUpdatesTestSuite } from "./suites/live-updates.suite"
2828
export { createRegressionTestSuite } from "./suites/regressions.suite"
29-
export { createAccumulatedDataTestSuite } from "./suites/accumulated-data.suite"

packages/db-collection-e2e/src/suites/accumulated-data.suite.ts

Lines changed: 0 additions & 103 deletions
This file was deleted.

packages/db-collection-e2e/src/suites/live-updates.suite.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,5 +271,52 @@ export function createLiveUpdatesTestSuite(
271271
await Promise.all([query1.cleanup(), query2.cleanup()])
272272
})
273273
})
274+
275+
describe(`Update Existing Records`, () => {
276+
it(`should update existing records in query results`, async () => {
277+
const config = await getConfig()
278+
279+
if (!config.mutations) {
280+
throw new Error(`Mutations not configured - test cannot run`)
281+
}
282+
283+
const usersCollection = config.collections.onDemand.users
284+
285+
const query = createLiveQueryCollection((q) =>
286+
q.from({ user: usersCollection })
287+
)
288+
289+
await query.preload()
290+
await waitForQueryData(query, { minSize: 1 })
291+
292+
// Get a user and update it
293+
const users = Array.from(query.state.values())
294+
const userToUpdate = users[0]
295+
296+
if (userToUpdate) {
297+
const originalAge = userToUpdate.age
298+
299+
// Update the user's age
300+
await config.mutations.updateUser(userToUpdate.id, {
301+
age: originalAge + 10,
302+
})
303+
304+
// Wait for update to sync
305+
await waitFor(
306+
() => {
307+
const updated = query.get(userToUpdate.id)
308+
return updated?.age === originalAge + 10
309+
},
310+
{ timeout: 5000, message: `Update did not sync to query` }
311+
)
312+
313+
// Verify the update
314+
const updatedUser = query.get(userToUpdate.id)
315+
expect(updatedUser?.age).toBe(originalAge + 10)
316+
}
317+
318+
await query.cleanup()
319+
})
320+
})
274321
})
275322
}

packages/db-collection-e2e/src/suites/mutations.suite.ts

Lines changed: 87 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import { randomUUID } from "node:crypto"
88
import { describe, expect, it } from "vitest"
9-
import { createLiveQueryCollection, eq, gt } from "@tanstack/db"
9+
import { createLiveQueryCollection, eq, gt, isNull } from "@tanstack/db"
1010
import { waitFor, waitForQueryData } from "../utils/helpers"
1111
import type { E2ETestConfig } from "../types"
1212

@@ -113,9 +113,8 @@ export function createMutationsTestSuite(
113113
it(`should handle update that makes record match predicate`, async () => {
114114
const config = await getConfig()
115115

116-
// Skip test if mutations not available (Query collection)
117116
if (!config.mutations) {
118-
return
117+
throw new Error(`Mutations not configured - test cannot run`)
119118
}
120119

121120
const usersCollection = config.collections.onDemand.users
@@ -154,9 +153,8 @@ export function createMutationsTestSuite(
154153
it(`should handle update that makes record unmatch predicate`, async () => {
155154
const config = await getConfig()
156155

157-
// Skip test if mutations not available (Query collection)
158156
if (!config.mutations) {
159-
return
157+
throw new Error(`Mutations not configured - test cannot run`)
160158
}
161159

162160
const usersCollection = config.collections.onDemand.users
@@ -193,6 +191,90 @@ export function createMutationsTestSuite(
193191
})
194192
})
195193

194+
describe(`Delete Mutations`, () => {
195+
it(`should handle delete removing record from query`, async () => {
196+
const config = await getConfig()
197+
198+
if (!config.mutations) {
199+
throw new Error(`Mutations not configured - test cannot run`)
200+
}
201+
202+
const usersCollection = config.collections.onDemand.users
203+
204+
const query = createLiveQueryCollection((q) =>
205+
q.from({ user: usersCollection })
206+
)
207+
208+
await query.preload()
209+
await waitForQueryData(query, { minSize: 1 })
210+
const initialSize = query.size
211+
expect(initialSize).toBeGreaterThan(0)
212+
213+
// Get a user and delete it
214+
const users = Array.from(query.state.values())
215+
const userToDelete = users[0]
216+
217+
if (userToDelete) {
218+
await config.mutations.deleteUser(userToDelete.id)
219+
220+
// Wait for delete to sync
221+
await waitFor(() => query.size < initialSize, {
222+
timeout: 5000,
223+
message: `Delete did not sync to query`,
224+
})
225+
226+
expect(query.size).toBe(initialSize - 1)
227+
}
228+
229+
await query.cleanup()
230+
})
231+
})
232+
233+
describe(`Soft Delete Pattern`, () => {
234+
it(`should filter out soft-deleted records`, async () => {
235+
const config = await getConfig()
236+
const usersCollection = config.collections.onDemand.users
237+
238+
const query = createLiveQueryCollection((q) =>
239+
q
240+
.from({ user: usersCollection })
241+
.where(({ user }) => isNull(user.deletedAt))
242+
)
243+
244+
await query.preload()
245+
await waitForQueryData(query, { minSize: 1 })
246+
247+
// All results should not be soft-deleted
248+
const results = Array.from(query.state.values())
249+
expect(results.length).toBeGreaterThan(0)
250+
results.forEach((u) => {
251+
expect(u.deletedAt).toBeNull()
252+
})
253+
254+
await query.cleanup()
255+
})
256+
257+
it(`should include soft-deleted records when not filtered`, async () => {
258+
const config = await getConfig()
259+
const usersCollection = config.collections.onDemand.users
260+
261+
const query = createLiveQueryCollection((q) =>
262+
q.from({ user: usersCollection })
263+
)
264+
265+
await query.preload()
266+
await waitForQueryData(query, { minSize: 1 })
267+
268+
// Should include both deleted and non-deleted
269+
const results = Array.from(query.state.values())
270+
const hasNotDeleted = results.some((u) => u.deletedAt === null)
271+
272+
expect(hasNotDeleted).toBe(true)
273+
274+
await query.cleanup()
275+
})
276+
})
277+
196278
describe(`Mutation with Queries`, () => {
197279
it(`should maintain query state during data changes`, async () => {
198280
const config = await getConfig()

packages/electric-db-collection/e2e/electric.e2e.test.ts

Lines changed: 0 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { createCollection } from "@tanstack/db"
99
import { electricCollectionOptions } from "../src/electric"
1010
import { makePgClient } from "../../db-collection-e2e/support/global-setup"
1111
import {
12-
createAccumulatedDataTestSuite,
1312
createCollationTestSuite,
1413
createDeduplicationTestSuite,
1514
createJoinsTestSuite,
@@ -380,99 +379,3 @@ describe(`Electric Collection E2E Tests`, () => {
380379
createLiveUpdatesTestSuite(getConfig)
381380
createRegressionTestSuite(getConfig)
382381
})
383-
384-
// Separate describe block for tests that expect accumulated data
385-
// These tests do NOT cleanup between tests to preserve data accumulation
386-
// SKIP: These tests have timing issues with Electric shape invalidation (409 must-refetch)
387-
// TODO: Investigate and fix shape state handling
388-
describe.skip(`Electric Collection E2E Tests - Accumulated Data`, () => {
389-
let config: E2ETestConfig
390-
let dbClient: Client
391-
let usersTable: string
392-
393-
beforeAll(async () => {
394-
const baseUrl = inject(`baseUrl`)
395-
const testSchema = inject(`testSchema`)
396-
const seedData = generateSeedData()
397-
398-
const testId = Date.now().toString(16)
399-
usersTable = `"users_accum_${testId}"`
400-
401-
dbClient = makePgClient({ options: `-csearch_path=${testSchema}` })
402-
await dbClient.connect()
403-
await dbClient.query(`SET search_path TO ${testSchema}`)
404-
405-
// Create and populate tables
406-
await dbClient.query(`CREATE TABLE ${usersTable} (
407-
id UUID PRIMARY KEY, name TEXT NOT NULL, email TEXT, age INTEGER NOT NULL,
408-
"isActive" BOOLEAN NOT NULL DEFAULT true, "createdAt" TIMESTAMP NOT NULL DEFAULT NOW(),
409-
metadata JSONB, "deletedAt" TIMESTAMP
410-
)`)
411-
412-
for (const user of seedData.users) {
413-
await dbClient.query(
414-
`INSERT INTO ${usersTable} (id, name, email, age, "isActive", "createdAt", metadata, "deletedAt")
415-
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`,
416-
[
417-
user.id,
418-
user.name,
419-
user.email,
420-
user.age,
421-
user.isActive,
422-
user.createdAt,
423-
user.metadata ? JSON.stringify(user.metadata) : null,
424-
user.deletedAt,
425-
]
426-
)
427-
}
428-
429-
// Create on-demand collection (NO cleanup between tests)
430-
const onDemandUsers = createCollection(
431-
electricCollectionOptions({
432-
id: `electric-accum-users-${testId}`,
433-
shapeOptions: {
434-
url: `${baseUrl}/v1/shape`,
435-
params: { table: `${testSchema}.${usersTable}` },
436-
},
437-
syncMode: `on-demand`,
438-
getKey: (item: any) => item.id,
439-
startSync: true,
440-
})
441-
)
442-
443-
await onDemandUsers.preload()
444-
445-
config = {
446-
collections: {
447-
eager: {
448-
users: onDemandUsers as any,
449-
posts: null as any,
450-
comments: null as any,
451-
},
452-
onDemand: {
453-
users: onDemandUsers as any,
454-
posts: null as any,
455-
comments: null as any,
456-
},
457-
},
458-
// No mutations for accumulated data suite
459-
setup: async () => {},
460-
teardown: async () => {
461-
await onDemandUsers.cleanup()
462-
await dbClient.query(`DROP TABLE IF EXISTS ${usersTable}`)
463-
await dbClient.end()
464-
},
465-
}
466-
}, 60000)
467-
468-
afterAll(async () => {
469-
await config.teardown()
470-
})
471-
472-
function getConfig() {
473-
return Promise.resolve(config)
474-
}
475-
476-
// Run accumulated data tests (no cleanup between these tests)
477-
createAccumulatedDataTestSuite(getConfig)
478-
})

0 commit comments

Comments
 (0)