diff --git a/server/tests/integration/trips.test.ts b/server/tests/integration/trips.test.ts index b2ffd8790..3cdf3fe91 100644 --- a/server/tests/integration/trips.test.ts +++ b/server/tests/integration/trips.test.ts @@ -26,18 +26,42 @@ vi.mock('../../src/config', () => ({ vi.mock('../../src/websocket', () => ({ broadcast: vi.fn(), broadcastToUser: vi.fn() })); import { db as testDb } from '../../src/db/database'; +import { MikroORM } from '@mikro-orm/core'; import { buildApp } from '../../src/bootstrap'; import { resetTestDb, resetRateLimits } from '../helpers/test-db'; +import type { FactoryOrm } from '../helpers/factories/context'; import { createUser, createAdmin, createTrip, addTripMember, createPlace, createReservation, createTag, createDayAccommodation, createBudgetItem, createPackingItem, createDayNote, createDayAssignment } from '../helpers/factories'; import { authCookie } from '../helpers/auth'; +import { countRows, findRow, findRows, insertRow, insertRows, updateRows } from '../helpers/factories/rows'; +import { readTripDays } from '../helpers/factories/trips'; +import { readUser } from '../helpers/factories/users'; +import { setAppSetting } from '../helpers/factories/settings'; +import { tagPlace } from '../helpers/factories/places'; +import { AppSettings } from '../../src/db/entities/AppSettings.entity'; +import { BudgetCategoryOrder } from '../../src/db/entities/BudgetCategoryOrder.entity'; +import { BudgetItems } from '../../src/db/entities/BudgetItems.entity'; +import { DayAccommodations } from '../../src/db/entities/DayAccommodations.entity'; +import { DayAssignments } from '../../src/db/entities/DayAssignments.entity'; +import { DayNotes } from '../../src/db/entities/DayNotes.entity'; +import { Days } from '../../src/db/entities/Days.entity'; +import { PackingItems } from '../../src/db/entities/PackingItems.entity'; +import { Places } from '../../src/db/entities/Places.entity'; +import { Reservations } from '../../src/db/entities/Reservations.entity'; +import { Tags } from '../../src/db/entities/Tags.entity'; +import { TodoItems } from '../../src/db/entities/TodoItems.entity'; +import { TripMembers } from '../../src/db/entities/TripMembers.entity'; +import { Trips } from '../../src/db/entities/Trips.entity'; +import { Users } from '../../src/db/entities/Users.entity'; import { invalidatePermissionsCache } from '../../src/nest/permissions/permissions-cache'; let nestApp: INestApplication; let app: Application; +let orm: FactoryOrm; beforeAll(async () => { nestApp = await buildApp(); app = nestApp.getHttpAdapter().getInstance(); + orm = nestApp.get(MikroORM); }); beforeEach(async () => { resetTestDb(testDb); @@ -67,7 +91,7 @@ describe('Create trip', () => { expect(res.body.trip.title).toBe('Paris Adventure'); // Verify days were generated (5 days: Jun 1–5) - const days = testDb.prepare('SELECT * FROM days WHERE trip_id = ? ORDER BY date').all(res.body.trip.id) as any[]; + const days = await findRows(orm, Days, { trip: res.body.trip.id }, { date: 'asc' }); expect(days).toHaveLength(5); expect(days[0].date).toBe('2026-06-01'); expect(days[4].date).toBe('2026-06-05'); @@ -87,7 +111,7 @@ describe('Create trip', () => { expect(res.body.trip.end_date).toBeNull(); // Should have 7 dateless placeholder days - const days = testDb.prepare('SELECT * FROM days WHERE trip_id = ? ORDER BY day_number').all(res.body.trip.id) as any[]; + const days = await readTripDays(orm, res.body.trip.id); expect(days).toHaveLength(7); expect(days[0].date).toBeNull(); }); @@ -104,7 +128,7 @@ describe('Create trip', () => { expect(res.body.trip.start_date).toBeNull(); expect(res.body.trip.day_count).toBe(20); - const days = testDb.prepare('SELECT * FROM days WHERE trip_id = ?').all(res.body.trip.id) as any[]; + const days = await findRows(orm, Days, { trip: res.body.trip.id }); expect(days).toHaveLength(20); }); @@ -136,7 +160,7 @@ describe('Create trip', () => { const { user } = createUser(testDb); // Restrict trip creation to admins only - testDb.prepare("INSERT INTO app_settings (key, value) VALUES ('perm_trip_create', 'admin')").run(); + await insertRow(orm, AppSettings, { key: 'perm_trip_create', value: 'admin' }); await invalidatePermissionsCache(); const res = await request(app) @@ -151,7 +175,7 @@ describe('Create trip', () => { it('TRIP-003 — trip_create permission set to admin allows admin user', async () => { const { user: admin } = createAdmin(testDb); - testDb.prepare("INSERT INTO app_settings (key, value) VALUES ('perm_trip_create', 'admin')").run(); + await insertRow(orm, AppSettings, { key: 'perm_trip_create', value: 'admin' }); await invalidatePermissionsCache(); const res = await request(app) @@ -211,7 +235,7 @@ describe('List trips', () => { const archivedTrip = createTrip(testDb, user.id, { title: 'Archived Trip' }); // Archive the second trip directly in the DB - testDb.prepare('UPDATE trips SET is_archived = 1 WHERE id = ?').run(archivedTrip.id); + await updateRows(orm, Trips, { id: archivedTrip.id }, { is_archived: 1 }); const res = await request(app) .get('/api/trips') @@ -229,7 +253,7 @@ describe('List trips', () => { const activeTrip = createTrip(testDb, user.id, { title: 'Active Trip' }); const archivedTrip = createTrip(testDb, user.id, { title: 'Archived Trip' }); - testDb.prepare('UPDATE trips SET is_archived = 1 WHERE id = ?').run(archivedTrip.id); + await updateRows(orm, Trips, { id: archivedTrip.id }, { is_archived: 1 }); const res = await request(app) .get('/api/trips?archived=1') @@ -347,7 +371,7 @@ describe('Update trip', () => { const trip = createTrip(testDb, user.id, { title: 'Archived Trip' }); // Archive it first - testDb.prepare('UPDATE trips SET is_archived = 1 WHERE id = ?').run(trip.id); + await updateRows(orm, Trips, { id: trip.id }, { is_archived: 1 }); // Unarchive via API const unarchiveRes = await request(app) @@ -374,7 +398,7 @@ describe('Update trip', () => { addTripMember(testDb, trip.id, member.id); // Restrict archiving to trip_owner only (this is actually the default, but set explicitly) - testDb.prepare("INSERT OR REPLACE INTO app_settings (key, value) VALUES ('perm_trip_archive', 'trip_owner')").run(); + await setAppSetting(orm, 'perm_trip_archive', 'trip_owner'); await invalidatePermissionsCache(); const res = await request(app) @@ -393,7 +417,7 @@ describe('Update trip', () => { addTripMember(testDb, trip.id, member.id); // Default trip_edit is trip_owner — members should be blocked - testDb.prepare("INSERT OR REPLACE INTO app_settings (key, value) VALUES ('perm_trip_edit', 'trip_owner')").run(); + await setAppSetting(orm, 'perm_trip_edit', 'trip_owner'); await invalidatePermissionsCache(); const res = await request(app) @@ -419,7 +443,7 @@ describe('Update trip', () => { const { user } = createUser(testDb); const trip = createTrip(testDb, user.id, { start_date: '2026-08-01', end_date: '2026-08-05' }); - const days = testDb.prepare('SELECT * FROM days WHERE trip_id = ? ORDER BY day_number').all(trip.id) as { id: number; date: string }[]; + const days = await readTripDays(orm, trip.id); expect(days).toHaveLength(5); const place = createPlace(testDb, trip.id); @@ -434,16 +458,16 @@ describe('Update trip', () => { expect(res.status).toBe(200); - const daysAfter = testDb.prepare('SELECT * FROM days WHERE trip_id = ? ORDER BY day_number').all(trip.id) as { id: number; date: string | null }[]; + const daysAfter = await readTripDays(orm, trip.id); expect(daysAfter).toHaveLength(5); expect(daysAfter.map(d => d.date)).toEqual(['2026-08-11', '2026-08-12', '2026-08-13', '2026-08-14', '2026-08-15']); - const assignmentsAfter = testDb.prepare('SELECT * FROM day_assignments WHERE id = ?').get(assignment.id) as { day_id: number } | undefined; - expect(assignmentsAfter).toBeDefined(); + const assignmentsAfter = await findRow(orm, DayAssignments, { id: assignment.id }); + expect(assignmentsAfter).not.toBeNull(); expect(assignmentsAfter!.day_id).toBe(daysAfter[0].id); - const notesAfter = testDb.prepare('SELECT * FROM day_notes WHERE id = ?').get(note.id) as { day_id: number } | undefined; - expect(notesAfter).toBeDefined(); + const notesAfter = await findRow(orm, DayNotes, { id: note.id }); + expect(notesAfter).not.toBeNull(); expect(notesAfter!.day_id).toBe(daysAfter[1].id); }); @@ -451,7 +475,7 @@ describe('Update trip', () => { const { user } = createUser(testDb); const trip = createTrip(testDb, user.id, { start_date: '2026-09-01', end_date: '2026-09-05' }); - const days = testDb.prepare('SELECT * FROM days WHERE trip_id = ? ORDER BY day_number').all(trip.id) as { id: number }[]; + const days = await readTripDays(orm, trip.id); const place = createPlace(testDb, trip.id); const a4 = createDayAssignment(testDb, days[3].id, place.id); const a5 = createDayAssignment(testDb, days[4].id, place.id); @@ -464,12 +488,12 @@ describe('Update trip', () => { expect(res.status).toBe(200); - const daysAfter = testDb.prepare('SELECT * FROM days WHERE trip_id = ? ORDER BY day_number').all(trip.id) as { id: number; date: string | null }[]; + const daysAfter = await readTripDays(orm, trip.id); expect(daysAfter).toHaveLength(3); expect(daysAfter.every(d => d.date !== null)).toBe(true); // Overflow days and their assignments deleted - const all = testDb.prepare('SELECT * FROM day_assignments WHERE id IN (?, ?)').all(a4.id, a5.id) as { id: number }[]; + const all = await findRows(orm, DayAssignments, { id: { $in: [a4.id, a5.id] } }); expect(all).toHaveLength(0); }); @@ -478,11 +502,11 @@ describe('Update trip', () => { // a whole, even with nights still inside the trip, and its booking does not. const { user } = createUser(testDb); const trip = createTrip(testDb, user.id, { start_date: '2026-09-01', end_date: '2026-09-06' }); - const days = testDb.prepare('SELECT * FROM days WHERE trip_id = ? ORDER BY day_number').all(trip.id) as { id: number }[]; + const days = await readTripDays(orm, trip.id); const place = createPlace(testDb, trip.id, { name: 'Harbour Hotel' }); const stay = createDayAccommodation(testDb, trip.id, place.id, days[3].id, days[5].id); const booking = createReservation(testDb, trip.id, { title: 'Harbour Hotel booking', type: 'hotel', day_id: days[3].id }); - testDb.prepare('UPDATE reservations SET accommodation_id = ? WHERE id = ?').run(stay.id, booking.id); + await updateRows(orm, Reservations, { id: booking.id }, { accommodation_id: String(stay.id) }); const sightseeing = createDayAssignment(testDb, days[5].id, place.id); const res = await request(app) @@ -491,13 +515,13 @@ describe('Update trip', () => { .send({ start_date: '2026-09-01', end_date: '2026-09-05' }); expect(res.status).toBe(200); - const daysAfter = testDb.prepare('SELECT id, date FROM days WHERE trip_id = ? ORDER BY day_number').all(trip.id) as { id: number; date: string }[]; + const daysAfter = await readTripDays(orm, trip.id); expect(daysAfter.map(d => d.id)).toEqual(days.slice(0, 5).map(d => d.id)); expect(daysAfter.at(-1)!.date).toBe('2026-09-05'); - expect(testDb.prepare('SELECT 1 FROM day_accommodations WHERE id = ?').get(stay.id)).toBeUndefined(); - expect(testDb.prepare('SELECT 1 FROM day_assignments WHERE id = ?').get(sightseeing.id)).toBeUndefined(); - expect(testDb.prepare('SELECT title FROM reservations WHERE id = ?').get(booking.id)).toEqual({ title: 'Harbour Hotel booking' }); - expect(testDb.prepare('SELECT 1 FROM places WHERE id = ?').get(place.id)).toBeDefined(); + expect(await findRow(orm, DayAccommodations, { id: stay.id })).toBeNull(); + expect(await findRow(orm, DayAssignments, { id: sightseeing.id })).toBeNull(); + expect((await findRow(orm, Reservations, { id: booking.id }))?.title).toBe('Harbour Hotel booking'); + expect(await findRow(orm, Places, { id: place.id })).not.toBeNull(); }); }); @@ -540,8 +564,8 @@ describe('Delete trip', () => { expect(res.status).toBe(404); // Trip still exists - const tripInDb = testDb.prepare('SELECT id FROM trips WHERE id = ?').get(trip.id); - expect(tripInDb).toBeDefined(); + const tripInDb = await findRow(orm, Trips, { id: trip.id }); + expect(tripInDb).not.toBeNull(); }); it('TRIP-019 — Trip member cannot delete trip → 403', async () => { @@ -574,10 +598,10 @@ describe('Delete trip', () => { expect(deleteRes.body.success).toBe(true); // Verify cascade: places and reservations should be gone - const places = testDb.prepare('SELECT id FROM places WHERE trip_id = ?').all(trip.id); + const places = await findRows(orm, Places, { trip: trip.id }); expect(places).toHaveLength(0); - const reservations = testDb.prepare('SELECT id FROM reservations WHERE trip_id = ?').all(trip.id); + const reservations = await findRows(orm, Reservations, { trip: trip.id }); expect(reservations).toHaveLength(0); }); @@ -644,8 +668,8 @@ describe('Trip members', () => { expect(res.body.member.role).toBe('member'); // Verify in DB - const dbEntry = testDb.prepare('SELECT * FROM trip_members WHERE trip_id = ? AND user_id = ?').get(trip.id, invitee.id); - expect(dbEntry).toBeDefined(); + const dbEntry = await findRow(orm, TripMembers, { trip: trip.id, user: invitee.id }); + expect(dbEntry).not.toBeNull(); }); it('TRIP-013 — POST /api/trips/:id/members adds a member by username → 201', async () => { @@ -718,8 +742,8 @@ describe('Trip members', () => { expect(res.body.success).toBe(true); // Verify removal in DB - const dbEntry = testDb.prepare('SELECT * FROM trip_members WHERE trip_id = ? AND user_id = ?').get(trip.id, member.id); - expect(dbEntry).toBeUndefined(); + const dbEntry = await findRow(orm, TripMembers, { trip: trip.id, user: member.id }); + expect(dbEntry).toBeNull(); }); it('TRIP-014 — Member can remove themselves from a trip → 200', async () => { @@ -750,9 +774,9 @@ describe('Trip members', () => { expect(res.status).toBe(201); expect(res.body.success).toBe(true); - const row = testDb.prepare('SELECT user_id FROM trips WHERE id = ?').get(trip.id) as { user_id: number }; - expect(row.user_id).toBe(member.id); - const memberRows = (testDb.prepare('SELECT user_id FROM trip_members WHERE trip_id = ?').all(trip.id) as { user_id: number }[]).map(r => r.user_id); + const row = await findRow(orm, Trips, { id: trip.id }); + expect(row?.user_id).toBe(member.id); + const memberRows = (await findRows(orm, TripMembers, { trip: trip.id })).map(r => r.user_id); expect(memberRows).toContain(owner.id); expect(memberRows).not.toContain(member.id); }); @@ -808,7 +832,7 @@ describe('Trip members', () => { expect(dir.body.users.some((u: any) => u.id === guestId)).toBe(false); // The synthetic email can never authenticate (resolves as an unknown email). - const email = (testDb.prepare('SELECT email FROM users WHERE id = ?').get(guestId) as any).email; + const email = (await readUser(orm, guestId)).email; const login = await request(app).post('/api/auth/login').send({ email, password: 'anything' }); expect(login.status).toBe(401); }); @@ -861,13 +885,13 @@ describe('Trip members', () => { .send({ name: 'Junior' }); expect(renamed.status).toBe(200); // #1446: the human name lives in display_name now (username is a non-shown uuid handle) - expect((testDb.prepare('SELECT display_name FROM users WHERE id = ?').get(guestId) as any).display_name).toBe('Junior'); + expect((await readUser(orm, guestId)).display_name).toBe('Junior'); const removed = await request(app) .delete(`/api/trips/${trip.id}/guests/${guestId}`) .set('Cookie', authCookie(owner.id)); expect(removed.status).toBe(200); - expect(testDb.prepare('SELECT id FROM users WHERE id = ?').get(guestId)).toBeUndefined(); + expect(await findRow(orm, Users, { id: guestId })).toBeNull(); }); it('TRIP-GUEST-003 — a guest cannot be invited as a member to any trip (#1362)', async () => { @@ -878,7 +902,7 @@ describe('Trip members', () => { .post(`/api/trips/${trip.id}/guests`) .set('Cookie', authCookie(owner.id)) .send({ name: 'Eve' }); - const email = (testDb.prepare('SELECT email FROM users WHERE id = ?').get(created.body.member.id) as any).email; + const email = (await readUser(orm, created.body.member.id)).email; const invite = await request(app) .post(`/api/trips/${otherTrip.id}/members`) @@ -895,7 +919,7 @@ describe('Trip members', () => { addTripMember(testDb, trip.id, member.id); // Restrict member management to trip_owner (default) - testDb.prepare("INSERT OR REPLACE INTO app_settings (key, value) VALUES ('perm_member_manage', 'trip_owner')").run(); + await setAppSetting(orm, 'perm_member_manage', 'trip_owner'); await invalidatePermissionsCache(); const res = await request(app) @@ -965,8 +989,8 @@ describe('Copy trip', () => { .send({}); expect(res.status).toBe(201); - const newTrip = testDb.prepare('SELECT * FROM trips WHERE id = ?').get(res.body.trip.id) as any; - expect(newTrip.user_id).toBe(member.id); + const newTrip = await findRow(orm, Trips, { id: res.body.trip.id }); + expect(newTrip?.user_id).toBe(member.id); }); it('TRIP-024 — non-member cannot copy a trip → 404', async () => { @@ -1040,7 +1064,7 @@ describe('ICS export', () => { // could read the value straight out of GET /api/trips/:id. const { user } = createUser(testDb); const trip = createTrip(testDb, user.id, { title: 'Trip' }); - testDb.prepare('UPDATE trips SET feed_token = ? WHERE id = ?').run('secret-feed-token', trip.id); + await updateRows(orm, Trips, { id: trip.id }, { feed_token: 'secret-feed-token' }); const one = await request(app).get(`/api/trips/${trip.id}`).set('Cookie', authCookie(user.id)); expect(one.status).toBe(200); @@ -1065,18 +1089,16 @@ describe('Copy trip with data', () => { end_date: '2025-09-03', }); - const days = testDb.prepare('SELECT * FROM days WHERE trip_id = ? ORDER BY day_number').all(trip.id) as any[]; + const days = await readTripDays(orm, trip.id); expect(days.length).toBe(3); // Place with a tag const place = createPlace(testDb, trip.id, { name: 'Tower Bridge' }); const tag = createTag(testDb, user.id, { name: 'Landmark' }); - testDb.prepare('INSERT INTO place_tags (place_id, tag_id) VALUES (?, ?)').run(place.id, tag.id); + await tagPlace(orm, place.id, [tag.id]); // Day assignment - testDb.prepare( - 'INSERT INTO day_assignments (day_id, place_id, order_index, notes) VALUES (?, ?, 0, ?)' - ).run(days[0].id, place.id, 'Visit in morning'); + await insertRow(orm, DayAssignments, { day: days[0].id, place: place.id, order_index: 0, notes: 'Visit in morning' }); // Accommodation spanning days 0→1 createDayAccommodation(testDb, trip.id, place.id, days[0].id, days[1].id); @@ -1103,45 +1125,43 @@ describe('Copy trip with data', () => { expect(newId).not.toBe(trip.id); // Days copied - const newDays = testDb.prepare('SELECT * FROM days WHERE trip_id = ? ORDER BY day_number').all(newId) as any[]; + const newDays = await readTripDays(orm, newId); expect(newDays).toHaveLength(3); // Place copied - const newPlaces = testDb.prepare('SELECT * FROM places WHERE trip_id = ?').all(newId) as any[]; + const newPlaces = await findRows(orm, Places, { trip: newId }); expect(newPlaces).toHaveLength(1); expect(newPlaces[0].name).toBe('Tower Bridge'); // Place tag copied - const newTags = testDb.prepare( - 'SELECT pt.* FROM place_tags pt JOIN places p ON p.id = pt.place_id WHERE p.trip_id = ?' - ).all(newId) as any[]; - expect(newTags).toHaveLength(1); + // One place_tags row per (place, tag) pair on the copy's places. + let newTags = 0; + for (const p of newPlaces) newTags += await countRows(orm, Tags, { place_tags_inverse: p.id }); + expect(newTags).toBe(1); // Assignment copied - const newAssignments = testDb.prepare( - 'SELECT da.* FROM day_assignments da JOIN days d ON d.id = da.day_id WHERE d.trip_id = ?' - ).all(newId) as any[]; + const newAssignments = await findRows(orm, DayAssignments, { day: { trip: newId } }); expect(newAssignments).toHaveLength(1); // Accommodation copied - const newAccom = testDb.prepare('SELECT * FROM day_accommodations WHERE trip_id = ?').all(newId) as any[]; + const newAccom = await findRows(orm, DayAccommodations, { trip: newId }); expect(newAccom).toHaveLength(1); // Reservation copied - const newResv = testDb.prepare('SELECT * FROM reservations WHERE trip_id = ?').all(newId) as any[]; + const newResv = await findRows(orm, Reservations, { trip: newId }); expect(newResv).toHaveLength(1); // Budget copied - const newBudget = testDb.prepare('SELECT * FROM budget_items WHERE trip_id = ?').all(newId) as any[]; + const newBudget = await findRows(orm, BudgetItems, { trip: newId }); expect(newBudget).toHaveLength(1); // Packing copied (checked reset to 0) - const newPacking = testDb.prepare('SELECT * FROM packing_items WHERE trip_id = ?').all(newId) as any[]; + const newPacking = await findRows(orm, PackingItems, { trip: newId }); expect(newPacking).toHaveLength(1); expect(newPacking[0].checked).toBe(0); // Day note copied - const newNotes = testDb.prepare('SELECT * FROM day_notes WHERE trip_id = ?').all(newId) as any[]; + const newNotes = await findRows(orm, DayNotes, { trip: newId }); expect(newNotes).toHaveLength(1); expect(newNotes[0].text).toBe('Pack early!'); }); @@ -1151,17 +1171,18 @@ describe('Copy trip with data', () => { const trip = createTrip(testDb, user.id, { title: 'Todo Trip' }); // Two todos: one checked and assigned — both should arrive unchecked and unassigned - testDb.prepare( - 'INSERT INTO todo_items (trip_id, name, checked, category, sort_order, due_date, description, priority) VALUES (?, ?, ?, ?, ?, ?, ?, ?)' - ).run(trip.id, 'Buy tickets', 0, 'Transport', 0, '2026-06-01', 'Check Ryanair', 1); - testDb.prepare( - 'INSERT INTO todo_items (trip_id, name, checked, category, sort_order, assigned_user_id, priority) VALUES (?, ?, ?, ?, ?, ?, ?)' - ).run(trip.id, 'Book hotel', 1, 'Accommodation', 1, user.id, 0); + await insertRow(orm, TodoItems, { + trip: trip.id, name: 'Buy tickets', checked: 0, category: 'Transport', sort_order: 0, due_date: '2026-06-01', description: 'Check Ryanair', priority: 1, + }); + await insertRow(orm, TodoItems, { + trip: trip.id, name: 'Book hotel', checked: 1, category: 'Accommodation', sort_order: 1, assignedUser: user.id, priority: 0, + }); // Two budget category order rows - const insOrder = testDb.prepare('INSERT INTO budget_category_order (trip_id, category, sort_order) VALUES (?, ?, ?)'); - insOrder.run(trip.id, 'Transport', 0); - insOrder.run(trip.id, 'Accommodation', 1); + await insertRows(orm, BudgetCategoryOrder, [ + { trip: trip.id, category: 'Transport', sort_order: 0 }, + { trip: trip.id, category: 'Accommodation', sort_order: 1 }, + ]); const res = await request(app) .post(`/api/trips/${trip.id}/copy`) @@ -1172,7 +1193,7 @@ describe('Copy trip with data', () => { const newId = res.body.trip.id; // Todos copied with checked reset and assigned_user_id nulled - const newTodos = testDb.prepare('SELECT * FROM todo_items WHERE trip_id = ? ORDER BY sort_order').all(newId) as any[]; + const newTodos = await findRows(orm, TodoItems, { trip: newId }, { sort_order: 'asc' }); expect(newTodos).toHaveLength(2); expect(newTodos[0].name).toBe('Buy tickets'); expect(newTodos[0].category).toBe('Transport'); @@ -1186,7 +1207,7 @@ describe('Copy trip with data', () => { expect(newTodos[1].assigned_user_id).toBeNull(); // Budget category order copied - const newOrder = testDb.prepare('SELECT category, sort_order FROM budget_category_order WHERE trip_id = ? ORDER BY sort_order').all(newId) as any[]; + const newOrder = await findRows(orm, BudgetCategoryOrder, { trip: newId }, { sort_order: 'asc' }); expect(newOrder).toHaveLength(2); expect(newOrder[0]).toMatchObject({ category: 'Transport', sort_order: 0 }); expect(newOrder[1]).toMatchObject({ category: 'Accommodation', sort_order: 1 }); @@ -1245,7 +1266,7 @@ describe('Trip bundle', () => { const { user: owner } = createUser(testDb); const { user: member } = createUser(testDb); const trip = createTrip(testDb, owner.id); - testDb.prepare('INSERT INTO trip_members (trip_id, user_id) VALUES (?, ?)').run(trip.id, member.id); + await insertRow(orm, TripMembers, { trip: trip.id, user: member.id }); const res = await request(app) .get(`/api/trips/${trip.id}/bundle`) @@ -1268,9 +1289,9 @@ describe('Trip bundle', () => { const { user: owner } = createUser(testDb); const { user: member } = createUser(testDb); const trip = createTrip(testDb, owner.id); - testDb.prepare('INSERT INTO trip_members (trip_id, user_id) VALUES (?, ?)').run(trip.id, member.id); - testDb.prepare('INSERT INTO packing_items (trip_id, name, checked, sort_order) VALUES (?, ?, 0, 0)').run(trip.id, 'Tent'); - testDb.prepare('INSERT INTO packing_items (trip_id, name, checked, sort_order, is_private, owner_id) VALUES (?, ?, 0, 1, 1, ?)').run(trip.id, 'Secret gift', owner.id); + await insertRow(orm, TripMembers, { trip: trip.id, user: member.id }); + await insertRow(orm, PackingItems, { trip: trip.id, name: 'Tent', checked: 0, sort_order: 0 }); + await insertRow(orm, PackingItems, { trip: trip.id, name: 'Secret gift', checked: 0, sort_order: 1, is_private: 1, owner: owner.id }); const ownerView = await request(app).get(`/api/trips/${trip.id}/bundle`).set('Cookie', authCookie(owner.id)); expect(ownerView.body.packingItems.map((i: { name: string }) => i.name).sort()).toEqual(['Secret gift', 'Tent']);