glam/apps/archief-assistent/e2e/auth.setup.ts

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 })
}