|
| 1 | +import dataclasses |
1 | 2 | import logging |
2 | 3 | from pathlib import Path |
3 | 4 | from unittest.mock import create_autospec |
4 | 5 |
|
5 | 6 | import pytest |
6 | 7 | from databricks.sdk import WorkspaceClient |
7 | 8 |
|
8 | | -from databricks.labs.lsql.dashboards import DashboardMetadata, Dashboards |
| 9 | +from databricks.labs.lsql.dashboards import ( |
| 10 | + DashboardMetadata, |
| 11 | + Dashboards, |
| 12 | + WidgetMetadata, |
| 13 | +) |
9 | 14 | from databricks.labs.lsql.lakeview import ( |
10 | 15 | CounterEncodingMap, |
11 | 16 | CounterSpec, |
@@ -36,6 +41,29 @@ def test_dashboard_configuration_from_and_as_dict_is_a_unit_function(): |
36 | 41 | assert dashboard_metadata.as_dict() == raw |
37 | 42 |
|
38 | 43 |
|
| 44 | +def test_widget_metadata_replaces_arguments(): |
| 45 | + widget_metadata = WidgetMetadata(1, 1) |
| 46 | + updated_metadata = widget_metadata.replace_from_arguments(["--width", "10", "--height", "10"]) |
| 47 | + assert updated_metadata.width == 10 |
| 48 | + assert updated_metadata.height == 10 |
| 49 | + |
| 50 | + |
| 51 | +@pytest.mark.parametrize("attribute", ["width", "height"]) |
| 52 | +def test_widget_metadata_replaces_one_attribute(attribute: str): |
| 53 | + widget_metadata = WidgetMetadata(1, 1) |
| 54 | + updated_metadata = widget_metadata.replace_from_arguments([f"--{attribute}", "10"]) |
| 55 | + |
| 56 | + other_fields = [field for field in dataclasses.fields(updated_metadata) if field.name != attribute] |
| 57 | + assert getattr(updated_metadata, attribute) == 10 |
| 58 | + assert all(getattr(updated_metadata, field.name) == 1 for field in other_fields) |
| 59 | + |
| 60 | + |
| 61 | +def test_widget_metadata_as_dict(): |
| 62 | + raw = {"width": 10, "height": 10} |
| 63 | + widget_metadata = WidgetMetadata(10, 10) |
| 64 | + assert widget_metadata.as_dict() == raw |
| 65 | + |
| 66 | + |
39 | 67 | def test_dashboards_saves_sql_files_to_folder(tmp_path): |
40 | 68 | ws = create_autospec(WorkspaceClient) |
41 | 69 | queries = Path(__file__).parent / "queries" |
@@ -339,6 +367,94 @@ def test_dashboards_creates_dashboards_where_text_widget_has_expected_text(tmp_p |
339 | 367 | ws.assert_not_called() |
340 | 368 |
|
341 | 369 |
|
| 370 | +@pytest.mark.parametrize( |
| 371 | + "header", |
| 372 | + [ |
| 373 | + "-- --width 6 --height 3", |
| 374 | + "/* --width 6 --height 3 */", |
| 375 | + "/*\n--width 6\n--height 3 */", |
| 376 | + ], |
| 377 | +) |
| 378 | +def test_dashboard_creates_dashboard_with_custom_sized_widget(tmp_path, header): |
| 379 | + ws = create_autospec(WorkspaceClient) |
| 380 | + |
| 381 | + query = f"{header}\nSELECT 82917019218921 AS big_number_needs_big_widget" |
| 382 | + with (tmp_path / "counter.sql").open("w") as f: |
| 383 | + f.write(query) |
| 384 | + |
| 385 | + lakeview_dashboard = Dashboards(ws).create_dashboard(tmp_path) |
| 386 | + position = lakeview_dashboard.pages[0].layout[0].position |
| 387 | + |
| 388 | + assert position.width == 6 |
| 389 | + assert position.height == 3 |
| 390 | + ws.assert_not_called() |
| 391 | + |
| 392 | + |
| 393 | +def test_dashboard_handles_incorrect_query_header(tmp_path, caplog): |
| 394 | + ws = create_autospec(WorkspaceClient) |
| 395 | + |
| 396 | + # Typo is on purpose |
| 397 | + query = "-- --widh 6 --height 3 \nSELECT 82917019218921 AS big_number_needs_big_widget" |
| 398 | + with (tmp_path / "counter.sql").open("w") as f: |
| 399 | + f.write(query) |
| 400 | + |
| 401 | + with caplog.at_level(logging.WARNING, logger="databricks.labs.lsql.dashboards"): |
| 402 | + lakeview_dashboard = Dashboards(ws).create_dashboard(tmp_path) |
| 403 | + |
| 404 | + position = lakeview_dashboard.pages[0].layout[0].position |
| 405 | + assert position.width == 1 |
| 406 | + assert position.height == 3 |
| 407 | + assert "--widh" in caplog.text |
| 408 | + ws.assert_not_called() |
| 409 | + |
| 410 | + |
| 411 | +@pytest.mark.parametrize( |
| 412 | + "query", |
| 413 | + [ |
| 414 | + "-- --height 5\nSELECT 1 AS count -- --width 6", |
| 415 | + "-- --height 5\nSELECT 1 AS count\n-- --width 6", |
| 416 | + "-- --height 5\nSELECT 1 AS count\n/* --width 6 */", |
| 417 | + "-- --height 5\n-- --width 6\nSELECT 1 AS count", |
| 418 | + "-- --height 5\n/* --width 6 */\nSELECT 1 AS count", |
| 419 | + "/* --height 5*/\n/* --width 6 */\nSELECT 1 AS count", |
| 420 | + "/* --height 5*/\n-- --width 6 */\nSELECT 1 AS count", |
| 421 | + ], |
| 422 | +) |
| 423 | +def test_dashboard_ignores_comment_on_other_lines(tmp_path, query): |
| 424 | + ws = create_autospec(WorkspaceClient) |
| 425 | + |
| 426 | + with (tmp_path / "counter.sql").open("w") as f: |
| 427 | + f.write(query) |
| 428 | + |
| 429 | + lakeview_dashboard = Dashboards(ws).create_dashboard(tmp_path) |
| 430 | + position = lakeview_dashboard.pages[0].layout[0].position |
| 431 | + |
| 432 | + assert position.width == 1 |
| 433 | + assert position.height == 5 |
| 434 | + ws.assert_not_called() |
| 435 | + |
| 436 | + |
| 437 | +@pytest.mark.parametrize( |
| 438 | + "query", |
| 439 | + [ |
| 440 | + "SELECT 1\n-- --width 6 --height 6", |
| 441 | + "SELECT 1\n/*\n--width 6\n--height 6*/", |
| 442 | + ], |
| 443 | +) |
| 444 | +def test_dashboard_ignores_non_header_comment(tmp_path, query): |
| 445 | + ws = create_autospec(WorkspaceClient) |
| 446 | + |
| 447 | + with (tmp_path / "counter.sql").open("w") as f: |
| 448 | + f.write(query) |
| 449 | + |
| 450 | + lakeview_dashboard = Dashboards(ws).create_dashboard(tmp_path) |
| 451 | + position = lakeview_dashboard.pages[0].layout[0].position |
| 452 | + |
| 453 | + assert position.width == 1 |
| 454 | + assert position.height == 3 |
| 455 | + ws.assert_not_called() |
| 456 | + |
| 457 | + |
342 | 458 | def test_dashboards_deploy_calls_create_without_dashboard_id(): |
343 | 459 | ws = create_autospec(WorkspaceClient) |
344 | 460 | dashboards = Dashboards(ws) |
|
0 commit comments