Files
edr-platform/apps/edr-passenger-api/src/modules/payments/payments.e2e-spec.ts

195 lines
5.5 KiB
TypeScript

import { Test, TestingModule } from "@nestjs/testing";
import { INestApplication, ValidationPipe } from "@nestjs/common";
import request from "supertest";
import { AppModule } from "../../app.module";
import { PrismaService } from "../../common/prisma.service";
describe("Payments E2E", () => {
let app: INestApplication;
let prisma: PrismaService;
let authToken: string;
let bookingId: string;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
app.useGlobalPipes(
new ValidationPipe({ transform: true, whitelist: true }),
);
await app.init();
prisma = app.get<PrismaService>(PrismaService);
const passenger = await prisma.passenger.create({ data: { iamUserId: 'test-iam-payments-user' } });
await prisma.walletAccount.create({
data: {
passengerId: passenger.id,
balanceMinor: 100000,
currency: "ETB",
},
});
authToken = "mock-jwt-token";
const station1 = await prisma.station.create({
data: {
code: "TST1",
name: "Test Station 1",
city: "Test City",
lat: 9.0,
lng: 38.0,
},
});
const station2 = await prisma.station.create({
data: {
code: "TST2",
name: "Test Station 2",
city: "Test City 2",
lat: 9.5,
lng: 38.5,
},
});
const train = await prisma.train.create({
data: { number: "TEST-001", name: "Test Train" },
});
const schedule = await prisma.trainSchedule.create({
data: {
trainId: train.id,
originStationId: station1.id,
destinationStationId: station2.id,
departureAt: new Date(Date.now() + 86400000),
arrivalAt: new Date(Date.now() + 90000000),
durationMinutes: 60,
},
});
const coachType = await prisma.coachType.create({
data: { name: "Standard", code: "STD" },
});
const seatClass = await prisma.seatClass.create({
data: {
name: "Economy Regular",
description: "Standard economy seating",
baseFareMinor: 45000,
isActive: true,
coachTypeId: coachType.id,
},
});
const coach = await prisma.coach.create({
data: {
coachTypeId: coachType.id,
number: "TEST-C1",
arrangement: "2+2",
capacity: 10,
status: "ACTIVE",
},
});
const seat = await prisma.seat.create({
data: {
coachId: coach.id,
row: 1,
col: "A",
seatNumber: "1A",
status: "AVAILABLE",
},
});
const booking = await prisma.booking.create({
data: {
bookingRef: "TEST-BOOK-001",
passengerId: passenger.id,
scheduleId: schedule.id,
status: "PENDING_PAYMENT",
totalMinor: 50000,
currency: "ETB",
},
});
await prisma.bookingSeat.create({
data: {
bookingId: booking.id,
seatId: seat.id,
scheduleId: schedule.id,
passengerName: "Test Passenger",
},
});
bookingId = booking.id;
});
afterAll(async () => {
await prisma.$transaction([
prisma.bookingSeat.deleteMany(),
prisma.paymentIntent.deleteMany(),
prisma.booking.deleteMany(),
prisma.coachAssignment.deleteMany(),
prisma.seat.deleteMany(),
prisma.coach.deleteMany(),
prisma.trainSchedule.deleteMany(),
prisma.train.deleteMany(),
prisma.station.deleteMany({ where: { code: { in: ["TST1", "TST2"] } } }),
prisma.walletLedgerEntry.deleteMany(),
prisma.walletAccount.deleteMany(),
prisma.passenger.deleteMany(),
]);
await app.close();
});
describe("POST /payments/initiate", () => {
it("should initiate wallet payment successfully", async () => {
const response = await request(app.getHttpServer())
.post("/payments/initiate")
.set("Authorization", `Bearer ${authToken}`)
.send({ bookingId, method: "WALLET" })
.expect(201);
expect(response.body.intentId).toBeDefined();
expect(response.body.status).toBe("SUCCEEDED");
});
it("should return 400 for invalid payment method", async () => {
await request(app.getHttpServer())
.post("/payments/initiate")
.set("Authorization", `Bearer ${authToken}`)
.send({ bookingId, method: "INVALID_METHOD" })
.expect(400);
});
it("should return 404 for non-existent booking", async () => {
await request(app.getHttpServer())
.post("/payments/initiate")
.set("Authorization", `Bearer ${authToken}`)
.send({ bookingId: "non-existent-id", method: "WALLET" })
.expect(404);
});
});
describe("GET /payments/intents/:bookingId", () => {
it("should get payment intent status", async () => {
const response = await request(app.getHttpServer())
.get(`/payments/intents/${bookingId}`)
.set("Authorization", `Bearer ${authToken}`)
.expect(200);
expect(response.body.intentId).toBeDefined();
expect(response.body.status).toBeDefined();
});
it("should return 404 for non-existent intent", async () => {
await request(app.getHttpServer())
.get("/payments/intents/non-existent-booking")
.set("Authorization", `Bearer ${authToken}`)
.expect(404);
});
});
// Provider webhooks moved to the payment microservice (apps/edr-payment-api /webhooks/*).
});