/**
* The tours-mode GPX import end to end through the real PlacesService and
* ToursService over the migrated per-worker DB: the places, their track
* colours and their tours facets commit in one transaction (PlacesService's
* importPreparedGpx nests in ToursService's as a savepoint), any failure on
* the way rolls all of it back, and the realtime events go out only after the
* commit. Failures are injected with SQLite triggers on the real tables.
*/
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi, type MockInstance } from 'vitest';
import { Logger } from '@nestjs/common';
vi.mock('../../../src/db/database', async () => {
const { createSnapshotTestDb, buildDbMock } = await import('../../helpers/db-mock');
return buildDbMock(createSnapshotTestDb());
});
vi.mock('../../../src/config', () => ({
JWT_SECRET: 'test-secret',
ENCRYPTION_KEY: 'a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6a7b8c9d0e1f2a3b4c5d6a7b8c9d0e1f2',
updateJwtSecret: () => {},
}));
import { db as testDb } from '../../../src/db/database';
import type { PlacePhotoCacheService } from '../../../src/nest/place-photos/place-photo-cache.service';
import type { AppSettingsRepository } from '../../../src/db/repositories/AppSettings.repository';
import type { UsersRepository } from '../../../src/db/repositories/Users.repository';
import type { UnitOfWork } from '../../../src/nest/database/unit-of-work';
import { UnsplashService } from '../../../src/nest/unsplash/unsplash.service';
import { RuntimeEnvService } from '../../../src/nest/app-config/runtime-env.service';
import { PermissionsService } from '../../../src/nest/permissions/permissions.service';
import { RealtimeService } from '../../../src/nest/realtime/realtime.service';
import { PlacesService } from '../../../src/nest/places/places.service';
import { MapsService } from '../../../src/nest/maps/maps.service';
import { QueryHelpersService } from '../../../src/nest/query-helpers/query-helpers.service';
import { JourneyDomainService } from '../../../src/nest/journey/journey-domain.service';
import { TrekPhotoRegistrationService } from '../../../src/nest/photos/trek-photo-registration.service';
import { ToursService } from '../../../src/nest/tours/tours.service';
import { gpxParser } from '../../../src/nest/places/places.helpers';
import { TrekPhotos } from '../../../src/db/entities/TrekPhotos.entity';
import { TripPhotos } from '../../../src/db/entities/TripPhotos.entity';
import { resetTestDb } from '../../helpers/test-db';
import { createTrip, createUser } from '../../helpers/factories';
import { accommodationsOver } from '../../helpers/accommodations-service';
import { makeStorageFixture } from '../../helpers/storage-fixture';
import { noGoogleQuota } from '../../helpers/google-quota';
import {
createTestUnitOfWork, createTestAppSettingsRepo, createTestUsersRepo, createTestTagsRepo, createTestPlaceRatingsRepo,
createTestAssignmentParticipantsRepo, createTestPlacesRepo, createTestTripMembersRepo, createTestDayAssignmentsRepo,
createTestCategoriesRepo, createTestTripsRepo, createTestCollectionPlacesRepo, sharedTestOrm,
} from '../../helpers/test-uow';
import type { EntityClass } from '@mikro-orm/core';
import { countRows, findRows } from '../../helpers/factories/rows';
import { Places } from '../../../src/db/entities/Places.entity';
import { TourWaypoints } from '../../../src/db/entities/TourWaypoints.entity';
import { Tours } from '../../../src/db/entities/Tours.entity';
import { createTestBudgetItemsRepo } from '../../helpers/files-repos';
import {
createTestJourneysRepo, createTestJourneyContributorsRepo, createTestJourneyTripsRepo, createTestJourneyEntriesRepo,
createTestJourneyPhotosRepo, createTestJourneyEntryPhotosRepo,
} from '../../helpers/journey-repos';
import { createTestToursRepo, createTestTourTypesRepo, createTestTourWaypointsRepo } from '../../helpers/tours-repos';
const mixedGpx = Buffer.from(`
Ignored POI
Route description
RidgeTrack description
100
150
120
`);
const TRIGGERS = ['fail_facet', 'fail_place', 'fail_color'];
/** The collaborator set the container hands PlacesService (the places.service.test.ts builder). */
async function makePlacesService(): Promise {
const photoCacheStub = { removeIfUnreferenced: vi.fn() } as unknown as PlacePhotoCacheService;
const noAppSettings = { getValue: async () => null } as unknown as AppSettingsRepository;
const noUsers = { getApiKeyColumn: async () => null } as unknown as UsersRepository;
const storage = makeStorageFixture('').storage;
const orm = await sharedTestOrm(testDb);
return new PlacesService(
new PermissionsService(await createTestAppSettingsRepo(testDb), await createTestUnitOfWork(testDb)),
new RealtimeService(),
new MapsService(photoCacheStub, noAppSettings, noUsers, {} as never, {} as never, noGoogleQuota),
new QueryHelpersService(await createTestTagsRepo(testDb), await createTestPlaceRatingsRepo(testDb), await createTestAssignmentParticipantsRepo(testDb)),
new UnsplashService(await createTestAppSettingsRepo(testDb), await createTestUsersRepo(testDb), new RuntimeEnvService(), storage),
photoCacheStub,
new JourneyDomainService(
new RealtimeService(), new TrekPhotoRegistrationService(orm.repo(TrekPhotos), orm.repo(TripPhotos), await createTestJourneyPhotosRepo(testDb)), await createTestUnitOfWork(testDb),
await createTestJourneysRepo(testDb), await createTestJourneyContributorsRepo(testDb),
await createTestJourneyTripsRepo(testDb), await createTestJourneyEntriesRepo(testDb), await createTestTripsRepo(testDb),
await createTestJourneyPhotosRepo(testDb), await createTestJourneyEntryPhotosRepo(testDb), await createTestPlacesRepo(testDb),
),
storage,
await accommodationsOver(testDb), await createTestUnitOfWork(testDb),
await createTestPlacesRepo(testDb),
await createTestTagsRepo(testDb),
await createTestPlaceRatingsRepo(testDb),
await createTestTripMembersRepo(testDb),
await createTestDayAssignmentsRepo(testDb),
await createTestCategoriesRepo(testDb),
await createTestTripsRepo(testDb),
await createTestBudgetItemsRepo(testDb),
await createTestCollectionPlacesRepo(testDb),
);
}
let uow: UnitOfWork;
let places: PlacesService;
let tours: ToursService;
let tripId: string;
let broadcast: MockInstance;
const countedTables = { places: Places, tours: Tours, tour_waypoints: TourWaypoints } as const;
const count = async (table: keyof typeof countedTables) =>
countRows(await sharedTestOrm(testDb), countedTables[table] as EntityClass