Skip to content

Commit c04d38b

Browse files
committed
add testcase
1 parent ef1ed30 commit c04d38b

File tree

2 files changed

+126
-10
lines changed

2 files changed

+126
-10
lines changed

notebooks/dataframes/anywidget_mode.ipynb

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
{
7777
"data": {
7878
"text/html": [
79-
"Query job a643d120-4af9-44fc-ba3c-ed461cf1092b is DONE. 0 Bytes processed. <a target=\"_blank\" href=\"https://console.cloud.google.com/bigquery?project=bigframes-dev&j=bq:US:a643d120-4af9-44fc-ba3c-ed461cf1092b&page=queryresults\">Open Job</a>"
79+
"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>"
8080
],
8181
"text/plain": [
8282
"<IPython.core.display.HTML object>"
@@ -139,10 +139,22 @@
139139
"id": "ce250157",
140140
"metadata": {},
141141
"outputs": [
142+
{
143+
"data": {
144+
"text/html": [
145+
"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>"
146+
],
147+
"text/plain": [
148+
"<IPython.core.display.HTML object>"
149+
]
150+
},
151+
"metadata": {},
152+
"output_type": "display_data"
153+
},
142154
{
143155
"data": {
144156
"application/vnd.jupyter.widget-view+json": {
145-
"model_id": "d2d4ef22ea9f414b89ea5bd85f0e6635",
157+
"model_id": "e74c3920b93644a0b2afdaa3841cad31",
146158
"version_major": 2,
147159
"version_minor": 1
148160
},
@@ -193,7 +205,7 @@
193205
{
194206
"data": {
195207
"application/vnd.jupyter.widget-view+json": {
196-
"model_id": "121e3d2f28004036a922e3a11a08d4b7",
208+
"model_id": "b4f7a3f86ef54e07b24ef10061088391",
197209
"version_major": 2,
198210
"version_minor": 1
199211
},
@@ -287,7 +299,7 @@
287299
{
288300
"data": {
289301
"application/vnd.jupyter.widget-view+json": {
290-
"model_id": "5ed335bbbc064e5391ea06a9a218642e",
302+
"model_id": "44a829aca2f24cfdba4b61afd1a259fe",
291303
"version_major": 2,
292304
"version_minor": 1
293305
},

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)