Files
ciaovolo/flight-comparator/tests/confirmed_flights.json
domverse 6421f83ca7 Add flight comparator web app with full scan pipeline
Full-stack flight price scanner built on fast-flights v3 (SOCS cookie bypass):

Backend (FastAPI + SQLite):
- REST API with rate limiting, Pydantic v2 validation, paginated responses
- Scan pipeline: resolves airports, queries every day in the window, saves
  individual flights + aggregate route stats to SQLite
- Background async scan processor with real-time progress tracking
- Airport search endpoint backed by OpenFlights dataset
- Daily scan window (all dates, not monthly samples)

Frontend (React 19 + TypeScript + Tailwind CSS v4):
- Dashboard with live scan status and recent scans
- Create scan form: country mode or specific airports (searchable dropdown)
- Scan detail page with expandable route rows showing individual flights
  (date, airline, departure, arrival, price) loaded on demand
- AirportSearch component with debounced live search and multi-select

Database:
- scans → routes → flights schema with FK cascade and auto-update triggers
- Migrations for schema evolution (relaxed country constraint)

Tests:
- 74 tests: unit + integration, isolated per-test SQLite DB
- Confirmed flight fixtures in tests/confirmed_flights.json (50 real flights,
  BDS→FMM Ryanair + BDS→DUS Eurowings, scraped Feb 2026)
- Integration tests parametrized from confirmed routes

Docker:
- Multi-stage builds, Compose orchestration, Nginx reverse proxy

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 17:11:51 +01:00

97 lines
6.5 KiB
JSON

