Defines a Playwright-based pipeline for visual screenshot diffing,
behavioral E2E verification, and gap analysis between the Angular
and React implementations. Documents known gaps in flight details,
popular requests logic, and flights map.
- Fix 5 pre-existing failures: default tab is 'route' not 'flight'
- Add test: route search results page hydrates filter from URL params
- Add test (skip): route search form end-to-end (needs live API)
- Add test (skip): calendar strip shows day numbers (needs live API)
- Mark feedback button test as fixme (component not wired in)
Calendar days API returns a 31-char bitmask ('1'=available, '0'=unavailable)
starting from baseDate-1. parseCalendarDays now converts this to yyyyMMdd
date strings matching Angular's search-page-base.component.ts logic.
Calendar strip buttons now show formatted day numbers instead of raw dates.
OnlineBoardFilter now accepts initial values from URL params so the
departure/arrival/date fields are populated on search results pages.
The v7_startTransition warning appeared because react-router 6.30.3
(bundled by Modern.js 2.70.8) emits future flag warnings by default.
A full Modern.js 2→3 upgrade was investigated but blocked by
@module-federation/modern-js ESM incompatibilities with Rsbuild 2.0
(uses __filename and require.resolve in ESM bundles, and the SSR
plugin calls api.modifyWebpackConfig which no longer exists).
Instead, opt into all v7 future flags via runtime.router config.
This silences the warning and prepares the codebase for an eventual
React Router v7 upgrade when the MF plugin catches up.
The [...flights]/page.tsx catch-all generated an incorrect route pattern
(schedule/:/flights) instead of a React Router splat (schedule/*).
Modern.js convention for catch-all routes is $.tsx at the directory level,
not [...param]/page.tsx. Moved to $.tsx and updated param access to use
the "*" splat key.
Fixes: /ru/schedule/SU0012-20220527 and multi-leg URLs now resolve.
Online board filter: use Angular sprite SVG for swap button, add dropdown
chevron to city AutoComplete inputs.
Schedule filter: add swap button between cities, replace two separate
date fields with single range Calendar matching Angular. Fix button text
to "Показать расписание", date label to "Показать расписание на".
Add dropdown chevrons to city inputs.
Null dates broke form submission — the handlers bail early when date
is null. Restore initialization to today/+7 days as before. The
Calendar placeholder prop still provides the format hint when cleared.
Add pixelmatch-based screenshot comparison script that captures Angular
(:4200) and React (:8080) at every route and generates pixel diff images.
Dev server: add mock /api/appSettings endpoint so Angular can bootstrap
when WAF blocks the real API.
Error page: add search input bar, align flex/spacing to Angular SCSS mixins,
match button display and illustration flex.
Online board filter: default to "route" tab expanded (Angular defaults to
route, not flight number).
Start pages: remove extra breadcrumb items — Angular start pages show only
"Главная", not the page title.
PageLayout: hide FeedbackButton — Angular gates it behind
FEEDBACK_BUTTON_AVAILABLE feature flag (off by default).
Schedule: add SearchHistory below filter, time selector fields (timeFrom/timeTo)
for outbound and return flights, breadcrumbs, and bottom description section.
Flights Map: add FILTER_INFO message in filter panel, disabled states on
toggles when no departure/arrival selected (matching Angular logic), breadcrumbs,
and replace plain "Loading..." text with animated spinner matching Angular
loader-sheet component.
Replace 4-radio-button filter with PrimeNG-style accordion (2 tabs: Flight Number, Route).
Add swap button between departure/arrival in route filter, clear button on flight number input,
time selector in route filter, flight number validation with error tooltip.
Add SearchHistory component below filter, Breadcrumbs in page header, FeedbackButton stub,
ScrollUpButton for scroll-to-top. SeoHead already wired on start page route.
All tests updated to match new accordion structure.
Locale switching is handled by the host site (aeroflot.ru), not the
Angular SPA. Removed 13-locale-switching.spec.ts (entire file, 27 tests)
and locale switcher tests from 01-navigation (5 tests) and
18-advanced-features (4 tests).
Cross-app: 213 passed, 146 skipped, 0 failed.
ru-ru: 15 passed, 0 failed.
- Restructure OnlineBoardFilter to use radio tabs (flight/departure/
arrival/route) with dynamic fields matching e2e test expectations
- Fix error page e2e tests to use client-side navigation (SSR renders
empty outside [lang]/layout) and use specific CSS class locators
- Replace deprecated transparentize() with rgba() in _shadows.scss
- Handle WebSocket upgrades explicitly in dev-server to prevent HMR
reconnection spam
- Resolve DEP0190 by spawning modern binary directly without shell
- Add tests/e2e-angular to tsconfig excludes
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.
Modern.js SSR intercepts all routes before any Express middleware,
so the API proxy runs as a separate Express server on port 8080.
Modern.js runs on 8081. The proxy uses curl subprocesses which go
through the system HTTPS proxy (GOST) with a proper TLS fingerprint
that the Aeroflot WAF accepts.
Usage: node scripts/dev-server.mjs (replaces pnpm dev for full-stack)
Also: remove stray e2e-angular test directory, fix env default to
same-origin /api.
Root cause of search not working: globalThis.fetch stored as a class
field loses its Window binding, causing 'Illegal invocation'. Fixed
with fetch.bind(globalThis).
Also fix calendar days endpoint date format from yyyyMMdd to
yyyy-MM-ddT00:00:00 matching Angular's ApiFormatterService.
- Point API_BASE_URL to localhost:4200 (Angular's dev proxy) which
correctly forwards to flights.test.aeroflot.ru with proper headers
- Convert URL date format (yyyyMMdd) to API format (yyyy-MM-ddT00:00:00)
matching Angular's ApiFormatterService behavior
- Add standalone api-proxy.mjs script for running without Angular
- Root page redirect uses both loader and client-side navigate
- SignalR hub URL points to platform.yc.webzavod.ru/tracker/hub
- Remove broken server/modern-js.server.ts (proxy handled externally)
useCitySearch hook loads cities from /api/dictionary/1/cities on first
use, then searches in-memory by name prefix and code -- matching the
Angular CitiesSearchService behavior. Wired into OnlineBoardFilter,
ScheduleStartPage, and FlightsMapFilter AutoComplete components.
API functions now build the full localized path matching the Angular
EndpointService pattern (/api/flights/{version}/{locale}/{endpoint}).
The dev proxy forwards /api and /flights to the test backend.
Tests failed because PageTabs uses Link from @modern-js/runtime/router
which wasn't included in the router mock. Added Link to the router mock,
added mocks for PageTabs, OnlineBoardFilter, and other transitive deps,
and updated error text assertions to match the new Russian strings.
When the API fetch fails (backend unavailable), show a styled white
error card with a Russian-language message and retry button instead
of barely-visible text on a dark background.
Wrap connection.start() in try/catch so that when the SignalR hub is
unreachable the status transitions to "offline" silently instead of
throwing unhandled errors that flood the browser console.
OnlineBoardFilter and ScheduleStartPage city fields now use PrimeReact
AutoComplete for visual parity with Angular's PrimeNG city-autocomplete.
ScheduleStartPage labels switched from hardcoded English to i18n keys.
PopularRequestsPanel uses stable content-based keys instead of array index.
Error page loads i18n translations on mount and supports all locale strings.
PageTabs now reads the FEATURE_FLIGHTS_MAP flag directly via useFeatureFlag
instead of relying on a prop default, matching the Angular page-tabs pattern.
FlightsMapFilter uses PrimeReact AutoComplete and Calendar instead of plain
HTML inputs, with i18n labels. MapCanvas init effect uses refs to avoid
React exhaustive-deps warnings. Root layout imports leaflet CSS and
PrimeReact theme globally. Env schema accepts NODE_ENV "test" for vitest.
- Move public/ to config/public/ (Modern.js serves static files
from config/public/, not public/)
- Add explicit background-size: 45px 45px on info tile icons
- All SVGs, fonts, and images now serve with correct MIME types
Enable flights-map tab by default (showFlightsMap=true) to match Angular
production config where flightsMap feature flag is true. The other three
items (tile icons, body background, popular-requests panel) were already
ported identically in the React SCSS.
Fix search button background to use $blue-light (#4a90e2) matching Angular's
color.blue-light class. Add missing !important flags on PopularRequestsPanel
mobile breakpoint rules to match Angular specificity.
Flights Map now uses PageLayout with PageTabs (flights-map tab active),
filter in content-left column, and map in a .frame section. Added SCSS
for filter panel and map wrapper matching Angular structure.
Error pages now show lady404/lady500 illustrations, large error code,
action buttons matching Angular (Buy Ticket, Home Page, Support), and
proper two-column flex layout with mobile fallback.
Schedule start page now uses PageLayout with PageTabs (schedule tab active),
filter form in content-left column, and the info section with titles-container
and PopularRequests in the main content area. SCSS matches Angular start.scss.
When the API is unavailable the popular requests panel was hidden
because the hook returned empty data on error. Add fallback mock data
matching Angular's test fixtures so the panel renders in dev and
degraded environments.
Add blue background/hover styles to the search button matching Angular's
.color.blue button pattern. Fix page title width to calc(100% - 120px)
matching Angular layout. Conditionally render sticky-content wrapper
to avoid empty DOM nodes.