import { expect, test } from '@playwright/test'; test('first-run wizard tests MySQL, creates the administrator and stays responsive', async ({ page }) => { let completed = false; await page.route('**/api/v1/setup/**', async (route) => { const request = route.request(); const pathname = new URL(request.url()).pathname; if (pathname === '/api/v1/setup/status') { await route.fulfill({ json: { data: { required: !completed, locked: completed, // Production status is locked after setup; readiness is not the // completion signal used by the redirect flow. ready: false, supportedDatabaseTypes: ['MYSQL'], message: completed ? '系统已完成安装' : '请完成安装', }, }, }); return; } const body = request.postDataJSON() as Record; expect(body.databaseType).toBe('MYSQL'); expect(body.database).toBe('kaidi_finance'); expect(body.setupCode).toBe('fixture-setup-code'); if (pathname.endsWith('/test-connection')) { await route.fulfill({ json: { data: { successful: true, databaseType: 'MYSQL', serverVersion: '8.4.6', schemaReady: false, message: 'MySQL 8.4 只读连接验证通过;尚未修改数据库,点击完成安装后才会执行迁移', }, }, }); return; } expect(body.adminUsername).toBe('admin'); expect(body.adminDisplayName).toBe('系统管理员'); completed = true; await route.fulfill({ json: { data: { completed: true, username: 'admin', message: '安装完成,系统正在切换到正式模式', restartAfterSeconds: 10, }, }, }); }); await page.setViewportSize({ width: 390, height: 844 }); await page.goto('/setup'); await expect(page.getByRole('heading', { name: '安装向导', exact: true })).toBeVisible(); await page.getByLabel('数据库密码').fill('fixture-db-password'); await page.getByLabel('安装码').fill('fixture-setup-code'); await page.getByRole('button', { name: '测试连接' }).click(); await expect( page.locator('.t-alert__description').filter({ hasText: 'MySQL 8.4 只读连接验证通过;尚未修改数据库,点击完成安装后才会执行迁移', }), ).toBeVisible(); await page.getByRole('button', { name: '下一步' }).click(); await page.getByLabel('管理员密码').fill('SetupAdmin@2026Strong'); await page.getByLabel('确认密码').fill('SetupAdmin@2026Strong'); await page.getByRole('button', { name: '完成安装' }).click(); await page.getByRole('button', { name: '确定', exact: true }).click(); await expect(page.getByText('安装完成', { exact: true })).toBeVisible(); await expect(page.getByText('安装完成,系统正在切换到正式模式')).toBeVisible(); await expect(page).toHaveURL(/\/login$/, { timeout: 15_000 }); const layout = await page.evaluate(() => ({ clientWidth: document.documentElement.clientWidth, scrollWidth: document.documentElement.scrollWidth, })); expect(layout.scrollWidth).toBeLessThanOrEqual(layout.clientWidth); }); test('confirms completion after the setup response is interrupted by a service restart', async ({ page }) => { let completionStarted = false; let recoveryChecks = 0; await page.route('**/api/v1/setup/**', async (route) => { const request = route.request(); const pathname = new URL(request.url()).pathname; if (pathname === '/api/v1/setup/status') { if (completionStarted) recoveryChecks += 1; const ready = completionStarted && recoveryChecks >= 2; await route.fulfill({ json: { data: { required: !completionStarted, locked: completionStarted, ready, supportedDatabaseTypes: ['MYSQL'], message: ready ? '系统已完成安装' : '请完成安装', }, }, }); return; } const body = request.postDataJSON() as Record; if (pathname.endsWith('/test-connection')) { await route.fulfill({ json: { data: { successful: true, databaseType: 'MYSQL', serverVersion: '8.4.6', schemaReady: false, message: 'MySQL 8.4 只读连接验证通过;尚未修改数据库,点击完成安装后才会执行迁移', }, }, }); return; } expect(body.adminUsername).toBe('admin'); completionStarted = true; await route.abort('connectionreset'); }); await page.goto('/setup'); await page.getByLabel('数据库密码').fill('fixture-db-password'); await page.getByLabel('安装码').fill('fixture-setup-code'); await page.getByRole('button', { name: '测试连接' }).click(); await page.getByRole('button', { name: '下一步' }).click(); await page.getByLabel('管理员密码').fill('SetupAdmin@2026Strong'); await page.getByLabel('确认密码').fill('SetupAdmin@2026Strong'); await page.getByRole('button', { name: '完成安装' }).click(); await page.getByRole('button', { name: '确定', exact: true }).click(); await expect(page.getByText('安装完成', { exact: true })).toBeVisible(); await expect(page.getByText('安装已完成,系统正在切换到正式模式')).toBeVisible(); await expect(page.getByText('网络请求失败')).toHaveCount(0); await expect(page).toHaveURL(/\/login$/, { timeout: 15_000 }); }); test('leaves the completed wizard when post-completion status polling is unavailable', async ({ page }) => { let completionStarted = false; await page.route('**/api/v1/setup/**', async (route) => { const request = route.request(); const pathname = new URL(request.url()).pathname; if (pathname === '/api/v1/setup/status') { if (completionStarted) { await route.abort('connectionreset'); return; } await route.fulfill({ json: { data: { required: true, locked: false, ready: false, supportedDatabaseTypes: ['MYSQL'], message: '请完成安装', }, }, }); return; } const body = request.postDataJSON() as Record; if (pathname.endsWith('/test-connection')) { await route.fulfill({ json: { data: { successful: true, databaseType: 'MYSQL', serverVersion: '8.4.6', schemaReady: false, message: 'MySQL 8.4 只读连接验证通过;尚未修改数据库,点击完成安装后才会执行迁移', }, }, }); return; } expect(body.adminUsername).toBe('admin'); completionStarted = true; await route.fulfill({ json: { data: { completed: true, username: 'admin', message: '安装完成,系统正在切换到正式模式', restartAfterSeconds: 1, }, }, }); }); await page.goto('/setup'); await page.getByLabel('数据库密码').fill('fixture-db-password'); await page.getByLabel('安装码').fill('fixture-setup-code'); await page.getByRole('button', { name: '测试连接' }).click(); await page.getByRole('button', { name: '下一步' }).click(); await page.getByLabel('管理员密码').fill('SetupAdmin@2026Strong'); await page.getByLabel('确认密码').fill('SetupAdmin@2026Strong'); await page.getByRole('button', { name: '完成安装' }).click(); await page.getByRole('button', { name: '确定', exact: true }).click(); await expect(page.getByText('安装完成', { exact: true })).toBeVisible(); await expect(page).toHaveURL(/\/login$/, { timeout: 5_000 }); });