Files
lotteryLaravel/e2e/tests/api/11.sso-mainsite.spec.ts
kang 6ec9634704
Some checks failed
lotterLaravel CI / test (push) Has been cancelled
feat: 添加E2E测试环境配置支持
添加LOTTERY_E2E环境变量来控制E2E测试相关功能,
包括绕过验证码、登录限制和钱包API URL验证,
同时更新composer.json以包含E2E专用的提供者和服务。
2026-06-18 14:42:22 +08:00

131 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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();
});