import { expect, test, type Page } from './fixtures'; // The Wallet section against the mock transport (no backend). The mock seeds a web/native (direct) // account holding a direct (120) + vk (400) chip segment and a small catalog (two chip-priced values // and one rouble-priced chip pack — see lib/mock/client.ts), so the compact balance, the split // storefront, the exchange-confirm dialog (with its store-compliance warning) and the Google Play // stub are all exercisable without a backend. async function loginLobby(page: Page): Promise { await page.goto('/'); await page.getByRole('button', { name: /guest/i }).click(); await expect(page.getByText('Your turn')).toBeVisible(); } async function openSettings(page: Page): Promise { await page.getByRole('button', { name: /Settings/ }).click(); // lobby ⚙️ tab await expect(page.locator('.pane')).toHaveCount(1); // let the slide settle } async function openWallet(page: Page): Promise { await openSettings(page); await page.getByRole('button', { name: 'Wallet', exact: true }).click(); await expect(page.getByTestId('wallet')).toBeVisible(); } test('wallet: balance, active benefits and the split storefront render for a durable account', async ({ page }) => { await loginLobby(page); await openWallet(page); // The compact balance leads with the context's own (direct/"Web") chips, then the linked vk // segment behind its logo. const balance = page.getByTestId('balance'); await expect(balance).toContainText('120'); await expect(balance).toContainText('400'); await expect(balance.locator('.plogo')).toHaveCount(1); // the one linked (vk) platform // The active benefits (the seeded 5 hints) sit above the store. await expect(page.getByRole('heading', { name: 'Active' })).toBeVisible(); await expect(page.getByTestId('active')).toContainText('Hints: 5'); await expect(page.getByRole('heading', { name: 'Store' })).toBeVisible(); // Default tab — Buy chips: one rouble-priced pack + the public offer, and no values. await expect(page.locator('[data-kind="pack"]')).toHaveCount(1); await expect(page.locator('[data-kind="pack"]')).toContainText('₽'); await expect(page.locator('[data-kind="pack"]').getByTestId('buy-pack')).toBeEnabled(); await expect(page.getByTestId('offer')).toContainText('Public offer'); await expect(page.locator('[data-kind="value"]')).toHaveCount(0); // Spend chips tab: the two chip-priced values, exchanged (not bought) with the "Exchange" button. await page.getByTestId('tab-spend').click(); await expect(page.locator('[data-kind="value"]')).toHaveCount(2); await expect(page.locator('[data-kind="value"]').first().getByTestId('buy')).toHaveText('Exchange'); }); test('wallet: buying a chip pack opens the provider payment page', async ({ page }) => { await loginLobby(page); await openWallet(page); // The purchase opens the provider's hosted-payment page in a new tab (window.open); capture it. await page.evaluate(() => { (window as { __opened?: string }).__opened = ''; window.open = ((u: string) => { (window as { __opened?: string }).__opened = u; return null; }) as typeof window.open; }); await page.locator('[data-kind="pack"]').getByTestId('buy-pack').click(); await expect .poll(() => page.evaluate(() => (window as { __opened?: string }).__opened)) .toContain('robokassa'); }); test('wallet: the tab sits between Friends and About', async ({ page }) => { await loginLobby(page); await openSettings(page); const labels = await page.locator('.tab .lbl').allInnerTexts(); const iFriends = labels.indexOf('Friends'); const iWallet = labels.indexOf('Wallet'); const iAbout = labels.indexOf('Info'); expect(iFriends).toBeGreaterThanOrEqual(0); expect(iWallet).toBe(iFriends + 1); expect(iAbout).toBe(iWallet + 1); }); test('wallet: a guest has no wallet (nor friends) tab', async ({ page }) => { await page.goto('/?guest'); await page.getByRole('button', { name: /guest/i }).click(); await expect(page.getByText('Your turn')).toBeVisible(); await openSettings(page); await expect(page.getByRole('button', { name: 'Wallet', exact: true })).toBeHidden(); await expect(page.getByRole('button', { name: 'Friends', exact: true })).toBeHidden(); }); test('wallet: the Google Play build hides the money purchases behind the RuStore stub', async ({ page }) => { await page.goto('/?gp'); await page.getByRole('button', { name: /guest/i }).click(); await expect(page.getByText('Your turn')).toBeVisible(); await openWallet(page); // Buy chips: the chip pack is gone; the stub points at the RuStore build. await expect(page.getByTestId('gp-stub')).toBeVisible(); await expect(page.locator('[data-kind="pack"]')).toHaveCount(0); // Spending earned chips still works — the values live in the Spend tab. await page.getByTestId('tab-spend').click(); await expect(page.locator('[data-kind="value"]').first().getByTestId('buy')).toBeVisible(); }); test('wallet: a web spend that would draw store chips confirms with a warning, then completes', async ({ page }) => { await loginLobby(page); await openWallet(page); await page.getByTestId('tab-spend').click(); // The 300-chip value drains direct (120) then reaches into vk (180) → a store segment → the confirm // dialog carries the cross-platform warning. await page.locator('[data-pid="val-noads-30"]').getByTestId('buy').click(); await expect(page.getByTestId('warn')).toBeVisible(); await page.getByTestId('spend-confirm').click(); // The spend applied: the no-ads benefit now shows an end date in the Active section. await expect(page.getByTestId('wallet')).toContainText('No ads until'); }); test('wallet: a spend the direct segment covers alone confirms without a warning', async ({ page }) => { await loginLobby(page); await openWallet(page); await page.getByTestId('tab-spend').click(); // The 100-chip value is covered by the direct segment (120) alone → the confirm dialog shows, but // with no cross-platform warning. await page.locator('[data-pid="val-hints-50"]').getByTestId('buy').click(); await expect(page.getByTestId('spend-body')).toBeVisible(); await expect(page.getByTestId('warn')).toBeHidden(); await page.getByTestId('spend-confirm').click(); // The hints benefit rose from 5 to 55. await expect(page.getByTestId('wallet')).toContainText('Hints: 55'); });