119 lines
3.7 KiB
TypeScript
119 lines
3.7 KiB
TypeScript
|
|
/**
|
||
|
|
* Integration test: berth maintenance-log service (add / get / update / delete).
|
||
|
|
*
|
||
|
|
* The schema + add/get already existed; this covers the new update + delete
|
||
|
|
* paths and the tenant guard (an entry can only be reached through its own
|
||
|
|
* berth + port). Runs against the real test DB.
|
||
|
|
*/
|
||
|
|
|
||
|
|
import { beforeAll, describe, expect, it } from 'vitest';
|
||
|
|
|
||
|
|
import { db } from '@/lib/db';
|
||
|
|
import { berthMaintenanceLog } from '@/lib/db/schema/berths';
|
||
|
|
import { eq } from 'drizzle-orm';
|
||
|
|
|
||
|
|
let svc: typeof import('@/lib/services/berths.service');
|
||
|
|
let makePort: typeof import('../helpers/factories').makePort;
|
||
|
|
let makeBerth: typeof import('../helpers/factories').makeBerth;
|
||
|
|
let makeAuditMeta: typeof import('../helpers/factories').makeAuditMeta;
|
||
|
|
|
||
|
|
beforeAll(async () => {
|
||
|
|
svc = await import('@/lib/services/berths.service');
|
||
|
|
const f = await import('../helpers/factories');
|
||
|
|
makePort = f.makePort;
|
||
|
|
makeBerth = f.makeBerth;
|
||
|
|
makeAuditMeta = f.makeAuditMeta;
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('berth maintenance log', () => {
|
||
|
|
async function setup() {
|
||
|
|
const port = await makePort();
|
||
|
|
const berth = await makeBerth({ portId: port.id });
|
||
|
|
const meta = makeAuditMeta({ portId: port.id });
|
||
|
|
return { port, berth, meta };
|
||
|
|
}
|
||
|
|
|
||
|
|
it('adds, lists (newest first), updates, and deletes an entry', async () => {
|
||
|
|
const { port, berth, meta } = await setup();
|
||
|
|
|
||
|
|
const created = await svc.addMaintenanceLog(
|
||
|
|
berth.id,
|
||
|
|
port.id,
|
||
|
|
{
|
||
|
|
category: 'repair',
|
||
|
|
description: 'Replaced cleat bolt',
|
||
|
|
cost: 120.5,
|
||
|
|
costCurrency: 'EUR',
|
||
|
|
responsibleParty: 'Dockside Ltd',
|
||
|
|
performedDate: '2026-05-10',
|
||
|
|
},
|
||
|
|
meta,
|
||
|
|
);
|
||
|
|
expect(created.category).toBe('repair');
|
||
|
|
expect(created.cost).toBe('120.5');
|
||
|
|
|
||
|
|
// A second, more recent entry to assert ordering.
|
||
|
|
await svc.addMaintenanceLog(
|
||
|
|
berth.id,
|
||
|
|
port.id,
|
||
|
|
{ category: 'inspection', description: 'Annual check', performedDate: '2026-05-20' },
|
||
|
|
meta,
|
||
|
|
);
|
||
|
|
|
||
|
|
const list = await svc.getMaintenanceLogs(berth.id, port.id);
|
||
|
|
expect(list).toHaveLength(2);
|
||
|
|
// Newest performedDate first.
|
||
|
|
expect(list[0]!.performedDate).toBe('2026-05-20');
|
||
|
|
expect(list[1]!.performedDate).toBe('2026-05-10');
|
||
|
|
|
||
|
|
const updated = await svc.updateMaintenanceLog(
|
||
|
|
berth.id,
|
||
|
|
created.id,
|
||
|
|
port.id,
|
||
|
|
{ description: 'Replaced cleat bolt + washer', cost: null },
|
||
|
|
meta,
|
||
|
|
);
|
||
|
|
expect(updated.description).toBe('Replaced cleat bolt + washer');
|
||
|
|
// cost cleared to null
|
||
|
|
expect(updated.cost).toBeNull();
|
||
|
|
|
||
|
|
await svc.deleteMaintenanceLog(berth.id, created.id, port.id, meta);
|
||
|
|
const afterDelete = await db
|
||
|
|
.select()
|
||
|
|
.from(berthMaintenanceLog)
|
||
|
|
.where(eq(berthMaintenanceLog.id, created.id));
|
||
|
|
expect(afterDelete).toHaveLength(0);
|
||
|
|
|
||
|
|
const remaining = await svc.getMaintenanceLogs(berth.id, port.id);
|
||
|
|
expect(remaining).toHaveLength(1);
|
||
|
|
expect(remaining[0]!.category).toBe('inspection');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('refuses to update or delete an entry through a different port (tenant guard)', async () => {
|
||
|
|
const { port, berth, meta } = await setup();
|
||
|
|
const otherPort = await makePort();
|
||
|
|
|
||
|
|
const entry = await svc.addMaintenanceLog(
|
||
|
|
berth.id,
|
||
|
|
port.id,
|
||
|
|
{ category: 'routine', description: 'Pressure wash', performedDate: '2026-05-15' },
|
||
|
|
meta,
|
||
|
|
);
|
||
|
|
|
||
|
|
await expect(
|
||
|
|
svc.updateMaintenanceLog(berth.id, entry.id, otherPort.id, { description: 'hijack' }, meta),
|
||
|
|
).rejects.toThrow();
|
||
|
|
|
||
|
|
await expect(
|
||
|
|
svc.deleteMaintenanceLog(berth.id, entry.id, otherPort.id, meta),
|
||
|
|
).rejects.toThrow();
|
||
|
|
|
||
|
|
// Untouched.
|
||
|
|
const [row] = await db
|
||
|
|
.select()
|
||
|
|
.from(berthMaintenanceLog)
|
||
|
|
.where(eq(berthMaintenanceLog.id, entry.id));
|
||
|
|
expect(row!.description).toBe('Pressure wash');
|
||
|
|
});
|
||
|
|
});
|