From 62950aed241f359a97f461a73dc58e7af162f00d Mon Sep 17 00:00:00 2001 From: Maurice Date: Thu, 1 Oct 2026 15:18:30 +0200 Subject: [PATCH] test(e2e): hand-made schemas follow the new columns; placing entries never blocks the refresh --- server/src/nest/journey/journey-photo-capture.service.ts | 9 ++++++++- server/tests/e2e/journey.e2e.test.ts | 9 ++++----- server/tests/e2e/packing.e2e.test.ts | 5 ++++- server/tests/e2e/places.e2e.test.ts | 2 +- server/tests/e2e/transit-provider.e2e.test.ts | 1 + .../unit/nest/journey-photo-capture.service.test.ts | 9 +++++++++ 6 files changed, 27 insertions(+), 8 deletions(-) diff --git a/server/src/nest/journey/journey-photo-capture.service.ts b/server/src/nest/journey/journey-photo-capture.service.ts index 16db9ef75..326af2f51 100644 --- a/server/src/nest/journey/journey-photo-capture.service.ts +++ b/server/src/nest/journey/journey-photo-capture.service.ts @@ -75,7 +75,14 @@ export class JourneyPhotoCaptureService { * which the owner can still name by hand. */ async placeEntries(trekPhotoIds: number[]): Promise { - const placed = this.journey.placeEntriesFromPhotos(trekPhotoIds); + let placed: ReturnType; + try { + placed = this.journey.placeEntriesFromPhotos(trekPhotoIds); + } catch (err) { + // An extra on top of the capture times: it must never cost the refresh below it. + console.error('[Journey] placing entries from photos failed:', err instanceof Error ? err.message : err); + return 0; + } if (!placed.length) return 0; await Promise.all(placed.map(async (p) => { try { diff --git a/server/tests/e2e/journey.e2e.test.ts b/server/tests/e2e/journey.e2e.test.ts index cf060cb7a..f1a5f2e54 100644 --- a/server/tests/e2e/journey.e2e.test.ts +++ b/server/tests/e2e/journey.e2e.test.ts @@ -486,12 +486,11 @@ describe('Journey e2e (real auth guard + temp SQLite)', () => { try { expect(res.status).toBe(201); expect(res.body.photos).toHaveLength(1); - // The plain backfill, the same one the provider adds run... - expect(backfillSchedule).toHaveBeenCalledWith([90], 1); - // ...but not the refreshing run behind it: a bulk upload would otherwise - // reload every open client once per photo. + // The capture backfill runs for the upload (and may place its entry, #1003)... await new Promise(resolve => setTimeout(resolve, 10)); - expect(backfillRun).not.toHaveBeenCalled(); + expect(backfillRun).toHaveBeenCalledWith([90], 1); + // ...but no journey refresh follows: a bulk upload would otherwise reload + // every open client once per photo. expect(jsvc.broadcastJourneyEvent).not.toHaveBeenCalled(); } finally { const storage = app.get(StorageService); diff --git a/server/tests/e2e/packing.e2e.test.ts b/server/tests/e2e/packing.e2e.test.ts index 41aed38bc..56263ec65 100644 --- a/server/tests/e2e/packing.e2e.test.ts +++ b/server/tests/e2e/packing.e2e.test.ts @@ -90,7 +90,10 @@ const { db } = vi.hoisted(() => { id INTEGER PRIMARY KEY AUTOINCREMENT, category_id INTEGER NOT NULL, name TEXT NOT NULL, - sort_order INTEGER NOT NULL DEFAULT 0 + sort_order INTEGER NOT NULL DEFAULT 0, + weight_grams INTEGER, + quantity INTEGER NOT NULL DEFAULT 1, + bag_name TEXT );`); // StorageRegistryService (behind StorageModule, now in this module chain) reads // this at onModuleInit. diff --git a/server/tests/e2e/places.e2e.test.ts b/server/tests/e2e/places.e2e.test.ts index 2a5db8d46..7dfad93d9 100644 --- a/server/tests/e2e/places.e2e.test.ts +++ b/server/tests/e2e/places.e2e.test.ts @@ -28,7 +28,7 @@ const { db } = vi.hoisted(() => { description TEXT, lat REAL, lng REAL, address TEXT, category_id INTEGER, price REAL, currency TEXT, place_time TEXT, end_time TEXT, duration_minutes INTEGER, notes TEXT, image_url TEXT, google_place_id TEXT, google_ftid TEXT, osm_id TEXT, amap_poi_id TEXT, website TEXT, phone TEXT, transport_mode TEXT, - route_geometry TEXT, route_color TEXT, stop_type TEXT, fill_percent INTEGER, + route_geometry TEXT, route_color TEXT, stop_type TEXT, fill_percent INTEGER, email TEXT, opening_hours TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP);`); tmp.exec(`CREATE TABLE categories (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, color TEXT, icon TEXT);`); tmp.exec(`CREATE TABLE tags (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, color TEXT, diff --git a/server/tests/e2e/transit-provider.e2e.test.ts b/server/tests/e2e/transit-provider.e2e.test.ts index 3827680e9..ab2d45046 100644 --- a/server/tests/e2e/transit-provider.e2e.test.ts +++ b/server/tests/e2e/transit-provider.e2e.test.ts @@ -23,6 +23,7 @@ const { db } = vi.hoisted(() => { email TEXT NOT NULL UNIQUE, role TEXT NOT NULL DEFAULT 'user', password_version INTEGER NOT NULL DEFAULT 0, maps_api_key TEXT, unsplash_api_key TEXT);`); tmp.exec('CREATE TABLE app_settings (key TEXT PRIMARY KEY, value TEXT);'); + tmp.exec('CREATE TABLE google_api_usage (day TEXT PRIMARY KEY, calls INTEGER NOT NULL DEFAULT 0);'); return { db: tmp }; }); vi.mock('../../src/db/database', () => ({ db, closeDb: () => {}, reinitialize: () => {} })); diff --git a/server/tests/unit/nest/journey-photo-capture.service.test.ts b/server/tests/unit/nest/journey-photo-capture.service.test.ts index cacd3385b..211214039 100644 --- a/server/tests/unit/nest/journey-photo-capture.service.test.ts +++ b/server/tests/unit/nest/journey-photo-capture.service.test.ts @@ -156,6 +156,15 @@ describe('JourneyPhotoCaptureService', () => { expect(nameEntryLocation).toHaveBeenCalledWith(7, 'Somewhere Road'); }); + it('JPCAP-1003d: placing entries that throws never costs the refresh of the gallery order', async () => { + const { svc, placeEntriesFromPhotos, broadcastJourneyEvent } = build(true); + placeEntriesFromPhotos.mockImplementation(() => { throw new Error('no such column'); }); + const error = vi.spyOn(console, 'error').mockImplementation(() => {}); + await expect(svc.fill(9, [11], 3)).resolves.toBe(true); + expect(broadcastJourneyEvent).toHaveBeenCalledWith(9, 'journey:photos:updated', {}); + expect(error).toHaveBeenCalledWith('[Journey] placing entries from photos failed:', 'no such column'); + }); + it('JPCAP-1003c: an upload whose backfill throws is logged', async () => { const { svc } = build(new Error('disk')); const error = vi.spyOn(console, 'error').mockImplementation(() => {});