Skip to content

Commit d143c29

Browse files
sh-rpYour Name
andauthored
Improve pipeline dashboard test coverage (#3091)
* disable most tests * try correct windows command for runnig marimo e2e tests * try without timeout * test only launch marimo * bump python version * try install playwright deps * fix e2e tests for dashboard on windows * enable e2e tests for dashboard * test macos 14 for dashboard e2e tests * add basic tests for ui elements * improve ui elements tests * revert changes to main github workflow * review fixes --------- Co-authored-by: Your Name <[email protected]>
1 parent 31a9c64 commit d143c29

File tree

5 files changed

+93
-48
lines changed

5 files changed

+93
-48
lines changed

.github/workflows/test_common.yml

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -133,30 +133,6 @@ jobs:
133133
run: |
134134
pytest tests/sources/sql_database
135135
if: matrix.python-version != '3.14.0-beta.4'
136-
137-
# test pipeline dashboard app, does not work with python 3.13
138-
- name: Install dlt with duckdb and dashboard
139-
# note: this also tests the workspace extra installation
140-
run: uv sync ${{ matrix.uv_sync_args }} --extra duckdb --extra workspace --group sentry-sdk --group pipeline --group sources --group dashboard-tests
141-
if: matrix.python-version != '3.14.0-beta.4'
142-
143-
- name: Install playwright
144-
run: playwright install
145-
if: matrix.python-version != '3.14.0-beta.4'
146-
147-
148-
# Run pipeline dashboard unit tests
149-
- name: Run pipeline dashboard unit tests
150-
run: |
151-
pytest tests/helpers/dashboard
152-
if: matrix.python-version != '3.9' && matrix.python-version != '3.14.0-beta.4'
153-
154-
# Run pipeline dashboard e2e tests (does not pass with python 3.9, does not pass on windows (playwright does not work somehow), does not pass on python 3.13 (ibis not available))
155-
- name: Run dashboard e2e
156-
run: |
157-
marimo run --headless dlt/helpers/dashboard/dlt_dashboard.py -- -- --pipelines-dir _storage/.dlt/pipelines/ --with_test_identifiers true & pytest --browser chromium tests/e2e
158-
if: matrix.python-version != '3.9' && matrix.os == 'ubuntu-latest' && matrix.python-version != '3.14.0-beta.4'
159-
160136
matrix_job_required_check:
161137
name: common | common tests
162138
needs: run_common

.github/workflows/test_tools_dashboard.yml

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ jobs:
2222
include:
2323

2424
# macos tests
25-
- os: macos-latest
26-
python-version: "3.11"
25+
- os: "macos-14"
26+
python-version: "3.12"
2727
shell: bash
2828

2929
# linux tests
@@ -43,7 +43,7 @@ jobs:
4343

4444
# windows tests
4545
- os: windows-latest
46-
python-version: "3.11"
46+
python-version: "3.12"
4747
shell: cmd
4848
pytest_args: '-m "not forked"'
4949

@@ -82,8 +82,8 @@ jobs:
8282
run: uv sync ${{ matrix.uv_sync_args }} --extra duckdb --extra workspace --group sentry-sdk --group pipeline --group sources --group dashboard-tests
8383
if: matrix.python-version != '3.14.0-beta.4'
8484

85-
- name: Install playwright
86-
run: playwright install
85+
- name: Install playwright & deps
86+
run: playwright install && playwright install-deps
8787
if: matrix.python-version != '3.14.0-beta.4'
8888

8989
# Run pipeline dashboard unit tests
@@ -95,10 +95,14 @@ jobs:
9595
# Mac is also disabled for the time being
9696
- name: Run dashboard e2e
9797
run: |
98-
marimo run --headless dlt/helpers/dashboard/dlt_dashboard.py -- -- --pipelines-dir _storage/.dlt/pipelines/ --with_test_identifiers true &
99-
sleep 10
98+
marimo run --headless dlt/helpers/dashboard/dlt_dashboard.py -- -- --pipelines-dir _storage/.dlt/pipelines/ --with_test_identifiers true & pytest --browser chromium tests/e2e
99+
if: matrix.python-version != '3.9' && matrix.python-version != '3.14.0-beta.4' && matrix.os != 'windows-latest'
100+
101+
- name: Run dashboard e2e windows
102+
run: |
103+
start marimo run --headless dlt/helpers/dashboard/dlt_dashboard.py -- -- --pipelines-dir _storage\.dlt\pipelines\ --with_test_identifiers true
100104
pytest --browser chromium tests/e2e
101-
if: matrix.python-version != '3.9' && matrix.os != 'windows-latest' && matrix.os != 'macos-latest' && matrix.python-version != '3.14.0-beta.4'
105+
if: matrix.python-version != '3.9' && matrix.python-version != '3.14.0-beta.4' && matrix.os == 'windows-latest'
102106

103107
matrix_job_required_check:
104108
name: common | common tests

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,6 @@ test-e2e-dashboard-headed:
182182
start-dlt-dashboard-e2e:
183183
uv run marimo run --headless dlt/helpers/dashboard/dlt_dashboard.py -- -- --pipelines-dir _storage/.dlt/pipelines --with_test_identifiers true
184184

185-
# creates the dashboard test pipelines globally for manual testingn of the dashboard app and cli
185+
# creates the dashboard test pipelines globally for manual testing of the dashboard app and cli
186186
create-test-pipelines:
187187
uv run python tests/helpers/dashboard/example_pipelines.py

tests/e2e/helpers/dashboard/test_e2e.py

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
from typing import Any, Literal
2+
import asyncio
3+
import sys
4+
import pathlib
25

36
import dlt
47
import pytest
@@ -20,6 +23,10 @@
2023

2124
from dlt.helpers.dashboard import strings as app_strings
2225

26+
# NOTE: The line below is needed for playwright to work on windows
27+
if sys.platform.startswith("win"):
28+
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
29+
2330

2431
@pytest.fixture()
2532
def simple_incremental_pipeline() -> Any:
@@ -90,6 +97,11 @@ def broken_resource():
9097
#
9198

9299

100+
def _normpath(path: str) -> str:
101+
"""normalize path to unix style and lowercase for windows tests"""
102+
return str(pathlib.Path(path)) if sys.platform.startswith("win") else path
103+
104+
93105
def _go_home(page: Page) -> None:
94106
page.goto("http://localhost:2718")
95107

@@ -141,7 +153,7 @@ def test_exception_pipeline(page: Page, failed_pipeline: Any):
141153

142154
# overview page
143155
_open_section(page, "overview")
144-
expect(page.get_by_text("_storage/.dlt/pipelines/failed_pipeline")).to_be_visible()
156+
expect(page.get_by_text(_normpath("_storage/.dlt/pipelines/failed_pipeline"))).to_be_visible()
145157
expect(
146158
page.get_by_text("Exception encountered during last pipeline run in step").nth(0)
147159
).to_be_visible()
@@ -166,8 +178,8 @@ def test_exception_pipeline(page: Page, failed_pipeline: Any):
166178
_open_section(page, "loads")
167179
expect(page.get_by_text(app_strings.loads_loading_failed_text[0:20])).to_be_visible()
168180

169-
_open_section(page, "ibis")
170-
expect(page.get_by_text(app_strings.ibis_backend_error_text[0:20])).to_be_visible()
181+
# _open_section(page, "ibis")
182+
# expect(page.get_by_text(app_strings.ibis_backend_error_text[0:20])).to_be_visible()
171183

172184

173185
def test_multi_schema_selection(page: Page, multi_schema_pipeline: Any):
@@ -211,7 +223,7 @@ def test_simple_incremental_pipeline(page: Page, simple_incremental_pipeline: An
211223

212224
# overview page
213225
_open_section(page, "overview")
214-
expect(page.get_by_text("_storage/.dlt/pipelines/one_two_three")).to_be_visible()
226+
expect(page.get_by_text(_normpath("_storage/.dlt/pipelines/one_two_three"))).to_be_visible()
215227

216228
# check schema info (this is the yaml part)
217229
_open_section(page, "schema")
@@ -261,8 +273,8 @@ def test_simple_incremental_pipeline(page: Page, simple_incremental_pipeline: An
261273
).to_be_visible() # this is in the loads table
262274

263275
# ibis page
264-
_open_section(page, "ibis")
265-
expect(page.get_by_text(app_strings.ibis_backend_connected_text)).to_be_visible()
276+
# _open_section(page, "ibis")
277+
# expect(page.get_by_text(app_strings.ibis_backend_connected_text)).to_be_visible()
266278

267279

268280
def test_fruit_pipeline(page: Page, fruit_pipeline: Any):
@@ -272,7 +284,7 @@ def test_fruit_pipeline(page: Page, fruit_pipeline: Any):
272284

273285
# overview page
274286
_open_section(page, "overview")
275-
expect(page.get_by_text("_storage/.dlt/pipelines/fruit_pipeline")).to_be_visible()
287+
expect(page.get_by_text(_normpath("_storage/.dlt/pipelines/fruit_pipeline"))).to_be_visible()
276288

277289
# check schema info (this is the yaml part)
278290
_open_section(page, "schema")
@@ -301,15 +313,17 @@ def test_fruit_pipeline(page: Page, fruit_pipeline: Any):
301313
).to_be_visible() # this is in the loads table
302314

303315
# ibis page
304-
_open_section(page, "ibis")
305-
expect(page.get_by_text(app_strings.ibis_backend_connected_text)).to_be_visible()
316+
# _open_section(page, "ibis")
317+
# expect(page.get_by_text(app_strings.ibis_backend_connected_text)).to_be_visible()
306318

307319

308320
def test_never_run_pipeline(page: Page, never_run_pipeline: Any):
309321
_go_home(page)
310322
page.get_by_role("link", name="never_run_pipeline").click()
311323

312-
expect(page.get_by_text("_storage/.dlt/pipelines/never_run_pipeline")).to_be_visible()
324+
expect(
325+
page.get_by_text(_normpath("_storage/.dlt/pipelines/never_run_pipeline"))
326+
).to_be_visible()
313327

314328
# check schema info (this is the yaml part)
315329
_open_section(page, "schema")
@@ -330,16 +344,18 @@ def test_never_run_pipeline(page: Page, never_run_pipeline: Any):
330344
_open_section(page, "loads")
331345
expect(page.get_by_text(app_strings.loads_loading_failed_text[0:20])).to_be_visible()
332346

333-
_open_section(page, "ibis")
334-
expect(page.get_by_text(app_strings.ibis_backend_error_text[0:20])).to_be_visible()
347+
# _open_section(page, "ibis")
348+
# expect(page.get_by_text(app_strings.ibis_backend_error_text[0:20])).to_be_visible()
335349

336350

337351
def test_no_destination_pipeline(page: Page, no_destination_pipeline: Any):
338352
# check no destination pipeline
339353
_go_home(page)
340354
page.get_by_role("link", name="no_destination_pipeline").click()
341355

342-
expect(page.get_by_text("_storage/.dlt/pipelines/no_destination_pipeline")).to_be_visible()
356+
expect(
357+
page.get_by_text(_normpath("_storage/.dlt/pipelines/no_destination_pipeline"))
358+
).to_be_visible()
343359

344360
# check schema info (this is the yaml part)
345361
_open_section(page, "schema")
@@ -365,5 +381,5 @@ def test_no_destination_pipeline(page: Page, no_destination_pipeline: Any):
365381
page.get_by_text("execution_context").nth(0)
366382
).to_be_visible() # this is only shown in trace yaml
367383

