diff --git a/docs/memories/wire_format_quirks.md b/docs/memories/wire_format_quirks.md index 056502ef..bc0bb68b 100644 --- a/docs/memories/wire_format_quirks.md +++ b/docs/memories/wire_format_quirks.md @@ -157,8 +157,9 @@ failure mode otherwise. that combination. These are indistinguishable from the response. Surface a helpful message -("Calendar empty. Matrix's calendar mode brownouts regularly; retry") and -include the deep-link URL so users can verify in the UI. +("Calendar empty. Matrix's calendar mode brownouts regularly; retry, use +flight calendar --fast for Google's date grid, or flight search for a single +date") and include the deep-link URL so users can verify in the UI. A fourth case is NOT one of these and must not wear that message: a fanned-out multi-airport calendar whose sub-queries never answered. There is no response to diff --git a/src/flight_cli/cli.py b/src/flight_cli/cli.py index 4dfea2a3..e7fd5f4c 100644 --- a/src/flight_cli/cli.py +++ b/src/flight_cli/cli.py @@ -5360,8 +5360,8 @@ def _render_calendar( if res.solution_count == 0 or not res.priced_days: console.print( "[yellow]Calendar empty.[/] Matrix's calendar mode " - "brownouts regularly; retry, or use [bold]flight search[/] " - "for a single date." + "brownouts regularly; retry, use [bold]flight calendar --fast[/] " + "for Google's date grid, or [bold]flight search[/] for a single date." ) return # Matrix chose the whole price string. This line parses markup and so does diff --git a/tests/test_calendar_empty_points_at_search.py b/tests/test_calendar_empty_points_at_search.py index c1deb871..844b5335 100644 --- a/tests/test_calendar_empty_points_at_search.py +++ b/tests/test_calendar_empty_points_at_search.py @@ -1,10 +1,12 @@ """An empty Matrix calendar points a one-date search at `flight search`. `flight fare` is a deprecated alias that prints its own deprecation warning, -so the advice beside "Calendar empty." names the command a user should run.""" +so the advice beside "Calendar empty." names the command a user should run. It +also names `flight calendar --fast`, Google's date grid, as the fallback.""" from __future__ import annotations +from pathlib import Path from typing import TYPE_CHECKING import pytest @@ -51,3 +53,25 @@ def test_an_empty_calendar_names_flight_search_for_a_single_date( assert "Calendar empty." in advice assert "flight fare" not in advice assert "flight search" in advice + + +def test_an_empty_calendar_offers_the_fast_google_grid( + monkeypatch: pytest.MonkeyPatch, +) -> None: + _serve_empty(monkeypatch) + result = CliRunner().invoke( + cli.app, [*_ROUTE, "--gf-transport", "http", "--no-cache"], env={"COLUMNS": "200"} + ) + assert result.exit_code == 0, result.output + advice = " ".join(result.stdout.split()) + assert "Calendar empty." in advice + assert "flight calendar --fast" in advice + + +def test_the_brownout_memo_quotes_the_fast_grid_advice() -> None: + memo = Path(__file__).parents[1] / "docs" / "memories" / "wire_format_quirks.md" + text = " ".join(memo.read_text().split()) + assert ( + "retry, use flight calendar --fast for Google's date grid, or flight search " + "for a single date" in text + )