feat: add frontend e2e coverage

This commit is contained in:
a.tolmachev
2026-04-05 22:22:44 +03:00
parent d33c52d51d
commit 0bd47d9944
18 changed files with 623 additions and 7 deletions
+11
View File
@@ -0,0 +1,11 @@
const { test, expect } = require('@playwright/test');
const { login, localized } = require('./helpers');
test('agents page shows demo cards and edit drawer opens', async ({ page }) => {
await login(page);
await page.goto('/agents');
await expect(page.locator('.page-heading')).toHaveText(localized('Agents', 'Агенты'));
await page.getByRole('button', { name: localized('New agent', 'Новый агент') }).click();
await expect(page.locator('.drawer-title')).toHaveText(localized('New agent', 'Новый агент'));
await expect(page.locator('.drawer')).toContainText(/mcp/i);
});
+13
View File
@@ -0,0 +1,13 @@
const { test, expect } = require('@playwright/test');
const { login, localized } = require('./helpers');
test('api keys page opens create key flow', async ({ page }) => {
await login(page);
await page.goto('/api-keys');
await expect(page.locator('.page-title')).toHaveText(localized('API Keys', 'API Ключи'));
await page.locator('#btn-create-key').click();
await expect(page.locator('.modal-title')).toHaveText(localized('Create API key', 'Создать API-ключ'));
await page.locator('#new-key-name').fill(`playwright-${Date.now()}`);
await page.locator('#modal-confirm-btn').click();
await expect(page.locator('#modal-reveal-body')).toContainText(localized('Copy this key now', 'Скопируйте этот ключ сейчас'));
});
+25
View File
@@ -0,0 +1,25 @@
const { expect } = require('@playwright/test');
const ADMIN_EMAIL = process.env.CRANK_E2E_ADMIN_EMAIL || 'owner@crank.local';
const ADMIN_PASSWORD = process.env.CRANK_E2E_ADMIN_PASSWORD || 'change-me-admin-password';
function localized(en, ru) {
return new RegExp(`(?:${en}|${ru})`, 'i');
}
async function login(page) {
await page.goto('/login');
await expect(page.locator('#login-form')).toBeVisible();
await page.locator('#email').fill(ADMIN_EMAIL);
await page.locator('#password').fill(ADMIN_PASSWORD);
await page.locator('.btn-signin').click();
await expect(page).toHaveURL(/\/$/);
await expect(page.locator('.page-title, .page-heading').first()).toBeVisible();
}
module.exports = {
ADMIN_EMAIL,
ADMIN_PASSWORD,
login,
localized,
};
+19
View File
@@ -0,0 +1,19 @@
const { test, expect } = require('@playwright/test');
const { ADMIN_EMAIL, ADMIN_PASSWORD, localized } = require('./helpers');
test('login page rejects invalid credentials', async ({ page }) => {
await page.goto('/login');
await page.locator('#email').fill(ADMIN_EMAIL);
await page.locator('#password').fill('wrong-password');
await page.locator('.btn-signin').click();
await expect(page.locator('#login-error')).toBeVisible();
});
test('login page signs in and redirects to operations', async ({ page }) => {
await page.goto('/login');
await page.locator('#email').fill(ADMIN_EMAIL);
await page.locator('#password').fill(ADMIN_PASSWORD);
await page.locator('.btn-signin').click();
await expect(page).toHaveURL(/\/$/);
await expect(page.locator('.page-title, .page-heading').first()).toHaveText(localized('Operations', 'Операции'));
});
+16
View File
@@ -0,0 +1,16 @@
const { test, expect } = require('@playwright/test');
const { login, localized } = require('./helpers');
test('logs and usage pages show seeded data', async ({ page }) => {
await login(page);
await page.goto('/logs');
await expect(page.locator('.page-title')).toHaveText(localized('Logs', 'Логи'));
await expect(page.locator('#log-list')).toBeVisible();
await expect(page.locator('#log-list').locator('.empty-state, .log-entry, .log-row, .log-item').first()).toBeVisible();
await page.goto('/usage');
await expect(page.locator('.page-title')).toHaveText(localized('Usage', 'Использование'));
await expect(page.locator('#chart-bars .chart-col')).toHaveCount(7);
await expect(page.locator('#usage-tbody tr')).toHaveCount(3);
});
+11
View File
@@ -0,0 +1,11 @@
const { test, expect } = require('@playwright/test');
const { login, localized } = require('./helpers');
test('operations page shows demo catalog and filter works', async ({ page }) => {
await login(page);
await expect(page.locator('.page-heading')).toHaveText(localized('Operations', 'Операции'));
await expect(page.locator('tbody tr')).toHaveCount(4);
await page.getByPlaceholder(localized('Search operations', 'Поиск операций')).fill('support');
await expect(page.locator('tbody tr')).toHaveCount(1);
await expect(page.locator('tbody tr').first()).toContainText(/support_lookup_ticket/i);
});
+13
View File
@@ -0,0 +1,13 @@
const { test, expect } = require('@playwright/test');
const { login, localized } = require('./helpers');
test('wizard loads and protocol selection updates flow', async ({ page }) => {
await login(page);
await page.goto('/wizard/');
await expect(page.locator('[data-step-counter]')).toContainText(localized('Step', 'Шаг'));
await expect(page.locator('#step-panel-1 .step-panel-title')).toContainText(localized('Choose a protocol', 'Выберите протокол'));
await page.getByText(/graphql/i).first().click();
await page.locator('#btn-continue').click();
await expect(page.locator('[data-step-counter]')).toContainText(/2/);
await expect(page.locator('#step-panel-2 .step-panel-title')).toContainText(localized('Select upstream', 'Выберите upstream'));
});
@@ -0,0 +1,16 @@
const { test, expect } = require('@playwright/test');
const { login, localized } = require('./helpers');
test('workspace and settings pages show live session data', async ({ page }) => {
await login(page);
await page.goto('/workspace-setup');
await expect(page.locator('#section-members')).toBeVisible();
await expect(page.locator('#members-count-label')).toBeVisible();
await expect(page.locator('#pending-invites')).toBeVisible();
await page.goto('/settings');
await expect(page.locator('.page-title')).toHaveText(localized('Account settings', 'Настройки аккаунта'));
await expect(page.locator('#settings-session-summary')).toBeVisible();
await expect(page.locator('#section-security')).toBeVisible();
});