/** * 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(); });