368-
_open_section(page, "ibis")
369-
expect(page.get_by_text(app_strings.ibis_backend_error_text[0:20])).to_be_visible()
384+
# _open_section(page, "ibis")
385+
# expect(page.get_by_text(app_strings.ibis_backend_error_text[0:20])).to_be_visible()
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import marimo as mo
2+
import dlt
3+
4+
5+
from dlt.helpers.dashboard.ui_elements import (
6+
build_title_and_subtitle,
7+
build_page_header,
8+
build_error_callout,
9+
)
10+
11+
12+
def test_build_title_and_subtitle():
13+
title = "Test Title"
14+
subtitle = "Test Subtitle"
15+
html = build_title_and_subtitle(title, subtitle).text
16+
assert title in html
17+
assert subtitle in html
18+
19+
20+
def test_build_page_header(success_pipeline_duckdb: dlt.Pipeline):
21+
title = "Test Title"
22+
subtitle = "Test Subtitle"
23+
subtitle_long = "Test Alternative Subtitle Long"
24+
25+
# not opened
26+
html = build_page_header(
27+
success_pipeline_duckdb, title, subtitle, subtitle_long, mo.ui.button()
28+
)[0].text
29+
assert title in html
30+
assert subtitle in html
31+
assert subtitle_long not in html
32+
33+
# opened
34+
html = build_page_header(
35+
success_pipeline_duckdb, title, subtitle, subtitle_long, mo.ui.button(value=True)
36+
)[0].text
37+
assert title in html
38+
assert subtitle not in html
39+
assert subtitle_long in html
40+
41+
42+
def test_build_error_callout():
43+
message = "Test Message"
44+
code = "Test Code"
45+
traceback_string = "Test Traceback String"
46+
html = build_error_callout(message, code, traceback_string).text
47+
assert message in html
48+
assert code in html
49+
assert traceback_string in html

0 commit comments

Comments
 (0)