This is an automated email from the ASF dual-hosted git repository. rusackas pushed a commit to branch feat/docs-screenshots-playwright in repository https://gitbox.apache.org/repos/asf/superset.git
commit f8148cc9004093e2ab0efd91bbffeff998ec5258 Author: Evan Rusackas <[email protected]> AuthorDate: Tue Jan 27 08:36:31 2026 -0800 feat(playwright): add documentation screenshot tests Add Playwright tests that capture UI screenshots for the docs site and README. Uses reliable example data (World Bank dashboard), relative URLs for APP_PREFIX support, and element visibility waits instead of networkidle to avoid WebSocket timeouts in SQL Lab. Captures: chart gallery, dashboard, chart editor (explore), and SQL Lab. Updates README to reference the new dashboard.jpg filename. Based on #36297 by @jfrag1. Co-Authored-By: Claude Opus 4.5 <[email protected]> --- README.md | 2 +- .../experimental/docs/docs-screenshots.spec.ts | 163 +++++++++++++++++++++ superset-frontend/playwright/utils/urls.ts | 5 +- 3 files changed, 168 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 73ccfc8a61..db50352ca5 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ Superset provides: **Craft Beautiful, Dynamic Dashboards** -<kbd><img title="View Dashboards" src="https://superset.apache.org/img/screenshots/slack_dash.jpg"/></kbd><br/> +<kbd><img title="View Dashboards" src="https://superset.apache.org/img/screenshots/dashboard.jpg"/></kbd><br/> **No-Code Chart Builder** diff --git a/superset-frontend/playwright/tests/experimental/docs/docs-screenshots.spec.ts b/superset-frontend/playwright/tests/experimental/docs/docs-screenshots.spec.ts new file mode 100644 index 0000000000..a2333a5acc --- /dev/null +++ b/superset-frontend/playwright/tests/experimental/docs/docs-screenshots.spec.ts @@ -0,0 +1,163 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Documentation Screenshot Tests + * + * Captures screenshots for the Superset documentation site. + * Depends on example data loaded via `superset load_examples` in CI. + * + * Run with: INCLUDE_EXPERIMENTAL=true npx playwright test experimental/docs/ + * + * Screenshots are saved to docs/static/img/screenshots/ for use in + * the README and documentation site. + */ + +import path from 'path'; +import { test, expect } from '@playwright/test'; +import { URL } from '../../../utils/urls'; + +const SCREENSHOTS_DIR = path.resolve( + __dirname, + '../../../../../docs/static/img/screenshots', +); + +test('chart gallery screenshot', async ({ page }) => { + await page.goto(URL.CHART_ADD); + + // Wait for chart creation page to load + await expect(page.getByText('Choose chart type')).toBeVisible({ + timeout: 15000, + }); + await page.getByRole('tab', { name: 'All charts' }).click(); + + // Wait for viz gallery to render chart type thumbnails + const vizGallery = page.locator('.viz-gallery'); + await expect(vizGallery).toBeVisible(); + await expect( + vizGallery.locator('[data-test="viztype-selector-container"]').first(), + ).toBeVisible(); + + await page.addStyleTag({ content: 'body { zoom: 0.8 }' }); + await vizGallery.screenshot({ + path: path.join(SCREENSHOTS_DIR, 'gallery.jpg'), + type: 'jpeg', + }); +}); + +test('dashboard screenshot', async ({ page }) => { + // Navigate to the World Bank dashboard via its slug (reliable example data) + await page.goto('superset/dashboard/world_health/'); + + // Wait for dashboard to fully render + const dashboardWrapper = page.locator( + '[data-test="dashboard-content-wrapper"]', + ); + await expect(dashboardWrapper).toBeVisible({ timeout: 30000 }); + + // Wait for charts to load inside the dashboard + await expect( + page.locator('.dashboard-component-chart-holder').first(), + ).toBeVisible({ timeout: 15000 }); + + // Allow charts a moment to finish rendering + await page.waitForTimeout(3000); + + await page.addStyleTag({ content: 'body { zoom: 0.8 }' }); + await dashboardWrapper.screenshot({ + path: path.join(SCREENSHOTS_DIR, 'dashboard.jpg'), + type: 'jpeg', + }); +}); + +test('chart editor screenshot', async ({ page }) => { + await page.goto(URL.CHART_LIST); + + // Wait for chart list to load + const listView = page.locator('[data-test="listview-table"]'); + await expect(listView).toBeVisible({ timeout: 15000 }); + + // Click the first chart link in the list to open explore + const firstChartLink = page + .locator('[data-test="table-row"] a[href*="/explore"]') + .first(); + await expect(firstChartLink).toBeVisible(); + await firstChartLink.click(); + + // Wait for explore page to fully load + await page.waitForURL('**/explore/**', { timeout: 15000 }); + await expect(page.locator('[data-test="slice-container"]')).toBeVisible({ + timeout: 15000, + }); + + await page.screenshot({ + path: path.join(SCREENSHOTS_DIR, 'explore.jpg'), + type: 'jpeg', + fullPage: true, + }); +}); + +test('SQL Lab screenshot', async ({ page }) => { + await page.goto(URL.SQLLAB); + + // Wait for SQL Lab editor to be ready + const aceEditor = page.locator('.ace_content'); + await expect(aceEditor).toBeVisible({ timeout: 15000 }); + + // Select the examples database + const databaseSelect = page.getByRole('combobox', { + name: /select database/i, + }); + await expect(databaseSelect).toBeVisible(); + await databaseSelect.click(); + await page.getByText('examples', { exact: true }).click(); + + // Select schema + const schemaSelect = page.getByRole('combobox', { + name: /select schema/i, + }); + await expect(schemaSelect).toBeEnabled({ timeout: 10000 }); + await schemaSelect.click(); + // Use the first available schema option + await page.getByRole('option').first().click(); + + // Type a query in the editor + await aceEditor.click(); + const editor = page.getByRole('textbox', { name: /cursor/i }); + await editor.fill('SELECT * FROM birth_names LIMIT 100'); + + // Run the query + const runButton = page.locator('[data-test="run-query-action"]'); + await expect(runButton).toBeVisible(); + await runButton.click(); + + // Wait for results table to appear (not networkidle which hangs on WebSockets) + await expect(page.locator('.ReactVirtualized__Table')).toBeVisible({ + timeout: 30000, + }); + + // Click editor area to deselect results + await aceEditor.click(); + + await page.screenshot({ + path: path.join(SCREENSHOTS_DIR, 'sql_lab.jpg'), + type: 'jpeg', + fullPage: true, + }); +}); diff --git a/superset-frontend/playwright/utils/urls.ts b/superset-frontend/playwright/utils/urls.ts index d83e33f755..fa5be71c8f 100644 --- a/superset-frontend/playwright/utils/urls.ts +++ b/superset-frontend/playwright/utils/urls.ts @@ -28,8 +28,11 @@ * = 'http://localhost:8088/app/prefix/tablemodelview/list' */ export const URL = { - DATASET_LIST: 'tablemodelview/list', + CHART_ADD: 'chart/add', + CHART_LIST: 'chart/list/', DASHBOARD_LIST: 'dashboard/list/', + DATASET_LIST: 'tablemodelview/list', LOGIN: 'login/', + SQLLAB: 'sqllab', WELCOME: 'superset/welcome/', } as const;
