Files
TREK/server/tests/integration/leg-mode-incoming.test.ts
T
Maurice e3982a8e2a test(server): seed the repository, MCP and e2e specs through the factories
Converts the raw prepare() fixtures and reads in the next set of specs to
the ORM factories and readers: the password reset, webauthn, dawarich,
budget, to-do and vacay repository specs, the journey, settings, addons and
share MCP specs, the plugin POI and operator egress specs, the feeds,
storage stats and query helper services, and the packing, collections,
day reorder, leg mode, upload context and trip access integration suites.

The notifications and google quota e2e suites now seed their users through
makeUser with pinned ids, and the notifications suite moves from hand-rolled
tables to the migrated snapshot. Legacy statements that serve as a parity
oracle and the raw rows the primary-relation spike holds toObject() against
stay raw, each with an allow marker naming why.
2026-10-08 18:46:47 +02:00

194 lines
8.5 KiB
TypeScript

/**
* Migration test for incoming_leg_transport_mode on day_assignments, plus
* read-path parity: the field must survive both the single-assignment
* projection and the day-LIST projection.
*/
import { describe, it, expect, vi, beforeAll, beforeEach, afterAll } from 'vitest';
import request from 'supertest';
import type { Application } from 'express';
import type { INestApplication } from '@nestjs/common';
// ─────────────────────────────────────────────────────────────────────────────
// Read-path parity (day-LIST endpoint) — mirrors the harness in
// tests/integration/assignments.test.ts verbatim.
// ─────────────────────────────────────────────────────────────────────────────
vi.mock('../../src/db/database', async () => {
const { createSnapshotTestDb, buildDbMock } = await import('../helpers/db-mock');
return buildDbMock(createSnapshotTestDb());
});
vi.mock('../../src/config', () => ({
JWT_SECRET: 'test-jwt-secret-for-trek-testing-only',
ENCRYPTION_KEY: 'a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6a7b8c9d0e1f2a3b4c5d6a7b8c9d0e1f2',
updateJwtSecret: () => {},
SESSION_DURATION: '24h',
SESSION_DURATION_MS: 86400000,
SESSION_DURATION_SECONDS: 86400,
DEFAULT_LANGUAGE: 'en',
}));
vi.mock('../../src/websocket', () => ({ broadcast: vi.fn(), broadcastToUser: vi.fn() }));
import { db as testDb2 } from '../../src/db/database';
import { MikroORM } from '@mikro-orm/core';
import { buildApp } from '../../src/bootstrap';
import { resetTestDb, resetRateLimits } from '../helpers/test-db';
import type { FactoryOrm } from '../helpers/factories/context';
import { createUser, createTrip, createDay, createPlace } from '../helpers/factories';
import { authCookie } from '../helpers/auth';
import { findRow, updateRows } from '../helpers/factories/rows';
import { DayAssignments } from '../../src/db/entities/DayAssignments.entity';
describe('incoming_leg_transport_mode read-path parity', () => {
let nestApp: INestApplication;
let app: Application;
let orm: FactoryOrm;
beforeAll(async () => {
nestApp = await buildApp();
app = nestApp.getHttpAdapter().getInstance();
orm = nestApp.get(MikroORM);
});
beforeEach(async () => {
resetTestDb(testDb2);
await resetRateLimits(nestApp);
});
afterAll(async () => {
await nestApp.close();
testDb2.close();
});
it('round-trips incoming_leg_transport_mode through the day-LIST endpoint', async () => {
const { user } = createUser(testDb2);
const trip = createTrip(testDb2, user.id);
const day = createDay(testDb2, trip.id, { date: '2025-06-01' });
const place = createPlace(testDb2, trip.id, { name: 'Test Place' });
const create = await request(app)
.post(`/api/trips/${trip.id}/days/${day.id}/assignments`)
.set('Cookie', authCookie(user.id))
.send({ place_id: place.id });
expect(create.status).toBe(201);
const assignmentId = create.body.assignment.id;
await updateRows(orm, DayAssignments, { id: assignmentId }, { incoming_leg_transport_mode: 'transit' });
const res = await request(app)
.get(`/api/trips/${trip.id}/days`)
.set('Cookie', authCookie(user.id));
expect(res.status).toBe(200);
const foundDay = res.body.days.find((d: any) => d.id === day.id);
const a = foundDay.assignments.find((x: any) => x.id === assignmentId);
expect(a.incoming_leg_transport_mode).toBe('transit');
});
// ───────────────────────────────────────────────────────────────────────────
// Write path — PUT .../transport gains `direction` (outgoing|incoming).
// ───────────────────────────────────────────────────────────────────────────
describe('PUT /assignments/:id/transport direction', () => {
it('defaults to outgoing (back-compat)', async () => {
const { user } = createUser(testDb2);
const trip = createTrip(testDb2, user.id);
const day = createDay(testDb2, trip.id, { date: '2025-06-01' });
const place = createPlace(testDb2, trip.id, { name: 'Test Place' });
const create = await request(app)
.post(`/api/trips/${trip.id}/days/${day.id}/assignments`)
.set('Cookie', authCookie(user.id))
.send({ place_id: place.id });
const assignmentId = create.body.assignment.id;
const res = await request(app)
.put(`/api/trips/${trip.id}/assignments/${assignmentId}/transport`)
.set('Cookie', authCookie(user.id))
.send({ transport_mode: 'cycling' });
expect(res.status).toBe(200);
const row = await findRow(orm, DayAssignments, { id: assignmentId });
expect(row?.leg_transport_mode).toBe('cycling');
expect(row?.incoming_leg_transport_mode).toBeNull();
});
it("direction: 'incoming' writes the incoming column", async () => {
const { user } = createUser(testDb2);
const trip = createTrip(testDb2, user.id);
const day = createDay(testDb2, trip.id, { date: '2025-06-01' });
const place = createPlace(testDb2, trip.id, { name: 'Test Place' });
const create = await request(app)
.post(`/api/trips/${trip.id}/days/${day.id}/assignments`)
.set('Cookie', authCookie(user.id))
.send({ place_id: place.id });
const assignmentId = create.body.assignment.id;
const res = await request(app)
.put(`/api/trips/${trip.id}/assignments/${assignmentId}/transport`)
.set('Cookie', authCookie(user.id))
.send({ transport_mode: 'transit', direction: 'incoming' });
expect(res.status).toBe(200);
const row = await findRow(orm, DayAssignments, { id: assignmentId });
expect(row?.incoming_leg_transport_mode).toBe('transit');
});
it('rejects an invalid direction with 400', async () => {
const { user } = createUser(testDb2);
const trip = createTrip(testDb2, user.id);
const day = createDay(testDb2, trip.id, { date: '2025-06-01' });
const place = createPlace(testDb2, trip.id, { name: 'Test Place' });
const create = await request(app)
.post(`/api/trips/${trip.id}/days/${day.id}/assignments`)
.set('Cookie', authCookie(user.id))
.send({ place_id: place.id });
const assignmentId = create.body.assignment.id;
const res = await request(app)
.put(`/api/trips/${trip.id}/assignments/${assignmentId}/transport`)
.set('Cookie', authCookie(user.id))
.send({ transport_mode: 'walking', direction: 'sideways' });
expect(res.status).toBe(400);
});
it('outgoing and incoming leg modes on one stop persist independently', async () => {
const { user } = createUser(testDb2);
const trip = createTrip(testDb2, user.id);
const day = createDay(testDb2, trip.id, { date: '2025-06-01' });
const place = createPlace(testDb2, trip.id, { name: 'Test Place' });
const create = await request(app)
.post(`/api/trips/${trip.id}/days/${day.id}/assignments`)
.set('Cookie', authCookie(user.id))
.send({ place_id: place.id });
const assignmentId = create.body.assignment.id;
await request(app)
.put(`/api/trips/${trip.id}/assignments/${assignmentId}/transport`)
.set('Cookie', authCookie(user.id))
.send({ transport_mode: 'cycling' })
.expect(200);
await request(app)
.put(`/api/trips/${trip.id}/assignments/${assignmentId}/transport`)
.set('Cookie', authCookie(user.id))
.send({ transport_mode: 'transit', direction: 'incoming' })
.expect(200);
const row = await findRow(orm, DayAssignments, { id: assignmentId });
expect(row?.leg_transport_mode).toBe('cycling');
expect(row?.incoming_leg_transport_mode).toBe('transit');
const res = await request(app)
.get(`/api/trips/${trip.id}/days`)
.set('Cookie', authCookie(user.id));
expect(res.status).toBe(200);
const foundDay = res.body.days.find((d: any) => d.id === day.id);
const a = foundDay.assignments.find((x: any) => x.id === assignmentId);
expect(a.leg_transport_mode).toBe('cycling');
expect(a.incoming_leg_transport_mode).toBe('transit');
});
});
});