375bcfb0fa
Copies Playwright e2e tests (58 specs, 300+ tests) designed for cross-app testing. Adapts API mocks to match real Aeroflot dictionary format (title objects with multilingual keys), adds board/schedule/days endpoint mocks, and provides Angular-specific Playwright config on port 4203.
200 lines
6.1 KiB
TypeScript
200 lines
6.1 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
test.describe('Search History (US-8)', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto('http://localhost:3000/ru-ru/onlineboard');
|
|
// Clear localStorage to start fresh
|
|
await page.evaluate(() => localStorage.clear());
|
|
// Reload after clearing
|
|
await page.reload();
|
|
});
|
|
|
|
test('should not display search history section when empty', async ({ page }) => {
|
|
const section = page.locator('[data-testid="landing-search-history"]');
|
|
await expect(section).not.toBeVisible();
|
|
});
|
|
|
|
test('should display search history section when items exist', async ({ page }) => {
|
|
// Setup: Add history to localStorage
|
|
await page.evaluate(() => {
|
|
const historyItem = {
|
|
id: '1',
|
|
label: 'SU 1402',
|
|
url: '/search?flight=SU1402',
|
|
timestamp: Date.now(),
|
|
};
|
|
localStorage.setItem('aeroflot_search_history', JSON.stringify([historyItem]));
|
|
});
|
|
|
|
// Reload to pick up the localStorage data
|
|
await page.reload();
|
|
|
|
const section = page.locator('[data-testid="landing-search-history"]');
|
|
await expect(section).toBeVisible();
|
|
});
|
|
|
|
test('should display history items correctly', async ({ page }) => {
|
|
// Setup: Add multiple history items
|
|
await page.evaluate(() => {
|
|
const historyItems = [
|
|
{
|
|
id: '1',
|
|
label: 'SU 1402',
|
|
url: '/search?flight=SU1402',
|
|
timestamp: Date.now(),
|
|
},
|
|
{
|
|
id: '2',
|
|
label: 'SU 1403',
|
|
url: '/search?flight=SU1403',
|
|
timestamp: Date.now() - 60000,
|
|
},
|
|
];
|
|
localStorage.setItem('aeroflot_search_history', JSON.stringify(historyItems));
|
|
});
|
|
|
|
await page.reload();
|
|
|
|
const items = page.locator('[data-testid="landing-search-history-item"]');
|
|
await expect(items).toHaveCount(2);
|
|
|
|
// Check for flight numbers
|
|
await expect(page.getByText('SU 1402')).toBeVisible();
|
|
await expect(page.getByText('SU 1403')).toBeVisible();
|
|
});
|
|
|
|
test('should display search history title', async ({ page }) => {
|
|
await page.evaluate(() => {
|
|
const historyItem = {
|
|
id: '1',
|
|
label: 'SU 1402',
|
|
url: '/search?flight=SU1402',
|
|
timestamp: Date.now(),
|
|
};
|
|
localStorage.setItem('aeroflot_search_history', JSON.stringify([historyItem]));
|
|
});
|
|
|
|
await page.reload();
|
|
|
|
// Note: Title depends on intl messages, might be "Search History" or Russian equivalent
|
|
const title = page.locator('[data-testid="landing-search-history"] h3');
|
|
await expect(title).toBeVisible();
|
|
});
|
|
|
|
test('should have clickable history items that are links', async ({ page }) => {
|
|
await page.evaluate(() => {
|
|
const historyItem = {
|
|
id: '1',
|
|
label: 'SU 1402',
|
|
url: '/search?flight=SU1402',
|
|
timestamp: Date.now(),
|
|
};
|
|
localStorage.setItem('aeroflot_search_history', JSON.stringify([historyItem]));
|
|
});
|
|
|
|
await page.reload();
|
|
|
|
const link = page.locator('[data-testid="landing-search-history-item"] a').first();
|
|
await expect(link).toHaveAttribute('href', /search\?flight=SU1402/);
|
|
});
|
|
|
|
test('should format timestamp as HH:MM', async ({ page }) => {
|
|
const testTime = new Date(2026, 3, 9, 14, 30, 0).getTime();
|
|
|
|
await page.evaluate((time) => {
|
|
const historyItem = {
|
|
id: '1',
|
|
label: 'SU 1402',
|
|
url: '/search?flight=SU1402',
|
|
timestamp: time,
|
|
};
|
|
localStorage.setItem('aeroflot_search_history', JSON.stringify([historyItem]));
|
|
}, testTime);
|
|
|
|
await page.reload();
|
|
|
|
// Check for time format HH:MM
|
|
const timeElement = page.locator('[data-testid="landing-search-history-item"] span').last();
|
|
const timeText = await timeElement.textContent();
|
|
expect(timeText).toMatch(/\d{2}:\d{2}/);
|
|
});
|
|
|
|
test('should persist history across page reloads', async ({ page }) => {
|
|
// Add history
|
|
await page.evaluate(() => {
|
|
const historyItem = {
|
|
id: '1',
|
|
label: 'SU 1402',
|
|
url: '/search?flight=SU1402',
|
|
timestamp: Date.now(),
|
|
};
|
|
localStorage.setItem('aeroflot_search_history', JSON.stringify([historyItem]));
|
|
});
|
|
|
|
await page.reload();
|
|
|
|
// Verify it exists
|
|
const items1 = page.locator('[data-testid="landing-search-history-item"]');
|
|
const count1 = await items1.count();
|
|
expect(count1).toBeGreaterThan(0);
|
|
|
|
// Reload again
|
|
await page.reload();
|
|
|
|
// Verify it still exists
|
|
const items2 = page.locator('[data-testid="landing-search-history-item"]');
|
|
const count2 = await items2.count();
|
|
expect(count2).toBe(count1);
|
|
});
|
|
|
|
test('should be responsive on mobile viewport', async ({ page }) => {
|
|
await page.setViewportSize({ width: 375, height: 667 });
|
|
|
|
await page.evaluate(() => {
|
|
const historyItem = {
|
|
id: '1',
|
|
label: 'SU 1402',
|
|
url: '/search?flight=SU1402',
|
|
timestamp: Date.now(),
|
|
};
|
|
localStorage.setItem('aeroflot_search_history', JSON.stringify([historyItem]));
|
|
});
|
|
|
|
await page.reload();
|
|
|
|
const section = page.locator('[data-testid="landing-search-history"]');
|
|
await expect(section).toBeVisible();
|
|
});
|
|
|
|
test('should handle large number of history items', async ({ page }) => {
|
|
// Create 20 history items
|
|
await page.evaluate(() => {
|
|
const historyItems = Array.from({ length: 20 }, (_, i) => ({
|
|
id: String(i + 1),
|
|
label: `SU ${1400 + i}`,
|
|
url: `/search?flight=SU${1400 + i}`,
|
|
timestamp: Date.now() - i * 60000,
|
|
}));
|
|
localStorage.setItem('aeroflot_search_history', JSON.stringify(historyItems));
|
|
});
|
|
|
|
await page.reload();
|
|
|
|
const items = page.locator('[data-testid="landing-search-history-item"]');
|
|
await expect(items).toHaveCount(20);
|
|
});
|
|
|
|
test('should handle corrupted localStorage data gracefully', async ({ page }) => {
|
|
// Corrupt the localStorage
|
|
await page.evaluate(() => {
|
|
localStorage.setItem('aeroflot_search_history', 'corrupted{invalid json');
|
|
});
|
|
|
|
await page.reload();
|
|
|
|
// Should not show history section
|
|
const section = page.locator('[data-testid="landing-search-history"]');
|
|
await expect(section).not.toBeVisible();
|
|
});
|
|
});
|