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 expect(page.locator('.agents-info-callout')).toContainText( localized('Group MCP tools around concrete tasks', 'Старайтесь группировать MCP инструменты') ); await expect(page.locator('.agent-card-date').first()).toContainText( localized('Set this endpoint', 'Данный эндпоинт') ); await expect(page.locator('.agent-card-date').filter({ hasText: localized('Catalog rev', 'Ревизия каталога'), }).first()).toBeVisible(); await page.getByRole('button', { name: localized('New agent', 'Новый агент') }).click(); await expect(page.locator('.drawer-title')).toHaveText(localized('New agent', 'Новый агент')); await expect(page.locator('.drawer-subtitle')).toContainText( localized('Describe the agent', 'Опишите агента') ); await expect(page.locator('[data-i18n="agents.drawer.slug_hint"]')).toContainText( localized('used as part of the endpoint', 'используется как часть endpoint-а') ); await expect(page.locator('.drawer')).toContainText(/mcp/i); }); test('agent drawer configures on-demand tool discovery and catalog sections', async ({ page }) => { await login(page); await page.goto('/agents'); await page.getByRole('button', { name: localized('New agent', 'Новый агент') }).click(); await page.locator('.ops-picker-item').first().click(); await page.locator('.tool-access-option').nth(1).click(); await expect(page.locator('.tool-search-config')).toBeVisible(); await page.getByRole('button', { name: localized('Add section', 'Добавить раздел') }).click(); const group = page.locator('.tool-group-card').first(); await group.locator('input').nth(0).fill('Finance'); await group.locator('input').nth(1).fill('finance'); await group.locator('textarea').fill('Invoices, payments and refunds'); await expect(group.locator('input').nth(1)).toHaveValue('finance'); await expect(page.locator('.tool-search-preview')).toBeVisible(); await page.locator('.tool-group-chip').first().click(); await page.locator('.tool-search-preview input').fill('frankfurter_latest_rate'); await page.locator('.tool-search-preview .btn-primary-sm').click(); await expect(page.locator('.tool-search-result').first()).toBeVisible(); }); test('agent lifecycle stale conflict shows localized recovery message', async ({ page }) => { await login(page); await page.goto('/agents'); await expect(page.locator('.agent-card').first()).toBeVisible(); await page.route(/\/api\/admin\/workspaces\/[^/]+\/agents\/[^/]+\/unpublish$/, async (route) => { await route.fulfill({ status: 409, contentType: 'application/json', headers: { 'x-request-id': '01a00000-0000-7000-8000-000000000001', 'x-trace-id': '01a00000000070008000000000000001', }, body: JSON.stringify({ error: { code: 'conflict', message: 'agent changed', context: { error_code: 'agent_stale_revision', }, }, }), }); }); page.once('dialog', async (dialog) => { expect(dialog.message()).toMatch(localized('Unpublish', 'Снять')); await dialog.accept(); }); await page.getByRole('button', { name: localized('Unpublish', 'Снять с публикации') }).first().click(); await expect(page.locator('.toast-error')).toContainText( localized( 'Agent changed in another request. Reload the drawer and retry.', 'Агент изменился в другом запросе. Перезагрузите форму и повторите действие.', ), ); });