import { test, expect } from '@playwright/test'; test.describe('Unicode Character Support (US-92)', () => { test.beforeEach(async ({ page }) => { await page.goto('/'); // Accept any cookie consent if present const cookieButton = page.locator('button:has-text("Accept")').first(); if (await cookieButton.isVisible({ timeout: 1000 }).catch(() => false)) { await cookieButton.click(); } }); test.describe('Unicode City Names - CJK Languages', () => { test('should accept Chinese city names (北京)', async ({ page }) => { const departureContainer = page.locator('[data-testid="filter-route-departure-input"]'); const departureInput = departureContainer.locator('input').first(); // Enter Chinese city name await departureInput.fill('北京'); const inputValue = await departureInput.inputValue(); expect(inputValue).toBe('北京'); }); test('should accept Japanese city names (東京)', async ({ page }) => { const departureContainer = page.locator('[data-testid="filter-route-departure-input"]'); const departureInput = departureContainer.locator('input').first(); // Enter Japanese city name await departureInput.fill('東京'); const inputValue = await departureInput.inputValue(); expect(inputValue).toBe('東京'); }); test('should accept Korean city names (서울)', async ({ page }) => { const departureContainer = page.locator('[data-testid="filter-route-departure-input"]'); const departureInput = departureContainer.locator('input').first(); // Enter Korean city name await departureInput.fill('서울'); const inputValue = await departureInput.inputValue(); expect(inputValue).toBe('서울'); }); }); test.describe('Unicode City Names - Arabic', () => { test('should accept Arabic city names (مصر)', async ({ page }) => { const departureContainer = page.locator('[data-testid="filter-route-departure-input"]'); const departureInput = departureContainer.locator('input').first(); // Enter Arabic city name await departureInput.fill('مصر'); const inputValue = await departureInput.inputValue(); expect(inputValue).toBe('مصر'); }); test('should accept Arabic city names (القاهرة)', async ({ page }) => { const departureContainer = page.locator('[data-testid="filter-route-departure-input"]'); const departureInput = departureContainer.locator('input').first(); // Enter Arabic city name await departureInput.fill('القاهرة'); const inputValue = await departureInput.inputValue(); expect(inputValue).toBe('القاهرة'); }); test('should accept Arabic city names (دبي)', async ({ page }) => { const departureContainer = page.locator('[data-testid="filter-route-departure-input"]'); const departureInput = departureContainer.locator('input').first(); // Enter Arabic city name await departureInput.fill('دبي'); const inputValue = await departureInput.inputValue(); expect(inputValue).toBe('دبي'); }); }); test.describe('Unicode City Names - Thai', () => { test('should accept Thai city names (กรุงเทพ)', async ({ page }) => { const departureContainer = page.locator('[data-testid="filter-route-departure-input"]'); const departureInput = departureContainer.locator('input').first(); // Enter Thai city name await departureInput.fill('กรุงเทพ'); const inputValue = await departureInput.inputValue(); expect(inputValue).toBe('กรุงเทพ'); }); test('should accept Thai city names (เชียงใหม่)', async ({ page }) => { const departureContainer = page.locator('[data-testid="filter-route-departure-input"]'); const departureInput = departureContainer.locator('input').first(); // Enter Thai city name await departureInput.fill('เชียงใหม่'); const inputValue = await departureInput.inputValue(); expect(inputValue).toBe('เชียงใหม่'); }); }); test.describe('Unicode with Punctuation and Spaces', () => { test('should accept Cyrillic with hyphens (Санкт-Петербург)', async ({ page }) => { const departureContainer = page.locator('[data-testid="filter-route-departure-input"]'); const departureInput = departureContainer.locator('input').first(); // Enter Cyrillic city with hyphen await departureInput.fill('Санкт-Петербург'); const inputValue = await departureInput.inputValue(); expect(inputValue).toBe('Санкт-Петербург'); }); test('should accept Latin with spaces (New York)', async ({ page }) => { const departureContainer = page.locator('[data-testid="filter-route-departure-input"]'); const departureInput = departureContainer.locator('input').first(); // Enter Latin city with space await departureInput.fill('New York'); const inputValue = await departureInput.inputValue(); expect(inputValue).toBe('New York'); }); test("should accept Latin with apostrophes (L'Aquila)", async ({ page }) => { const departureContainer = page.locator('[data-testid="filter-route-departure-input"]'); const departureInput = departureContainer.locator('input').first(); // Enter Latin city with apostrophe await departureInput.fill("L'Aquila"); const inputValue = await departureInput.inputValue(); expect(inputValue).toBe("L'Aquila"); }); }); test.describe('Unicode Rejection - Invalid Characters', () => { test('should reject emoji characters', async ({ page }) => { const consoleErrors: string[] = []; page.on('console', (msg) => { if (msg.type() === 'error') { consoleErrors.push(msg.text()); } }); const departureContainer = page.locator('[data-testid="filter-route-departure-input"]'); const departureInput = departureContainer.locator('input').first(); // Try to enter emoji with text await departureInput.fill('Москва 🎉'); await departureInput.blur(); await page.waitForTimeout(100); // Input should not accept or display emoji const inputValue = await departureInput.inputValue(); expect(inputValue).not.toContain('🎉'); }); test('should reject numeric characters', async ({ page }) => { const departureContainer = page.locator('[data-testid="filter-route-departure-input"]'); const departureInput = departureContainer.locator('input').first(); // Try to enter text with numbers await departureInput.fill('City123'); await departureInput.blur(); await page.waitForTimeout(100); // Input should not accept numbers const inputValue = await departureInput.inputValue(); expect(inputValue).not.toContain('123'); }); }); test.describe('Unicode Preservation in UI', () => { test('should preserve Unicode characters when clearing and re-entering', async ({ page }) => { const departureContainer = page.locator('[data-testid="filter-route-departure-input"]'); const departureInput = departureContainer.locator('input').first(); // First entry await departureInput.fill('北京'); let inputValue = await departureInput.inputValue(); expect(inputValue).toBe('北京'); // Clear and re-enter await departureInput.clear(); await departureInput.fill('北京'); inputValue = await departureInput.inputValue(); expect(inputValue).toBe('北京'); }); test('should handle multiple Unicode scripts in sequence', async ({ page }) => { const departureContainer = page.locator('[data-testid="filter-route-departure-input"]'); const departureInput = departureContainer.locator('input').first(); const arrivalContainer = page.locator('[data-testid="filter-route-arrival-input"]'); const arrivalInput = arrivalContainer.locator('input').first(); // Enter different Unicode scripts await departureInput.fill('北京'); await arrivalInput.fill('مصر'); expect(await departureInput.inputValue()).toBe('北京'); expect(await arrivalInput.inputValue()).toBe('مصر'); }); test('should trim whitespace from Unicode city names', async ({ page }) => { const departureContainer = page.locator('[data-testid="filter-route-departure-input"]'); const departureInput = departureContainer.locator('input').first(); // Enter Unicode with whitespace await departureInput.fill(' 東京 '); await departureInput.blur(); const inputValue = await departureInput.inputValue(); // After sanitization, whitespace should be trimmed expect(inputValue.trim()).toBe('東京'); }); }); test.describe('Console - No Errors on Unicode Input', () => { test('should not produce errors when handling Unicode characters', async ({ page }) => { const consoleErrors: string[] = []; page.on('console', (msg) => { if (msg.type() === 'error') { consoleErrors.push(msg.text()); } }); const departureContainer = page.locator('[data-testid="filter-route-departure-input"]'); const departureInput = departureContainer.locator('input').first(); // Test various Unicode scripts const testInputs = ['北京', 'مصر', 'กรุงเทพ', 'Москва', 'Paris']; for (const input of testInputs) { await departureInput.clear(); await departureInput.fill(input); await departureInput.blur(); await page.waitForTimeout(50); } // Should not have any console errors related to Unicode handling expect(consoleErrors).toHaveLength(0); }); test('should not throw errors on search with Unicode input', async ({ page }) => { const consoleErrors: string[] = []; page.on('console', (msg) => { if (msg.type() === 'error') { consoleErrors.push(msg.text()); } }); const departureContainer = page.locator('[data-testid="filter-route-departure-input"]'); const departureInput = departureContainer.locator('input').first(); const arrivalContainer = page.locator('[data-testid="filter-route-arrival-input"]'); const arrivalInput = arrivalContainer.locator('input').first(); const searchBtn = page.locator('[data-testid="filter-route-search"]'); // Enter Unicode cities and attempt search await departureInput.fill('北京'); await arrivalInput.fill('مصر'); // Try to click search (if enabled) if (await searchBtn.isEnabled()) { await searchBtn.click(); await page.waitForTimeout(200); } // Should not have console errors expect(consoleErrors).toHaveLength(0); }); }); });