Skip to content

Commit 80b7aaa

Browse files
Lingling PengLingling Peng
authored andcommitted
add unit test for _query_table_row_set function; add a concrete type for QUERY_RESULT
1 parent 47e06fb commit 80b7aaa

File tree

3 files changed

+181
-3
lines changed

3 files changed

+181
-3
lines changed

synapseclient/core/constants/concrete_types.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,5 @@
101101
# Query Table Bundle Request
102102
# https://rest-docs.synapse.org/rest/org/sagebionetworks/repo/model/table/QueryBundleRequest.html
103103
QUERY_BUNDLE_REQUEST = "org.sagebionetworks.repo.model.table.QueryBundleRequest"
104+
105+
QUERY_RESULT = "org.sagebionetworks.repo.model.table.QueryResult"

synapseclient/models/table_components.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from synapseclient.core.constants import concrete_types
2121
from synapseclient.core.constants.concrete_types import (
2222
QUERY_BUNDLE_REQUEST,
23+
QUERY_RESULT,
2324
QUERY_TABLE_CSV_REQUEST,
2425
)
2526
from synapseclient.core.utils import delete_none_keys, from_unix_epoch_time
@@ -821,12 +822,12 @@ class QueryResult:
821822
This result is modeled from: <https://rest-docs.synapse.org/rest/org/sagebionetworks/repo/model/table/QueryResult.html>
822823
"""
823824

824-
concrete_type: str
825-
"""The concrete type of this object"""
826-
827825
query_results: RowSet
828826
"""Represents a set of row of a TableEntity (RowSet)"""
829827

828+
concrete_type: str = QUERY_RESULT
829+
"""The concrete type of this object"""
830+
830831
next_page_token: Optional[QueryNextPageToken] = None
831832
"""Token for retrieving the next page of results, if available"""
832833

tests/unit/synapseclient/mixins/unit_test_table_components.py

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from synapseclient.api import ViewEntityType, ViewTypeMask
1414
from synapseclient.core.constants.concrete_types import (
1515
QUERY_BUNDLE_REQUEST,
16+
QUERY_RESULT,
1617
QUERY_TABLE_CSV_REQUEST,
1718
)
1819
from synapseclient.core.utils import MB
@@ -34,6 +35,7 @@
3435
ViewUpdateMixin,
3536
_query_table_csv,
3637
_query_table_next_page,
38+
_query_table_row_set,
3739
)
3840
from synapseclient.models.table_components import (
3941
ActionRequiredCount,
@@ -2496,6 +2498,179 @@ def test_fill_from_dict_with_complete_response(self):
24962498
assert result.headers[1].id == "222"
24972499

24982500

2501+
class TestQueryTableRowSet:
2502+
"""Test suite for the _query_table_row_set function."""
2503+
2504+
@pytest.fixture
2505+
def mock_synapse_client(self):
2506+
"""Mock Synapse client for testing."""
2507+
mock_client = MagicMock()
2508+
return mock_client
2509+
2510+
@pytest.fixture
2511+
def sample_query_result_bundle(self):
2512+
"""Sample QueryResultBundle response."""
2513+
return QueryResultBundle(
2514+
query_result=QueryResult(
2515+
concrete_type=QUERY_RESULT,
2516+
query_results=RowSet(
2517+
table_id="syn123456",
2518+
etag="test-etag",
2519+
headers=[
2520+
SelectColumn(
2521+
name="test_col", column_type=ColumnType.STRING, id="242777"
2522+
),
2523+
SelectColumn(
2524+
name="test_col2", column_type=ColumnType.STRING, id="242778"
2525+
),
2526+
],
2527+
rows=[
2528+
Row(
2529+
row_id=1,
2530+
version_number=1,
2531+
etag=None,
2532+
values=["random string1", "random string2"],
2533+
)
2534+
],
2535+
),
2536+
next_page_token=None,
2537+
),
2538+
query_count=1,
2539+
select_columns=[
2540+
SelectColumn(name="col1", column_type=ColumnType.STRING, id="111"),
2541+
SelectColumn(name="col2", column_type=ColumnType.INTEGER, id="222"),
2542+
],
2543+
max_rows_per_page=1000,
2544+
column_models=[
2545+
Column(
2546+
id="242777",
2547+
name="test_col",
2548+
column_type=ColumnType.STRING,
2549+
facet_type=None,
2550+
default_value=None,
2551+
maximum_size=50,
2552+
maximum_list_length=None,
2553+
enum_values=None,
2554+
json_sub_columns=None,
2555+
),
2556+
Column(
2557+
id="242778",
2558+
name="test_col2",
2559+
column_type=ColumnType.STRING,
2560+
facet_type=None,
2561+
default_value=None,
2562+
maximum_size=50,
2563+
maximum_list_length=None,
2564+
enum_values=None,
2565+
json_sub_columns=None,
2566+
),
2567+
],
2568+
facets=[],
2569+
sum_file_sizes=SumFileSizes(sum_file_size_bytes=1024, greater_than=False),
2570+
last_updated_on="2025-08-26T21:38:31.677Z",
2571+
combined_sql="SELECT col1, col2 FROM syn123456",
2572+
actions_required=None,
2573+
)
2574+
2575+
@pytest.mark.asyncio
2576+
async def test_query_table_row_set_basic(
2577+
self, mock_synapse_client, sample_query_result_bundle
2578+
):
2579+
"""Test basic query_table_row_set functionality."""
2580+
# GIVEN a query and mock response
2581+
query = "SELECT col1, col2 FROM syn123456"
2582+
2583+
with (
2584+
patch(
2585+
"synapseclient.models.mixins.table_components.extract_synapse_id_from_query",
2586+
return_value="syn123456",
2587+
) as mock_extract_id,
2588+
patch.object(
2589+
QueryBundleRequest,
2590+
"send_job_and_wait_async",
2591+
return_value=sample_query_result_bundle,
2592+
) as mock_send_job,
2593+
):
2594+
# WHEN calling _query_table_row_set
2595+
result = await _query_table_row_set(
2596+
query=query,
2597+
synapse=mock_synapse_client,
2598+
)
2599+
2600+
# THEN verify the result
2601+
assert isinstance(result, QueryResultBundle)
2602+
assert result.query_count == 1
2603+
assert result.query_result == sample_query_result_bundle.query_result
2604+
assert result.select_columns == sample_query_result_bundle.select_columns
2605+
assert result.sum_file_sizes == sample_query_result_bundle.sum_file_sizes
2606+
assert result.last_updated_on == sample_query_result_bundle.last_updated_on
2607+
assert result.combined_sql == sample_query_result_bundle.combined_sql
2608+
assert result.column_models == sample_query_result_bundle.column_models
2609+
assert result.facets == sample_query_result_bundle.facets
2610+
assert (
2611+
result.actions_required == sample_query_result_bundle.actions_required
2612+
)
2613+
2614+
# Verify extract_synapse_id_from_query was called correctly
2615+
mock_extract_id.assert_called_once_with(query)
2616+
2617+
# Verify send_job_and_wait_async was called correctly
2618+
mock_send_job.assert_called_once_with(synapse_client=mock_synapse_client)
2619+
2620+
@pytest.mark.asyncio
2621+
async def test_query_table_row_set_with_parameters(
2622+
self, mock_synapse_client, sample_query_result_bundle
2623+
):
2624+
"""Test _query_table_row_set with all optional parameters."""
2625+
# GIVEN a query with all parameters
2626+
query = "SELECT col1, col2 FROM syn123456"
2627+
limit = 100
2628+
offset = 50
2629+
part_mask = 0x1 | 0x2 | 0x4 # Query results + count + select columns
2630+
2631+
with (
2632+
patch(
2633+
"synapseclient.models.mixins.table_components.extract_synapse_id_from_query",
2634+
return_value="syn123456",
2635+
) as mock_extract_id,
2636+
patch(
2637+
"synapseclient.models.mixins.table_components.Query"
2638+
) as mock_query_class,
2639+
patch.object(
2640+
QueryBundleRequest,
2641+
"send_job_and_wait_async",
2642+
return_value=sample_query_result_bundle,
2643+
) as mock_send_job,
2644+
):
2645+
# Create mock instances
2646+
mock_query_instance = MagicMock()
2647+
mock_query_class.return_value = mock_query_instance
2648+
2649+
# WHEN calling _query_table_row_set with parameters
2650+
result = await _query_table_row_set(
2651+
query=query,
2652+
synapse=mock_synapse_client,
2653+
limit=limit,
2654+
offset=offset,
2655+
part_mask=part_mask,
2656+
)
2657+
# THEN verify the Query was created with correct parameters
2658+
mock_query_class.assert_called_once_with(
2659+
sql=query,
2660+
include_entity_etag=True,
2661+
limit=limit,
2662+
offset=offset,
2663+
)
2664+
2665+
# THEN verify the result structure
2666+
assert isinstance(result, QueryResultBundle)
2667+
assert result.query_count == 1
2668+
assert result.query_result == sample_query_result_bundle.query_result
2669+
2670+
# Verify the QueryBundleRequest was created with correct parameters
2671+
mock_send_job.assert_called_once_with(synapse_client=mock_synapse_client)
2672+
2673+
24992674
class TestQueryTableNextPage:
25002675
"""Test suite for the _query_table_next_page function."""
25012676

0 commit comments

Comments
 (0)