mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-23 23:46:35 +00:00
feat(db): AppSettings and Users repositories; forFeature wiring pattern
This commit is contained in:
@@ -93,13 +93,14 @@ import { NotificationsModule } from '../../src/nest/notifications/notifications.
|
||||
import { TrekExceptionFilter } from '../../src/nest/common/trek-exception.filter';
|
||||
import { ZodValidationPipe } from '../../src/nest/common/zod-validation.pipe';
|
||||
import { TestUnitOfWorkModule } from '../helpers/test-uow';
|
||||
import { createTestMikroOrmModule } from '../helpers/test-orm';
|
||||
|
||||
describe('Admin e2e (real auth + admin guard + temp SQLite)', () => {
|
||||
let server: Server;
|
||||
let app: Awaited<ReturnType<typeof build>>;
|
||||
|
||||
async function build() {
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), DatabaseModule, RealtimeModule, AdminModule, OidcModule, SettingsModule, NotificationsModule] }).compile();
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), await createTestMikroOrmModule(db), DatabaseModule, RealtimeModule, AdminModule, OidcModule, SettingsModule, NotificationsModule] }).compile();
|
||||
const nest = moduleRef.createNestApplication();
|
||||
nest.use(cookieParser());
|
||||
// Mirror the production APP_PIPE (app.module.ts): DTO-typed bodies validate
|
||||
|
||||
@@ -76,13 +76,14 @@ import { AssignmentsModule } from '../../src/nest/assignments/assignments.module
|
||||
import { TrekExceptionFilter } from '../../src/nest/common/trek-exception.filter';
|
||||
import { ZodValidationPipe } from '../../src/nest/common/zod-validation.pipe';
|
||||
import { TestUnitOfWorkModule } from '../helpers/test-uow';
|
||||
import { createTestMikroOrmModule } from '../helpers/test-orm';
|
||||
|
||||
describe('Assignments e2e (real auth guard + temp SQLite)', () => {
|
||||
let server: Server;
|
||||
let app: Awaited<ReturnType<typeof build>>;
|
||||
|
||||
async function build() {
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), DatabaseModule, RealtimeModule, AssignmentsModule] })
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), await createTestMikroOrmModule(db), DatabaseModule, RealtimeModule, AssignmentsModule] })
|
||||
.overrideProvider(JourneyDomainService)
|
||||
.useValue({ reconcileTripSkeletons })
|
||||
.compile();
|
||||
|
||||
@@ -37,6 +37,7 @@ import { DatabaseModule } from '../../src/nest/database/database.module';
|
||||
import { FeedsModule } from '../../src/nest/feeds/feeds.module';
|
||||
import { TrekExceptionFilter } from '../../src/nest/common/trek-exception.filter';
|
||||
import { TestUnitOfWorkModule } from '../helpers/test-uow';
|
||||
import { createTestMikroOrmModule } from '../helpers/test-orm';
|
||||
|
||||
describe('Calendar feed visibility e2e (real CalendarService over temp SQLite)', () => {
|
||||
let server: Server;
|
||||
@@ -44,7 +45,7 @@ describe('Calendar feed visibility e2e (real CalendarService over temp SQLite)',
|
||||
let feedToken: string;
|
||||
|
||||
async function build() {
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), DatabaseModule, FeedsModule] }).compile();
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), await createTestMikroOrmModule(db), DatabaseModule, FeedsModule] }).compile();
|
||||
const nest = moduleRef.createNestApplication();
|
||||
nest.useGlobalFilters(new TrekExceptionFilter());
|
||||
await nest.init();
|
||||
|
||||
@@ -60,6 +60,7 @@ import { AddonsService } from '../../src/nest/addons/addons.service';
|
||||
import { TrekExceptionFilter } from '../../src/nest/common/trek-exception.filter';
|
||||
import { ZodValidationPipe } from '../../src/nest/common/zod-validation.pipe';
|
||||
import { TestUnitOfWorkModule } from '../helpers/test-uow';
|
||||
import { createTestMikroOrmModule } from '../helpers/test-orm';
|
||||
|
||||
/**
|
||||
* Every outbound call an instance would ever receive, stubbed to throw. A route
|
||||
@@ -100,7 +101,7 @@ describe('Dawarich e2e (real addon gate + real auth guard + real services + temp
|
||||
let strangerSuggestionId: number;
|
||||
|
||||
async function build() {
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), DatabaseModule, DawarichModule] })
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), await createTestMikroOrmModule(db), DatabaseModule, DawarichModule] })
|
||||
.overrideProvider(AddonsService)
|
||||
.useValue({ isAddonEnabled })
|
||||
.overrideProvider(DawarichClient)
|
||||
|
||||
@@ -91,13 +91,14 @@ import { DayNotesModule } from '../../src/nest/day-notes/day-notes.module';
|
||||
import { TrekExceptionFilter } from '../../src/nest/common/trek-exception.filter';
|
||||
import { ZodValidationPipe } from '../../src/nest/common/zod-validation.pipe';
|
||||
import { TestUnitOfWorkModule } from '../helpers/test-uow';
|
||||
import { createTestMikroOrmModule } from '../helpers/test-orm';
|
||||
|
||||
describe('Days + day-notes e2e (real auth guard + temp SQLite, real day SQL)', () => {
|
||||
let server: Server;
|
||||
let app: Awaited<ReturnType<typeof build>>;
|
||||
|
||||
async function build() {
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), DatabaseModule, RealtimeModule, DaysModule, DayNotesModule] }).compile();
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), await createTestMikroOrmModule(db), DatabaseModule, RealtimeModule, DaysModule, DayNotesModule] }).compile();
|
||||
const nest = moduleRef.createNestApplication();
|
||||
nest.use(cookieParser());
|
||||
nest.useGlobalPipes(new ZodValidationPipe());
|
||||
|
||||
@@ -78,6 +78,7 @@ import { AppConfigModule } from '../../src/nest/app-config/app-config.module';
|
||||
import { GlobalAuthGuard } from '../../src/nest/auth/global-auth.guard';
|
||||
import { MfaPolicyGuard } from '../../src/nest/auth/mfa-policy.guard';
|
||||
import { TestUnitOfWorkModule } from '../helpers/test-uow';
|
||||
import { createTestMikroOrmModule } from '../helpers/test-orm';
|
||||
|
||||
const BASE = 'https://trek.example.test';
|
||||
|
||||
@@ -93,7 +94,7 @@ describe('Calendar-feed e2e (real auth guard + temp SQLite)', () => {
|
||||
// on the feed controller passed here while production 401'd every calendar
|
||||
// client).
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [await TestUnitOfWorkModule.forRoot(db), AppConfigModule, DatabaseModule, RealtimeModule, FeedsModule],
|
||||
imports: [await TestUnitOfWorkModule.forRoot(db), await createTestMikroOrmModule(db), AppConfigModule, DatabaseModule, RealtimeModule, FeedsModule],
|
||||
providers: [
|
||||
{ provide: APP_GUARD, useClass: GlobalAuthGuard },
|
||||
{ provide: APP_GUARD, useClass: MfaPolicyGuard },
|
||||
|
||||
@@ -71,13 +71,14 @@ import { AddonsService } from '../../src/nest/addons/addons.service';
|
||||
import { TrekExceptionFilter } from '../../src/nest/common/trek-exception.filter';
|
||||
import { ZodValidationPipe } from '../../src/nest/common/zod-validation.pipe';
|
||||
import { TestUnitOfWorkModule } from '../helpers/test-uow';
|
||||
import { createTestMikroOrmModule } from '../helpers/test-orm';
|
||||
|
||||
describe('Journey e2e (real auth guard + temp SQLite)', () => {
|
||||
let server: Server;
|
||||
let app: Awaited<ReturnType<typeof build>>;
|
||||
|
||||
async function build() {
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), DatabaseModule, JourneyModule] })
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), await createTestMikroOrmModule(db), DatabaseModule, JourneyModule] })
|
||||
.overrideProvider(JourneyDomainService)
|
||||
.useValue(jsvc)
|
||||
.overrideProvider(JourneyShareService)
|
||||
|
||||
@@ -86,13 +86,14 @@ import { PlacesService } from '../../src/nest/places/places.service';
|
||||
import { TrekExceptionFilter } from '../../src/nest/common/trek-exception.filter';
|
||||
import { ZodValidationPipe } from '../../src/nest/common/zod-validation.pipe';
|
||||
import { TestUnitOfWorkModule } from '../helpers/test-uow';
|
||||
import { createTestMikroOrmModule } from '../helpers/test-orm';
|
||||
|
||||
describe('Places e2e (real auth guard + temp SQLite)', () => {
|
||||
let server: Server;
|
||||
let app: Awaited<ReturnType<typeof build>>;
|
||||
|
||||
async function build() {
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), DatabaseModule, RealtimeModule, PlacesModule] })
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), await createTestMikroOrmModule(db), DatabaseModule, RealtimeModule, PlacesModule] })
|
||||
.overrideProvider(JourneyDomainService)
|
||||
.useValue({
|
||||
onPlaceCreated: vi.fn().mockResolvedValue(undefined),
|
||||
|
||||
@@ -58,6 +58,7 @@ import { createTables } from '../../src/db/schema';
|
||||
import { runMigrations } from '../../src/db/migrations';
|
||||
import { NotificationsService } from '../../src/nest/notifications/notifications.service';
|
||||
import { TestUnitOfWorkModule } from '../helpers/test-uow';
|
||||
import { createTestMikroOrmModule } from '../helpers/test-orm';
|
||||
|
||||
describe('Reservations + accommodations e2e (real auth guard + temp SQLite, real reservation SQL)', () => {
|
||||
let server: Server;
|
||||
@@ -65,7 +66,7 @@ describe('Reservations + accommodations e2e (real auth guard + temp SQLite, real
|
||||
let tripId: number;
|
||||
|
||||
async function build() {
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), DatabaseModule, RealtimeModule, ReservationsModule, AccommodationsModule] })
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), await createTestMikroOrmModule(db), DatabaseModule, RealtimeModule, ReservationsModule, AccommodationsModule] })
|
||||
.overrideProvider(NotificationsService)
|
||||
.useValue({ send: notificationSend })
|
||||
.compile();
|
||||
|
||||
@@ -29,6 +29,7 @@ import type { Server } from 'http';
|
||||
import request from 'supertest';
|
||||
import { describe, it, expect, beforeAll, afterAll, beforeEach, vi, type MockInstance } from 'vitest';
|
||||
import { TestUnitOfWorkModule } from '../helpers/test-uow';
|
||||
import { createTestMikroOrmModule } from '../helpers/test-orm';
|
||||
|
||||
const { db } = vi.hoisted(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
@@ -96,7 +97,7 @@ describe('Roadtrip e2e (real guard chain + temp SQLite)', () => {
|
||||
|
||||
async function build() {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [await TestUnitOfWorkModule.forRoot(db), DatabaseModule, RealtimeModule, RoadtripModule],
|
||||
imports: [await TestUnitOfWorkModule.forRoot(db), await createTestMikroOrmModule(db), DatabaseModule, RealtimeModule, RoadtripModule],
|
||||
}).compile();
|
||||
const nest = moduleRef.createNestApplication();
|
||||
nest.use(cookieParser());
|
||||
|
||||
@@ -32,13 +32,14 @@ import { SettingsModule } from '../../src/nest/settings/settings.module';
|
||||
import { TrekExceptionFilter } from '../../src/nest/common/trek-exception.filter';
|
||||
import { ZodValidationPipe } from '../../src/nest/common/zod-validation.pipe';
|
||||
import { TestUnitOfWorkModule } from '../helpers/test-uow';
|
||||
import { createTestMikroOrmModule } from '../helpers/test-orm';
|
||||
|
||||
describe('Settings e2e (real auth guard + temp SQLite)', () => {
|
||||
let server: Server;
|
||||
let app: Awaited<ReturnType<typeof build>>;
|
||||
|
||||
async function build() {
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), DatabaseModule, SettingsModule] }).compile();
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), await createTestMikroOrmModule(db), DatabaseModule, SettingsModule] }).compile();
|
||||
const nest = moduleRef.createNestApplication();
|
||||
nest.use(cookieParser());
|
||||
nest.useGlobalFilters(new TrekExceptionFilter());
|
||||
|
||||
@@ -59,6 +59,7 @@ import { DatabaseModule } from '../../src/nest/database/database.module';
|
||||
import { TrekExceptionFilter } from '../../src/nest/common/trek-exception.filter';
|
||||
import { ZodValidationPipe } from '../../src/nest/common/zod-validation.pipe';
|
||||
import { TestUnitOfWorkModule } from '../helpers/test-uow';
|
||||
import { createTestMikroOrmModule } from '../helpers/test-orm';
|
||||
|
||||
describe('Share-link e2e (real auth guard + real SQL over temp SQLite)', () => {
|
||||
let server: Server;
|
||||
@@ -66,7 +67,7 @@ describe('Share-link e2e (real auth guard + real SQL over temp SQLite)', () => {
|
||||
let tripId: number;
|
||||
|
||||
async function build() {
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), DatabaseModule, ShareModule] })
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), await createTestMikroOrmModule(db), DatabaseModule, ShareModule] })
|
||||
.overrideProvider(PlacePhotoCacheService).useValue({ serveKey })
|
||||
.compile();
|
||||
const nest = moduleRef.createNestApplication();
|
||||
|
||||
@@ -33,6 +33,7 @@ import { RealtimeModule } from '../../src/nest/realtime/realtime.module';
|
||||
import { TrekExceptionFilter } from '../../src/nest/common/trek-exception.filter';
|
||||
import { clearGoogleTransitCache } from '../../src/nest/transit/google-transit.provider';
|
||||
import { TestUnitOfWorkModule } from '../helpers/test-uow';
|
||||
import { createTestMikroOrmModule } from '../helpers/test-orm';
|
||||
|
||||
const ADMIN = 1;
|
||||
|
||||
@@ -49,7 +50,7 @@ describe('Transit backend switch e2e (#1699)', () => {
|
||||
|
||||
async function build() {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [await TestUnitOfWorkModule.forRoot(db), DatabaseModule, RealtimeModule, TransitModule],
|
||||
imports: [await TestUnitOfWorkModule.forRoot(db), await createTestMikroOrmModule(db), DatabaseModule, RealtimeModule, TransitModule],
|
||||
}).compile();
|
||||
const nest = moduleRef.createNestApplication();
|
||||
nest.use(cookieParser());
|
||||
|
||||
@@ -31,6 +31,7 @@ import { DatabaseModule } from '../../src/nest/database/database.module';
|
||||
import { RealtimeModule } from '../../src/nest/realtime/realtime.module';
|
||||
import { TrekExceptionFilter } from '../../src/nest/common/trek-exception.filter';
|
||||
import { TestUnitOfWorkModule } from '../helpers/test-uow';
|
||||
import { createTestMikroOrmModule } from '../helpers/test-orm';
|
||||
|
||||
describe('Transit proxy e2e (real auth guard + temp SQLite)', () => {
|
||||
let server: Server;
|
||||
@@ -42,7 +43,7 @@ describe('Transit proxy e2e (real auth guard + temp SQLite)', () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
// DatabaseModule + RealtimeModule are @Global in the app graph;
|
||||
// TransitModule's DaysModule/ReservationsModule imports need them here.
|
||||
imports: [await TestUnitOfWorkModule.forRoot(db), DatabaseModule, RealtimeModule, TransitModule],
|
||||
imports: [await TestUnitOfWorkModule.forRoot(db), await createTestMikroOrmModule(db), DatabaseModule, RealtimeModule, TransitModule],
|
||||
}).compile();
|
||||
const nest = moduleRef.createNestApplication();
|
||||
nest.use(cookieParser());
|
||||
|
||||
@@ -133,13 +133,14 @@ import { BudgetService } from '../../src/nest/budget/budget.service';
|
||||
import { TripsModule } from '../../src/nest/trips/trips.module';
|
||||
import { TrekExceptionFilter } from '../../src/nest/common/trek-exception.filter';
|
||||
import { TestUnitOfWorkModule } from '../helpers/test-uow';
|
||||
import { createTestMikroOrmModule } from '../helpers/test-orm';
|
||||
|
||||
describe('Trips e2e (real auth guard + temp SQLite)', () => {
|
||||
let server: Server;
|
||||
let app: Awaited<ReturnType<typeof build>>;
|
||||
|
||||
async function build() {
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), DatabaseModule, RealtimeModule, TripsModule] }).compile();
|
||||
const moduleRef = await Test.createTestingModule({ imports: [await TestUnitOfWorkModule.forRoot(db), await createTestMikroOrmModule(db), DatabaseModule, RealtimeModule, TripsModule] }).compile();
|
||||
const nest = moduleRef.createNestApplication();
|
||||
nest.use(cookieParser());
|
||||
nest.useGlobalFilters(new TrekExceptionFilter());
|
||||
|
||||
@@ -115,6 +115,9 @@ import { ReservationImportMcp } from '../../src/nest/reservation-import/reservat
|
||||
import { HelpMcp } from '../../src/nest/help/help.mcp';
|
||||
import { AddonsMcp } from '../../src/nest/addons/addons.mcp';
|
||||
import { createTestUnitOfWork } from './test-uow';
|
||||
import { createTestOrm } from './test-orm';
|
||||
import { AppSettings } from '../../src/db/entities/AppSettings.entity';
|
||||
import type { AppSettingsRepository } from '../../src/db/repositories/AppSettings.repository';
|
||||
|
||||
/**
|
||||
* Hand-wired counterpart of the boot-time discovery in McpRegistryService,
|
||||
@@ -126,6 +129,7 @@ import { createTestUnitOfWork } from './test-uow';
|
||||
export async function createMcpTestRegistry(): Promise<McpRegistry> {
|
||||
const dbService = new DatabaseService(db);
|
||||
const generalStorage = makeStorageFixture('').storage;
|
||||
const appSettings = (await createTestOrm(dbService.connection)).repo(AppSettings) as AppSettingsRepository;
|
||||
const permissionsService = new PermissionsService(dbService, await createTestUnitOfWork(dbService.connection));
|
||||
// Same argument list as auth.bridge.ts. AtlasService used to sit in third
|
||||
// place; when getTravelStats moved onto AtlasService itself the edge was
|
||||
@@ -232,7 +236,7 @@ export async function createMcpTestRegistry(): Promise<McpRegistry> {
|
||||
new SchoolHolidaysMcp(new SchoolHolidaysService(dbService, await createTestUnitOfWork(dbService.connection)), guards),
|
||||
new TripsMcp(tripsService, todoService, collabService, authService, calendarService, membersService, readModelService, addonsService, guards),
|
||||
new TripPromptsMcp(tripsService, readModelService, packingService, addonsService),
|
||||
new ShareMcp(new ShareService(dbService, new SettingsService(dbService, await createTestUnitOfWork(dbService.connection)), permissionsService, queryHelpersService, placePhotoCache, await createTestUnitOfWork(dbService.connection)), authService, guards),
|
||||
new ShareMcp(new ShareService(dbService, new SettingsService(dbService, await createTestUnitOfWork(dbService.connection), appSettings), permissionsService, queryHelpersService, placePhotoCache, await createTestUnitOfWork(dbService.connection)), authService, guards),
|
||||
new FeedsMcp(new FeedsService(dbService, calendarService), dbService, new RuntimeEnvService(), guards),
|
||||
new TripInviteMcp(new TripInviteService(dbService, permissionsService, new TripMembershipService(dbService), await createTestUnitOfWork(dbService.connection)), dbService, new RuntimeEnvService(), guards, new AuditService(dbService)),
|
||||
new MapsMcp(mapsService),
|
||||
@@ -240,12 +244,12 @@ export async function createMcpTestRegistry(): Promise<McpRegistry> {
|
||||
new CollectionsMcp(new CollectionsService(dbService, permissionsService, realtimeService, notificationsStub(), generalStorage, await createTestUnitOfWork(dbService.connection)), dbService, authService, addonsService),
|
||||
new TransitMcp(new TransitService(new GoogleTransitProvider(dbService)), daysService, reservationsService, dbService, authService, guards),
|
||||
new AtlasMcp(new AtlasService(dbService, await createTestUnitOfWork(dbService.connection)), addonsService, authService),
|
||||
new JourneyMcp(journeyDomain, new JourneyShareService(dbService, journeyDomain, new SettingsService(dbService, await createTestUnitOfWork(dbService.connection))), addonsService, authService, captureBackfill),
|
||||
new JourneyMcp(journeyDomain, new JourneyShareService(dbService, journeyDomain, new SettingsService(dbService, await createTestUnitOfWork(dbService.connection), appSettings)), addonsService, authService, captureBackfill),
|
||||
new MemoriesMcp(immichService, synologyService, dbService, addonsService),
|
||||
new NotificationsMcp(await makeNotificationsService(dbService, realtimeService), authService),
|
||||
new AirtrailMcp(new AirtrailService(dbService, new AuditService(dbService), new AirtrailClient()), addonsService),
|
||||
new ReservationImportMcp(new AirtrailImportService(dbService, realtimeService, reservationsService, new AirtrailClient(), new AirtrailService(dbService, new AuditService(dbService), new AirtrailClient())), dbService, authService, guards, addonsService),
|
||||
new SettingsMcp(new SettingsService(dbService, await createTestUnitOfWork(dbService.connection)), authService),
|
||||
new SettingsMcp(new SettingsService(dbService, await createTestUnitOfWork(dbService.connection), appSettings), authService),
|
||||
new HelpMcp(), new AddonsMcp(addonsService),
|
||||
new TripWarningsMcp(new PluginHooks({ providersOf: () => [], invokeHook: async () => [] } as unknown as PluginRuntimeService), dbService),
|
||||
new PluginSearchMcp(new PluginHooks({ providersOf: () => [], invokeHook: async () => [] } as unknown as PluginRuntimeService)),
|
||||
|
||||
@@ -73,6 +73,9 @@ import { TrekPhotosRepository } from '../../src/nest/photos/trek-photos.reposito
|
||||
import { RuntimeEnvService } from '../../src/nest/app-config/runtime-env.service';
|
||||
import { makeStorageFixture } from './storage-fixture';
|
||||
import { createTestUnitOfWork } from './test-uow';
|
||||
import { createTestOrm } from './test-orm';
|
||||
import { AppSettings } from '../../src/db/entities/AppSettings.entity';
|
||||
import type { AppSettingsRepository } from '../../src/db/repositories/AppSettings.repository';
|
||||
|
||||
/**
|
||||
* Hand-wired counterpart of the PluginsModule DI graph for no-Nest tests
|
||||
@@ -86,6 +89,7 @@ import { createTestUnitOfWork } from './test-uow';
|
||||
*/
|
||||
export async function createPluginRpcHostFactory(dbs: DatabaseService): Promise<PluginRpcHostFactory> {
|
||||
const generalStorage = makeStorageFixture('').storage;
|
||||
const appSettings = (await createTestOrm(dbs.connection)).repo(AppSettings) as AppSettingsRepository;
|
||||
const permissions = new PermissionsService(dbs, await createTestUnitOfWork(dbs.connection));
|
||||
const exchangeRates = new ExchangeRatesService();
|
||||
const realtime = new RealtimeService();
|
||||
@@ -107,7 +111,7 @@ export async function createPluginRpcHostFactory(dbs: DatabaseService): Promise<
|
||||
const assignments = new AssignmentsService(dbs, permissions, realtime, queryHelpers, journey, await createTestUnitOfWork(dbs.connection));
|
||||
const membership = new TripMembershipService(dbs);
|
||||
const notifications = await makeNotificationsService(dbs, realtime);
|
||||
const llmConfig = new LlmConfigResolver(new SettingsService(dbs, await createTestUnitOfWork(dbs.connection)), dbs, addons);
|
||||
const llmConfig = new LlmConfigResolver(new SettingsService(dbs, await createTestUnitOfWork(dbs.connection), appSettings), dbs, addons);
|
||||
const oauth = new PluginOAuthService(dbs);
|
||||
const accommodations = new AccommodationsService(dbs, permissions, realtime, assignments, await createTestUnitOfWork(dbs.connection));
|
||||
// After it: deleting a place cancels the nights booked at it through this one.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { EntityClass, EntityRepository, GetRepository } from '@mikro-orm/core';
|
||||
import { MikroORM, type EntityManager } from '@mikro-orm/sqlite';
|
||||
import { MikroOrmModule } from '@mikro-orm/nestjs';
|
||||
import type { DynamicModule } from '@nestjs/common';
|
||||
import type Database from 'better-sqlite3';
|
||||
import { ALL_ENTITIES } from '../../src/db/entities';
|
||||
import { createBoundSqliteDriver } from '../../src/db/orm-driver';
|
||||
@@ -65,3 +67,28 @@ export async function createTestOrm(
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* `MikroOrmModule.forRoot`, bound to a suite's own better-sqlite3 handle the
|
||||
* same way `createTestOrm` is, for the partial `Test.createTestingModule`
|
||||
* e2e harnesses (`imports: [DatabaseModule, RealtimeModule, SomeModule]`)
|
||||
* that don't go through `buildApp()`.
|
||||
*
|
||||
* `buildApp()` always registers `MikroOrmModule.forRoot` (D5), so any domain
|
||||
* module that uses `@InjectRepository`/`MikroOrmModule.forFeature` needs an
|
||||
* `EntityManager` provider in the graph to resolve at all — a partial harness
|
||||
* that composes such a module without this fails Nest's DI at `compile()`,
|
||||
* not at the assertion. `allowGlobalContext` is left at its production
|
||||
* default (`false`): these are real HTTP requests through
|
||||
* `createNestApplication()`, so `registerRequestContext` (the NestJS
|
||||
* integration's default) forks a context-resolving EntityManager per request
|
||||
* the same way `buildApp()` does — no test-only global context needed here.
|
||||
*/
|
||||
export function createTestMikroOrmModule(db: Database.Database): DynamicModule | Promise<DynamicModule> {
|
||||
return MikroOrmModule.forRoot({
|
||||
entities: [...ALL_ENTITIES],
|
||||
driver: createBoundSqliteDriver(() => db),
|
||||
dbName: ':memory:',
|
||||
discovery: { warnWhenNoEntities: false },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest';
|
||||
import { createSnapshotTestDb } from '../../../helpers/db-mock';
|
||||
import { resetTestDb } from '../../../helpers/test-db';
|
||||
import { createTestOrm, type TestOrm } from '../../../helpers/test-orm';
|
||||
import { AppSettings } from '../../../../src/db/entities/AppSettings.entity';
|
||||
import type { AppSettingsRepository } from '../../../../src/db/repositories/AppSettings.repository';
|
||||
|
||||
const testDb = createSnapshotTestDb();
|
||||
let t: TestOrm;
|
||||
let appSettings: AppSettingsRepository;
|
||||
|
||||
beforeAll(async () => {
|
||||
t = await createTestOrm(testDb);
|
||||
appSettings = t.repo(AppSettings) as AppSettingsRepository;
|
||||
});
|
||||
beforeEach(() => { resetTestDb(testDb); t.clear(); });
|
||||
afterAll(async () => { await t.close(); testDb.close(); });
|
||||
|
||||
function rawRow(key: string): unknown {
|
||||
return testDb.prepare('SELECT * FROM app_settings WHERE key = ?').get(key);
|
||||
}
|
||||
|
||||
function insertRaw(key: string, value: string | null): void {
|
||||
testDb.prepare('INSERT INTO app_settings (key, value) VALUES (?, ?)').run(key, value);
|
||||
}
|
||||
|
||||
describe('AppSettingsRepository', () => {
|
||||
it('APPSETREPO-001: getValue reads the stored value', async () => {
|
||||
insertRaw('bag_tracking_enabled', 'true');
|
||||
expect(await appSettings.getValue('bag_tracking_enabled')).toBe('true');
|
||||
});
|
||||
|
||||
it('APPSETREPO-002: getValue returns null for an unset key', async () => {
|
||||
expect(await appSettings.getValue('does_not_exist')).toBeNull();
|
||||
});
|
||||
|
||||
it('APPSETREPO-003: getValues reads several keys into a Map, silently dropping keys with no row', async () => {
|
||||
insertRaw('collab_chat_enabled', 'false');
|
||||
insertRaw('collab_notes_enabled', 'true');
|
||||
const values = await appSettings.getValues(['collab_chat_enabled', 'collab_notes_enabled', 'collab_links_enabled']);
|
||||
expect(values).toEqual(new Map([['collab_chat_enabled', 'false'], ['collab_notes_enabled', 'true']]));
|
||||
});
|
||||
|
||||
it('APPSETREPO-004: setValue inserts a new row exactly as INSERT OR REPLACE would', async () => {
|
||||
await appSettings.setValue('bag_tracking_enabled', 'true');
|
||||
expect(rawRow('bag_tracking_enabled')).toStrictEqual({ key: 'bag_tracking_enabled', value: 'true' });
|
||||
});
|
||||
|
||||
it('APPSETREPO-005: setValue on an existing key replaces the value only — the row (key, value) is byte-identical to INSERT OR REPLACE/ON CONFLICT DO UPDATE, because app_settings has no third column for either to reset', async () => {
|
||||
insertRaw('bag_tracking_enabled', 'false');
|
||||
await appSettings.setValue('bag_tracking_enabled', 'true');
|
||||
expect(rawRow('bag_tracking_enabled')).toStrictEqual({ key: 'bag_tracking_enabled', value: 'true' });
|
||||
// Only the one row exists for that key — no duplicate/ghost row from upsert.
|
||||
expect(testDb.prepare('SELECT COUNT(*) as c FROM app_settings WHERE key = ?').get('bag_tracking_enabled')).toEqual({ c: 1 });
|
||||
});
|
||||
|
||||
it('APPSETREPO-006: deleteValue removes the row and returns the legacy DELETE-affected-row count', async () => {
|
||||
insertRaw('whitespace_migration_collision', 'true');
|
||||
expect(await appSettings.deleteValue('whitespace_migration_collision')).toBe(1);
|
||||
expect(rawRow('whitespace_migration_collision')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('APPSETREPO-007: deleteValue on a missing key is a no-op that reports 0 rows', async () => {
|
||||
expect(await appSettings.deleteValue('does_not_exist')).toBe(0);
|
||||
});
|
||||
|
||||
it('APPSETREPO-008: findByKeyPrefix matches every key sharing the prefix, in whatever order the table returns them', async () => {
|
||||
insertRaw('perm_view_days', '1');
|
||||
insertRaw('perm_edit_budget', '2');
|
||||
insertRaw('unrelated_key', '3');
|
||||
const rows = await appSettings.findByKeyPrefix('perm_');
|
||||
expect(rows.map((r) => r.key).sort()).toEqual(['perm_edit_budget', 'perm_view_days']);
|
||||
expect(rows).toEqual(expect.arrayContaining([
|
||||
{ key: 'perm_view_days', value: '1' },
|
||||
{ key: 'perm_edit_budget', value: '2' },
|
||||
]));
|
||||
});
|
||||
|
||||
it('APPSETREPO-009: findByKeyPrefix with no matches returns an empty array', async () => {
|
||||
insertRaw('unrelated_key', 'x');
|
||||
expect(await appSettings.findByKeyPrefix('perm_')).toEqual([]);
|
||||
});
|
||||
|
||||
// LIKE-escaping finding: neither the legacy `LIKE 'prefix%'` literal nor
|
||||
// `$like`'s bound parameter here escapes `%`/`_` in the prefix — a bound
|
||||
// LIKE parameter's wildcards are interpreted by SQLite exactly like a
|
||||
// literal's are, so `findByKeyPrefix` reproduces the legacy statement's
|
||||
// matches (and its same non-escaping quirk) for a prefix containing either
|
||||
// character. These tests compare the repository's result against the
|
||||
// legacy raw-SQL statement directly, not against a hand-picked expectation.
|
||||
describe('LIKE escaping — % and _ in the prefix are wildcards, not escaped, exactly as the legacy statement behaved', () => {
|
||||
function legacyPrefixMatch(prefix: string): { key: string; value: string }[] {
|
||||
return testDb.prepare('SELECT key, value FROM app_settings WHERE key LIKE ?').all(`${prefix}%`) as {
|
||||
key: string;
|
||||
value: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
it('APPSETREPO-010: an underscore in the prefix matches any single character there, like a raw LIKE pattern would', async () => {
|
||||
// 'ab_c%' as a LIKE pattern: '_' matches any one character, so both
|
||||
// 'ab_cd' (literal underscore) and 'abXcd' (any other character) match.
|
||||
insertRaw('ab_cd', '1');
|
||||
insertRaw('abXcd', '2');
|
||||
insertRaw('abcd', '3'); // one character short at that position — no match
|
||||
const rows = await appSettings.findByKeyPrefix('ab_c');
|
||||
expect(rows.map((r) => r.key).sort()).toEqual(legacyPrefixMatch('ab_c').map((r) => r.key).sort());
|
||||
expect(rows.map((r) => r.key).sort()).toEqual(['abXcd', 'ab_cd']);
|
||||
});
|
||||
|
||||
it('APPSETREPO-011: a percent sign in the prefix matches zero or more characters there, like a raw LIKE pattern would', async () => {
|
||||
// 'ab%c%' as a LIKE pattern: '%' matches zero-or-more, so both
|
||||
// 'abc' (zero characters at the % position) and 'abZZc' match.
|
||||
insertRaw('abc', '1');
|
||||
insertRaw('abZZc', '2');
|
||||
insertRaw('abd', '3'); // no 'c' after the gap — no match
|
||||
const rows = await appSettings.findByKeyPrefix('ab%c');
|
||||
expect(rows.map((r) => r.key).sort()).toEqual(legacyPrefixMatch('ab%c').map((r) => r.key).sort());
|
||||
expect(rows.map((r) => r.key).sort()).toEqual(['abZZc', 'abc']);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,56 @@
|
||||
import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest';
|
||||
import { createSnapshotTestDb } from '../../../helpers/db-mock';
|
||||
import { resetTestDb } from '../../../helpers/test-db';
|
||||
import { createTestOrm, type TestOrm } from '../../../helpers/test-orm';
|
||||
import { createUser } from '../../../helpers/factories';
|
||||
import { Users } from '../../../../src/db/entities/Users.entity';
|
||||
import type { UsersRepository } from '../../../../src/db/repositories/Users.repository';
|
||||
|
||||
const testDb = createSnapshotTestDb();
|
||||
let t: TestOrm;
|
||||
let users: UsersRepository;
|
||||
|
||||
beforeAll(async () => {
|
||||
t = await createTestOrm(testDb);
|
||||
users = t.repo(Users) as UsersRepository;
|
||||
});
|
||||
beforeEach(() => { resetTestDb(testDb); t.clear(); });
|
||||
afterAll(async () => { await t.close(); testDb.close(); });
|
||||
|
||||
describe('UsersRepository', () => {
|
||||
it('USERSREPO-001: getEmail reads the stored email, matching SELECT email FROM users WHERE id = ?', async () => {
|
||||
const { user } = createUser(testDb, { email: 'someone@example.com' });
|
||||
expect(await users.getEmail(user.id)).toBe('someone@example.com');
|
||||
const raw = testDb.prepare('SELECT email FROM users WHERE id = ?').get(user.id) as { email: string };
|
||||
expect(await users.getEmail(user.id)).toBe(raw.email);
|
||||
});
|
||||
|
||||
it('USERSREPO-002: getEmail returns null for a user id that does not exist', async () => {
|
||||
expect(await users.getEmail(999999)).toBeNull();
|
||||
});
|
||||
|
||||
it('USERSREPO-003: getApiKeyColumn reads maps_api_key, matching SELECT maps_api_key FROM users WHERE id = ?', async () => {
|
||||
const { user } = createUser(testDb);
|
||||
testDb.prepare('UPDATE users SET maps_api_key = ? WHERE id = ?').run('encrypted-maps-key', user.id);
|
||||
expect(await users.getApiKeyColumn(user.id, 'maps_api_key')).toBe('encrypted-maps-key');
|
||||
});
|
||||
|
||||
it('USERSREPO-004: getApiKeyColumn reads unsplash_api_key, not the other two columns', async () => {
|
||||
const { user } = createUser(testDb);
|
||||
testDb.prepare('UPDATE users SET maps_api_key = ?, unsplash_api_key = ?, amap_api_key = ? WHERE id = ?')
|
||||
.run('maps-value', 'unsplash-value', 'amap-value', user.id);
|
||||
expect(await users.getApiKeyColumn(user.id, 'unsplash_api_key')).toBe('unsplash-value');
|
||||
});
|
||||
|
||||
it('USERSREPO-005: getApiKeyColumn reads amap_api_key', async () => {
|
||||
const { user } = createUser(testDb);
|
||||
testDb.prepare('UPDATE users SET amap_api_key = ? WHERE id = ?').run('amap-value', user.id);
|
||||
expect(await users.getApiKeyColumn(user.id, 'amap_api_key')).toBe('amap-value');
|
||||
});
|
||||
|
||||
it('USERSREPO-006: getApiKeyColumn returns null for an unset column and for a missing user', async () => {
|
||||
const { user } = createUser(testDb);
|
||||
expect(await users.getApiKeyColumn(user.id, 'maps_api_key')).toBeNull();
|
||||
expect(await users.getApiKeyColumn(999999, 'maps_api_key')).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,92 @@
|
||||
import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest';
|
||||
import { createSnapshotTestDb } from '../../../../helpers/db-mock';
|
||||
import { resetTestDb } from '../../../../helpers/test-db';
|
||||
import { createTestOrm, type TestOrm } from '../../../../helpers/test-orm';
|
||||
import { createCategory, createTag, createUser } from '../../../../helpers/factories';
|
||||
import { Categories } from '../../../../../src/db/entities/Categories.entity';
|
||||
import { Tags } from '../../../../../src/db/entities/Tags.entity';
|
||||
import type { CategoriesRepository } from '../../../../../src/db/repositories/Categories.repository';
|
||||
import type { TagsRepository } from '../../../../../src/db/repositories/Tags.repository';
|
||||
import { findOwnedByUser, findOwnedOrGlobal, listForOwner } from '../../../../../src/db/repositories/_shared/owned-lookup';
|
||||
|
||||
const testDb = createSnapshotTestDb();
|
||||
let t: TestOrm;
|
||||
let categories: CategoriesRepository;
|
||||
let tags: TagsRepository;
|
||||
|
||||
beforeAll(async () => {
|
||||
t = await createTestOrm(testDb);
|
||||
categories = t.repo(Categories) as CategoriesRepository;
|
||||
tags = t.repo(Tags) as TagsRepository;
|
||||
});
|
||||
beforeEach(() => { resetTestDb(testDb); t.clear(); });
|
||||
afterAll(async () => { await t.close(); testDb.close(); });
|
||||
|
||||
describe('listForOwner', () => {
|
||||
it('OWNEDLOOKUP-001: lists only the owner’s rows, ordered by the given field ascending — Tags (a strictly-owned entity, user_id NOT NULL)', async () => {
|
||||
const { user: owner } = createUser(testDb);
|
||||
const { user: other } = createUser(testDb);
|
||||
createTag(testDb, owner.id, { name: 'Zebra' });
|
||||
createTag(testDb, owner.id, { name: 'Apple' });
|
||||
createTag(testDb, other.id, { name: 'Middle' });
|
||||
|
||||
const rows = await listForOwner<Tags>(tags, 'user', owner.id, 'name');
|
||||
expect(rows.map((r) => r.name)).toEqual(['Apple', 'Zebra']);
|
||||
expect(rows.every((r) => r.user_id === owner.id)).toBe(true);
|
||||
});
|
||||
|
||||
it('OWNEDLOOKUP-002: an owner with no rows gets an empty list', async () => {
|
||||
const { user: owner } = createUser(testDb);
|
||||
expect(await listForOwner<Tags>(tags, 'user', owner.id, 'name')).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findOwnedByUser', () => {
|
||||
it('OWNEDLOOKUP-003: finds a row the given user owns', async () => {
|
||||
const { user: owner } = createUser(testDb);
|
||||
const tag = createTag(testDb, owner.id, { name: 'Mine' });
|
||||
const found = await findOwnedByUser<Tags>(tags, tag.id, 'user', owner.id);
|
||||
expect(found?.id).toBe(tag.id);
|
||||
expect(found?.name).toBe('Mine');
|
||||
});
|
||||
|
||||
it('OWNEDLOOKUP-004: refuses a row owned by somebody else', async () => {
|
||||
const { user: owner } = createUser(testDb);
|
||||
const { user: stranger } = createUser(testDb);
|
||||
const tag = createTag(testDb, owner.id, { name: 'Mine' });
|
||||
expect(await findOwnedByUser<Tags>(tags, tag.id, 'user', stranger.id)).toBeNull();
|
||||
});
|
||||
|
||||
it('OWNEDLOOKUP-005: returns null for an id that does not exist', async () => {
|
||||
const { user: owner } = createUser(testDb);
|
||||
expect(await findOwnedByUser<Tags>(tags, 999999, 'user', owner.id)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('findOwnedOrGlobal', () => {
|
||||
it('OWNEDLOOKUP-006: finds a row the given user owns — Categories (a permissively-owned entity, user_id nullable)', async () => {
|
||||
const { user: owner } = createUser(testDb);
|
||||
const category = createCategory(testDb, { name: 'Mine', user_id: owner.id });
|
||||
const found = await findOwnedOrGlobal<Categories>(categories, category.id, 'user', owner.id);
|
||||
expect(found?.id).toBe(category.id);
|
||||
});
|
||||
|
||||
it('OWNEDLOOKUP-007: finds a row with no owner at all (a globally-shared row)', async () => {
|
||||
const { user: someone } = createUser(testDb);
|
||||
const global = createCategory(testDb, { name: 'Global', user_id: null });
|
||||
const found = await findOwnedOrGlobal<Categories>(categories, global.id, 'user', someone.id);
|
||||
expect(found?.id).toBe(global.id);
|
||||
});
|
||||
|
||||
it('OWNEDLOOKUP-008: refuses a row owned by somebody else — a non-null owner that is not the caller is not global', async () => {
|
||||
const { user: owner } = createUser(testDb);
|
||||
const { user: stranger } = createUser(testDb);
|
||||
const category = createCategory(testDb, { name: 'Theirs', user_id: owner.id });
|
||||
expect(await findOwnedOrGlobal<Categories>(categories, category.id, 'user', stranger.id)).toBeNull();
|
||||
});
|
||||
|
||||
it('OWNEDLOOKUP-009: returns null for an id that does not exist', async () => {
|
||||
const { user: someone } = createUser(testDb);
|
||||
expect(await findOwnedOrGlobal<Categories>(categories, 999999, 'user', someone.id)).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -42,26 +42,33 @@ import { JourneyShareService } from '../../../src/nest/journey/journey-share.ser
|
||||
import { SettingsService } from '../../../src/nest/settings/settings.service';
|
||||
import { db as dbConn } from '../../../src/db/database';
|
||||
import { createTestUnitOfWork } from '../../helpers/test-uow';
|
||||
import { createTestOrm, type TestOrm } from '../../helpers/test-orm';
|
||||
import { AppSettings } from '../../../src/db/entities/AppSettings.entity';
|
||||
import type { AppSettingsRepository } from '../../../src/db/repositories/AppSettings.repository';
|
||||
|
||||
const dbs = new DatabaseService(dbConn);
|
||||
let svc: JourneyShareService;
|
||||
let t: TestOrm;
|
||||
|
||||
beforeAll(async () => {
|
||||
createTables(testDb);
|
||||
runMigrations(testDb);
|
||||
const uow = await createTestUnitOfWork(testDb);
|
||||
t = await createTestOrm(testDb);
|
||||
svc = new JourneyShareService(
|
||||
dbs,
|
||||
new JourneyDomainService(dbs, new RealtimeService(), new TrekPhotosRepository(dbs), uow),
|
||||
new SettingsService(dbs, uow),
|
||||
new SettingsService(dbs, uow, t.repo(AppSettings) as AppSettingsRepository),
|
||||
);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
resetTestDb(testDb);
|
||||
t.clear();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
afterAll(async () => {
|
||||
await t.close();
|
||||
testDb.close();
|
||||
});
|
||||
|
||||
|
||||
@@ -45,23 +45,34 @@ import { createTables } from '../../../src/db/schema';
|
||||
import { runMigrations } from '../../../src/db/migrations';
|
||||
import { resetTestDb } from '../../helpers/test-db';
|
||||
import { createUser } from '../../helpers/factories';
|
||||
import { createTestOrm, type TestOrm } from '../../helpers/test-orm';
|
||||
import { DatabaseService } from '../../../src/nest/database/database.service';
|
||||
import { SettingsService } from '../../../src/nest/settings/settings.service';
|
||||
import { createTestUnitOfWork } from '../../helpers/test-uow';
|
||||
import { AppSettings } from '../../../src/db/entities/AppSettings.entity';
|
||||
import type { AppSettingsRepository } from '../../../src/db/repositories/AppSettings.repository';
|
||||
|
||||
let svc: SettingsService;
|
||||
let t: TestOrm;
|
||||
|
||||
beforeAll(async () => {
|
||||
createTables(testDb);
|
||||
runMigrations(testDb);
|
||||
svc = new SettingsService(new DatabaseService(testDb), await createTestUnitOfWork(testDb));
|
||||
t = await createTestOrm(testDb);
|
||||
svc = new SettingsService(
|
||||
new DatabaseService(testDb),
|
||||
await createTestUnitOfWork(testDb),
|
||||
t.repo(AppSettings) as AppSettingsRepository,
|
||||
);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
resetTestDb(testDb);
|
||||
t.clear();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
afterAll(async () => {
|
||||
await t.close();
|
||||
testDb.close();
|
||||
});
|
||||
|
||||
|
||||
@@ -61,15 +61,20 @@ import { SettingsService } from '../../../src/nest/settings/settings.service';
|
||||
import { QueryHelpersService } from '../../../src/nest/query-helpers/query-helpers.service';
|
||||
import type { User } from '../../../src/types';
|
||||
import { createTestUnitOfWork } from '../../helpers/test-uow';
|
||||
import { createTestOrm, type TestOrm } from '../../helpers/test-orm';
|
||||
import { AppSettings } from '../../../src/db/entities/AppSettings.entity';
|
||||
import type { AppSettingsRepository } from '../../../src/db/repositories/AppSettings.repository';
|
||||
|
||||
let svc: ShareService;
|
||||
let t: TestOrm;
|
||||
|
||||
beforeAll(async () => {
|
||||
createTables(testDb);
|
||||
runMigrations(testDb);
|
||||
t = await createTestOrm(testDb);
|
||||
svc = new ShareService(
|
||||
new DatabaseService(testDb),
|
||||
new SettingsService(new DatabaseService(testDb), await createTestUnitOfWork(testDb)),
|
||||
new SettingsService(new DatabaseService(testDb), await createTestUnitOfWork(testDb), t.repo(AppSettings) as AppSettingsRepository),
|
||||
permissionsStub,
|
||||
new QueryHelpersService(new DatabaseService(testDb)),
|
||||
photoCacheStub,
|
||||
@@ -79,11 +84,13 @@ beforeAll(async () => {
|
||||
|
||||
beforeEach(() => {
|
||||
resetTestDb(testDb);
|
||||
t.clear();
|
||||
checkPermission.mockReset();
|
||||
serveKey.mockReset();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
afterAll(async () => {
|
||||
await t.close();
|
||||
testDb.close();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user