Skip to content

Commit 4ef3d58

Browse files
Add more suggest next sub ses tests (#597)
* Fix get next sub / ses on TUI and extend AWS, SSH, GDrive tests. * Also remove aws folder. * Apply PR feedback and refactor tests. * Move check_next_sub_ses_in_tui to tui base. * Update tests/tests_transfers/ssh/test_ssh_suggest_next.py Co-authored-by: Shrey Singh <96627769+cs7-shrey@users.noreply.github.com> * Update tests/tests_transfers/aws/test_aws_suggest_next.py Co-authored-by: Shrey Singh <96627769+cs7-shrey@users.noreply.github.com> --------- Co-authored-by: Shrey Singh <96627769+cs7-shrey@users.noreply.github.com>
1 parent 1f50248 commit 4ef3d58

10 files changed

Lines changed: 225 additions & 24 deletions

File tree

datashuttle/tui/tabs/create_folders.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -338,10 +338,9 @@ def suggest_next_sub_ses(
338338
in canonical_configs.get_connection_methods_list()
339339
)
340340

341-
if (
342-
include_central
343-
and self.interface.project.cfg["connection_method"] == "ssh"
344-
):
341+
if include_central and self.interface.project.cfg[
342+
"connection_method"
343+
] in ["aws", "gdrive", "ssh"]:
345344
self.searching_central_popup_widget = (
346345
SearchingCentralForNextSubSesPopup(prefix)
347346
)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import pytest
2+
3+
from datashuttle.utils import rclone
4+
5+
from ... import test_utils
6+
from ...tests_tui.tui_base import TuiBase
7+
from ..base_transfer import BaseTransfer
8+
from . import aws_test_utils
9+
10+
11+
@pytest.mark.skipif(
12+
not aws_test_utils.has_aws_environment_variables(),
13+
reason="AWS set up environment variables must be set.",
14+
)
15+
class TestAWSSuggestNext(BaseTransfer, TuiBase):
16+
@pytest.fixture(
17+
scope="function",
18+
)
19+
def aws_setup(self, setup_project_paths):
20+
"""
21+
Setup pathtable and project for AWS transfer tests.
22+
"""
23+
project = test_utils.make_project(setup_project_paths["project_name"])
24+
aws_test_utils.setup_project_for_aws(project)
25+
aws_test_utils.setup_aws_connection(project)
26+
27+
yield project
28+
29+
rclone.call_rclone(
30+
f"purge central_{project.project_name}_gdrive:{project.cfg['central_path'].parent}"
31+
)
32+
33+
@pytest.mark.asyncio
34+
async def test_aws_suggest_next_sub_ses(
35+
self,
36+
aws_setup,
37+
):
38+
""" """
39+
project = aws_setup
40+
41+
await self.check_next_sub_ses_in_tui(project)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import pytest
2+
3+
from datashuttle.utils import rclone
4+
5+
from ... import test_utils
6+
from ...tests_tui.tui_base import TuiBase
7+
from ..base_transfer import BaseTransfer
8+
from . import gdrive_test_utils
9+
10+
11+
@pytest.mark.skipif(
12+
not gdrive_test_utils.has_gdrive_environment_variables(),
13+
reason="Google Drive set up environment variables must be set.",
14+
)
15+
class TestGDriveSuggestNext(BaseTransfer, TuiBase):
16+
@pytest.fixture(
17+
scope="function",
18+
)
19+
def gdrive_setup(self, setup_project_paths):
20+
"""
21+
Setup pathtable and project for GDrive transfer tests.
22+
"""
23+
project = test_utils.make_project(setup_project_paths["project_name"])
24+
gdrive_test_utils.setup_project_for_gdrive(
25+
project,
26+
)
27+
gdrive_test_utils.setup_gdrive_connection(project)
28+
29+
yield project
30+
31+
rclone.call_rclone(
32+
f"purge central_{project.project_name}_gdrive:{project.cfg['central_path'].parent}"
33+
)
34+
35+
@pytest.mark.asyncio
36+
async def test_gdrive_suggest_next_sub_ses(
37+
self,
38+
gdrive_setup,
39+
):
40+
""" """
41+
project = gdrive_setup
42+
43+
await self.check_next_sub_ses_in_tui(project)

tests/tests_transfers/ssh/base_ssh.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class BaseSSHTransfer(BaseTransfer):
2525
@pytest.fixture(
2626
scope="class",
2727
)
28-
def setup_ssh_container(self):
28+
def setup_ssh_container_fixture(self):
2929
"""
3030
Set up the Dockerfile container for SSH tests and
3131
delete it on teardown.

tests/tests_transfers/ssh/test_ssh_setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
)
2424
class TestSSH(BaseSSHTransfer):
2525
@pytest.fixture(scope="function")
26-
def project(test, tmp_path, setup_ssh_container):
26+
def project(test, tmp_path, setup_ssh_container_fixture):
2727
"""Set up a project with configs for SSH into
2828
the test Dockerfile image.
2929
"""
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import platform
2+
3+
import pytest
4+
5+
from ... import test_utils
6+
from ...tests_tui.tui_base import TuiBase
7+
from . import ssh_test_utils
8+
from .base_ssh import BaseSSHTransfer
9+
10+
TEST_SSH = ssh_test_utils.docker_is_running()
11+
12+
13+
@pytest.mark.skipif(
14+
platform.system == "Darwin", reason="Docker set up is not robust on macOS."
15+
)
16+
@pytest.mark.skipif(
17+
not TEST_SSH,
18+
reason="SSH tests are not run as docker is either not installed, "
19+
"running or current user is not in the docker group.",
20+
)
21+
class TestSSHDriveSuggestNext(BaseSSHTransfer, TuiBase):
22+
@pytest.fixture(
23+
scope="function",
24+
)
25+
def ssh_setup(self, setup_project_paths, setup_ssh_container_fixture):
26+
"""
27+
Setup pathtable and project for SSH transfer tests.
28+
"""
29+
project = test_utils.make_project(setup_project_paths["project_name"])
30+
ssh_test_utils.setup_project_for_ssh(
31+
project,
32+
)
33+
ssh_test_utils.setup_ssh_connection(project)
34+
35+
yield project
36+
37+
@pytest.mark.asyncio
38+
async def test_ssh_suggest_next_sub_ses(
39+
self,
40+
ssh_setup,
41+
):
42+
""" """
43+
project = ssh_setup
44+
45+
await self.check_next_sub_ses_in_tui(project)

tests/tests_transfers/ssh/test_ssh_transfer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class TestSSHTransfer(BaseSSHTransfer):
2121
@pytest.fixture(
2222
scope="class",
2323
)
24-
def ssh_setup(self, pathtable_and_project, setup_ssh_container):
24+
def ssh_setup(self, pathtable_and_project, setup_ssh_container_fixture):
2525
"""
2626
After initial project setup (in `pathtable_and_project`)
2727
setup a container and the project's SSH connection to the container.

tests/tests_tui/aws/__init__.py

Whitespace-only changes.

tests/tests_tui/test_tui_create_folders.py

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -762,20 +762,3 @@ async def create_folders_and_check_output(
762762
sessions=sessions,
763763
folder_used=folder_used,
764764
)
765-
766-
async def double_click_input(self, pilot, sub_or_ses, control=False):
767-
"""Helper function to double click input to suggest next sub or ses.
768-
769-
Because this function is performed in separate asyncio task, this was a little
770-
brittle in the CI tests leading to random errors. The below
771-
combination of awaiting the test, then pausing, stopped the errors.
772-
"""
773-
expand_name = "session" if sub_or_ses == "ses" else "subject"
774-
775-
await self.double_click(
776-
pilot, f"#create_folders_{expand_name}_input", control=control
777-
)
778-
await test_utils.await_task_by_name_if_present(
779-
f"suggest_next_{sub_or_ses}_async_task"
780-
)
781-
await pilot.pause(0.5)

tests/tests_tui/tui_base.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import shutil
2+
13
import pytest_asyncio
24
from textual.widgets._tabbed_content import ContentTab
35

46
from datashuttle.configs import canonical_configs
7+
from datashuttle.tui.app import TuiApp
58
from datashuttle.tui.screens.project_manager import ProjectManagerScreen
69
from 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

Comments
 (0)