From d8fef5879999292e04ff8ec3279f0b070edc7d8f Mon Sep 17 00:00:00 2001 From: Maurice Date: Mon, 12 Oct 2026 19:56:44 +0000 Subject: [PATCH] test(server): the new suites check a missing result instead of asserting it away --- server/tests/unit/nest/auth.service.test.ts | 6 ++-- .../tests/unit/nest/budget.service.db.test.ts | 34 +++++++++---------- server/tests/unit/nest/oauth.service.test.ts | 7 ++-- .../unit/nest/reservations.service.test.ts | 3 +- server/tests/unit/nest/trips.service.test.ts | 6 +++- server/tests/unit/nest/vacay.service.test.ts | 2 +- 6 files changed, 33 insertions(+), 25 deletions(-) diff --git a/server/tests/unit/nest/auth.service.test.ts b/server/tests/unit/nest/auth.service.test.ts index d066d8a39..0a3fd7c04 100644 --- a/server/tests/unit/nest/auth.service.test.ts +++ b/server/tests/unit/nest/auth.service.test.ts @@ -924,8 +924,10 @@ describe('registerUser — success paths', () => { it('AUTH-DB-056b: a signup marks the address it typed in, except for the first account', async () => { const first = await svc.registerUser({ username: 'owner', email: 'owner@x.com', password: 'Secure123!' }); const second = await svc.registerUser({ username: 'joiner', email: 'joiner@x.com', password: 'Secure123!' }); - expect((await readUser(orm, first.auditUserId!)).email_self_asserted).toBe(0); - expect((await readUser(orm, second.auditUserId!)).email_self_asserted).toBe(1); + expect(first.auditUserId).toEqual(expect.any(Number)); + expect(second.auditUserId).toEqual(expect.any(Number)); + expect((await readUser(orm, Number(first.auditUserId))).email_self_asserted).toBe(0); + expect((await readUser(orm, Number(second.auditUserId))).email_self_asserted).toBe(1); }); it('AUTH-DB-057: missing fields / bad email / duplicate answer their bespoke 400/409s', async () => { diff --git a/server/tests/unit/nest/budget.service.db.test.ts b/server/tests/unit/nest/budget.service.db.test.ts index 327a8e940..e2899fe04 100644 --- a/server/tests/unit/nest/budget.service.db.test.ts +++ b/server/tests/unit/nest/budget.service.db.test.ts @@ -2148,10 +2148,10 @@ describe('someone who left the trip keeps their part of an expense (#2604)', () member_ids: [alice.id, bob.id, carol.id], }); - expect(saved!.total_price).toBe(180); - expect(saved!.payers.map(p => p.user_id).sort()).toEqual([alice.id, bob.id].sort()); - expect(saved!.members.map(m => m.user_id).sort()).toEqual([alice.id, bob.id, carol.id].sort()); - expect(saved!.persons).toBe(3); + expect(saved?.total_price).toBe(180); + expect(saved?.payers.map(p => p.user_id).sort()).toEqual([alice.id, bob.id].sort()); + expect(saved?.members.map(m => m.user_id).sort()).toEqual([alice.id, bob.id, carol.id].sort()); + expect(saved?.persons).toBe(3); const settlement = await budget.calculateSettlement(trip.id); expect(balanceSum(settlement.balances)).toBe(0); }); @@ -2170,8 +2170,8 @@ describe('someone who left the trip keeps their part of an expense (#2604)', () members: [{ user_id: alice.id, amount: 30 }, { user_id: bob.id, amount: 30 }, { user_id: carol.id, amount: 30 }], }); - expect(saved!.total_price).toBe(90); - expect(saved!.members.reduce((a, m) => a + (m.amount ?? 0), 0)).toBe(90); + expect(saved?.total_price).toBe(90); + expect(saved?.members.reduce((a, m) => a + (m.amount ?? 0), 0)).toBe(90); const settlement = await budget.calculateSettlement(trip.id); expect(balanceSum(settlement.balances)).toBe(0); expect(settlement.balances.find(b => b.user_id === bob.id)?.balance).toBe(60); @@ -2189,11 +2189,11 @@ describe('someone who left the trip keeps their part of an expense (#2604)', () member_ids: [alice.id, bob.id, outsider.id], }); - expect(saved!.payers.map(p => p.user_id)).toEqual([alice.id]); - expect(saved!.members.map(m => m.user_id)).not.toContain(outsider.id); - expect(saved!.total_price).toBe(40); + expect(saved?.payers.map(p => p.user_id)).toEqual([alice.id]); + expect(saved?.members.map(m => m.user_id)).not.toContain(outsider.id); + expect(saved?.total_price).toBe(40); const viaMembers = await budget.updateMembers(item.id, trip.id, [alice.id, outsider.id]); - expect(viaMembers!.members.map(m => m.user_id)).toEqual([alice.id]); + expect(viaMembers?.members.map(m => m.user_id)).toEqual([alice.id]); }); it('BUDGET-SVC-DB-090: leaving a former member out of the save removes them', async () => { @@ -2207,10 +2207,10 @@ describe('someone who left the trip keeps their part of an expense (#2604)', () payers: [{ user_id: alice.id, amount: 30 }], member_ids: [alice.id, carol.id], }); - expect(saved!.members.map(m => m.user_id).sort()).toEqual([alice.id, carol.id].sort()); + expect(saved?.members.map(m => m.user_id).sort()).toEqual([alice.id, carol.id].sort()); // Once gone from the expense, they cannot be put back while off the trip. const again = await budget.updateBudgetItem(item.id, trip.id, { member_ids: [alice.id, bob.id, carol.id] }); - expect(again!.members.map(m => m.user_id)).not.toContain(bob.id); + expect(again?.members.map(m => m.user_id)).not.toContain(bob.id); }); it('BUDGET-SVC-DB-091: a former member who was only in the split can be recorded as the payer', async () => { @@ -2224,8 +2224,8 @@ describe('someone who left the trip keeps their part of an expense (#2604)', () payers: [{ user_id: bob.id, amount: 50 }], member_ids: [alice.id, bob.id], }); - expect(saved!.payers.map(p => p.user_id)).toEqual([bob.id]); - expect(saved!.total_price).toBe(50); + expect(saved?.payers.map(p => p.user_id)).toEqual([bob.id]); + expect(saved?.total_price).toBe(50); }); it('BUDGET-SVC-DB-092: the paid ticks survive a form save', async () => { @@ -2254,11 +2254,11 @@ describe('someone who left the trip keeps their part of an expense (#2604)', () await membersSvc.removeMember(trip.id, bob.id); const payers = await budget.setItemPayers(item.id, trip.id, [{ user_id: alice.id, amount: 20 }, { user_id: bob.id, amount: 20 }]); - expect(payers!.total_price).toBe(40); - expect(payers!.payers.map(p => p.user_id).sort()).toEqual([alice.id, bob.id].sort()); + expect(payers?.total_price).toBe(40); + expect(payers?.payers.map(p => p.user_id).sort()).toEqual([alice.id, bob.id].sort()); const members = await budget.updateMembers(item.id, trip.id, [alice.id, bob.id]); - expect(members!.members.map(m => m.user_id).sort()).toEqual([alice.id, bob.id].sort()); + expect(members?.members.map(m => m.user_id).sort()).toEqual([alice.id, bob.id].sort()); }); it('BUDGET-SVC-DB-094: a new expense still takes only people on the trip', async () => { diff --git a/server/tests/unit/nest/oauth.service.test.ts b/server/tests/unit/nest/oauth.service.test.ts index 5f48d0e14..b315db90d 100644 --- a/server/tests/unit/nest/oauth.service.test.ts +++ b/server/tests/unit/nest/oauth.service.test.ts @@ -958,14 +958,15 @@ describe('getUserByAccessToken — includes clientId (C2)', () => { it('reports the email as verified unless the account typed it in itself', async () => { const { user } = createUser(testDb); const created = await makeClient(user.id); - const clientId = created.client!.client_id as string; + const clientId = created.client?.client_id; + if (typeof clientId !== 'string') throw new Error('the client was not created'); const first = await issueTokens(clientId, user.id, ['trips:read']); - expect((await getUserByAccessToken(first.access_token))!.emailVerified).toBe(true); + expect((await getUserByAccessToken(first.access_token))?.emailVerified).toBe(true); await updateRows(t, Users, { id: user.id }, { email_self_asserted: 1 }); const second = await issueTokens(clientId, user.id, ['trips:read']); - expect((await getUserByAccessToken(second.access_token))!.emailVerified).toBe(false); + expect((await getUserByAccessToken(second.access_token))?.emailVerified).toBe(false); }); }); diff --git a/server/tests/unit/nest/reservations.service.test.ts b/server/tests/unit/nest/reservations.service.test.ts index f0117013d..359502f63 100644 --- a/server/tests/unit/nest/reservations.service.test.ts +++ b/server/tests/unit/nest/reservations.service.test.ts @@ -848,7 +848,8 @@ describe('ReservationsService (DI-native, real SQL)', () => { const { trip } = ownerTrip(); budget.linkBudgetItemToReservation.mockReturnValue({ id: 8 }); const created = await svc.create(String(trip.id), { title: 'Ferry', type: 'ferry', reservation_time: '2026-11-13T08:30' } as never); - const current = (await svc.getReservation(String(created.reservation.id), String(trip.id)))!; + const current = await svc.getReservation(String(created.reservation.id), String(trip.id)); + if (!current) throw new Error('the booking was not created'); await svc.updateWithCost(String(created.reservation.id), String(trip.id), { title: 'Ferry' } as never, current, { total_price: 30000 }); diff --git a/server/tests/unit/nest/trips.service.test.ts b/server/tests/unit/nest/trips.service.test.ts index 6cc6bb59b..aecb6d3b9 100644 --- a/server/tests/unit/nest/trips.service.test.ts +++ b/server/tests/unit/nest/trips.service.test.ts @@ -1471,7 +1471,11 @@ describe('folded trip CRUD', () => { const copied = await storedRows(BudgetItems, { trip: newTripId }, { name: 'asc' }, ['id', 'name', 'total_price', 'persons', 'paid_by_user_id', 'ticket_json']) as { id: number; name: string; total_price: number; persons: number | null; paid_by_user_id: number | null; ticket_json: string | null; }[]; - const byName = (name: string) => copied.find(c => c.name === name)!; + const byName = (name: string) => { + const row = copied.find(c => c.name === name); + if (!row) throw new Error(`no copied expense named ${name}`); + return row; + }; expect(copied.map(c => [c.name, c.total_price])).toEqual([['Rental car', 180], ['Seafood dinner', 90], ['Solo lunch', 50]]); // The copier's own expense is copied whole. diff --git a/server/tests/unit/nest/vacay.service.test.ts b/server/tests/unit/nest/vacay.service.test.ts index 26aa941ae..80a4541d6 100644 --- a/server/tests/unit/nest/vacay.service.test.ts +++ b/server/tests/unit/nest/vacay.service.test.ts @@ -34,7 +34,7 @@ import { createTestVacayHolidayCalendarsRepo, createTestSchoolHolidayRegionsRepo import type { EntityClass, EntityDTO, FilterQuery, FindOptions } from '@mikro-orm/core'; import { sharedTestOrm } from '../../helpers/test-uow'; import { - countRows, deleteRows, findRow, findRows, insertRow, insertRowIgnoringConflict, updateRows, upsertRow, + countRows, findRow, findRows, insertRow, insertRowIgnoringConflict, updateRows, upsertRow, } from '../../helpers/factories/rows'; import { SchoolHolidayCountries } from '../../../src/db/entities/SchoolHolidayCountries.entity'; import { SchoolHolidayRegions } from '../../../src/db/entities/SchoolHolidayRegions.entity';