Full rewrite of Flights/Services/JSXWebViewFetcher.swift implementing a 19-step WKWebView flow that drives the jsx.com one-way search UI, then calls POST /api/nsk/v4/availability/search/simple directly via fetch() from within the page context using the anonymous auth token read from sessionStorage["navitaire.digital.token"]. Why the direct call instead of clicking Find Flights: WKWebView's synthetic MouseEvents have isTrusted=false, and JSX's custom datepicker commits its day-cell selection into the Angular FormControl only on trusted user gestures. The result is that the date input displays "Sat, Apr 11" but the underlying FormControl stays null, so Angular's search() sees form.invalid === true and silently returns without firing a request. Playwright sidesteps this because CDP's Input.dispatchMouseEvent produces trusted events; WKWebView has no equivalent. The fix is to drive the UI steps (for page warm-up and smoke testing) but then call the API directly — the same-origin fetch inherits the browser's cookies and TLS fingerprint so Akamai sees it as legitimate traffic, same as the lowfare/estimate GET that already works through the page. Every step has an action and one or more post-condition verifications. On failure the runner dumps the action's returned data fields, page state (URL, selector counts, form error markers), and both the last initiated AND last completed api.jsx.com calls so network-level blocks and form-validation bails can be distinguished. New return type JSXSearchResult exposes every unique flight from the search/simple response as [JSXFlight] with per-class load breakdowns (classOfService, productClass, availableCount, fareTotal, revenueTotal) so callers can see all flights, not just one. Flights/Services/AirlineLoadService.swift: fetchJSXLoad now consumes the [JSXFlight] array, logs every returned flight, and picks the requested flight by digit-match. Deleted 495 lines of dead JSX helpers (_fetchJSXLoad_oldMultiStep, parseJSXResponse, findJSXJourneys, extractJSXFlightNumber, extractJSXAvailableSeats, collectJSXAvailableCounts, parseJSXLowFareEstimate, normalizeFlightNumber). scripts/jsx_playwright_search.mjs: standalone Playwright reference implementation of the same flow. Launches real Chrome with --remote- debugging-port and attaches via chromium.connectOverCDP() — this bypasses Akamai's fingerprint check on Playwright's own launch and produced the UI-flow steps and per-flight extractor logic that the Swift rewrite mirrors. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
35 KiB
35 KiB