1+ import shutil
2+
13import pytest_asyncio
24from textual .widgets ._tabbed_content import ContentTab
35
46from datashuttle .configs import canonical_configs
7+ from datashuttle .tui .app import TuiApp
58from datashuttle .tui .screens .project_manager import ProjectManagerScreen
69from datashuttle .tui .screens .project_selector import ProjectSelectorScreen
710
@@ -23,6 +26,9 @@ def tui_size(self):
2326 """
2427 return (500 , 500 )
2528
29+ # Fixtures
30+ # ---------------------------------------------------------------------------------
31+
2632 @pytest_asyncio .fixture (scope = "function" )
2733 async def empty_project_paths (self , tmp_path_factory , monkeypatch ):
2834 """Get the paths and project name for a non-existent (i.e. not
@@ -64,6 +70,9 @@ async def setup_project_paths(self, empty_project_paths):
6470
6571 return empty_project_paths
6672
73+ # Helper Functions
74+ # ---------------------------------------------------------------------------------
75+
6776 def monkeypatch_print (self , _monkeypatch ):
6877 """Calls to `print` in datashuttle crash the TUI in the
6978 test environment. I am not sure why. Get around this
@@ -240,3 +249,84 @@ async def click_and_await_transfer(self, pilot):
240249 await transfer_task
241250
242251 await self .close_messagebox (pilot )
252+
253+ async def double_click_input (self , pilot , sub_or_ses , control = False ):
254+ """Helper function to double click input to suggest next sub or ses.
255+
256+ Because this function is performed in separate asyncio task, this was a little
257+ brittle in the CI tests leading to random errors. The below
258+ combination of awaiting the test, then pausing, stopped the errors.
259+ """
260+ expand_name = "session" if sub_or_ses == "ses" else "subject"
261+
262+ await self .double_click (
263+ pilot , f"#create_folders_{ expand_name } _input" , control = control
264+ )
265+ await test_utils .await_task_by_name_if_present (
266+ f"suggest_next_{ sub_or_ses } _async_task"
267+ )
268+ await pilot .pause (0.5 )
269+
270+ # Shared checks
271+ # ---------------------------------------------------------------------------------
272+
273+ async def check_next_sub_ses_in_tui (self , project ):
274+ """A central function for testing next sub / ses in the TUI.
275+
276+ This test is shared between ssh, aws and gdrive tests that
277+ use the same logic to test the get next sub / ses functionality.
278+
279+ First, sub / ses folders are created in the project and uploaded
280+ centrally. Then, the folders are removed from the local path.
281+ In this way, we can be use that `include_central` (which searches
282+ the remote for the next sub / ses) is behaving correctly and not just
283+ reading the local path.
284+
285+ Because sub-001 is created, the suggested sub we expect is sub-002.
286+ Because ses-002 is created in sub-001, the suggested ses we expect is ses-003.
287+ """
288+ test_utils .make_local_folders_with_files_in (
289+ project , "rawdata" , "sub-001" , ["ses-001" , "ses-002" ]
290+ )
291+ project .upload_entire_project ()
292+
293+ shutil .rmtree (project .get_local_path ())
294+
295+ app = TuiApp ()
296+ async with app .run_test (size = self .tui_size ()) as pilot :
297+ await self .check_and_click_onto_existing_project (
298+ pilot , project .project_name
299+ )
300+
301+ # Turn on the central checkbox
302+ await self .scroll_to_click_pause (
303+ pilot , "#create_folders_settings_button"
304+ )
305+ await self .scroll_to_click_pause (
306+ pilot , "#suggest_next_sub_ses_central_checkbox"
307+ )
308+ await self .scroll_to_click_pause (
309+ pilot , "#create_folders_settings_close_button"
310+ )
311+
312+ await self .fill_input (
313+ pilot , "#create_folders_subject_input" , "sub-001"
314+ )
315+
316+ await self .double_click_input (pilot , "ses" )
317+
318+ assert (
319+ pilot .app .screen .query_one (
320+ "#create_folders_session_input"
321+ ).value
322+ == "ses-003"
323+ )
324+
325+ await self .double_click_input (pilot , "sub" )
326+
327+ assert (
328+ pilot .app .screen .query_one (
329+ "#create_folders_subject_input"
330+ ).value
331+ == "sub-002"
332+ )
0 commit comments