diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9483b1d..c40e76e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -270,6 +270,7 @@ jobs: - { angular: cockpit-chat-tool-calls-angular, python: cockpit/chat/tool-calls/python } - { angular: cockpit-chat-subagents-angular, python: cockpit/chat/subagents/python } - { angular: cockpit-chat-interrupts-angular, python: cockpit/chat/interrupts/python } + - { angular: cockpit-chat-messages-angular, python: cockpit/chat/messages/python } steps: - uses: actions/checkout@v6.0.2 - uses: actions/setup-node@v6.3.0 diff --git a/cockpit/chat/messages/angular/e2e/c-messages.spec.ts b/cockpit/chat/messages/angular/e2e/c-messages.spec.ts new file mode 100644 index 00000000..a5296986 --- /dev/null +++ b/cockpit/chat/messages/angular/e2e/c-messages.spec.ts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +import { test, expect } from '@playwright/test'; +import { submitAndWaitForResponse } from '../../../../../libs/e2e-harness/src'; + +const PROMPT = 'Hello'; + +test('c-messages: user message and AI response both render', async ({ page }) => { + const bubble = await submitAndWaitForResponse(page, PROMPT); + + await expect( + page.locator('chat-message[data-role="user"]').last(), + ).toContainText(PROMPT); + + await expect(bubble).toContainText('chat-messages capability demo'); +}); + +test('c-messages: chat-message-list renders both turns', async ({ page }) => { + await submitAndWaitForResponse(page, PROMPT); + + // Post-PR-#466 the demo projects user + assistant templates, so the + // list renders one bubble per message. Regression coverage for that fix. + await expect(page.locator('chat-message-list chat-message')).toHaveCount(2); +}); diff --git a/cockpit/chat/messages/angular/e2e/fixtures/c-messages.json b/cockpit/chat/messages/angular/e2e/fixtures/c-messages.json new file mode 100644 index 00000000..da3feb9f --- /dev/null +++ b/cockpit/chat/messages/angular/e2e/fixtures/c-messages.json @@ -0,0 +1,10 @@ +{ + "fixtures": [ + { + "match": { "userMessage": "Hello" }, + "response": { + "content": "Hi! I'm the chat-messages capability demo. I show how ChatMessageListComponent, ChatInputComponent, and ChatTypingIndicatorComponent render together. Try sending a few messages to see the bubbles and typing indicator in action." + } + } + ] +} diff --git a/cockpit/chat/messages/angular/e2e/global-setup-impl.ts b/cockpit/chat/messages/angular/e2e/global-setup-impl.ts new file mode 100644 index 00000000..4dd2510d --- /dev/null +++ b/cockpit/chat/messages/angular/e2e/global-setup-impl.ts @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +import { resolve } from 'node:path'; +import { createGlobalSetup } from '../../../../../libs/e2e-harness/src'; + +export default createGlobalSetup({ + langgraphCwd: 'cockpit/chat/messages/python', + langgraphPort: 5501, + angularProject: 'cockpit-chat-messages-angular', + angularPort: 4501, + fixturesDir: resolve(__dirname, 'fixtures'), +}); diff --git a/cockpit/chat/messages/angular/e2e/playwright.config.ts b/cockpit/chat/messages/angular/e2e/playwright.config.ts new file mode 100644 index 00000000..d5bba8de --- /dev/null +++ b/cockpit/chat/messages/angular/e2e/playwright.config.ts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT +import { defineConfig, devices } from '@playwright/test'; + +export default defineConfig({ + testDir: '.', + testMatch: '**/*.spec.ts', + fullyParallel: false, + workers: 1, + retries: process.env.CI ? 2 : 0, + reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', + use: { + baseURL: 'http://localhost:4501', + trace: 'retain-on-failure', + }, + projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], + globalSetup: './global-setup-impl.ts', + globalTeardown: require.resolve('../../../../../libs/e2e-harness/src/global-teardown'), +}); diff --git a/cockpit/chat/messages/angular/e2e/tsconfig.json b/cockpit/chat/messages/angular/e2e/tsconfig.json new file mode 100644 index 00000000..0b5aeecb --- /dev/null +++ b/cockpit/chat/messages/angular/e2e/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ES2022", + "moduleResolution": "Bundler", + "esModuleInterop": true, + "strict": true, + "skipLibCheck": true, + "noEmit": true, + "types": ["node"] + }, + "include": ["**/*.ts"], + "exclude": ["node_modules", "test-results", "playwright-report"] +} diff --git a/cockpit/chat/messages/angular/project.json b/cockpit/chat/messages/angular/project.json index 7666bfb9..def2639d 100644 --- a/cockpit/chat/messages/angular/project.json +++ b/cockpit/chat/messages/angular/project.json @@ -87,6 +87,12 @@ "cwd": "cockpit/chat/messages/angular", "command": "npx tsx -e \"import { chatMessagesAngularModule } from './src/index.ts'; const module = chatMessagesAngularModule; if (module.id !== 'chat-messages-angular' || module.title !== 'Chat Messages (Angular)') { throw new Error('Unexpected module shape for ' + module.id); }\"" } + }, + "e2e": { + "executor": "@nx/playwright:playwright", + "options": { + "config": "cockpit/chat/messages/angular/e2e/playwright.config.ts" + } } } }