118 lines
4 KiB
TypeScript
118 lines
4 KiB
TypeScript
|
|
import { test, expect } from "@playwright/test";
|
||
|
|
import AxeBuilder from "@axe-core/playwright";
|
||
|
|
|
||
|
|
test.describe("AI Chat Widget", () => {
|
||
|
|
test.beforeEach(async ({ page }) => {
|
||
|
|
await page.goto("/");
|
||
|
|
await page.waitForLoadState("networkidle");
|
||
|
|
});
|
||
|
|
|
||
|
|
test("widget button is visible and opens chat panel", async ({ page }) => {
|
||
|
|
const widgetButton = page.locator('button[title="AI Assistant"]');
|
||
|
|
await expect(widgetButton).toBeVisible();
|
||
|
|
|
||
|
|
await widgetButton.click();
|
||
|
|
await page.waitForTimeout(500);
|
||
|
|
|
||
|
|
const chatWindow = page.locator('[role="dialog"]').first();
|
||
|
|
await expect(chatWindow).toBeVisible();
|
||
|
|
});
|
||
|
|
|
||
|
|
test("widget sends message and shows user message", async ({ page }) => {
|
||
|
|
await page.goto("/");
|
||
|
|
await page.waitForLoadState("networkidle");
|
||
|
|
|
||
|
|
const widgetButton = page.locator('button[title="AI Assistant"]');
|
||
|
|
await widgetButton.click();
|
||
|
|
await page.waitForTimeout(300);
|
||
|
|
|
||
|
|
const input = page.locator('input[aria-label="Chat message input"]');
|
||
|
|
await expect(input).toBeVisible();
|
||
|
|
|
||
|
|
await input.fill("Hello, what can you help me with?");
|
||
|
|
await page.keyboard.press("Enter");
|
||
|
|
await page.waitForTimeout(500);
|
||
|
|
|
||
|
|
const userMessage = page.locator('text="Hello, what can you help me with?"').first();
|
||
|
|
await expect(userMessage).toBeVisible({ timeout: 5000 });
|
||
|
|
});
|
||
|
|
|
||
|
|
test("widget does not send empty message", async ({ page }) => {
|
||
|
|
await page.goto("/");
|
||
|
|
await page.waitForLoadState("networkidle");
|
||
|
|
|
||
|
|
const widgetButton = page.locator('button[title="AI Assistant"]');
|
||
|
|
await widgetButton.click();
|
||
|
|
await page.waitForTimeout(300);
|
||
|
|
|
||
|
|
const input = page.locator('input[aria-label="Chat message input"]');
|
||
|
|
await input.fill(" ");
|
||
|
|
await page.keyboard.press("Enter");
|
||
|
|
await page.waitForTimeout(500);
|
||
|
|
|
||
|
|
const messages = page.locator('[role="log"]');
|
||
|
|
const count = await messages.count();
|
||
|
|
expect(count).toBeLessThanOrEqual(1);
|
||
|
|
});
|
||
|
|
|
||
|
|
test("widget does not send message while loading", async ({ page }) => {
|
||
|
|
await page.goto("/");
|
||
|
|
await page.waitForLoadState("networkidle");
|
||
|
|
|
||
|
|
await page.route("**/api/gateway/api/ai/chat/message", async (route) => {
|
||
|
|
await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ message: "Response", conversation_id: "test", intent: "general", confidence: 0.9 }) });
|
||
|
|
await page.waitForTimeout(5000);
|
||
|
|
});
|
||
|
|
|
||
|
|
const widgetButton = page.locator('button[title="AI Assistant"]');
|
||
|
|
await widgetButton.click();
|
||
|
|
await page.waitForTimeout(300);
|
||
|
|
|
||
|
|
const input = page.locator('input[aria-label="Chat message input"]');
|
||
|
|
await input.fill("Test message");
|
||
|
|
await page.keyboard.press("Enter");
|
||
|
|
await page.waitForTimeout(100);
|
||
|
|
await input.fill("Second message");
|
||
|
|
await page.keyboard.press("Enter");
|
||
|
|
|
||
|
|
await page.waitForTimeout(6000);
|
||
|
|
const messages = page.locator('[role="log"]');
|
||
|
|
const count = await messages.count();
|
||
|
|
expect(count).toBeLessThanOrEqual(2);
|
||
|
|
});
|
||
|
|
|
||
|
|
test("chat widget has no critical accessibility violations", async ({ page }) => {
|
||
|
|
await page.goto("/");
|
||
|
|
await page.waitForLoadState("networkidle");
|
||
|
|
|
||
|
|
const widgetButton = page.locator('button[title="AI Assistant"]');
|
||
|
|
await widgetButton.click();
|
||
|
|
await page.waitForTimeout(500);
|
||
|
|
|
||
|
|
const dialog = page.locator('[role="dialog"]');
|
||
|
|
await expect(dialog).toBeVisible();
|
||
|
|
|
||
|
|
const results = await new AxeBuilder({ page }).analyze();
|
||
|
|
|
||
|
|
const criticalViolations = results.violations.filter(
|
||
|
|
(v: { impact: string }) => v.impact === "critical"
|
||
|
|
);
|
||
|
|
expect(criticalViolations).toEqual([]);
|
||
|
|
});
|
||
|
|
|
||
|
|
test("widget close button works", async ({ page }) => {
|
||
|
|
await page.goto("/");
|
||
|
|
await page.waitForLoadState("networkidle");
|
||
|
|
|
||
|
|
const widgetButton = page.locator('button[title="AI Assistant"]');
|
||
|
|
await widgetButton.click();
|
||
|
|
await page.waitForTimeout(300);
|
||
|
|
|
||
|
|
const closeButton = page.locator('button[aria-label="Close chat"]');
|
||
|
|
await closeButton.click();
|
||
|
|
await page.waitForTimeout(300);
|
||
|
|
|
||
|
|
const chatWindow = page.locator('[role="dialog"]');
|
||
|
|
await expect(chatWindow).not.toBeVisible();
|
||
|
|
});
|
||
|
|
});
|