mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
41 lines
1.7 KiB
TypeScript
41 lines
1.7 KiB
TypeScript
import { test, expect } from "@playwright/test";
|
|
import { PrismaClient } from "@prisma/client";
|
|
import { bookOneAdult } from "../../fixtures/booking-flow";
|
|
|
|
const prisma = new PrismaClient();
|
|
test.afterAll(async () => {
|
|
await prisma.$disconnect();
|
|
});
|
|
|
|
/**
|
|
* UA-13 ✅ — client-forged booking total (matrix A1 / ISSUES C-1), guarded through the REAL browser.
|
|
* We intercept the outgoing POST /bookings and rewrite reviewedTotalMinor (and every per-seat
|
|
* seatFareMinor) to 1. The server has two trust branches — sum-of-seatFareMinor when all are present,
|
|
* else reviewedTotalMinor — so the forge targets both. The server must recompute the authoritative
|
|
* fare and REJECT the mismatched client amount with a 4xx, persisting nothing.
|
|
*/
|
|
test("UA-13: server rejects a client-forged reviewedTotalMinor=1 (C-1)", async ({ page }) => {
|
|
const r = await bookOneAdult(page, {
|
|
nationality: "Ethiopian",
|
|
paymentMethod: "WALLET",
|
|
tolerateBookingError: true,
|
|
// Forge both the per-seat fares and the reviewed total → 1.
|
|
mutateBookingBody: (body) => ({
|
|
...body,
|
|
reviewedTotalMinor: 1,
|
|
passengers: (body.passengers ?? []).map((p: any) => ({ ...p, seatFareMinor: 1 })),
|
|
}),
|
|
});
|
|
|
|
// The real fare the engine computed is far above 1…
|
|
expect(r.cardFareMinor).toBeGreaterThan(1000);
|
|
// …the browser forced reviewedTotalMinor=1, and the server must REFUSE it with a 4xx.
|
|
expect(r.reviewedTotalMinor).toBe(1);
|
|
expect(r.bookingStatus).toBeGreaterThanOrEqual(400);
|
|
expect(r.bookingStatus).toBeLessThan(500);
|
|
// No booking id was returned, and no 1-minor booking was persisted.
|
|
expect(r.bookingId).toBeFalsy();
|
|
const forged = await prisma.booking.findFirst({ where: { totalMinor: 1 } });
|
|
expect(forged).toBeNull();
|
|
});
|