1+ import pandas as pd
2+ from pandas .testing import assert_frame_equal
13import pytest
4+ from unittest import mock
25
36from genie import dashboard_table_updater as dash_update
47
58
9+ @pytest .fixture
10+ def mock_syn (tmp_path ):
11+ """Fixture for a fake synapse client and test file."""
12+ syn = mock .MagicMock ()
13+
14+ # Create a fake clinical file
15+ clinical_path = tmp_path / "clinical.txt"
16+ clinical_path .write_text ("SAMPLE_ID\n S1\n S2\n S3\n " )
17+
18+ # Entity returned by syn.get for the clinical file
19+ clinical_entity = mock .MagicMock ()
20+ clinical_entity .path = str (clinical_path )
21+
22+ # syn.get() will return this entity when given file_mapping["sample"]
23+ syn .get .return_value = clinical_entity
24+
25+ # Default columns of existing table
26+ syn .getTableColumns .return_value = [{"name" : "SAMPLE_ID" }]
27+
28+ return syn
29+
30+
631@pytest .mark .parametrize (
732 "input_string_time, expected_output_time" ,
833 [
@@ -17,3 +42,118 @@ def test_that_string_to_unix_epoch_time_milliseconds_gives_expected_time(
1742):
1843 output = dash_update .string_to_unix_epoch_time_milliseconds (input_string_time )
1944 assert output == expected_output_time
45+
46+
47+ def test_that_update_samples_in_release_table_adds_column_and_calls_update (
48+ tmp_path , mock_syn
49+ ):
50+ """Test that a new release column is added and load._update_table gets correct data."""
51+ file_mapping = {"sample" : "syn123" }
52+ release = "5.3-consortium"
53+ samples_in_release_synid = "syn999"
54+
55+ # Fake DataFrames for clinical and existing table
56+ clinical_df = pd .DataFrame ({"SAMPLE_ID" : ["S1" , "S2" , "S3" ]})
57+ existing_df = pd .DataFrame ({"SAMPLE_ID" : ["S1" ], release : [1 ]})
58+
59+ with (
60+ mock .patch .object (pd , "read_csv" , return_value = clinical_df ) as mock_read ,
61+ mock .patch .object (
62+ dash_update .extract , "get_syntabledf" , return_value = existing_df
63+ ) as mock_extract ,
64+ mock .patch .object (dash_update .load , "_update_table" ) as mock_update ,
65+ ):
66+ dash_update .update_samples_in_release_table (
67+ syn = mock_syn ,
68+ file_mapping = file_mapping ,
69+ release = release ,
70+ samples_in_release_synid = samples_in_release_synid ,
71+ )
72+
73+ # --- Assertions on Synapse calls ---
74+ mock_syn .get .assert_has_calls (
75+ [
76+ mock .call (file_mapping ["sample" ], followLink = True ),
77+ mock .call (samples_in_release_synid ),
78+ ]
79+ )
80+ mock_syn .getTableColumns .assert_called_once_with (samples_in_release_synid )
81+
82+ # --- Assertions on pd.read_csv ---
83+ mock_read .assert_called_once ()
84+ assert list (mock_read .return_value .columns ) == ["SAMPLE_ID" ]
85+
86+ # --- Assertions on extract.get_syntabledf ---
87+ mock_extract .assert_called_once_with (
88+ syn = mock_syn ,
89+ query_string = f'SELECT SAMPLE_ID, "{ release } " FROM { samples_in_release_synid } ' ,
90+ )
91+
92+ # --- Assertions on load._update_table inputs ---
93+ mock_update .assert_called_once ()
94+ args , kwargs = mock_update .call_args
95+
96+ # Extract arguments
97+ _ , _ , samples_in_releasedf , synid_arg , key_cols = args
98+
99+ # Ensure correct Synapse ID and key columns
100+ assert synid_arg == samples_in_release_synid
101+ assert key_cols == ["SAMPLE_ID" ]
102+
103+ # Check that new samples and old samples are in expected order
104+ assert_frame_equal (
105+ samples_in_releasedf .reset_index (drop = True ),
106+ pd .DataFrame (
107+ {"SAMPLE_ID" : ["S2" , "S3" , "S1" ], "5.3-consortium" : [1 , 1 , 1 ]}
108+ ),
109+ )
110+
111+
112+ def test_that_update_samples_in_release_table_existing_column_calls_update_directly (
113+ mock_syn ,
114+ ):
115+ """If the release column already exists, we skip creating new column but still call _update_table."""
116+ release = "5.3-consortium"
117+ file_mapping = {"sample" : "syn123" }
118+ samples_in_release_synid = "syn999"
119+
120+ # Pretend the release column already exists
121+ mock_syn .getTableColumns .return_value = [{"name" : "SAMPLE_ID" }, {"name" : release }]
122+
123+ clinical_df = pd .DataFrame ({"SAMPLE_ID" : ["S1" , "S2" ]})
124+ existing_df = pd .DataFrame ({"SAMPLE_ID" : ["S2" , "S1" ], release : [1 , 1 ]})
125+
126+ with (
127+ mock .patch .object (pd , "read_csv" , return_value = clinical_df ) as mock_read ,
128+ mock .patch .object (
129+ dash_update .extract , "get_syntabledf" , return_value = existing_df
130+ ) as mock_extract ,
131+ mock .patch .object (dash_update .load , "_update_table" ) as mock_update ,
132+ ):
133+
134+ dash_update .update_samples_in_release_table (
135+ syn = mock_syn ,
136+ file_mapping = file_mapping ,
137+ release = release ,
138+ samples_in_release_synid = samples_in_release_synid ,
139+ )
140+ # --- Assertions on Synapse calls ---
141+ mock_syn .get .assert_has_calls (
142+ [
143+ mock .call (file_mapping ["sample" ], followLink = True ),
144+ ]
145+ )
146+ args , kwargs = mock_update .call_args
147+
148+ # Extract arguments
149+ _ , _ , samples_in_releasedf , synid_arg , key_cols = args
150+
151+ # Ensure correct Synapse ID and key columns
152+ assert synid_arg == samples_in_release_synid
153+ assert key_cols == ["SAMPLE_ID" ]
154+
155+ # Check that new samples and old samples are in expected order
156+ assert_frame_equal (
157+ samples_in_releasedf .reset_index (drop = True ),
158+ pd .DataFrame ({"SAMPLE_ID" : ["S1" , "S2" ], "5.3-consortium" : [1 , 1 ]}),
159+ )
0 commit comments