137 lines
4.7 KiB
TypeScript
137 lines
4.7 KiB
TypeScript
import { Page } from '@playwright/test'
|
|
|
|
/**
|
|
* Helper to login and navigate to chat page
|
|
*
|
|
* Uses environment variables for test credentials:
|
|
* - TEST_USER_EMAIL: Email for test account
|
|
* - TEST_USER_PASSWORD: Password for test account
|
|
*
|
|
* Run tests with credentials:
|
|
* TEST_USER_EMAIL=your@email.com TEST_USER_PASSWORD=yourpass pnpm test:e2e
|
|
*/
|
|
export async function loginAndNavigate(page: Page): Promise<void> {
|
|
await page.goto('/')
|
|
|
|
// Get credentials from environment variables
|
|
const email = process.env.TEST_USER_EMAIL
|
|
const password = process.env.TEST_USER_PASSWORD
|
|
|
|
if (!email || !password) {
|
|
throw new Error(
|
|
'TEST_USER_EMAIL and TEST_USER_PASSWORD environment variables are required.\n' +
|
|
'Run: TEST_USER_EMAIL=your@email.com TEST_USER_PASSWORD=yourpass pnpm test:e2e'
|
|
)
|
|
}
|
|
|
|
// Check if already logged in (look for navigation or user menu)
|
|
const chatNav = page.getByRole('link', { name: /chat/i })
|
|
try {
|
|
await chatNav.waitFor({ state: 'visible', timeout: 2000 })
|
|
return // Already logged in
|
|
} catch {
|
|
// Not logged in, continue with login flow
|
|
}
|
|
|
|
// Perform login
|
|
const emailInput = page.getByRole('textbox', { name: /e-mail/i })
|
|
const passwordInput = page.getByRole('textbox', { name: /wachtwoord/i })
|
|
const loginButton = page.getByRole('button', { name: /inloggen/i })
|
|
|
|
await emailInput.fill(email)
|
|
await passwordInput.fill(password)
|
|
await loginButton.click()
|
|
|
|
// Wait for chat page to load - look for the chat input textbox
|
|
await page.waitForSelector('input[placeholder*="vraag"]', { timeout: 30000 })
|
|
}
|
|
|
|
/**
|
|
* Wait for chat interface to be ready
|
|
*/
|
|
export async function waitForChatReady(page: Page): Promise<void> {
|
|
// Wait for the chat input textbox (placeholder contains "vraag")
|
|
await page.waitForSelector('input[placeholder*="vraag"]', { timeout: 10000 })
|
|
}
|
|
|
|
/**
|
|
* Get the chat input element
|
|
*/
|
|
export function getChatInput(page: Page) {
|
|
return page.locator('input[placeholder*="vraag"]')
|
|
}
|
|
|
|
/**
|
|
* Get the send button (button in the chat form that's not disabled)
|
|
*/
|
|
export function getSendButton(page: Page) {
|
|
// The send button is typically next to the input
|
|
return page.locator('button').filter({ has: page.locator('img') }).last()
|
|
}
|
|
|
|
/**
|
|
* Submit a query and wait for assistant response
|
|
* Returns the response text content
|
|
*/
|
|
export async function askQuestion(page: Page, question: string): Promise<string> {
|
|
const chatInput = getChatInput(page)
|
|
|
|
// Count existing response messages before sending
|
|
const mainArea = page.locator('main')
|
|
const existingResponses = await mainArea.locator('p').filter({
|
|
hasText: /Er zijn \d+|instellingen gevonden/
|
|
}).count()
|
|
|
|
await chatInput.fill(question)
|
|
await chatInput.press('Enter')
|
|
|
|
// First wait for loading to complete - the input gets disabled and progressbar appears
|
|
// Wait for the input to be disabled (loading state)
|
|
await page.waitForSelector('input[placeholder*="vraag"][disabled]', { timeout: 5000 }).catch(() => {})
|
|
|
|
// Then wait for loading to finish (input re-enabled)
|
|
await page.waitForSelector('input[placeholder*="vraag"]:not([disabled])', { timeout: 45000 })
|
|
|
|
// Now find the NEW response - there should be more response paragraphs than before
|
|
const responseLocator = mainArea.locator('p').filter({
|
|
hasText: /Er zijn \d+|instellingen gevonden|\d+ archie|\d+ muse|\d+ bibliothe/
|
|
})
|
|
|
|
// Wait for a new response to appear (count should increase)
|
|
await page.waitForFunction(
|
|
({ selector, expectedCount }) => {
|
|
const elements = document.querySelectorAll(selector)
|
|
let count = 0
|
|
elements.forEach(el => {
|
|
if (el.textContent && /Er zijn \d+|instellingen gevonden/.test(el.textContent)) {
|
|
count++
|
|
}
|
|
})
|
|
return count > expectedCount
|
|
},
|
|
{ selector: 'main p', expectedCount: existingResponses },
|
|
{ timeout: 15000 }
|
|
).catch(() => {})
|
|
|
|
// Get the LAST response (most recent one)
|
|
const lastResponse = responseLocator.last()
|
|
await lastResponse.waitFor({ timeout: 5000 })
|
|
|
|
// Get the text content of the response
|
|
const text = await lastResponse.textContent()
|
|
return text || ''
|
|
}
|
|
|
|
/**
|
|
* Wait for any assistant response to appear
|
|
* More flexible version that doesn't require specific text patterns
|
|
*/
|
|
export async function waitForAssistantResponse(page: Page, timeout: number = 45000): Promise<void> {
|
|
// Wait for loading to complete - look for response content
|
|
// The response typically appears in a paragraph or message container
|
|
await page.waitForFunction(() => {
|
|
// Look for any new content that appeared after sending
|
|
const messages = document.querySelectorAll('p, [class*="message"]')
|
|
return messages.length > 0
|
|
}, { timeout })
|
|
}
|