Some checks failed
lotterLaravel CI / test (push) Has been cancelled
添加LOTTERY_E2E环境变量来控制E2E测试相关功能, 包括绕过验证码、登录限制和钱包API URL验证, 同时更新composer.json以包含E2E专用的提供者和服务。
86 lines
2.6 KiB
TypeScript
86 lines
2.6 KiB
TypeScript
/**
|
||
* E2E:主站超时 pending_reconcile → 后台 reconcile-jobs 扫描检出。
|
||
*/
|
||
|
||
import { test, expect } from '@playwright/test';
|
||
import {
|
||
adminLoginViaBypass,
|
||
adminCtxOf,
|
||
configureWalletMock,
|
||
playerCtxOf,
|
||
playerLoginViaBypass,
|
||
resetE2EPlayer,
|
||
resetWalletMock,
|
||
setMockWalletMode,
|
||
} from './_helper';
|
||
|
||
const CURRENCY = (process.env.LOTTERY_DEFAULT_CURRENCY ?? 'NPR').toUpperCase();
|
||
const MOCK_BASE = `http://127.0.0.1:${process.env.E2E_MOCK_WALLET_PORT ?? '5555'}`;
|
||
|
||
function isoDateOffset(days: number): string {
|
||
const d = new Date();
|
||
d.setDate(d.getDate() + days);
|
||
return d.toISOString().slice(0, 10);
|
||
}
|
||
|
||
test.beforeEach(async () => {
|
||
await resetWalletMock();
|
||
await setMockWalletMode('success');
|
||
});
|
||
|
||
test('transfer-out 504 pending_reconcile → reconcile-jobs 扫描到差异项', async () => {
|
||
test.setTimeout(120_000);
|
||
|
||
await resetE2EPlayer();
|
||
await configureWalletMock(MOCK_BASE);
|
||
await setMockWalletMode('504');
|
||
|
||
const session = await playerLoginViaBypass();
|
||
const playerId = session.player.id;
|
||
const idemKey = `e2e-reconcile-${Date.now()}`;
|
||
|
||
const player = await playerCtxOf(session.access_token);
|
||
const tout = await player.post('/api/v1/wallet/transfer-out', {
|
||
data: {
|
||
amount: 10_000,
|
||
currency: CURRENCY,
|
||
idempotent_key: idemKey,
|
||
},
|
||
});
|
||
const toutBody = (await tout.json()) as any;
|
||
expect(Number(toutBody.code)).toBe(1002);
|
||
await player.dispose();
|
||
|
||
const adminSession = await adminLoginViaBypass();
|
||
const admin = await adminCtxOf(adminSession.accessToken);
|
||
|
||
const scan = await admin.post('/api/v1/admin/reconcile-jobs', {
|
||
data: {
|
||
reconcile_type: 'wallet_transfer',
|
||
date_from: isoDateOffset(-1),
|
||
date_to: isoDateOffset(0),
|
||
player_id: playerId,
|
||
},
|
||
});
|
||
expect(scan.ok(), `reconcile-jobs create status=${scan.status()}`).toBeTruthy();
|
||
const scanBody = (await scan.json()) as any;
|
||
expect(scanBody.code).toBe(0);
|
||
expect(Number(scanBody.data.item_count)).toBeGreaterThanOrEqual(1);
|
||
|
||
const jobId = scanBody.data.id;
|
||
const items = await admin.get(`/api/v1/admin/reconcile-jobs/${jobId}/items?size=20`);
|
||
expect(items.ok()).toBeTruthy();
|
||
const itemsBody = (await items.json()) as any;
|
||
expect(itemsBody.code).toBe(0);
|
||
expect(itemsBody.data.items.length).toBeGreaterThanOrEqual(1);
|
||
|
||
const hit = itemsBody.data.items.find(
|
||
(it: any) =>
|
||
String(it.side_a_ref ?? '').startsWith('TO_') ||
|
||
String(it.side_b_ref ?? '').startsWith('TO_'),
|
||
);
|
||
expect(hit, '扫描结果应包含 pending_reconcile 转账单引用').toBeTruthy();
|
||
|
||
await admin.dispose();
|
||
});
|