From c4904df2929b6a37e5a0f7235a14c5abe516ddbe Mon Sep 17 00:00:00 2001 From: j-atkins <106238905+j-atkins@users.noreply.github.com> Date: Mon, 20 Apr 2026 13:10:00 +0200 Subject: [PATCH 1/2] update BLANK -> NULL in response to textual breaking change in v8 --- src/virtualship/cli/_plan.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/virtualship/cli/_plan.py b/src/virtualship/cli/_plan.py index 618906a3..895abf29 100644 --- a/src/virtualship/cli/_plan.py +++ b/src/virtualship/cli/_plan.py @@ -736,7 +736,7 @@ def compose(self) -> ComposeResult: id=f"wp{self.index}_year", value=int(self.waypoint.time.year) if self.waypoint.time - else Select.BLANK, + else Select.NULL, prompt="YYYY", classes="year-select", ) @@ -746,7 +746,7 @@ def compose(self) -> ComposeResult: id=f"wp{self.index}_month", value=int(self.waypoint.time.month) if self.waypoint.time - else Select.BLANK, + else Select.NULL, prompt="MM", classes="month-select", ) @@ -756,7 +756,7 @@ def compose(self) -> ComposeResult: id=f"wp{self.index}_day", value=int(self.waypoint.time.day) if self.waypoint.time - else Select.BLANK, + else Select.NULL, prompt="DD", classes="day-select", ) @@ -766,7 +766,7 @@ def compose(self) -> ComposeResult: id=f"wp{self.index}_hour", value=int(self.waypoint.time.hour) if self.waypoint.time - else Select.BLANK, + else Select.NULL, prompt="hh", classes="hour-select", ) @@ -775,7 +775,7 @@ def compose(self) -> ComposeResult: minute_value = ( int(self.waypoint.time.minute) if self.waypoint.time - else Select.BLANK + else Select.NULL ) # if the current minute is not a multiple of 5, add it to the options From 51eb0ba2c1479821856e3df302df98e44dd03825 Mon Sep 17 00:00:00 2001 From: j-atkins <106238905+j-atkins@users.noreply.github.com> Date: Mon, 20 Apr 2026 13:20:30 +0200 Subject: [PATCH 2/2] add test --- tests/cli/test_plan.py | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/tests/cli/test_plan.py b/tests/cli/test_plan.py index ab4c4228..f0522cde 100644 --- a/tests/cli/test_plan.py +++ b/tests/cli/test_plan.py @@ -150,3 +150,52 @@ async def test_UI_changes(): # cleanup shutil.rmtree(tmpdir) + + +@pytest.mark.asyncio +async def test_UI_opens_with_null_time_and_instrument(): + """Test that the UI opens correctly when waypoints have time: null and instrument: null.""" + tmpdir = Path(tempfile.mkdtemp()) + + instruments_config = InstrumentsConfig.model_validate( + yaml.safe_load(get_example_expedition()).get("instruments_config") + ) + ship_config = yaml.safe_load(get_example_expedition()).get("ship_config") + waypoints = [ + Waypoint( + location=Location(0, 0), + time=datetime(2022, 1, 1, 0, 0, 0), + instrument=["CTD"], + ), + Waypoint( + location=Location(0.01, 0.01), + time=None, + instrument=None, + ), + Waypoint( + location=Location(0.02, 0.02), + time=None, + instrument=None, + ), + ] + expedition = Expedition( + schedule=Schedule(waypoints=waypoints), + instruments_config=instruments_config, + ship_config=ship_config, + ) + + expedition.to_yaml(tmpdir / EXPEDITION) + + app = PlanApp(path=tmpdir) + + async with app.run_test(size=(120, 100)) as pilot: + await pilot.pause(0.5) + + plan_screen = pilot.app.screen + expedition_editor = plan_screen.query_one(ExpeditionEditor) + + # verify the app opened without errors by checking the editor loaded + assert expedition_editor is not None + + # cleanup + shutil.rmtree(tmpdir)