refactor(reservations): reservations, endpoints and travelers through repositories

This commit is contained in:
jubnl
2026-09-23 14:58:36 +02:00
parent 3a26d03b00
commit 7ee0403eaf
23 changed files with 1709 additions and 326 deletions
@@ -1,5 +1,6 @@
import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest';
import { Platform } from '@mikro-orm/core';
import { expressionBuilder } from 'kysely';
import { createSnapshotTestDb } from '../../../helpers/db-mock';
import { resetTestDb } from '../../../helpers/test-db';
import { createTestOrm, type TestOrm } from '../../../helpers/test-orm';
@@ -9,11 +10,13 @@ import {
absDifference,
caseWhenEquals,
castInteger,
castIntegerKysely,
coalesce,
coalesceParam,
columnIncrementedBy,
columnRef,
concat,
concatKysely,
countAll,
countAllRef,
currentTimestamp,
@@ -27,10 +30,22 @@ import {
minOf,
nowMinusDays,
startsWithIsoDate,
startsWithIsoDateKysely,
substring,
substringKysely,
trim,
} from '../../../../src/db/dialect/sql-functions';
/** The `users` columns the Kysely-expression tests below read/write, narrowed the same way every other Kysely-typed repository method in this program declares its own `TDB`. */
interface UsersKyselyDB {
users: {
id: number;
username: string;
display_name: string | null;
created_at: string | null;
};
}
const testDb = createSnapshotTestDb();
let t: TestOrm;
@@ -507,6 +522,8 @@ describe('sql-functions (sqlite)', () => {
['2026-09-21 13:05:09', true],
['not-a-date', false],
['2026-1-1', false], // not zero-padded — the legacy pattern is exactly 4-2-2 digit classes, not a wildcard shorthand
['abcd-ef-gh', false], // Task 0 review L1 — the wider '????-??-??*' shorthand WOULD match this (a `?` matches any char); the digit-class pattern must not
['yyyy-mm-dd', false], // Task 0 review L1 — same reason, letters where the pattern requires digits
['', false],
[null, false],
];
@@ -686,4 +703,182 @@ describe('sql-functions (sqlite)', () => {
const foreign = new FakePlatform();
expect(() => dayDistance(foreign, 'u.date', '2026-01-01')).toThrow(/no implementation for platform FakePlatform/);
});
// Plan 3d Task 0 review (H1/L1): the five helpers above return a MikroORM
// RawQueryFragment, which stringifies to a literal `?` token and throws at
// execution when handed into a Kysely statement — verified directly below
// (the whole reason these Kysely-native twins exist). Task 2 absorbed this
// finding; DY23 (`ReservationsRepository.restampLinkedReservation`) is the
// first consumer.
it('SQLF-048: a MikroORM RawQueryFragment cannot be coerced to a plain string outside the MikroORM QueryBuilder that produced it — the H1 finding, proven directly ([Symbol.toPrimitive]("string") returns an internal Symbol key the QueryBuilder recognises to re-substitute the real SQL text; nothing else, Kysely included, understands that key, which is why the Kysely-native twins below exist instead of reusing this fragment)', () => {
const platform = t.em.getPlatform();
const fragment = startsWithIsoDate(platform, 'username');
expect(typeof fragment[Symbol.toPrimitive]('string')).toBe('symbol');
expect(() => `${fragment}`).toThrow(TypeError);
});
it('SQLF-049: startsWithIsoDateKysely matches the same shapes as startsWithIsoDate (dates, non-dates, letters-in-place-of-digits, empty, NULL)', async () => {
const platform = t.em.getPlatform();
const cases: Array<[string | null, boolean]> = [
['2026-09-21', true],
['2026-09-21T13:05:09Z', true],
['not-a-date', false],
['2026-1-1', false],
['abcd-ef-gh', false],
['yyyy-mm-dd', false],
['', false],
[null, false],
];
for (const [value, expected] of cases) {
const { user } = createUser(testDb);
testDb.prepare('UPDATE users SET display_name = ? WHERE id = ?').run(value, user.id);
const row = await t.em.getKysely<UsersKyselyDB>()
.selectFrom('users')
.select((eb) => [startsWithIsoDateKysely(platform, eb, 'display_name').as('matched')])
.where('id', '=', user.id)
.executeTakeFirstOrThrow();
expect(Boolean(row.matched)).toBe(expected);
const raw = testDb
.prepare(`SELECT (display_name GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*') as matched FROM users WHERE id = ?`)
.get(user.id) as { matched: number | null };
expect(Boolean(raw.matched)).toBe(expected);
}
});
it('SQLF-050: an unknown platform fails closed for startsWithIsoDateKysely', () => {
class FakePlatform extends Platform {}
const foreign = new FakePlatform();
const eb = expressionBuilder<UsersKyselyDB, 'users'>();
expect(() => startsWithIsoDateKysely(foreign, eb, 'username')).toThrow(/no implementation for platform FakePlatform/);
});
it('SQLF-051: substringKysely(ref, start) — the two-arg form — matches substr(col, N)', async () => {
const { user } = createUser(testDb, { username: 'kysely-iso-ts' });
testDb.prepare('UPDATE users SET display_name = ? WHERE id = ?').run('2026-09-21T13:05:09Z', user.id);
const platform = t.em.getPlatform();
const row = await t.em.getKysely<UsersKyselyDB>()
.selectFrom('users')
.select((eb) => [substringKysely(platform, eb, 'display_name', 12).as('n')])
.where('id', '=', user.id)
.executeTakeFirstOrThrow();
expect(row.n).toBe('13:05:09Z');
const expected = testDb.prepare('SELECT substr(display_name, 12) as n FROM users WHERE id = ?').get(user.id) as { n: string };
expect(row.n).toBe(expected.n);
});
it('SQLF-052: substringKysely(ref, start, length) — the three-arg form — matches substr(col, N, L)', async () => {
const { user } = createUser(testDb, { username: 'kysely-iso-ts-2' });
testDb.prepare('UPDATE users SET display_name = ? WHERE id = ?').run('2026-09-21T13:05:09Z', user.id);
const platform = t.em.getPlatform();
const row = await t.em.getKysely<UsersKyselyDB>()
.selectFrom('users')
.select((eb) => [substringKysely(platform, eb, 'display_name', 1, 10).as('n')])
.where('id', '=', user.id)
.executeTakeFirstOrThrow();
expect(row.n).toBe('2026-09-21');
const expected = testDb.prepare('SELECT substr(display_name, 1, 10) as n FROM users WHERE id = ?').get(user.id) as { n: string };
expect(row.n).toBe(expected.n);
});
it('SQLF-053: substringKysely rejects a non-positive start or a negative length', () => {
const platform = t.em.getPlatform();
const eb = expressionBuilder<UsersKyselyDB, 'users'>();
expect(() => substringKysely(platform, eb, 'username', 0)).toThrow(/1-based integer start/);
expect(() => substringKysely(platform, eb, 'username', 1.5)).toThrow(/1-based integer start/);
expect(() => substringKysely(platform, eb, 'username', 1, -1)).toThrow(/non-negative integer length/);
expect(() => substringKysely(platform, eb, 'username', 1, 1.5)).toThrow(/non-negative integer length/);
});
it('SQLF-054: concatKysely renders <col> || <bound-literal> || substringKysely(...), composing a nested Kysely expression (the shape concat() cannot do)', async () => {
const { user } = createUser(testDb, { username: 'concat-me' });
testDb.prepare('UPDATE users SET display_name = ? WHERE id = ?').run('2026-09-21T13:05', user.id);
const platform = t.em.getPlatform();
const row = await t.em.getKysely<UsersKyselyDB>()
.selectFrom('users')
.select((eb) => [
concatKysely(platform, eb, { column: 'username' }, { value: '@' }, { expression: substringKysely(platform, eb, 'display_name', 12) }).as('n'),
])
.where('id', '=', user.id)
.executeTakeFirstOrThrow();
expect(row.n).toBe('concat-me@13:05');
const expected = testDb
.prepare("SELECT username || ? || substr(display_name, 12) as n FROM users WHERE id = ?")
.get('@', user.id) as { n: string };
expect(row.n).toBe(expected.n);
});
it('SQLF-055: concatKysely rejects fewer than two parts', () => {
const platform = t.em.getPlatform();
const eb = expressionBuilder<UsersKyselyDB, 'users'>();
expect(() => concatKysely(platform, eb, { column: 'username' })).toThrow(/at least two parts/);
expect(() => concatKysely(platform, eb)).toThrow(/at least two parts/);
});
it('SQLF-056: an unknown platform fails closed for concatKysely and substringKysely', () => {
class FakePlatform extends Platform {}
const foreign = new FakePlatform();
const eb = expressionBuilder<UsersKyselyDB, 'users'>();
expect(() => concatKysely(foreign, eb, { column: 'username' }, { value: 'x' })).toThrow(/no implementation for platform FakePlatform/);
expect(() => substringKysely(foreign, eb, 'username', 1)).toThrow(/no implementation for platform FakePlatform/);
});
it('SQLF-057: castIntegerKysely matches both "14" and "14.0" TEXT rows against a bound INTEGER value (the accommodation_id shape, §18.1)', async () => {
const platform = t.em.getPlatform();
const { user: exact } = createUser(testDb);
testDb.prepare('UPDATE users SET display_name = ? WHERE id = ?').run('14', exact.id);
const { user: dotZero } = createUser(testDb);
testDb.prepare('UPDATE users SET display_name = ? WHERE id = ?').run('14.0', dotZero.id);
const { user: other } = createUser(testDb);
testDb.prepare('UPDATE users SET display_name = ? WHERE id = ?').run('15', other.id);
const rows = await t.em.getKysely<UsersKyselyDB>()
.selectFrom('users')
.select('id')
.where('id', 'in', [exact.id, dotZero.id, other.id])
.where((eb) => eb(castIntegerKysely(platform, eb, 'display_name'), '=', 14))
.orderBy('id', 'asc')
.execute();
expect(rows.map((r) => r.id)).toEqual([exact.id, dotZero.id]);
const expected = testDb
.prepare('SELECT id FROM users WHERE id IN (?, ?, ?) AND CAST(display_name AS INTEGER) = ? ORDER BY id ASC')
.all(exact.id, dotZero.id, other.id, 14);
expect(rows).toEqual(expected);
});
it('SQLF-058: an unknown platform fails closed for castIntegerKysely', () => {
class FakePlatform extends Platform {}
const foreign = new FakePlatform();
const eb = expressionBuilder<UsersKyselyDB, 'users'>();
expect(() => castIntegerKysely(foreign, eb, 'display_name')).toThrow(/no implementation for platform FakePlatform/);
});
it('SQLF-059: DY23\'s exact shape compiles to the expected SQL text (compiled {sql, parameters} capture)', () => {
const platform = t.em.getPlatform();
const compiled = t.em.getKysely<UsersKyselyDB>()
.updateTable('users')
.set((eb) => ({
username: eb
.case()
.when('username', 'is', null)
.then(eb.val('2026-09-21'))
.else(concatKysely(platform, eb, { value: '2026-09-21' }, { expression: substringKysely(platform, eb, 'created_at', 11) }))
.end(),
}))
.where('id', '=', 1)
.compile();
expect(compiled.sql).toBe(
'update "users" set "username" = case when "username" is null then ? else ? || substr("created_at", ?) end where "id" = ?',
);
expect(compiled.parameters).toEqual(['2026-09-21', '2026-09-21', 11, 1]);
});
});
@@ -57,7 +57,7 @@ import { CalendarModule } from '../../../src/nest/calendar/calendar.module';
import { expectRegisteredProvider } from '../../helpers/module-providers';
import { notificationsStub } from '../../helpers/notifications';
import { accommodationsOver } from '../../helpers/accommodations-service';
import { createTestUnitOfWork, createTestAppSettingsRepo } from '../../helpers/test-uow';
import { createTestUnitOfWork, createTestAppSettingsRepo, createTestReservationsRepo, createTestReservationEndpointsRepo, createTestReservationTravelersRepo, createTestReservationDayPositionsRepo, createTestDayAccommodationsRepo, createTestDaysRepo, createTestPlacesRepo, createTestDayAssignmentsRepo, createTestTripMembersRepo, createTestUsersRepo, createTestTripsRepo } from '../../helpers/test-uow';
const dbs = () => new DatabaseService(testDb);
@@ -69,7 +69,7 @@ beforeAll(async () => {
budgetSvc = new BudgetService(dbs(), new PermissionsService(await createTestAppSettingsRepo(dbs().connection), await createTestUnitOfWork(dbs().connection)), new ExchangeRatesService(), new RealtimeService(), await createTestUnitOfWork(dbs().connection));
svc = new CalendarService(
dbs(),
new ReservationsService(dbs(), new PermissionsService(await createTestAppSettingsRepo(dbs().connection), await createTestUnitOfWork(dbs().connection)), budgetSvc, new RealtimeService(), notificationsStub(), new ReservationsReadService(dbs()), await accommodationsOver(dbs()), await createTestUnitOfWork(dbs().connection)),
new ReservationsService(dbs(), new PermissionsService(await createTestAppSettingsRepo(dbs().connection), await createTestUnitOfWork(dbs().connection)), budgetSvc, new RealtimeService(), notificationsStub(), new ReservationsReadService(await createTestReservationsRepo(dbs().connection), await createTestReservationEndpointsRepo(dbs().connection), await createTestReservationTravelersRepo(dbs().connection)), await accommodationsOver(dbs()), await createTestUnitOfWork(dbs().connection), await createTestReservationsRepo(dbs().connection), await createTestReservationEndpointsRepo(dbs().connection), await createTestReservationTravelersRepo(dbs().connection), await createTestReservationDayPositionsRepo(dbs().connection), await createTestDayAccommodationsRepo(dbs().connection), await createTestDaysRepo(dbs().connection), await createTestPlacesRepo(dbs().connection), await createTestDayAssignmentsRepo(dbs().connection), await createTestTripMembersRepo(dbs().connection), await createTestUsersRepo(dbs().connection), await createTestTripsRepo(dbs().connection)),
);
});
@@ -68,6 +68,8 @@ import {
createTestUnitOfWork, createTestAppSettingsRepo, createTestDatabaseService,
createTestDaysRepo, createTestDayAssignmentsRepo, createTestDayNotesRepo, createTestTripsRepo,
createTestTagsRepo, createTestPlaceRatingsRepo, createTestAssignmentParticipantsRepo,
createTestReservationsRepo,
createTestReservationEndpointsRepo,
} from '../../helpers/test-uow';
let svc: DaysService;
@@ -83,6 +85,8 @@ beforeAll(async () => {
await createTestDayAssignmentsRepo(testDb),
await createTestDayNotesRepo(testDb),
await createTestTripsRepo(testDb),
await createTestReservationsRepo(testDb),
await createTestReservationEndpointsRepo(testDb),
);
});
let accommodations: Awaited<ReturnType<typeof makeAccommodationsService>>;
@@ -839,6 +843,8 @@ describe('DaysService.canEdit', () => {
await createTestDayAssignmentsRepo(testDb),
await createTestDayNotesRepo(testDb),
await createTestTripsRepo(testDb),
await createTestReservationsRepo(testDb),
await createTestReservationEndpointsRepo(testDb),
);
const trip = { id: 1, user_id: 1 } as never;
@@ -75,12 +75,12 @@ const bridge = {
import { RealtimeService } from '../../../src/nest/realtime/realtime.service';
import { notificationsStub } from '../../helpers/notifications';
import { makeAccommodationsService } from '../../helpers/accommodations-service';
import { createTestUnitOfWork, createTestDatabaseService } from '../../helpers/test-uow';
import { createTestUnitOfWork, createTestDatabaseService, createTestReservationsRepo, createTestReservationEndpointsRepo, createTestReservationTravelersRepo, createTestReservationDayPositionsRepo, createTestDayAccommodationsRepo, createTestDaysRepo, createTestPlacesRepo, createTestDayAssignmentsRepo, createTestTripMembersRepo, createTestUsersRepo, createTestTripsRepo } from '../../helpers/test-uow';
let svc: ReservationsService;
beforeAll(async () => {
const dbs = await createTestDatabaseService(testDb);
svc = new ReservationsService(dbs, permissionsStub, budget as unknown as BudgetService, new RealtimeService(), notificationsStub(notif.send), new ReservationsReadService(dbs), await makeAccommodationsService(testDb), await createTestUnitOfWork(testDb));
svc = new ReservationsService(dbs, permissionsStub, budget as unknown as BudgetService, new RealtimeService(), notificationsStub(notif.send), new ReservationsReadService(await createTestReservationsRepo(testDb), await createTestReservationEndpointsRepo(testDb), await createTestReservationTravelersRepo(testDb)), await makeAccommodationsService(testDb), await createTestUnitOfWork(testDb), await createTestReservationsRepo(testDb), await createTestReservationEndpointsRepo(testDb), await createTestReservationTravelersRepo(testDb), await createTestReservationDayPositionsRepo(testDb), await createTestDayAccommodationsRepo(testDb), await createTestDaysRepo(testDb), await createTestPlacesRepo(testDb), await createTestDayAssignmentsRepo(testDb), await createTestTripMembersRepo(testDb), await createTestUsersRepo(testDb), await createTestTripsRepo(testDb));
});
beforeAll(() => { createTables(testDb); runMigrations(testDb); });
@@ -959,8 +959,15 @@ describe('ReservationsService — quirk fixes (post-fold)', () => {
const { trip } = ownerTrip({ start_date: '2030-05-01', end_date: '2030-05-02' });
const place = createPlace(testDb, trip.id);
const days = testDb.prepare('SELECT id FROM days WHERE trip_id = ? ORDER BY day_number').all(trip.id) as { id: number }[];
// sequence is an unbindable object -> the endpoint INSERT throws mid-write.
const badEndpoints = [{ role: 'from', name: 'A', code: null, lat: 1, lng: 2, timezone: null, local_time: null, local_date: null, sequence: {} }];
// Plan 3d Task 2 (§15a): `sequence: {}` (an unbindable object) no longer
// throws once RS17 goes through `em.insert()` — MikroORM serialises it
// instead of handing it to a raw bind. A repository-level spy
// reproduces the same "the write mid-transaction fails" shape the fault
// injection existed to prove, still inside the SAME `uow.transactional`
// this test's rollback assertion depends on.
const endpointsRepo = await createTestReservationEndpointsRepo(testDb);
const spy = vi.spyOn(endpointsRepo, 'insertEndpoint').mockRejectedValueOnce(new Error('boom'));
const badEndpoints = [{ role: 'from', name: 'A', code: null, lat: 1, lng: 2, timezone: null, local_time: null, local_date: null }];
await expect(svc.create(String(trip.id), {
title: 'Hotel', type: 'hotel',
create_accommodation: { place_id: place.id, start_day_id: days[0].id, end_day_id: days[1].id },
@@ -968,15 +975,19 @@ describe('ReservationsService — quirk fixes (post-fold)', () => {
} as never)).rejects.toThrow();
expect(testDb.prepare('SELECT COUNT(*) as c FROM reservations WHERE trip_id = ?').get(trip.id)).toEqual({ c: 0 });
expect(testDb.prepare('SELECT COUNT(*) as c FROM day_accommodations WHERE trip_id = ?').get(trip.id)).toEqual({ c: 0 });
spy.mockRestore();
});
it('RESV-FIX-002: update is atomic — a failing endpoint save rolls back the field update', async () => {
const { trip } = ownerTrip();
const res = createReservation(testDb, trip.id, { title: 'Old' });
const current = (await svc.getReservation(String(res.id), String(trip.id)))!;
const badEndpoints = [{ role: 'from', name: 'A', code: null, lat: 1, lng: 2, timezone: null, local_time: null, local_date: null, sequence: {} }];
const endpointsRepo = await createTestReservationEndpointsRepo(testDb);
const spy = vi.spyOn(endpointsRepo, 'insertEndpoint').mockRejectedValueOnce(new Error('boom'));
const badEndpoints = [{ role: 'from', name: 'A', code: null, lat: 1, lng: 2, timezone: null, local_time: null, local_date: null }];
await expect(svc.update(String(res.id), String(trip.id), { title: 'New', endpoints: badEndpoints } as never, current)).rejects.toThrow();
expect(testDb.prepare('SELECT title FROM reservations WHERE id = ?').get(res.id)).toEqual({ title: 'Old' });
spy.mockRestore();
});
});
@@ -84,6 +84,11 @@ import {
createTestDaysRepo, createTestDayAssignmentsRepo, createTestDayNotesRepo, createTestTripsRepo,
createTestTripMembersRepo, createTestTagsRepo, createTestPlaceRatingsRepo, createTestAssignmentParticipantsRepo,
createTestGooglePlacePhotoMetaRepo, createTestPlacesRepo, createTestCategoriesRepo,
createTestReservationsRepo,
createTestReservationEndpointsRepo,
createTestReservationTravelersRepo,
createTestReservationDayPositionsRepo,
createTestDayAccommodationsRepo,
} from '../../helpers/test-uow';
// Real sibling services over the same in-memory DB — the aggregation runs the
@@ -123,6 +128,8 @@ beforeAll(async () => {
await createTestDayAssignmentsRepo(dbs().connection),
await createTestDayNotesRepo(dbs().connection),
await createTestTripsRepo(dbs().connection),
await createTestReservationsRepo(dbs().connection),
await createTestReservationEndpointsRepo(dbs().connection),
);
placesSvc = new PlacesService(
dbs(), new PermissionsService(await createTestAppSettingsRepo(dbs().connection), await createTestUnitOfWork(dbs().connection)), new RealtimeService(),
@@ -146,7 +153,7 @@ const buildReadModel = async (tripsRepo: TripsRepository, roster: TripMembersSer
new TripReadModelService(
tripsRepo, roster, daysSvc, accommodationsSvc, budgetSvc,
new PackingService(dbs(), new PermissionsService(await createTestAppSettingsRepo(dbs().connection), await createTestUnitOfWork(dbs().connection)), new RealtimeService(), notificationsStub(), await createTestUnitOfWork(dbs().connection)),
new ReservationsService(dbs(), new PermissionsService(await createTestAppSettingsRepo(dbs().connection), await createTestUnitOfWork(dbs().connection)), budgetSvc, new RealtimeService(), notificationsStub(), new ReservationsReadService(dbs()), await accommodationsOver(dbs()), await createTestUnitOfWork(dbs().connection)),
new ReservationsService(dbs(), new PermissionsService(await createTestAppSettingsRepo(dbs().connection), await createTestUnitOfWork(dbs().connection)), budgetSvc, new RealtimeService(), notificationsStub(), new ReservationsReadService(await createTestReservationsRepo(dbs().connection), await createTestReservationEndpointsRepo(dbs().connection), await createTestReservationTravelersRepo(dbs().connection)), await accommodationsOver(dbs()), await createTestUnitOfWork(dbs().connection), await createTestReservationsRepo(dbs().connection), await createTestReservationEndpointsRepo(dbs().connection), await createTestReservationTravelersRepo(dbs().connection), await createTestReservationDayPositionsRepo(dbs().connection), await createTestDayAccommodationsRepo(dbs().connection), await createTestDaysRepo(dbs().connection), await createTestPlacesRepo(dbs().connection), await createTestDayAssignmentsRepo(dbs().connection), await createTestTripMembersRepo(dbs().connection), await createTestUsersRepo(dbs().connection), await createTestTripsRepo(dbs().connection)),
new CollabService(dbs(), new PermissionsService(await createTestAppSettingsRepo(dbs().connection), await createTestUnitOfWork(dbs().connection)), new RealtimeService(), notificationsStub(), makeStorageFixture('').storage, new RateLimitService(), await createTestUnitOfWork(dbs().connection)),
placesSvc,
new TodoService(dbs(), new PermissionsService(await createTestAppSettingsRepo(dbs().connection), await createTestUnitOfWork(dbs().connection)), new RealtimeService(), await createTestUnitOfWork(dbs().connection)),
+9 -2
View File
@@ -93,6 +93,11 @@ import {
createTestDaysRepo, createTestDayAssignmentsRepo, createTestDayNotesRepo, createTestTripsRepo,
createTestTripMembersRepo, createTestTagsRepo, createTestPlaceRatingsRepo, createTestAssignmentParticipantsRepo,
createTestGooglePlacePhotoMetaRepo, createTestPlacesRepo, createTestCategoriesRepo,
createTestReservationsRepo,
createTestReservationEndpointsRepo,
createTestReservationTravelersRepo,
createTestReservationDayPositionsRepo,
createTestDayAccommodationsRepo,
} from '../../helpers/test-uow';
// Real sibling services over the same in-memory DB — updateTrip's date-shift
@@ -156,6 +161,8 @@ beforeAll(async () => {
await createTestDayAssignmentsRepo(dbs().connection),
await createTestDayNotesRepo(dbs().connection),
await createTestTripsRepo(dbs().connection),
await createTestReservationsRepo(dbs().connection),
await createTestReservationEndpointsRepo(dbs().connection),
);
placesSvc = new PlacesService(
dbs(),
@@ -178,7 +185,7 @@ beforeAll(async () => {
);
svc = new TripsService(
dbs(),
new ReservationsService(dbs(), new PermissionsService(await createTestAppSettingsRepo(dbs().connection), await createTestUnitOfWork(dbs().connection)), budgetSvc, new RealtimeService(), notificationsStub(), new ReservationsReadService(dbs()), accommodationsSvc, await createTestUnitOfWork(dbs().connection)),
new ReservationsService(dbs(), new PermissionsService(await createTestAppSettingsRepo(dbs().connection), await createTestUnitOfWork(dbs().connection)), budgetSvc, new RealtimeService(), notificationsStub(), new ReservationsReadService(await createTestReservationsRepo(dbs().connection), await createTestReservationEndpointsRepo(dbs().connection), await createTestReservationTravelersRepo(dbs().connection)), accommodationsSvc, await createTestUnitOfWork(dbs().connection), await createTestReservationsRepo(dbs().connection), await createTestReservationEndpointsRepo(dbs().connection), await createTestReservationTravelersRepo(dbs().connection), await createTestReservationDayPositionsRepo(dbs().connection), await createTestDayAccommodationsRepo(dbs().connection), await createTestDaysRepo(dbs().connection), await createTestPlacesRepo(dbs().connection), await createTestDayAssignmentsRepo(dbs().connection), await createTestTripMembersRepo(dbs().connection), await createTestUsersRepo(dbs().connection), await createTestTripsRepo(dbs().connection)),
daysSvc,
new PermissionsService(await createTestAppSettingsRepo(dbs().connection), await createTestUnitOfWork(dbs().connection)),
budgetSvc,
@@ -193,7 +200,7 @@ beforeAll(async () => {
readModelSvc = new TripReadModelService(
await createTestTripsRepo(dbs().connection), membersSvc, daysSvc, accommodationsSvc, budgetSvc,
new PackingService(dbs(), new PermissionsService(await createTestAppSettingsRepo(dbs().connection), await createTestUnitOfWork(dbs().connection)), new RealtimeService(), notificationsStub(), await createTestUnitOfWork(dbs().connection)),
new ReservationsService(dbs(), new PermissionsService(await createTestAppSettingsRepo(dbs().connection), await createTestUnitOfWork(dbs().connection)), budgetSvc, new RealtimeService(), notificationsStub(), new ReservationsReadService(dbs()), accommodationsSvc, await createTestUnitOfWork(dbs().connection)),
new ReservationsService(dbs(), new PermissionsService(await createTestAppSettingsRepo(dbs().connection), await createTestUnitOfWork(dbs().connection)), budgetSvc, new RealtimeService(), notificationsStub(), new ReservationsReadService(await createTestReservationsRepo(dbs().connection), await createTestReservationEndpointsRepo(dbs().connection), await createTestReservationTravelersRepo(dbs().connection)), accommodationsSvc, await createTestUnitOfWork(dbs().connection), await createTestReservationsRepo(dbs().connection), await createTestReservationEndpointsRepo(dbs().connection), await createTestReservationTravelersRepo(dbs().connection), await createTestReservationDayPositionsRepo(dbs().connection), await createTestDayAccommodationsRepo(dbs().connection), await createTestDaysRepo(dbs().connection), await createTestPlacesRepo(dbs().connection), await createTestDayAssignmentsRepo(dbs().connection), await createTestTripMembersRepo(dbs().connection), await createTestUsersRepo(dbs().connection), await createTestTripsRepo(dbs().connection)),
new CollabService(dbs(), new PermissionsService(await createTestAppSettingsRepo(dbs().connection), await createTestUnitOfWork(dbs().connection)), new RealtimeService(), notificationsStub(), coversFx.storage, new RateLimitService(), await createTestUnitOfWork(dbs().connection)),
placesSvc,
new TodoService(dbs(), new PermissionsService(await createTestAppSettingsRepo(dbs().connection), await createTestUnitOfWork(dbs().connection)), new RealtimeService(), await createTestUnitOfWork(dbs().connection)),
@@ -23,7 +23,7 @@ import type { AirtrailClient } from '../../../src/nest/integrations/airtrail.cli
import type { AirtrailService } from '../../../src/nest/integrations/airtrail.service';
import { notificationsStub } from '../../helpers/notifications';
import { accommodationsOver } from '../../helpers/accommodations-service';
import { createTestUnitOfWork, createTestAppSettingsRepo } from '../../helpers/test-uow';
import { createTestUnitOfWork, createTestAppSettingsRepo, createTestReservationsRepo, createTestReservationEndpointsRepo, createTestReservationTravelersRepo, createTestReservationDayPositionsRepo, createTestDayAccommodationsRepo, createTestDaysRepo, createTestPlacesRepo, createTestDayAssignmentsRepo, createTestTripMembersRepo, createTestUsersRepo, createTestTripsRepo } from '../../helpers/test-uow';
// The client and the per-user credentials are the only stubs; the reservation
// writes go through the real service against the real test DB, as before. They
@@ -44,8 +44,12 @@ async function makeImportService(): Promise<AirtrailImportService> {
new BudgetService(dbs(), permissions, new ExchangeRatesService(), realtime, await createTestUnitOfWork(dbs().connection)),
realtime,
notificationsStub(),
new ReservationsReadService(dbs()),
new ReservationsReadService(await createTestReservationsRepo(dbs().connection), await createTestReservationEndpointsRepo(dbs().connection), await createTestReservationTravelersRepo(dbs().connection)),
await accommodationsOver(dbs()), await createTestUnitOfWork(dbs().connection),
await createTestReservationsRepo(dbs().connection), await createTestReservationEndpointsRepo(dbs().connection), await createTestReservationTravelersRepo(dbs().connection),
await createTestReservationDayPositionsRepo(dbs().connection), await createTestDayAccommodationsRepo(dbs().connection),
await createTestDaysRepo(dbs().connection), await createTestPlacesRepo(dbs().connection), await createTestDayAssignmentsRepo(dbs().connection),
await createTestTripMembersRepo(dbs().connection), await createTestUsersRepo(dbs().connection), await createTestTripsRepo(dbs().connection),
),
{ listFlights } as unknown as AirtrailClient,
{