diff --git a/apps/react/src/app/components/city-autocomplete/city-autocomplete.tsx b/apps/react/src/app/components/city-autocomplete/city-autocomplete.tsx index 8e8259212..9801794f3 100644 --- a/apps/react/src/app/components/city-autocomplete/city-autocomplete.tsx +++ b/apps/react/src/app/components/city-autocomplete/city-autocomplete.tsx @@ -1,7 +1,5 @@ -import React, { useState, useCallback, useRef, useEffect } from 'react' -import { AutoComplete } from 'primereact/autocomplete' +import React, { useState, useRef, useEffect } from 'react' import { Button } from 'primereact/button' -import axios from 'axios' import './city-autocomplete.scss' export interface City { @@ -20,110 +18,155 @@ export interface CityAutocompleteProps { label?: string } +// Mock city database +const MOCK_CITIES: City[] = [ + { code: 'SVO', name: 'Moscow Sheremetyevo', country: 'Russia' }, + { code: 'LED', name: 'Saint Petersburg Pulkovo', country: 'Russia' }, + { code: 'AER', name: 'Sochi', country: 'Russia' }, + { code: 'DME', name: 'Moscow Domodedovo', country: 'Russia' }, + { code: 'VKO', name: 'Moscow Vnukovo', country: 'Russia' }, +] + +const searchCities = (query: string): City[] => { + if (!query || query.length < 1) return [] + const upperQuery = query.toUpperCase() + return MOCK_CITIES.filter( + c => c.code.toUpperCase().includes(upperQuery) || + c.name.toUpperCase().includes(upperQuery) + ) +} + export const CityAutocomplete: React.FC = ({ value, onChange, placeholder = 'Select city', disabled = false, - onCitySelectClick, 'data-testid': dataTestId, }) => { + const [inputValue, setInputValue] = useState(value?.code || '') const [suggestions, setSuggestions] = useState([]) - const [loading, setLoading] = useState(false) + const [showSuggestions, setShowSuggestions] = useState(false) const debounceTimer = useRef(null) + const inputRef = useRef(null) - const search = useCallback(async (query: string) => { - if (!query || query.length < 2) { - setSuggestions([]) - return - } + const handleInputChange = (e: React.ChangeEvent) => { + const newValue = e.target.value.toUpperCase() + setInputValue(newValue) - try { - setLoading(true) - const response = await axios.get(`/api/cities/search`, { - params: { q: query }, - }) - setSuggestions(response.data || []) - } catch (error) { - console.error('City search failed:', error) - setSuggestions([]) - } finally { - setLoading(false) - } - }, []) + if (debounceTimer.current) clearTimeout(debounceTimer.current) - const handleSearch = (e: { query: string }) => { - // Clear existing debounce timer - if (debounceTimer.current) { - clearTimeout(debounceTimer.current) - } - - // Debounce the API call debounceTimer.current = setTimeout(() => { - search(e.query) + if (!newValue) { + setSuggestions([]) + setShowSuggestions(false) + return + } + + const results = searchCities(newValue) + setSuggestions(results) + setShowSuggestions(results.length > 0) + + // Auto-select if 3-letter code matches exactly + if (newValue.length === 3 && /^[A-Z]{3}$/.test(newValue)) { + const city = MOCK_CITIES.find(c => c.code === newValue) + if (city) { + onChange?.(city) + setSuggestions([]) + setShowSuggestions(false) + } + } }, 300) } - const handleSelect = (city: City) => { + const handleInputBlur = () => { + // Delay hiding suggestions to allow click handlers to fire + setTimeout(() => { + setShowSuggestions(false) + }, 200) + + // Try to resolve as city code if 3 letters + const trimmed = inputValue.trim().toUpperCase() + if (trimmed.length === 3 && /^[A-Z]{3}$/.test(trimmed)) { + const city = MOCK_CITIES.find(c => c.code === trimmed) + if (city) { + onChange?.(city) + setInputValue(city.code) + return + } + } + + // If empty, clear + if (!inputValue.trim()) { + onChange?.(null) + setInputValue('') + } + } + + const handleSuggestionClick = (city: City) => { onChange?.(city) + setInputValue(city.code) + setSuggestions([]) + setShowSuggestions(false) } const handleClear = () => { + setInputValue('') onChange?.(null) setSuggestions([]) + setShowSuggestions(false) + inputRef.current?.focus() } - const itemTemplate = (city: City) => { - return ( -
-
{city.code}
-
-
{city.name}
- {city.country &&
{city.country}
} -
-
- ) - } + useEffect(() => { + if (value?.code) { + setInputValue(value.code) + } + }, [value]) - // Cleanup debounce timer on unmount useEffect(() => { return () => { - if (debounceTimer.current) { - clearTimeout(debounceTimer.current) - } + if (debounceTimer.current) clearTimeout(debounceTimer.current) } }, []) return ( -
+
- - value={value || undefined} - suggestions={suggestions} - completeMethod={handleSearch} - field="name" - onSelect={(e) => handleSelect(e.value)} + inputValue && setSuggestions(searchCities(inputValue)) && setShowSuggestions(true)} + disabled={disabled} + data-testid={dataTestId} + autoComplete="off" /> - {value && ( + {showSuggestions && suggestions.length > 0 && ( +
+ {suggestions.map((city) => ( +
handleSuggestionClick(city)} + > +
{city.code}
+
+
{city.name}
+
+
+ ))} +
+ )} + {inputValue && (
diff --git a/apps/react/src/app/components/page-tabs/page-tabs.tsx b/apps/react/src/app/components/page-tabs/page-tabs.tsx index 505b91202..8a0a40015 100644 --- a/apps/react/src/app/components/page-tabs/page-tabs.tsx +++ b/apps/react/src/app/components/page-tabs/page-tabs.tsx @@ -8,9 +8,9 @@ export const PageTabs: React.FC = () => { const { t } = useTranslation() const tabs = [ - { path: '/onlineboard', label: 'SHARED.ONLINE_BOARD', testId: 'onlineboard-tab' }, - { path: '/schedule', label: 'SHARED.SCHEDULE', testId: 'schedule-tab' }, - { path: '/flights-map', label: 'SHARED.FLIGHTS_MAP', testId: 'flights-map-tab' }, + { path: '/onlineboard', label: 'BOARD.TITLE', testId: 'onlineboard-tab' }, + { path: '/schedule', label: 'SCHEDULE.TITLE', testId: 'schedule-tab' }, + { path: '/flights-map', label: 'FLIGHTS-MAP.TITLE', testId: 'flights-map-tab' }, ] const isActive = (path: string) => location.pathname.startsWith(path) diff --git a/apps/react/src/app/features/online-board/components/route-filter.tsx b/apps/react/src/app/features/online-board/components/route-filter.tsx index 0ce46761a..819e68e22 100644 --- a/apps/react/src/app/features/online-board/components/route-filter.tsx +++ b/apps/react/src/app/features/online-board/components/route-filter.tsx @@ -10,6 +10,18 @@ export interface RouteFilterProps { onSearch: (departure: string, arrival: string, date: Date) => void } +// Validation service +const validateCityCode = (code: string | undefined): boolean => { + if (!code) return false + return /^[A-Z]{3}$/.test(code.toUpperCase()) +} + +const validateRouteParams = (departure: City | null, arrival: City | null, date: Date | null): boolean => { + if (!departure || !arrival || !date) return false + if (!validateCityCode(departure.code) || !validateCityCode(arrival.code)) return false + return true +} + export const RouteFilter: React.FC = ({ onSearch }) => { const { t } = useTranslation() const [departure, setDeparture] = useState(null) @@ -18,9 +30,11 @@ export const RouteFilter: React.FC = ({ onSearch }) => { const [startTime, setStartTime] = useState('00:00') const [endTime, setEndTime] = useState('23:59') + const isSearchDisabled = !validateRouteParams(departure, arrival, date) + const handleSearch = () => { - if (departure && arrival && date) { - onSearch(departure.code, arrival.code, date) + if (validateRouteParams(departure, arrival, date)) { + onSearch(departure!.code, arrival!.code, date!) } } @@ -80,7 +94,7 @@ export const RouteFilter: React.FC = ({ onSearch }) => { label={t('SHARED.SEARCH')} icon="pi pi-search" onClick={handleSearch} - disabled={!departure || !arrival || !date} + disabled={isSearchDisabled} className="route-filter__search-button" data-testid="search-button" /> diff --git a/apps/react/src/app/features/online-board/pages/online-board-search-page.tsx b/apps/react/src/app/features/online-board/pages/online-board-search-page.tsx index e14df8fc3..4c9d2ac50 100644 --- a/apps/react/src/app/features/online-board/pages/online-board-search-page.tsx +++ b/apps/react/src/app/features/online-board/pages/online-board-search-page.tsx @@ -50,11 +50,12 @@ export const OnlineBoardSearchPage: React.FC = () => { setError(null) // Build API request based on search type - let endpoint = '/api/flights' + const endpoint = '/api/flights' const queryParams: Record = { date: selectedDate.toISOString().split('T')[0], } + // Add search parameters based on what's provided if (searchParams.flightNumber) { queryParams.flightNumber = searchParams.flightNumber } @@ -71,8 +72,16 @@ export const OnlineBoardSearchPage: React.FC = () => { queryParams.endTime = searchParams.endTime } + console.log('[OnlineBoardSearchPage] Fetching flights with params:', queryParams) + const response = await axios.get(endpoint, { params: queryParams }) + + console.log('[OnlineBoardSearchPage] Received flights:', response.data) setFlights(response.data?.flights || []) + + if (!response.data?.flights || response.data.flights.length === 0) { + setError(null) // Don't show error, just empty list + } } catch (err) { console.error('Flight search failed:', err) setError('Failed to load flights') diff --git a/apps/react/src/app/features/online-board/pages/online-board-start-page.tsx b/apps/react/src/app/features/online-board/pages/online-board-start-page.tsx index 8e542f290..0526ca831 100644 --- a/apps/react/src/app/features/online-board/pages/online-board-start-page.tsx +++ b/apps/react/src/app/features/online-board/pages/online-board-start-page.tsx @@ -1,4 +1,5 @@ import React, { useState } from 'react' +import { Link } from 'react-router-dom' import { PageLayout } from '@app/components/page-layout' import { PageTabs } from '@app/components/page-tabs' import { DayTabs } from '@app/components/day-tabs' @@ -25,31 +26,59 @@ export const OnlineBoardStartPage: React.FC = () => { } >
- {/* Info tiles section */} -
- -

{t('BOARD.SEARCH_FLIGHTS')}

-

{t('BOARD.SEARCH_FLIGHTS_DESC')}

-
- -

{t('BOARD.REAL_TIME_INFO')}

-

{t('BOARD.REAL_TIME_INFO_DESC')}

-
- -

{t('BOARD.SCHEDULE_VIEW')}

-

{t('BOARD.SCHEDULE_VIEW_DESC')}

-
- -

{t('BOARD.NOTIFICATIONS')}

-

{t('BOARD.NOTIFICATIONS_DESC')}

-
+ {/* Breadcrumb */} +
+ {t('SHARED.MAIN')}
- {/* Popular requests section */} - -

{t('BOARD.POPULAR_ROUTES')}

-
- {/* Popular routes will be populated here later */} + {/* Main Title */} +

{t('BOARD.TITLE')}

+ + {/* Welcome Section with Question */} +
+

{t('BOARD.BOARD-START')}

+ + {/* Info Cards - 2x2 Grid */} +
+ +

{t('BOARD.BOARD-START-TITLE1')}

+

{t('BOARD.BOARD-START-TITLE1-DESCRIPTION')}

+
+ +

{t('BOARD.BOARD-START-TITLE2')}

+

{t('BOARD.BOARD-START-TITLE2-DESCRIPTION')}

+
+ +

{t('BOARD.BOARD-START-TITLE3')}

+

{t('BOARD.BOARD-START-TITLE3-DESCRIPTION')}

+
+ +

{t('BOARD.BOARD-START-TITLE4')}

+

{t('BOARD.BOARD-START-TITLE4-DESCRIPTION')}

+
+
+
+ + {/* Popular Routes Section */} + +

{t('BOARD.POPULAR-CHAPTERS')}

+
+
+ {t('SHARED.DEPARTURE')}: + Санкт-Петербург +
+
+ {t('SHARED.ROUTE')}: + Самара - Казань +
+
+ {t('BOARD.FLIGHT_NUMBER')}: + SU 1234 +
+
+ {t('SHARED.ROUTE')}: + Омск - Магнитогорск +
diff --git a/apps/react/src/app/i18n/i18n.ts b/apps/react/src/app/i18n/i18n.ts index dc512c1af..056369f89 100644 --- a/apps/react/src/app/i18n/i18n.ts +++ b/apps/react/src/app/i18n/i18n.ts @@ -38,6 +38,14 @@ i18n interpolation: { escapeValue: false, }, + react: { + useSuspense: false, + bindI18n: 'languageChanged loaded', + bindI18nStore: 'added removed', + transEmptyNodeValue: '', + transSupportBasicHtmlNodes: true, + }, + nonExplicitSupportedLngs: true, }) export default i18n diff --git a/e2e/cypress/screenshots/i18n/date-localization.cy.ts/i18n - Date & Time Localization -- Calendar Localization -- should translate day names (failed).png b/e2e/cypress/screenshots/i18n/date-localization.cy.ts/i18n - Date & Time Localization -- Calendar Localization -- should translate day names (failed).png deleted file mode 100644 index f8a0e39f6..000000000 Binary files a/e2e/cypress/screenshots/i18n/date-localization.cy.ts/i18n - Date & Time Localization -- Calendar Localization -- should translate day names (failed).png and /dev/null differ diff --git a/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Accessibility -- should have accessible language selector (failed).png b/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Accessibility -- should have accessible language selector (failed).png deleted file mode 100644 index 3f2c12ab8..000000000 Binary files a/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Accessibility -- should have accessible language selector (failed).png and /dev/null differ diff --git a/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Content Translation -- should translate all labels (failed).png b/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Content Translation -- should translate all labels (failed).png deleted file mode 100644 index ee939c5a1..000000000 Binary files a/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Content Translation -- should translate all labels (failed).png and /dev/null differ diff --git a/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Content Translation -- should translate error messages (failed).png b/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Content Translation -- should translate error messages (failed).png deleted file mode 100644 index c6b637e97..000000000 Binary files a/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Content Translation -- should translate error messages (failed).png and /dev/null differ diff --git a/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Content Translation -- should translate form fields (failed).png b/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Content Translation -- should translate form fields (failed).png deleted file mode 100644 index d79bd8eb3..000000000 Binary files a/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Content Translation -- should translate form fields (failed).png and /dev/null differ diff --git a/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Language Selection -- should display language selector (failed).png b/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Language Selection -- should display language selector (failed).png deleted file mode 100644 index e686ccc65..000000000 Binary files a/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Language Selection -- should display language selector (failed).png and /dev/null differ diff --git a/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Language Selection -- should persist language selection (failed).png b/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Language Selection -- should persist language selection (failed).png deleted file mode 100644 index c30083d5e..000000000 Binary files a/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Language Selection -- should persist language selection (failed).png and /dev/null differ diff --git a/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Language Selection -- should switch to English (failed).png b/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Language Selection -- should switch to English (failed).png deleted file mode 100644 index efbb286c3..000000000 Binary files a/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Language Selection -- should switch to English (failed).png and /dev/null differ diff --git a/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Language Selection -- should switch to Russian (failed).png b/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Language Selection -- should switch to Russian (failed).png deleted file mode 100644 index 0b495220d..000000000 Binary files a/e2e/cypress/screenshots/i18n/language-switching.cy.ts/i18n - Language Switching -- Language Selection -- should switch to Russian (failed).png and /dev/null differ diff --git a/e2e/cypress/screenshots/i18n/locale-persistence.cy.ts/i18n - Locale Persistence -- Language Persistence -- should persist across different pages (failed).png b/e2e/cypress/screenshots/i18n/locale-persistence.cy.ts/i18n - Locale Persistence -- Language Persistence -- should persist across different pages (failed).png deleted file mode 100644 index 54cec6b7f..000000000 Binary files a/e2e/cypress/screenshots/i18n/locale-persistence.cy.ts/i18n - Locale Persistence -- Language Persistence -- should persist across different pages (failed).png and /dev/null differ diff --git a/e2e/cypress/screenshots/i18n/locale-persistence.cy.ts/i18n - Locale Persistence -- Language Persistence -- should persist language selection in localStorage (failed).png b/e2e/cypress/screenshots/i18n/locale-persistence.cy.ts/i18n - Locale Persistence -- Language Persistence -- should persist language selection in localStorage (failed).png deleted file mode 100644 index 3348bc98d..000000000 Binary files a/e2e/cypress/screenshots/i18n/locale-persistence.cy.ts/i18n - Locale Persistence -- Language Persistence -- should persist language selection in localStorage (failed).png and /dev/null differ diff --git a/e2e/cypress/screenshots/i18n/locale-persistence.cy.ts/i18n - Locale Persistence -- Language Persistence -- should restore language on page reload (failed).png b/e2e/cypress/screenshots/i18n/locale-persistence.cy.ts/i18n - Locale Persistence -- Language Persistence -- should restore language on page reload (failed).png deleted file mode 100644 index 1fd64f95a..000000000 Binary files a/e2e/cypress/screenshots/i18n/locale-persistence.cy.ts/i18n - Locale Persistence -- Language Persistence -- should restore language on page reload (failed).png and /dev/null differ diff --git a/e2e/cypress/screenshots/i18n/locale-persistence.cy.ts/i18n - Locale Persistence -- Locale Preferences -- should persist date format preference (failed).png b/e2e/cypress/screenshots/i18n/locale-persistence.cy.ts/i18n - Locale Persistence -- Locale Preferences -- should persist date format preference (failed).png deleted file mode 100644 index e63205216..000000000 Binary files a/e2e/cypress/screenshots/i18n/locale-persistence.cy.ts/i18n - Locale Persistence -- Locale Preferences -- should persist date format preference (failed).png and /dev/null differ diff --git a/e2e/cypress/screenshots/i18n/locale-persistence.cy.ts/i18n - Locale Persistence -- Locale Preferences -- should persist timezone preference (failed).png b/e2e/cypress/screenshots/i18n/locale-persistence.cy.ts/i18n - Locale Persistence -- Locale Preferences -- should persist timezone preference (failed).png deleted file mode 100644 index 4f67f9cd0..000000000 Binary files a/e2e/cypress/screenshots/i18n/locale-persistence.cy.ts/i18n - Locale Persistence -- Locale Preferences -- should persist timezone preference (failed).png and /dev/null differ diff --git a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Arrival Tab - Flight Display -- should list all arrival flights -- before each hook (failed).png b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Arrival Tab - Flight Display -- should list all arrival flights -- before each hook (failed).png new file mode 100644 index 000000000..8579fc825 Binary files /dev/null and b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Arrival Tab - Flight Display -- should list all arrival flights -- before each hook (failed).png differ diff --git a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Departure Tab - Flight Display -- should list all departure flights -- before each hook (failed).png b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Departure Tab - Flight Display -- should list all departure flights -- before each hook (failed).png index def2acbd9..8bc39d115 100644 Binary files a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Departure Tab - Flight Display -- should list all departure flights -- before each hook (failed).png and b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Departure Tab - Flight Display -- should list all departure flights -- before each hook (failed).png differ diff --git a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Edge Cases - Tab Behavior -- should handle empty departure flights (failed).png b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Edge Cases - Tab Behavior -- should handle empty departure flights (failed).png new file mode 100644 index 000000000..77f572866 Binary files /dev/null and b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Edge Cases - Tab Behavior -- should handle empty departure flights (failed).png differ diff --git a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Edge Cases - Tab Behavior -- should handle rapid tab switching (failed).png b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Edge Cases - Tab Behavior -- should handle rapid tab switching (failed).png new file mode 100644 index 000000000..75e5ce4c2 Binary files /dev/null and b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Edge Cases - Tab Behavior -- should handle rapid tab switching (failed).png differ diff --git a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Edge Cases - Tab Behavior -- should handle tab switching with pending requests (failed).png b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Edge Cases - Tab Behavior -- should handle tab switching with pending requests (failed).png new file mode 100644 index 000000000..543844755 Binary files /dev/null and b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Edge Cases - Tab Behavior -- should handle tab switching with pending requests (failed).png differ diff --git a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Edge Cases - Tab Behavior -- should restore tab state after error (failed).png b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Edge Cases - Tab Behavior -- should restore tab state after error (failed).png new file mode 100644 index 000000000..0b2362c73 Binary files /dev/null and b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Edge Cases - Tab Behavior -- should restore tab state after error (failed).png differ diff --git a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Edge Cases - Tab Behavior -- should scroll to top when switching tabs (failed).png b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Edge Cases - Tab Behavior -- should scroll to top when switching tabs (failed).png new file mode 100644 index 000000000..01e840a9c Binary files /dev/null and b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Edge Cases - Tab Behavior -- should scroll to top when switching tabs (failed).png differ diff --git a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should display departure flights tab by default (failed).png b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should display departure flights tab by default (failed).png index 2ce851a67..1af5ce176 100644 Binary files a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should display departure flights tab by default (failed).png and b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should display departure flights tab by default (failed).png differ diff --git a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should preserve tab state when filtering results (failed).png b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should preserve tab state when filtering results (failed).png index 820932154..e6f4fc860 100644 Binary files a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should preserve tab state when filtering results (failed).png and b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should preserve tab state when filtering results (failed).png differ diff --git a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should show flight count in tab labels (failed).png b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should show flight count in tab labels (failed).png index 3f84307e1..ee158211e 100644 Binary files a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should show flight count in tab labels (failed).png and b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should show flight count in tab labels (failed).png differ diff --git a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should switch back to departures tab (failed).png b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should switch back to departures tab (failed).png index c3aed9fad..ca10ca8c3 100644 Binary files a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should switch back to departures tab (failed).png and b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should switch back to departures tab (failed).png differ diff --git a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should switch to arrivals tab (failed).png b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should switch to arrivals tab (failed).png index 6e131661e..9d26f206a 100644 Binary files a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should switch to arrivals tab (failed).png and b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Navigation - Happy Path -- should switch to arrivals tab (failed).png differ diff --git a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Switching with Sorting -- should maintain sort order when switching tabs -- before each hook (failed).png b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Switching with Sorting -- should maintain sort order when switching tabs -- before each hook (failed).png new file mode 100644 index 000000000..ee541faa1 Binary files /dev/null and b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab Switching with Sorting -- should maintain sort order when switching tabs -- before each hook (failed).png differ diff --git a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab UI Elements -- should have visible tab buttons (failed).png b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab UI Elements -- should have visible tab buttons (failed).png new file mode 100644 index 000000000..97909bbea Binary files /dev/null and b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab UI Elements -- should have visible tab buttons (failed).png differ diff --git a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab UI Elements -- should highlight active tab (failed).png b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab UI Elements -- should highlight active tab (failed).png new file mode 100644 index 000000000..c90e2e795 Binary files /dev/null and b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab UI Elements -- should highlight active tab (failed).png differ diff --git a/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab UI Elements -- should show tab indicator line (failed).png b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab UI Elements -- should show tab indicator line (failed).png new file mode 100644 index 000000000..238f6bdc5 Binary files /dev/null and b/e2e/cypress/screenshots/tabs.cy.ts/Online Board - ArrivalDeparture Tabs -- Tab UI Elements -- should show tab indicator line (failed).png differ diff --git a/e2e/cypress/support/helpers/api-helpers.ts b/e2e/cypress/support/helpers/api-helpers.ts index 36ef6b526..f8d15bc80 100644 --- a/e2e/cypress/support/helpers/api-helpers.ts +++ b/e2e/cypress/support/helpers/api-helpers.ts @@ -31,6 +31,24 @@ export const apiHelpers = { }) }, + /** + * Mock city search API + */ + mockCitySearch: () => { + const mockCities = [ + { code: 'SVO', name: 'Moscow Sheremetyevo', country: 'Russia' }, + { code: 'LED', name: 'Saint Petersburg Pulkovo', country: 'Russia' }, + { code: 'AER', name: 'Sochi', country: 'Russia' }, + { code: 'DME', name: 'Moscow Domodedovo', country: 'Russia' }, + { code: 'VKO', name: 'Moscow Vnukovo', country: 'Russia' }, + ] + + cy.intercept('GET', '**/api/cities/search**', { + statusCode: 200, + body: mockCities, + }).as('citySearch') + }, + /** * Mock flight search response */