Skip to content

Commit b6b9b4c

Browse files
committed
add testcase
1 parent 22b4200 commit b6b9b4c

File tree

2 files changed

+115
-11
lines changed

2 files changed

+115
-11
lines changed

notebooks/dataframes/anywidget_mode.ipynb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
{
7676
"data": {
7777
"text/html": [
78-
"Query job c5fcfd5e-1617-49c8-afa3-86ca21019de4 is DONE. 0 Bytes processed. <a target=\"_blank\" href=\"https://console.cloud.google.com/bigquery?project=bigframes-dev&j=bq:US:c5fcfd5e-1617-49c8-afa3-86ca21019de4&page=queryresults\">Open Job</a>"
78+
"Query job 1ea2b594-2bd7-46de-a3c8-6aeee5884ba2 is DONE. 0 Bytes processed. <a target=\"_blank\" href=\"https://console.cloud.google.com/bigquery?project=bigframes-dev&j=bq:US:1ea2b594-2bd7-46de-a3c8-6aeee5884ba2&page=queryresults\">Open Job</a>"
7979
],
8080
"text/plain": [
8181
"<IPython.core.display.HTML object>"
@@ -141,7 +141,7 @@
141141
{
142142
"data": {
143143
"text/html": [
144-
"Query job ab900a53-5011-4e80-85d5-0ef2958598db is DONE. 171.4 MB processed. <a target=\"_blank\" href=\"https://console.cloud.google.com/bigquery?project=bigframes-dev&j=bq:US:ab900a53-5011-4e80-85d5-0ef2958598db&page=queryresults\">Open Job</a>"
144+
"Query job 67e679e9-94da-47f7-8be1-8b4a496fbfbd is DONE. 171.4 MB processed. <a target=\"_blank\" href=\"https://console.cloud.google.com/bigquery?project=bigframes-dev&j=bq:US:67e679e9-94da-47f7-8be1-8b4a496fbfbd&page=queryresults\">Open Job</a>"
145145
],
146146
"text/plain": [
147147
"<IPython.core.display.HTML object>"
@@ -153,7 +153,7 @@
153153
{
154154
"data": {
155155
"application/vnd.jupyter.widget-view+json": {
156-
"model_id": "bda63ba739dc4d5f83a5e18eb27b2686",
156+
"model_id": "e74c3920b93644a0b2afdaa3841cad31",
157157
"version_major": 2,
158158
"version_minor": 1
159159
},
@@ -204,7 +204,7 @@
204204
{
205205
"data": {
206206
"application/vnd.jupyter.widget-view+json": {
207-
"model_id": "9bffeb73549e48419c3dd895edfe30e8",
207+
"model_id": "b4f7a3f86ef54e07b24ef10061088391",
208208
"version_major": 2,
209209
"version_minor": 1
210210
},
@@ -290,7 +290,7 @@
290290
{
291291
"data": {
292292
"application/vnd.jupyter.widget-view+json": {
293-
"model_id": "dfd4fa3a1c6f4b3eb1877cb0e9ba7e94",
293+
"model_id": "44a829aca2f24cfdba4b61afd1a259fe",
294294
"version_major": 2,
295295
"version_minor": 1
296296
},

tests/system/small/test_anywidget.py

Lines changed: 110 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import typing
16+
1517
import pandas as pd
1618
import pytest
1719

@@ -61,11 +63,12 @@ def table_widget(paginated_bf_df: bf.dataframe.DataFrame):
6163
Helper fixture to create a TableWidget instance with a fixed page size.
6264
This reduces duplication across tests that use the same widget configuration.
6365
"""
64-
from bigframes import display
66+
67+
from bigframes.display import TableWidget
6568

6669
with bf.option_context("display.repr_mode", "anywidget", "display.max_rows", 2):
6770
# Delay context manager cleanup of `max_rows` until after tests finish.
68-
yield display.TableWidget(paginated_bf_df)
71+
yield TableWidget(paginated_bf_df)
6972

7073

7174
@pytest.fixture(scope="module")
@@ -90,10 +93,10 @@ def small_bf_df(
9093
@pytest.fixture
9194
def small_widget(small_bf_df):
9295
"""Helper fixture for tests using a DataFrame smaller than the page size."""
93-
from bigframes import display
96+
from bigframes.display import TableWidget
9497

9598
with bf.option_context("display.repr_mode", "anywidget", "display.max_rows", 5):
96-
yield display.TableWidget(small_bf_df)
99+
yield TableWidget(small_bf_df)
97100

98101

99102
@pytest.fixture(scope="module")
@@ -135,10 +138,10 @@ def test_widget_initialization_should_calculate_total_row_count(
135138
paginated_bf_df: bf.dataframe.DataFrame,
136139
):
137140
"""A TableWidget should correctly calculate the total row count on creation."""
138-
from bigframes import display
141+
from bigframes.display import TableWidget
139142

140143
with bf.option_context("display.repr_mode", "anywidget", "display.max_rows", 2):
141-
widget = display.TableWidget(paginated_bf_df)
144+
widget = TableWidget(paginated_bf_df)
142145

143146
assert widget.row_count == EXPECTED_ROW_COUNT
144147

@@ -436,6 +439,107 @@ def test_widget_creation_should_load_css_for_rendering(table_widget):
436439
assert ".bigframes-widget .footer" in css_content
437440

438441

442+
def test_widget_row_count_should_be_immutable_after_creation(
443+
paginated_bf_df: bf.dataframe.DataFrame,
444+
):
445+
"""
446+
Given a widget created with a specific configuration when global display
447+
options are changed later, the widget's original row_count should remain
448+
unchanged.
449+
"""
450+
from bigframes.display import TableWidget
451+
452+
with bf.option_context("display.repr_mode", "anywidget", "display.max_rows", 2):
453+
widget = TableWidget(paginated_bf_df)
454+
initial_row_count = widget.row_count
455+
assert initial_row_count == EXPECTED_ROW_COUNT
456+
457+
# Change a global option that could influence row count
458+
bf.options.display.max_rows = 10
459+
460+
# The widget's row count was fixed at creation and should not change.
461+
assert widget.row_count == initial_row_count
462+
463+
464+
def test_widget_should_fallback_to_zero_rows_when_total_rows_is_none(
465+
paginated_bf_df: bf.dataframe.DataFrame, monkeypatch: pytest.MonkeyPatch
466+
):
467+
"""
468+
Given an internal component that fails to provide a total row count,
469+
when the widget is created, the row_count should safely fall back to 0.
470+
"""
471+
from bigframes.core.blocks import PandasBatches
472+
473+
# Simulate an internal failure where total_rows returns None
474+
monkeypatch.setattr(PandasBatches, "total_rows", property(lambda self: None))
475+
476+
with bf.option_context("display.repr_mode", "anywidget"):
477+
from bigframes.display import TableWidget
478+
479+
widget = TableWidget(paginated_bf_df)
480+
481+
assert widget.row_count == 0
482+
483+
484+
def test_widget_should_fallback_to_zero_rows_when_batches_are_invalid_type(
485+
paginated_bf_df: bf.dataframe.DataFrame, monkeypatch: pytest.MonkeyPatch
486+
):
487+
"""
488+
Given an internal component that returns an unexpected data type,
489+
when the widget is created, the row_count should safely fall back to 0.
490+
"""
491+
# Simulate internal method returning an unexpected type (a simple iterator)
492+
def mock_to_pandas_batches(self, **kwargs):
493+
return iter([paginated_bf_df.to_pandas().iloc[:2]])
494+
495+
monkeypatch.setattr(
496+
"bigframes.dataframe.DataFrame.to_pandas_batches", mock_to_pandas_batches
497+
)
498+
499+
with bf.option_context("display.repr_mode", "anywidget"):
500+
from bigframes.display import TableWidget
501+
502+
widget = TableWidget(paginated_bf_df)
503+
504+
assert widget.row_count == 0
505+
506+
507+
@pytest.mark.parametrize(
508+
"max_results, expected_rows",
509+
[
510+
(None, EXPECTED_ROW_COUNT),
511+
(3, 3),
512+
(10, EXPECTED_ROW_COUNT),
513+
],
514+
ids=["no_limit", "limit_is_less_than_total", "limit_is_greater_than_total"],
515+
)
516+
def test_widget_row_count_should_respect_max_results_on_creation(
517+
paginated_bf_df: bf.dataframe.DataFrame,
518+
max_results: typing.Optional[int],
519+
expected_rows: int,
520+
):
521+
"""
522+
Given a max_results value, when a TableWidget is created with custom batches,
523+
its row_count should be correctly capped by that value.
524+
"""
525+
with bf.option_context("display.repr_mode", "anywidget", "display.max_rows", 2):
526+
from bigframes.core.blocks import PandasBatches
527+
from bigframes.display import TableWidget
528+
529+
widget = TableWidget(paginated_bf_df)
530+
531+
# Override batches with max_results to test the behavior
532+
widget._batches = paginated_bf_df.to_pandas_batches(
533+
page_size=widget.page_size, max_results=max_results
534+
)
535+
536+
# Re-apply thelogic to update row_count
537+
if isinstance(widget._batches, PandasBatches):
538+
widget.row_count = widget._batches.total_rows or 0
539+
540+
assert widget.row_count == expected_rows
541+
542+
439543
# TODO(shuowei): Add tests for custom index and multiindex
440544
# This may not be necessary for the SQL Cell use case but should be
441545
# considered for completeness.

0 commit comments

Comments
 (0)