{
"_meta": {
"description": "Confirmed real flights from live Google Flights queries, scraped via fast-flights v3 with SOCS cookie. Used as ground truth for integration tests.",
"source_scan_id": 54,
"origin": "BDS",
"window": "2026-02-26 to 2026-05-27",
"scraped_at": "2026-02-25",
"total_flights": 50
},
"routes": {
"BDS-FMM": {
"origin": "BDS",
"destination": "FMM",
"airline": "Ryanair",
"flight_count": 39,
"min_price": 15.0,
"max_price": 193.0,
"flights": [
{"date": "2026-04-01", "departure": "09:20", "arrival": "11:10", "price": 15.0},
{"date": "2026-03-30", "departure": "18:45", "arrival": "20:35", "price": 21.0},
{"date": "2026-04-22", "departure": "09:20", "arrival": "11:10", "price": 24.0},
{"date": "2026-04-02", "departure": "09:40", "arrival": "11:30", "price": 26.0},
{"date": "2026-04-17", "departure": "19:35", "arrival": "21:25", "price": 27.0},
{"date": "2026-04-24", "departure": "19:35", "arrival": "21:25", "price": 27.0},
{"date": "2026-03-29", "departure": "10:05", "arrival": "11:55", "price": 29.0},
{"date": "2026-05-11", "departure": "18:45", "arrival": "20:35", "price": 30.0},
{"date": "2026-04-15", "departure": "09:20", "arrival": "11:10", "price": 31.0},
{"date": "2026-05-07", "departure": "09:40", "arrival": "11:30", "price": 32.0},
{"date": "2026-04-23", "departure": "09:40", "arrival": "11:30", "price": 34.0},
{"date": "2026-04-16", "departure": "09:40", "arrival": "11:30", "price": 35.0},
{"date": "2026-05-20", "departure": "09:20", "arrival": "11:10", "price": 35.0},
{"date": "2026-04-27", "departure": "18:45", "arrival": "20:35", "price": 40.0},
{"date": "2026-05-06", "departure": "09:20", "arrival": "11:10", "price": 40.0},
{"date": "2026-04-20", "departure": "18:45", "arrival": "20:35", "price": 41.0},
{"date": "2026-04-29", "departure": "09:20", "arrival": "11:10", "price": 41.0},
{"date": "2026-05-13", "departure": "09:20", "arrival": "11:10", "price": 44.0},
{"date": "2026-04-26", "departure": "10:05", "arrival": "11:55", "price": 45.0},
{"date": "2026-05-21", "departure": "09:40", "arrival": "11:30", "price": 46.0},
{"date": "2026-04-13", "departure": "18:45", "arrival": "20:35", "price": 48.0},
{"date": "2026-05-14", "departure": "09:40", "arrival": "11:30", "price": 48.0},
{"date": "2026-05-27", "departure": "09:20", "arrival": "11:10", "price": 48.0},
{"date": "2026-04-19", "departure": "10:05", "arrival": "11:55", "price": 51.0},
{"date": "2026-04-03", "departure": "19:35", "arrival": "21:25", "price": 55.0},
{"date": "2026-04-30", "departure": "09:40", "arrival": "11:30", "price": 58.0},
{"date": "2026-05-10", "departure": "10:05", "arrival": "11:55", "price": 63.0},
{"date": "2026-04-05", "departure": "10:05", "arrival": "11:55", "price": 65.0},
{"date": "2026-04-10", "departure": "19:35", "arrival": "21:25", "price": 72.0},
{"date": "2026-04-09", "departure": "09:40", "arrival": "11:30", "price": 78.0},
{"date": "2026-05-25", "departure": "18:45", "arrival": "20:35", "price": 81.0},
{"date": "2026-05-04", "departure": "18:45", "arrival": "20:35", "price": 82.0},
{"date": "2026-05-18", "departure": "18:45", "arrival": "20:35", "price": 84.0},
{"date": "2026-04-08", "departure": "09:20", "arrival": "11:10", "price": 96.0},
{"date": "2026-05-24", "departure": "10:05", "arrival": "11:55", "price": 108.0},
{"date": "2026-05-03", "departure": "10:05", "arrival": "11:55", "price": 134.0},
{"date": "2026-04-06", "departure": "18:45", "arrival": "20:35", "price": 144.0},
{"date": "2026-04-12", "departure": "10:05", "arrival": "11:55", "price": 146.0},
{"date": "2026-05-17", "departure": "10:05", "arrival": "11:55", "price": 193.0}
],
"notes": "Ryanair operates ~5-6x/week. Two daily slots: morning (09:20/09:40/10:05) and evening (18:45/19:35). Season starts late March 2026."
},
"BDS-DUS": {
"origin": "BDS",
"destination": "DUS",
"airline": "Eurowings",
"flight_count": 11,
"min_price": 40.0,
"max_price": 270.0,
"flights": [
{"date": "2026-04-04", "departure": "09:20", "arrival": "11:40", "price": 40.0},
{"date": "2026-05-12", "departure": "19:45", "arrival": "22:05", "price": 90.0},
{"date": "2026-04-18", "departure": "11:20", "arrival": "13:40", "price": 120.0},
{"date": "2026-04-25", "departure": "11:20", "arrival": "13:40", "price": 120.0},
{"date": "2026-05-09", "departure": "11:20", "arrival": "13:40", "price": 120.0},
{"date": "2026-05-19", "departure": "19:45", "arrival": "22:05", "price": 140.0},
{"date": "2026-05-23", "departure": "11:20", "arrival": "13:40", "price": 160.0},
{"date": "2026-05-26", "departure": "19:45", "arrival": "22:05", "price": 160.0},
{"date": "2026-05-02", "departure": "11:20", "arrival": "13:40", "price": 240.0},
{"date": "2026-04-11", "departure": "09:20", "arrival": "11:40", "price": 270.0},
{"date": "2026-05-16", "departure": "11:20", "arrival": "13:40", "price": 270.0}
],
"notes": "Eurowings operates Saturdays only (verified: all 11 dates are Saturdays). Two time slots: morning (09:20 or 11:20) and evening (19:45). Cheapest in April."
}
},
"confirmed_dates_for_testing": {
"description": "Specific (origin, destination, date) tuples confirmed to return >=1 flight from the live API. Safe to use in integration tests without risk of flakiness due to no-service days.",
"entries": [
{"origin": "BDS", "destination": "FMM", "date": "2026-04-01", "min_flights": 1, "airline": "Ryanair", "price": 15.0},
{"origin": "BDS", "destination": "FMM", "date": "2026-04-15", "min_flights": 1, "airline": "Ryanair", "price": 31.0},
{"origin": "BDS", "destination": "FMM", "date": "2026-05-07", "min_flights": 1, "airline": "Ryanair", "price": 32.0},
{"origin": "BDS", "destination": "DUS", "date": "2026-04-04", "min_flights": 1, "airline": "Eurowings", "price": 40.0},
{"origin": "BDS", "destination": "DUS", "date": "2026-04-18", "min_flights": 1, "airline": "Eurowings", "price": 120.0},
{"origin": "BDS", "destination": "DUS", "date": "2026-05-09", "min_flights": 1, "airline": "Eurowings", "price": 120.0},
{"origin": "BDS", "destination": "DUS", "date": "2026-05-23", "min_flights": 1, "airline": "Eurowings", "price": 160.0}
]
}
}