Files
crank/apps/ui/tests/e2e/streaming.spec.js
T
2026-04-06 12:44:47 +03:00

126 lines
4.3 KiB
JavaScript

const { test, expect } = require('@playwright/test');
const {
buildGrpcSessionOperationPayload,
buildRestAsyncJobOperationPayload,
buildRestWindowOperationPayload,
initializeMcpSession,
login,
mcpToolCall,
setupPublishedAgent,
uniqueName,
} = require('./helpers');
test('rest window tool executes through MCP', async ({ page }) => {
await login(page);
const operationName = uniqueName('playwright_window_logs');
const agentSlug = uniqueName('sales_window');
const payload = buildRestWindowOperationPayload(operationName);
const bundle = await setupPublishedAgent(page, {
operationPayload: payload,
agentSlug,
toolName: operationName,
toolTitle: 'Playwright Window Logs',
toolDescription: 'Collects a bounded SSE log window from the local fixture.',
});
const mcp = await initializeMcpSession({
workspaceSlug: bundle.workspace.slug,
agentSlug,
apiKey: bundle.apiKeySecret,
});
const result = await mcpToolCall(mcp, operationName, {});
expect(result.window_complete).toBe(true);
expect(result.has_more).toBe(false);
expect(Array.isArray(result.items)).toBe(true);
expect(result.items).toHaveLength(3);
expect(result.items[0].message).toBe('billing started');
expect(result.items[2].message).toBe('invoice timeout');
});
test('grpc session tools create persisted stream sessions visible in UI', async ({ page }) => {
await login(page);
const operationName = uniqueName('playwright_echo_session');
const agentSlug = uniqueName('sales_session');
const payload = buildGrpcSessionOperationPayload(operationName);
const bundle = await setupPublishedAgent(page, {
operationPayload: payload,
agentSlug,
toolName: operationName,
toolTitle: 'Playwright gRPC Session',
toolDescription: 'Streams gRPC echo messages through a bounded MCP session tool family.',
});
const mcp = await initializeMcpSession({
workspaceSlug: bundle.workspace.slug,
agentSlug,
apiKey: bundle.apiKeySecret,
});
const started = await mcpToolCall(mcp, `${operationName}_start`, { message: 'hello' });
const sessionId = started.session_id;
expect(started.status).toBe('running');
const polled = await mcpToolCall(mcp, `${operationName}_poll`, { session_id: sessionId });
expect(polled.session_id).toBe(sessionId);
expect(Array.isArray(polled.items)).toBe(true);
expect(polled.items[0].message).toContain('hello');
await page.goto('/stream-sessions');
const sessionCard = page.locator(`.resource-card[data-session-id="${sessionId}"]`);
await expect(sessionCard).toBeVisible();
await sessionCard.locator('[data-action="toggle"]').click();
await expect(sessionCard.locator('.resource-detail-pre')).toBeVisible();
await sessionCard.locator('[data-action="stop"]').click();
await expect(sessionCard.locator('[data-action="stop"]')).toHaveCount(0);
});
test('async job tools complete and expose results in UI', async ({ page }) => {
await login(page);
const operationName = uniqueName('playwright_async_lead');
const agentSlug = uniqueName('sales_async');
const payload = buildRestAsyncJobOperationPayload(operationName);
const bundle = await setupPublishedAgent(page, {
operationPayload: payload,
agentSlug,
toolName: operationName,
toolTitle: 'Playwright Async Lead',
toolDescription: 'Creates a lead through the async job MCP tool family.',
});
const mcp = await initializeMcpSession({
workspaceSlug: bundle.workspace.slug,
agentSlug,
apiKey: bundle.apiKeySecret,
});
const started = await mcpToolCall(mcp, `${operationName}_start`, { email: 'user@example.com' });
const jobId = started.job_id;
expect(started.status).toBe('running');
let status = null;
for (let attempt = 0; attempt < 20; attempt += 1) {
status = await mcpToolCall(mcp, `${operationName}_status`, { job_id: jobId });
if (status.status === 'completed') {
break;
}
await page.waitForTimeout(50);
}
expect(status.status).toBe('completed');
const result = await mcpToolCall(mcp, `${operationName}_result`, { job_id: jobId });
expect(result.id).toBe('lead_123');
await page.goto('/async-jobs');
const jobCard = page.locator(`.resource-card[data-job-id="${jobId}"]`);
await expect(jobCard).toBeVisible();
await jobCard.locator('[data-action="toggle"]').click();
await expect(page.locator(`[data-result-for="${jobId}"]`)).toContainText('lead_123');
});