import { test, expect } from '@playwright/test'; import { ensureUser, hsReachable, loginUI, uniq } from './localHs'; // [Gitea #201 KE-1] When the server keeps rejecting this device's key uploads // with "One time key … already exists", the app says so and offers the fix. const CONFLICT = { errcode: 'M_UNKNOWN', error: 'One time key signed_curve25519:AAAAAAAAAA0 already exists. Old key: {}; new key: {}', }; test.describe('key upload recovery (#201)', () => { test.beforeAll(async () => { test.skip(!(await hsReachable()), 'local homeserver not running'); }); test('a diverged device sees the banner, and Fix opens the logout dialog', async ({ page }) => { test.setTimeout(240_000); const user = await ensureUser(uniq('kup')); let rejected = 0; await page.route(/\/_matrix\/client\/v3\/keys\/upload/, async (route) => { rejected += 1; await route.fulfill({ status: 400, json: CONFLICT }); }); await loginUI(page, user); const banner = page .getByRole('alert') .filter({ hasText: /Encryption on this device is out of sync/ }); await expect(banner).toBeVisible({ timeout: 200_000 }); console.log(`key uploads rejected: ${rejected}`); expect(rejected).toBeGreaterThanOrEqual(3); await banner.getByRole('button', { name: 'Details' }).click(); await expect(banner).toContainText('Settings → Devices'); await expect(banner).toContainText('already exists'); await banner.getByRole('button', { name: /Fix: sign out/ }).click(); await expect(page.getByRole('dialog').getByText('Logout').first()).toBeVisible(); }); test('a healthy device never sees it', async ({ page }) => { test.setTimeout(120_000); const user = await ensureUser(uniq('kok')); await loginUI(page, user); await page.getByText('Connecting...').first().waitFor({ state: 'detached', timeout: 90_000 }); await page.waitForTimeout(5000); await expect(page.getByText(/Encryption on this device is out of sync/)).toHaveCount(0); }); });