async def test_selectcomp_view_existing(storage_dir, activity_testbed) -> None: # GIVEN details_screen = activity_testbed.mock( "compman.ui.compdetails.CompetitionDetailsScreen") storage.save_competition(storage.StoredCompetition("one", title="One")) storage.save_competition(storage.StoredCompetition("two", title="Two")) # WHEN async with activity_testbed.shown(SelectCompetitionScreen) as act: content = activity_testbed.render() assert "One" in content assert "Two" in content focus = activity_testbed.get_focus_widgets()[-1] assert focus.get_label() == "One" await activity_testbed.keypress("enter") # THEN selected = act.response.result() assert selected.id == "one" settings = storage.get_settings() assert settings.current_competition_id == "one"
async def test_taskdownload_refresh_api(storage_dir, soarscore, widget_testbed) -> None: comp = storage.StoredCompetition( "test", "Test Competition", soaringspot_url="http://soaringspot.com/test", selected_class="Club", ) act = ActivityStub(urwid.SolidFill("T")) wdg = TaskDownloadWidget(act, comp) wtb = widget_testbed.for_widget(wdg) soarscore.tasks = [] await act.wait_for_tasks() rendered = wtb.render() assert "No task for today" in rendered # When refresh() is called soarscore.tasks = [ SoarScoreTaskInfo( comp_class="Club", title="Club Task", day_no=1, task_no=1, timestamp="now", task_url="http://soarscore.com/club.tsk", ), ] wdg.refresh() # Then view should be updated - no todays task in this case await act.wait_for_tasks() rendered = wtb.render() assert "Club Task day 1 task 1" in rendered
async def test_soaringspot_existing(storage_dir: str, soaringspot: SoaringSpotFixture, activity_testbed: ActivityTestbed) -> None: # GIVEN storage.save_competition(storage.StoredCompetition(id="one", title="One")) soaringspot.competitions = [ SoaringSpotContest( id="one", href="http://soaringspot.local/one", title="One", description="First contest", ), SoaringSpotContest( id="two", href="http://soaringspot.local/two", title="Two", description="Second contest", ), ] # WHEN async with activity_testbed.shown(SoaringSpotPickerScreen): await activity_testbed.gather_tasks() focused = activity_testbed.get_focus_widgets()[-1] assert focused.get_label() == "One" assert "First contest" in activity_testbed.render() await activity_testbed.keypress("enter") # THEN res = await activity_testbed.response() assert isinstance(res, storage.StoredCompetition) assert res.id == "one" assert res.title == "One" assert res.soaringspot_url == "http://soaringspot.local/one"
async def test_mainmenu_details_after_select(storage_dir, activity_testbed) -> None: welcome_screen = activity_testbed.mock("compman.ui.welcome.WelcomeScreen") select_screen = activity_testbed.mock( "compman.ui.selectcomp.SelectCompetitionScreen") details_screen = activity_testbed.mock( "compman.ui.compdetails.CompetitionDetailsScreen") async with activity_testbed.shown(MainMenuScreen) as act: await asyncio.sleep(0) # WHEN assert welcome_screen.shown # Go back to main menu await activity_testbed.keypress("esc") # There should be only one option now: select competition focused = activity_testbed.get_focus_widgets()[-1] assert focused.get_label() == "Select Competition" await activity_testbed.keypress("enter") assert select_screen.shown selected = storage.StoredCompetition("test", "Test Competition") # breakpoint() select_screen.finish(selected) await asyncio.sleep(0) # receive competition from selector await asyncio.sleep(0) # run the details screen assert details_screen.shown
async def test_mainmenu_details(storage_dir, activity_testbed) -> None: # GIVEN welcome_screen = activity_testbed.mock("compman.ui.welcome.WelcomeScreen") details_screen = activity_testbed.mock( "compman.ui.compdetails.CompetitionDetailsScreen") async with activity_testbed.shown(MainMenuScreen): # WHEN await asyncio.sleep(0) assert welcome_screen.shown comp = storage.StoredCompetition("test", "Test competition") storage.save_competition(comp) settings = storage.get_settings() settings.current_competition_id = comp.id await activity_testbed.keypress("esc") contents = activity_testbed.render() assert "Current Competition" in contents focused = activity_testbed.get_focus_widgets()[-1] assert focused.get_label() == "Current Competition" await activity_testbed.keypress("enter") # THEN assert details_screen.shown
async def test_taskdownload_no_ss_url(storage_dir, soarscore, widget_testbed) -> None: comp = storage.StoredCompetition("test", "Test Competition",) act = ActivityStub(urwid.SolidFill("T")) wdg = TaskDownloadWidget(act, comp) wtb = widget_testbed.for_widget(wdg) # When soaringspot url is missing, do not fetch current tasks rendered = wtb.render() assert rendered.strip() == ""
def _setup_test_comp() -> storage.StoredCompetition: comp = storage.StoredCompetition( id="test", title="Test Competition", soaringspot_url="https://soaringspot.local/test", ) storage.save_competition(comp, set_current=True) return comp
def sample_competition(storage_dir): comp = storage.StoredCompetition("test", "Test competition") storage.save_competition(comp) settings = storage.get_settings() settings.current_competition_id = comp.id storage.save_settings() try: yield comp finally: settings.current_competition_id = None storage.save_settings() storage.delete_competition(comp.id)
def test_get_waypoint_files(storage_dir) -> None: # GIVEN comp = storage.StoredCompetition(id="first", title="First Competition") storage.save_competition(comp) # WHEN storage.store_file("first", "waypoint.cup", io.BytesIO(b"test")) files = storage.get_waypoint_files("first") assert [f.name for f in files] == ["waypoint.cup"] files = storage.get_airspace_files("first") assert files == []
def _on_competition_selected( self, btn: urwid.Widget, sscomp: soaringspot.SoaringSpotContest) -> None: comp = storage.load_competition(sscomp.id) if comp is not None: comp.title = sscomp.title comp.soaringspot_url = sscomp.href else: comp = storage.StoredCompetition(id=sscomp.id, title=sscomp.title, soaringspot_url=sscomp.href) storage.save_competition(comp) self._emit("select", comp)
async def test_taskdownload_task_download( storage_dir, soarscore, widget_testbed ) -> None: state = {"downloading_task": None} def _on_download_task(ev, task): state["downloading_task"] = task comp = storage.StoredCompetition( "test", "Test Competition", soaringspot_url="http://soaringspot.com/test", selected_class="Club", ) act = ActivityStub(urwid.SolidFill("T")) wdg = TaskDownloadWidget(act, comp) urwid.connect_signal(wdg, "download", _on_download_task) wtb = widget_testbed.for_widget(wdg) soarscore.tasks = [ SoarScoreTaskInfo( comp_class="Club", title="Club Task", day_no=1, task_no=1, timestamp="now", task_url="http://soarscore.com/club.tsk", ), SoarScoreTaskInfo( comp_class="Standard", title="Standard Task", day_no=1, task_no=1, timestamp="now", task_url="http://soarscore.com/standard.tsk", ), ] await act.wait_for_tasks() rendered = wtb.render() assert "Club Task day 1 task 1" in rendered # When we click download focused = wtb.get_focus_widgets()[-1] assert focused.label == "Download" await wtb.keypress("enter") # "download" event emits assert state["downloading_task"] is not None tsk = state["downloading_task"] assert tsk.title == "Club Task"
async def test_taskdownload_noclasses(storage_dir, soarscore, widget_testbed) -> None: comp = storage.StoredCompetition( "test", "Test Competition", soaringspot_url="http://soaringspot.com/test" ) act = ActivityStub(urwid.SolidFill("T")) wdg = TaskDownloadWidget(act, comp) wtb = widget_testbed.for_widget(wdg) # await act.wait_for_tasks() await asyncio.sleep(0) assert "Fetching today's task..." in wtb.render() # When classes are not known, we cannot pick task await act.wait_for_tasks() assert "Select competition class to download task" in wtb.render()
async def test_taskdownload_notask(storage_dir, soarscore, widget_testbed) -> None: comp = storage.StoredCompetition( "test", "Test Competition", soaringspot_url="http://soaringspot.com/test", selected_class="Club", ) act = ActivityStub(urwid.SolidFill("T")) wdg = TaskDownloadWidget(act, comp) wtb = widget_testbed.for_widget(wdg) await act.wait_for_tasks() rendered = wtb.render() assert "No task for today" in rendered assert "Refresh" in rendered
async def test_classselector_no_comp_url(storage_dir, widget_testbed) -> None: # GIVEN comp = storage.StoredCompetition("test", "Test Competition") act = ActivityStub(urwid.SolidFill("T")) # WHEN wdg = CompetitionClassSelectorWidget(act, comp) wtb = widget_testbed.for_widget(wdg) await act.wait_for_tasks() # THEN rendered = wtb.render() # When soaringspot url is not specified, we don't render class selector assert rendered.strip() == ""
def test_save_competition(storage_dir) -> None: # GIVEN comp = storage.StoredCompetition( id="first", title="First Competition", soaringspot_url="http://localhost", airspace="airspace.txt", waypoints="waypoints.txt", ) # WHEN storage.save_competition(comp) # THEN comps = storage.list_competitions() assert [c.id for c in comps] == ["first"]
async def test_classselector_fetch_error(storage_dir, soaringspot, widget_testbed) -> None: comp = storage.StoredCompetition( "test", "Test Competition", soaringspot_url="http://soaringspot.com/test") act = ActivityStub(urwid.SolidFill("T")) soaringspot.fetch_clases_exc = SoaringSpotClientError("Test error") wdg = CompetitionClassSelectorWidget(act, comp) wtb = widget_testbed.for_widget(wdg) await act.wait_for_tasks() assert "Error fetching competition classes: Test error" in wtb.render()
async def test_classselector_cancel_selection(storage_dir, soaringspot, widget_testbed) -> None: soaringspot.classes = [] comp = storage.StoredCompetition( "test", "Test Competition", soaringspot_url="http://soaringspot.com/test", classes=["Club", "Standard"], selected_class="Club", ) act = ActivityStub(urwid.SolidFill("T")) wdg = CompetitionClassSelectorWidget(act, comp) wtb = widget_testbed.for_widget(wdg) rendered = wtb.render() assert "Competition class" in rendered assert "Club" in rendered # Press "Change" focused = wtb.get_focus_widgets()[-1] assert "Change" in focused.label await wtb.keypress("enter") # There are no classes for this competition anymore await act.wait_for_tasks() rendered = wtb.render() assert "No classes available for this competition" in rendered assert "Club" not in rendered assert "Standard" not in rendered assert "Cancel" in rendered # Press cancel await wtb.keypress("down") focused = wtb.get_focus_widgets()[-1] assert "Cancel" in focused.label await wtb.keypress("enter") # Previously selected class is kept around rendered = wtb.render() assert "Competition class" in rendered assert "Club" in rendered assert wdg.selectable() is False
async def test_selectcomp_new_comp_select(storage_dir, activity_testbed) -> None: sspicker_screen = activity_testbed.mock( "compman.ui.soaringspot.SoaringSpotPickerScreen") sspicker_screen.result = storage.StoredCompetition("one", title="One") details_screen = activity_testbed.mock( "compman.ui.compdetails.CompetitionDetailsScreen") async with activity_testbed.shown(SelectCompetitionScreen) as act: focus = activity_testbed.get_focus_widgets()[-1] assert "New competition" in focus.get_label() await activity_testbed.keypress("enter") assert sspicker_screen.shown selected = act.response.result() assert selected.id == "one"
async def test_taskdownload_refresh_btn(storage_dir, soarscore, widget_testbed) -> None: comp = storage.StoredCompetition( "test", "Test Competition", soaringspot_url="http://soaringspot.com/test", selected_class="Club", ) act = ActivityStub(urwid.SolidFill("T")) wdg = TaskDownloadWidget(act, comp) wtb = widget_testbed.for_widget(wdg) soarscore.tasks = [ SoarScoreTaskInfo( comp_class="Club", title="Old Club Task", day_no=1, task_no=1, timestamp="yesteday", task_url="http://soarscore.com/club.tsk", ), ] await act.wait_for_tasks() rendered = wtb.render() assert "Old Club Task day 1 task 1" in rendered assert "Refresh" in rendered # When refresh button is pressed soarscore.tasks = [ SoarScoreTaskInfo( comp_class="Club", title="New Club Task", day_no=2, task_no=2, timestamp="now", task_url="http://soarscore.com/club.tsk", ), ] await wtb.keypress("right", "enter") await act.wait_for_tasks() rendered = wtb.render() assert "New Club Task day 2 task 2" in rendered
def test_load_competition_existing(storage_dir) -> None: # GIVEN comp = storage.StoredCompetition( id="first", title="First Competition", soaringspot_url="http://localhost", airspace="airspace.txt", waypoints=None, ) storage.save_competition(comp) # WHEN loaded = storage.load_competition("first") assert loaded is not None # THEN assert loaded.id == "first" assert loaded.title == "First Competition" assert loaded.soaringspot_url == "http://localhost" assert loaded.airspace == "airspace.txt" assert loaded.waypoints == None
async def test_welcomescreen_setup_comp( storage_dir, soaringspot, activity_testbed ) -> None: # User picks a competition and end up in competition details screen # GIVEN sspicker_screen = activity_testbed.mock( "compman.ui.soaringspot.SoaringSpotPickerScreen" ) sspicker_screen.result = storage.StoredCompetition( id="test", title="Test", soaringspot_url="http://test" ) details_screen = activity_testbed.mock( "compman.ui.compdetails.CompetitionDetailsScreen" ) async with activity_testbed.shown(WelcomeScreen): # WHEN await activity_testbed.keypress("enter") # THEN assert sspicker_screen.shown assert storage.get_settings().current_competition_id == "test"
async def test_classselector_change_class(storage_dir, soaringspot, widget_testbed) -> None: # GIVEN soaringspot.classes = ["Club", "Standard", "15 Meter"] comp = storage.StoredCompetition( "test", "Test Competition", soaringspot_url="http://soaringspot.com/test", classes=["Club", "Standard"], selected_class="Club", ) act = ActivityStub(urwid.SolidFill("T")) wdg = CompetitionClassSelectorWidget(act, comp) wtb = widget_testbed.for_widget(wdg) rendered = wtb.render() assert "Competition class" in rendered assert "Club" in rendered # Press "Change" focused = wtb.get_focus_widgets()[-1] assert "Change" in focused.label await wtb.keypress("enter") # We start to fetch classes, but allow to select from known ones rendered = wtb.render() assert "Fetching competition classes..." in rendered assert "(X) Club" in rendered assert "( ) Standard" in rendered assert "15 Meter" not in rendered # When fetching completed, 15 meter class is available for selection await act.wait_for_tasks() rendered = wtb.render() assert "(X) Club" in rendered assert "( ) Standard" in rendered assert "( ) 15 Meter" in rendered
async def test_taskdownload_task_view(storage_dir, soarscore, widget_testbed) -> None: comp = storage.StoredCompetition( "test", "Test Competition", soaringspot_url="http://soaringspot.com/test", selected_class="Club", ) act = ActivityStub(urwid.SolidFill("T")) wdg = TaskDownloadWidget(act, comp) wtb = widget_testbed.for_widget(wdg) soarscore.tasks = [ SoarScoreTaskInfo( comp_class="Club", title="Club Task", day_no=1, task_no=1, timestamp="now", task_url="http://soarscore.com/club.tsk", ), SoarScoreTaskInfo( comp_class="Standard", title="Standard Task", day_no=1, task_no=1, timestamp="now", task_url="http://soarscore.com/standard.tsk", ), ] # Task title and other data should be displayed await act.wait_for_tasks() rendered = wtb.render() assert "Today's task" in rendered assert "Club Task day 1 task 1" in rendered assert "Generated on now" in rendered assert "Download" in rendered assert "Refresh" in rendered
async def test_classselector_initial_selection(storage_dir, soaringspot, widget_testbed) -> None: # GIVEN comp = storage.StoredCompetition( "test", "Test Competition", soaringspot_url="http://soaringspot.com/test") act = ActivityStub(urwid.SolidFill("T")) soaringspot.classes = ["Club", "Standard", "15 Meter"] wdg = CompetitionClassSelectorWidget(act, comp) wtb = widget_testbed.for_widget(wdg) # Initially the progress message is shown await asyncio.sleep(0) assert "Fetching competition classes" in wtb.render() # When classes are fetched, picker is shown await act.wait_for_tasks() rendered = wtb.render() assert "Pick your competition class:" in rendered assert "( ) Club" in rendered assert "( ) Standard" in rendered assert "( ) 15 Meter" in rendered # Select "Standard" class. Initially the last class is selected await wtb.keypress("up", "enter") rendered = wtb.render() assert "Competition class" in rendered assert "Standard" in rendered assert "Club" not in rendered assert "Change" in rendered # Competition class is selected assert comp.classes == ["Club", "Standard", "15 Meter"] assert comp.selected_class == "Standard"
async def test_taskdownload_fetch_error(storage_dir, soarscore, widget_testbed) -> None: comp = storage.StoredCompetition( "test", "Test Competition", soaringspot_url="http://soaringspot.com/test", selected_class="Club", ) act = ActivityStub(urwid.SolidFill("T")) wdg = TaskDownloadWidget(act, comp) wtb = widget_testbed.for_widget(wdg) soarscore.tasks = [] await act.wait_for_tasks() rendered = wtb.render() assert "No task for today" in rendered assert "Refresh" in rendered soarscore.fetch_latest_tasks_exc = SoarScoreClientError("Internet error") focused = wtb.get_focus_widgets()[-1] assert focused.label == " Refresh " await wtb.keypress("enter") await act.wait_for_tasks() assert "Error fetching today's task: Internet error" in wtb.render()