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,130 @@
/**
* E2E主站 SSO JWT + 钱包 mock 异常504 / 业务拒绝)。
*/
import { test, expect, request as pwRequest } from '@playwright/test';
import {
configureWalletMock,
fetchOpenDrawNo,
mintSsoJwt,
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'}`;
test.beforeEach(async () => {
await resetWalletMock();
await setMockWalletMode('success');
});
test('SSO JWT 首次 /player/me 自动建档', async () => {
const { jwt, site_player_id } = await mintSsoJwt();
const ctx = await pwRequest.newContext({
extraHTTPHeaders: { Authorization: `Bearer ${jwt}` },
});
const me = await ctx.get('/api/v1/player/me');
expect(me.ok()).toBeTruthy();
const body = (await me.json()) as any;
expect(body.code).toBe(0);
expect(body.data.site_player_id).toBe(site_player_id);
expect(String(body.data.username)).toMatch(/^nlotto\d{6}$/);
await ctx.dispose();
});
test('主站 mock 504 → transfer-out 1002 pending_reconcile', async () => {
await resetE2EPlayer();
await configureWalletMock(MOCK_BASE);
await setMockWalletMode('504');
const session = await playerLoginViaBypass();
const ctx = await pwRequest.newContext({
extraHTTPHeaders: { Authorization: `Bearer ${session.access_token}` },
});
const r = await ctx.post('/api/v1/wallet/transfer-out', {
data: {
amount: 10_000,
currency: CURRENCY,
idempotent_key: `e2e-mock-504-${Date.now()}`,
},
});
const body = (await r.json()) as any;
expect(Number(body.code)).toBe(1002);
await ctx.dispose();
});
test('主站 mock reject → transfer-out 1009', async () => {
await resetE2EPlayer();
await configureWalletMock(MOCK_BASE);
await setMockWalletMode('reject');
const session = await playerLoginViaBypass();
const ctx = await pwRequest.newContext({
extraHTTPHeaders: { Authorization: `Bearer ${session.access_token}` },
});
const r = await ctx.post('/api/v1/wallet/transfer-out', {
data: {
amount: 10_000,
currency: CURRENCY,
idempotent_key: `e2e-mock-reject-${Date.now()}`,
},
});
const body = (await r.json()) as any;
expect(Number(body.code)).toBe(1009);
await ctx.dispose();
});
test('SSO JWT + 主站 mock 成功 → transfer-in + 下注', async () => {
test.setTimeout(120_000);
const { jwt } = await mintSsoJwt(`e2e-sso-wallet-${Date.now()}`);
await configureWalletMock(MOCK_BASE);
await setMockWalletMode('success');
const ctx = await pwRequest.newContext({
extraHTTPHeaders: { Authorization: `Bearer ${jwt}` },
});
const me = await ctx.get('/api/v1/player/me');
expect(me.ok()).toBeTruthy();
const meBody = (await me.json()) as any;
expect(meBody.code).toBe(0);
expect(meBody.data.funding_mode).toBe('wallet');
expect(meBody.data.auth_source).toBe('main_site_sso');
const bal0 = await ctx.get('/api/v1/wallet/balance');
const before = Number((await bal0.json()).data.balance);
const tin = await ctx.post('/api/v1/wallet/transfer-in', {
data: {
amount: 30_000,
currency: CURRENCY,
idempotent_key: `e2e-sso-tin-${Date.now()}`,
},
});
expect(tin.ok()).toBeTruthy();
const tinBody = (await tin.json()) as any;
expect(tinBody.code).toBe(0);
expect(Number(tinBody.data.lottery_balance_after)).toBeGreaterThan(before);
const drawNo = await fetchOpenDrawNo();
const place = await ctx.post('/api/v1/ticket/place', {
data: {
draw_id: drawNo,
currency_code: CURRENCY,
client_trace_id: `e2e-sso-bet-${Date.now()}`,
lines: [{ number: '1234', play_code: 'straight', amount: 5_000 }],
},
});
expect(place.ok()).toBeTruthy();
const placeBody = (await place.json()) as any;
expect(placeBody.code).toBe(0);
await ctx.dispose();
});