91 lines
3.6 KiB
JavaScript
91 lines
3.6 KiB
JavaScript
const { test, expect } = require('@playwright/test');
|
|
const { login, localized } = require('./helpers');
|
|
|
|
test('logs approval panel renders safe pending approval metadata', async ({ page }) => {
|
|
await login(page);
|
|
let approveCalled = false;
|
|
|
|
await page.route(/\/api\/admin\/workspaces\/[^/]+\/approvals(?:\?.*)?$/, async (route) => {
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({
|
|
items: [
|
|
{
|
|
approval: {
|
|
id: 'approval_ui_safe_summary',
|
|
agent_id: 'agent_sales',
|
|
operation_id: 'op_charge_customer',
|
|
operation_version: 3,
|
|
status: 'pending',
|
|
risk_level: 'dangerous',
|
|
request_id: 'req_approval_ui',
|
|
trace_id: '0af7651916cd43dd8448eb211c80319c',
|
|
request_payload: {
|
|
email: 'customer@example.com',
|
|
api_key: '[REDACTED]',
|
|
},
|
|
response_payload: null,
|
|
created_at: '2026-08-22T10:00:00Z',
|
|
expires_at: '2026-08-22T10:05:00Z',
|
|
decided_at: null,
|
|
decision_note: null,
|
|
},
|
|
},
|
|
],
|
|
}),
|
|
});
|
|
});
|
|
await page.route(/\/api\/admin\/workspaces\/[^/]+\/approvals\/approval_ui_safe_summary\/approve$/, async (route) => {
|
|
approveCalled = true;
|
|
const body = JSON.parse(route.request().postData() || '{}');
|
|
expect(body).toEqual({ approve: 'yes' });
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({
|
|
approval: {
|
|
id: 'approval_ui_safe_summary',
|
|
agent_id: 'agent_sales',
|
|
operation_id: 'op_charge_customer',
|
|
operation_version: 3,
|
|
status: 'approved',
|
|
risk_level: 'dangerous',
|
|
request_id: 'req_approval_ui',
|
|
trace_id: '0af7651916cd43dd8448eb211c80319c',
|
|
request_payload: { email: 'customer@example.com', api_key: '[REDACTED]' },
|
|
response_payload: { approve: 'yes' },
|
|
created_at: '2026-08-22T10:00:00Z',
|
|
expires_at: '2026-08-22T10:05:00Z',
|
|
decided_at: '2026-08-22T10:01:00Z',
|
|
decision_note: null,
|
|
},
|
|
}),
|
|
});
|
|
});
|
|
page.on('dialog', async (dialog) => {
|
|
expect(dialog.message()).toMatch(localized(
|
|
'Approve this pending confirmation request?',
|
|
'Подтвердить эту заявку?',
|
|
));
|
|
await dialog.accept();
|
|
});
|
|
|
|
await page.goto('/logs');
|
|
await expect(page.locator('.approval-panel-title')).toHaveText(
|
|
localized('Human confirmations', 'Подтверждения человеком'),
|
|
);
|
|
await expect(page.locator('#approval-list')).toContainText('approval_ui_safe_summary');
|
|
await expect(page.locator('#approval-list')).toContainText('op_charge_customer v3');
|
|
await expect(page.locator('#approval-list')).toContainText('agent_sales');
|
|
await expect(page.locator('#approval-list')).toContainText('customer@example.com');
|
|
await expect(page.locator('#approval-list')).toContainText('[REDACTED]');
|
|
await expect(page.locator('#approval-list')).toContainText('req_approval_ui');
|
|
await expect(page.locator('#approval-list')).toContainText('0af7651916cd43dd8448eb211c80319c');
|
|
await expect(page.locator('.approval-approve')).toHaveText(localized('Approve', 'Подтвердить'));
|
|
await expect(page.locator('.approval-deny')).toHaveText(localized('Deny', 'Отклонить'));
|
|
await expect(page.locator('#approval-list')).not.toContainText('SECRET_APPROVAL_CANARY');
|
|
await page.locator('.approval-approve').click();
|
|
await expect.poll(() => approveCalled).toBe(true);
|
|
});
|