import { type Page, type Locator } from '@playwright/test'; /** * Select a gender option from the gender combobox using keyboard navigation (ArrowDown + Enter). * Works with both native - use selectOption as fallback if keyboard doesn't work const optionValues: Record = { 'Male': 'Male', 'Female': 'Female', 'Other': 'Other', 'Prefer not to say': 'Prefer not to say', }; const value = optionValues[genderValue]; if (value) { await genderSelect.selectOption(value); } } else if (inputVisible) { // Custom combobox input - click to open dropdown await genderInput.click(); // Build the option selector based on the gender value // For DashboardDesignPreview-style dropdowns, options appear in a list // Try to find and click the matching option const optionLocator = page.locator(`text="${genderValue}"`).first(); const optionVisible = await optionLocator.isVisible().catch(() => false); if (optionVisible) { await optionLocator.click(); } else { // Fallback: type the value and press Enter await genderInput.fill(genderValue); await genderInput.press('Enter'); } } } /** * Select a gender option using direct JavaScript value injection via page.evaluate. * This bypasses the UI and directly sets the value in the DOM/state. * * @param page - Playwright page object * @param genderValue - One of: "Male", "Female", "Other", "Prefer not to say" * @param fieldKey - The field key, defaults to "gender" */ export async function setGenderViaJS(page: Page, genderValue: string, fieldKey = 'gender'): Promise { // Try native select first const nativeSelectWorked = await page.evaluate((value: string) => { const selects = Array.from(document.querySelectorAll('select')); for (const sel of selects) { const options = Array.from(sel.options).map((o: HTMLOptionElement) => o.value); if (options.includes(value)) { sel.value = value; sel.dispatchEvent(new Event('change', { bubbles: true })); return true; } } return false; }, genderValue); if (!nativeSelectWorked) { // Try custom combobox - inject into input value and trigger input event await page.evaluate((value: string) => { const inputs = Array.from(document.querySelectorAll('input')); for (const input of inputs) { const placeholder = input.getAttribute('placeholder') || ''; if (placeholder.toLowerCase().includes('gender') || placeholder.toLowerCase().includes('select')) { input.value = value; input.dispatchEvent(new Event('input', { bubbles: true })); input.dispatchEvent(new Event('change', { bubbles: true })); return; } } }, genderValue); } } /** * Select gender using keyboard ArrowDown + Enter sequence. * This is the preferred approach for custom comboboxes. * * @param page - Playwright page object * @param genderValue - The gender option to select */ export async function selectGenderArrowDownEnter(page: Page, genderValue: string): Promise { // Find gender field - try select first, then input let genderField: Locator | null = null; let isSelect = false; try { const selectLocator = page.locator('select'); if (await selectLocator.isVisible()) { genderField = selectLocator; isSelect = true; } } catch { // not visible } if (!genderField) { // Try input with placeholder matching gender or Select const inputs = page.locator('input'); const count = await inputs.count(); for (let i = 0; i < count; i++) { const input = inputs.nth(i); const placeholder = await input.getAttribute('placeholder').catch(() => ''); if (placeholder && (placeholder.toLowerCase().includes('gender') || placeholder.toLowerCase().includes('select'))) { if (await input.isVisible()) { genderField = input; break; } } } } if (!genderField) { throw new Error('Gender field not found on page'); } if (isSelect) { // For native select: click to focus, then ArrowDown + Enter await genderField.click(); await genderField.press('ArrowDown'); await genderField.press('Enter'); } else { // For custom combobox: click to open dropdown list await genderField.click(); // Wait briefly for dropdown to appear await page.waitForTimeout(300); // Press ArrowDown to navigate to the option await genderField.press('ArrowDown'); // Press Enter to select await genderField.press('Enter'); } }