Files
goodgo-platform/e2e/api/payments.spec.ts
Ho Ngoc Hai da10ac64c6 test(e2e): update all E2E specs for latest API and fixtures
Update 17 E2E test files including admin, auth, inquiries, listings,
payments, search, subscriptions, and MCP specs. Update listings fixture
and global setup to align with latest schema changes.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-11 01:40:45 +07:00

152 lines
4.8 KiB
TypeScript

import { test, expect, registerUser } from '../fixtures';
test.describe('Payments API', () => {
let accessToken: string;
test.beforeAll(async ({ request }) => {
const { accessToken: token } = await registerUser(request);
accessToken = token;
});
test.describe('POST /payments — Create payment', () => {
test('creates a VNPay payment and returns payment URL', async ({ request }) => {
const res = await request.post('payments', {
data: {
provider: 'VNPAY',
type: 'LISTING_FEE',
amountVND: '500000',
description: 'E2E test listing fee payment',
returnUrl: 'https://example.com/payments/callback',
},
headers: { Authorization: `Bearer ${accessToken}` },
});
// Payment creation may fail if VNPay not configured — accept 201 or 502/503
if (res.status() >= 500) {
test.skip(true, 'Payment gateway not configured in test env');
return;
}
expect(res.status()).toBe(201);
const body = await res.json();
expect(body).toHaveProperty('paymentId');
expect(body).toHaveProperty('paymentUrl');
});
test('rejects payment with missing required fields', async ({ request }) => {
const res = await request.post('payments', {
data: { provider: 'VNPAY' },
headers: { Authorization: `Bearer ${accessToken}` },
});
expect(res.ok()).toBeFalsy();
expect(res.status()).toBe(400);
});
test('rejects payment with invalid provider', async ({ request }) => {
const res = await request.post('payments', {
data: {
provider: 'INVALID_PROVIDER',
type: 'LISTING_FEE',
amountVND: '500000',
description: 'Invalid provider test',
returnUrl: 'https://example.com/callback',
},
headers: { Authorization: `Bearer ${accessToken}` },
});
expect(res.ok()).toBeFalsy();
expect(res.status()).toBe(400);
});
test('rejects payment with invalid type', async ({ request }) => {
const res = await request.post('payments', {
data: {
provider: 'VNPAY',
type: 'INVALID_TYPE',
amountVND: '500000',
description: 'Invalid type test',
returnUrl: 'https://example.com/callback',
},
headers: { Authorization: `Bearer ${accessToken}` },
});
expect(res.ok()).toBeFalsy();
expect(res.status()).toBe(400);
});
test('rejects unauthenticated payment creation', async ({ request }) => {
const res = await request.post('payments', {
data: {
provider: 'VNPAY',
type: 'LISTING_FEE',
amountVND: '500000',
description: 'Unauth test',
returnUrl: 'https://example.com/callback',
},
});
expect(res.status()).toBe(401);
});
});
test.describe('GET /payments — List transactions', () => {
test('returns paginated transaction list for authenticated user', async ({ request }) => {
const res = await request.get('payments', {
headers: { Authorization: `Bearer ${accessToken}` },
});
expect(res.status()).toBe(200);
const body = await res.json();
expect(body).toHaveProperty('items');
expect(Array.isArray(body.items)).toBeTruthy();
});
test('supports pagination params', async ({ request }) => {
const res = await request.get('payments', {
params: { limit: 5, offset: 0 },
headers: { Authorization: `Bearer ${accessToken}` },
});
expect(res.status()).toBe(200);
const body = await res.json();
expect(body.items.length).toBeLessThanOrEqual(5);
});
test('rejects unauthenticated transaction list', async ({ request }) => {
const res = await request.get('payments');
expect(res.status()).toBe(401);
});
});
test.describe('GET /payments/:id — Get payment status', () => {
test('returns 401 for unauthenticated request', async ({ request }) => {
const res = await request.get('payments/some-payment-id');
expect(res.status()).toBe(401);
});
test('returns 404 for non-existent payment', async ({ request }) => {
const res = await request.get('payments/non-existent-payment-id', {
headers: { Authorization: `Bearer ${accessToken}` },
});
expect(res.ok()).toBeFalsy();
expect([404, 400]).toContain(res.status());
});
});
test.describe('POST /payments/:id/refund — Refund (admin only)', () => {
test('rejects refund from non-admin user', async ({ request }) => {
const res = await request.post('payments/some-id/refund', {
data: { reason: 'Test refund from non-admin' },
headers: { Authorization: `Bearer ${accessToken}` },
});
expect(res.ok()).toBeFalsy();
expect([401, 403]).toContain(res.status());
});
});
});