feat: 添加E2E测试环境配置支持
Some checks failed
lotterLaravel CI / test (push) Has been cancelled

添加LOTTERY_E2E环境变量来控制E2E测试相关功能,
包括绕过验证码、登录限制和钱包API URL验证,
同时更新composer.json以包含E2E专用的提供者和服务。
This commit is contained in:
2026-06-18 14:42:22 +08:00
parent 6b2ea39ea1
commit 6ec9634704
45 changed files with 3702 additions and 6 deletions

View File

@@ -0,0 +1,85 @@
/**
* 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();
});