You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by jl...@apache.org on 2026/04/02 19:00:14 UTC
(superset) branch master updated: chore(tests): promote Playwright experimental tests to stable (#38924)
This is an automated email from the ASF dual-hosted git repository.
jli pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new 5662ecab154 chore(tests): promote Playwright experimental tests to stable (#38924)
5662ecab154 is described below
commit 5662ecab15458071383e51d8b74918cf822e6180
Author: Joe Li <jo...@preset.io>
AuthorDate: Thu Apr 2 12:00:06 2026 -0700
chore(tests): promote Playwright experimental tests to stable (#38924)
Co-authored-by: Claude Opus 4.6 (1M context) <no...@anthropic.com>
---
.../cypress/e2e/chart_list/list.test.ts | 171 ---------------------
.../cypress/e2e/dataset/dataset_list.test.ts | 42 -----
.../cypress-base/cypress/e2e/explore/utils.ts | 33 +---
.../cypress-base/cypress/utils/index.ts | 22 ---
.../cypress-base/cypress/utils/urls.ts | 5 -
.../playwright/components/modals/index.ts | 3 +
.../playwright/pages/ChartListPage.ts | 39 ++++-
.../{experimental => }/chart/chart-list.spec.ts | 73 +++++++--
.../{experimental => }/chart/chart-test-helpers.ts | 6 +-
.../dashboard/dashboard-list.spec.ts | 21 ++-
.../dashboard/dashboard-test-helpers.ts | 4 +-
.../{experimental => }/dashboard/export.spec.ts | 6 +-
.../{experimental => }/dashboard/theme.spec.ts | 12 +-
.../dataset/create-dataset.spec.ts | 20 +--
.../dataset/dataset-list.spec.ts | 57 +++----
.../dataset/dataset-test-helpers.ts | 4 +-
16 files changed, 163 insertions(+), 355 deletions(-)
diff --git a/superset-frontend/cypress-base/cypress/e2e/chart_list/list.test.ts b/superset-frontend/cypress-base/cypress/e2e/chart_list/list.test.ts
deleted file mode 100644
index 9f507bca4ab..00000000000
--- a/superset-frontend/cypress-base/cypress/e2e/chart_list/list.test.ts
+++ /dev/null
@@ -1,171 +0,0 @@
-/**
- * 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.
- */
-import { CHART_LIST } from 'cypress/utils/urls';
-import { setGridMode, toggleBulkSelect } from 'cypress/utils';
-import {
- setFilter,
- interceptBulkDelete,
- interceptUpdate,
- interceptDelete,
- interceptFiltering,
- interceptFavoriteStatus,
-} from '../explore/utils';
-
-function orderAlphabetical() {
- setFilter('Sort', 'Alphabetical');
-}
-
-function openProperties() {
- cy.get('[aria-label="more"]').eq(0).click();
- cy.getBySel('chart-list-edit-option').click();
-}
-
-function openMenu() {
- cy.get('[aria-label="more"]').eq(0).click();
-}
-
-function confirmDelete() {
- cy.getBySel('delete-modal-input').type('DELETE');
- cy.getBySel('modal-confirm-button').click();
-}
-
-function visitChartList() {
- interceptFiltering();
- interceptFavoriteStatus();
- cy.visit(CHART_LIST);
- cy.wait('@filtering');
- cy.wait('@favoriteStatus');
-}
-
-describe('Charts list', () => {
- describe('common actions', () => {
- beforeEach(() => {
- visitChartList();
- });
-
- it('should bulk delete correctly', () => {
- cy.createSampleCharts([0, 1, 2, 3]);
-
- interceptBulkDelete();
- toggleBulkSelect();
-
- // bulk deletes in card-view
- setGridMode('card');
- orderAlphabetical();
-
- cy.getBySel('skeleton-card').should('not.exist');
- cy.getBySel('styled-card').contains('1 - Sample chart').click();
- cy.getBySel('styled-card').contains('2 - Sample chart').click();
- cy.getBySel('bulk-select-action').contains('Delete').click();
- confirmDelete();
- cy.wait('@bulkDelete');
- cy.getBySel('styled-card')
- .eq(1)
- .should('not.contain', '1 - Sample chart');
- cy.getBySel('styled-card')
- .eq(2)
- .should('not.contain', '2 - Sample chart');
-
- // bulk deletes in list-view
- setGridMode('list');
- cy.get('.loading').should('not.exist');
- cy.getBySel('table-row').contains('3 - Sample chart').should('exist');
- cy.getBySel('table-row').contains('4 - Sample chart').should('exist');
- cy.get('[data-test="table-row"] input[type="checkbox"]').eq(0).click();
- cy.get('[data-test="table-row"] input[type="checkbox"]').eq(1).click();
- cy.getBySel('bulk-select-action').eq(0).contains('Delete').click();
- confirmDelete();
- cy.wait('@bulkDelete');
- cy.get('.loading').should('exist');
- cy.get('.loading').should('not.exist');
- cy.getBySel('table-row').eq(0).should('not.contain', '3 - Sample chart');
- cy.getBySel('table-row').eq(1).should('not.contain', '4 - Sample chart');
- });
-
- it('should delete correctly in card mode', () => {
- cy.createSampleCharts([0, 1]);
- interceptDelete();
-
- // deletes in card-view
- setGridMode('card');
- orderAlphabetical();
-
- cy.getBySel('styled-card').contains('1 - Sample chart');
- openMenu();
- cy.getBySel('chart-list-delete-option').click();
- confirmDelete();
- cy.wait('@delete');
- cy.getBySel('styled-card')
- .contains('1 - Sample chart')
- .should('not.exist');
- });
-
- it('should delete correctly in list mode', () => {
- cy.createSampleCharts([2, 3]);
- interceptDelete();
- cy.getBySel('sort-header').contains('Name').click();
-
- // Modal closes immediately without this
- cy.wait(2000);
-
- cy.getBySel('table-row').eq(0).contains('3 - Sample chart');
- cy.getBySel('delete').eq(0).click();
- confirmDelete();
- cy.wait('@delete');
- cy.get('.loading').should('exist');
- cy.get('.loading').should('not.exist');
- cy.getBySel('table-row').eq(0).should('not.contain', '3 - Sample chart');
- });
-
- it('should edit correctly', () => {
- cy.createSampleCharts([0]);
- interceptUpdate();
-
- // edits in card-view
- setGridMode('card');
- orderAlphabetical();
- cy.getBySel('skeleton-card').should('not.exist');
- cy.getBySel('styled-card').eq(0).contains('1 - Sample chart');
-
- // change title
- openProperties();
- cy.getBySel('properties-modal-name-input').type(' | EDITED');
- cy.get('button:contains("Save")').click();
- cy.wait('@update');
- cy.getBySel('styled-card').eq(0).contains('1 - Sample chart | EDITED');
-
- // edits in list-view
- setGridMode('list');
- // Wait for list view to fully render after mode change
- cy.get('.loading').should('not.exist');
- cy.getBySel('table-row').should('be.visible');
- // Target the specific row by chart title to avoid flakiness from row ordering
- cy.getBySel('table-row')
- .contains('1 - Sample chart | EDITED')
- .parents('[data-test="table-row"]')
- .find('[data-test="edit-alt"]')
- .click();
- cy.getBySel('properties-modal-name-input').clear();
- cy.getBySel('properties-modal-name-input').type('1 - Sample chart');
- cy.get('button:contains("Save")').click();
- cy.wait('@update');
- cy.getBySel('table-row').contains('1 - Sample chart').should('exist');
- });
- });
-});
diff --git a/superset-frontend/cypress-base/cypress/e2e/dataset/dataset_list.test.ts b/superset-frontend/cypress-base/cypress/e2e/dataset/dataset_list.test.ts
deleted file mode 100644
index 6bf0419cdda..00000000000
--- a/superset-frontend/cypress-base/cypress/e2e/dataset/dataset_list.test.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * 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.
- */
-
-import { DATASET_LIST_PATH } from 'cypress/utils/urls';
-
-describe('Dataset list', () => {
- before(() => {
- cy.visit(DATASET_LIST_PATH);
- });
-
- xit('should open Explore on dataset name click', () => {
- cy.intercept('**/api/v1/explore/**').as('explore');
- cy.get('[data-test="listview-table"] [data-test="internal-link"]')
- .contains('birth_names')
- .click();
- cy.wait('@explore');
- cy.get('[data-test="datasource-control"] .title-select').contains(
- 'birth_names',
- );
- cy.get('.metric-option-label').first().contains('COUNT(*)');
- cy.get('.column-option-label').first().contains('ds');
- cy.get('[data-test="fast-viz-switcher"] > div:not([role="button"]')
- .contains('Table')
- .should('be.visible');
- });
-});
diff --git a/superset-frontend/cypress-base/cypress/e2e/explore/utils.ts b/superset-frontend/cypress-base/cypress/e2e/explore/utils.ts
index 93dbe99baa2..5a4df482ec0 100644
--- a/superset-frontend/cypress-base/cypress/e2e/explore/utils.ts
+++ b/superset-frontend/cypress-base/cypress/e2e/explore/utils.ts
@@ -23,18 +23,6 @@ export function interceptFiltering() {
cy.intercept('GET', `**/api/v1/chart/?q=*`).as('filtering');
}
-export function interceptBulkDelete() {
- cy.intercept('DELETE', `**/api/v1/chart/?q=*`).as('bulkDelete');
-}
-
-export function interceptDelete() {
- cy.intercept('DELETE', `**/api/v1/chart/*`).as('delete');
-}
-
-export function interceptFavoriteStatus() {
- cy.intercept('GET', '**/api/v1/chart/favorite_status/*').as('favoriteStatus');
-}
-
export function interceptUpdate() {
cy.intercept('PUT', `**/api/v1/chart/*`).as('update');
}
@@ -43,32 +31,13 @@ export const interceptV1ChartData = (alias = 'v1Data') => {
cy.intercept('**/api/v1/chart/data*').as(alias);
};
-export function interceptExploreJson(alias = 'getJson') {
- cy.intercept('POST', `**/superset/explore_json/**`).as(alias);
-}
-
-export const interceptFormDataKey = () => {
- cy.intercept('POST', '**/api/v1/explore/form_data').as('formDataKey');
-};
-
-export function interceptExploreGet() {
+function interceptExploreGet() {
cy.intercept({
method: 'GET',
url: /.*\/api\/v1\/explore\/\?(form_data_key|dashboard_page_id|slice_id)=.*/,
}).as('getExplore');
}
-export function setFilter(filter: string, option: string) {
- interceptFiltering();
-
- cy.get(`[aria-label^="${filter}"]`).first().click();
- cy.get(`.ant-select-item-option[title="${option}"]`).first().click({
- force: true,
- });
-
- cy.wait('@filtering');
-}
-
export function saveChartToDashboard(chartName: string, dashboardName: string) {
interceptDashboardGet();
interceptUpdate();
diff --git a/superset-frontend/cypress-base/cypress/utils/index.ts b/superset-frontend/cypress-base/cypress/utils/index.ts
index 00ff58ab9aa..0c12c23aba7 100644
--- a/superset-frontend/cypress-base/cypress/utils/index.ts
+++ b/superset-frontend/cypress-base/cypress/utils/index.ts
@@ -25,28 +25,6 @@ export interface ChartSpec {
viz: string;
}
-const viewTypeIcons = {
- card: 'appstore',
- list: 'unordered-list',
-};
-
-export function setGridMode(type: 'card' | 'list') {
- const icon = viewTypeIcons[type];
- cy.get(`[aria-label="${icon}"]`).click();
-}
-
-export function toggleBulkSelect() {
- cy.getBySel('bulk-select').click();
-}
-
-export function clearAllInputs() {
- cy.get('body').then($body => {
- if ($body.find('.ant-select-clear').length) {
- cy.get('.ant-select-clear').click({ multiple: true, force: true });
- }
- });
-}
-
const toSlicelike = ($chart: JQuery<HTMLElement>): Slice => {
const chartId = $chart.attr('data-test-chart-id');
const vizType = $chart.attr('data-test-viz-type');
diff --git a/superset-frontend/cypress-base/cypress/utils/urls.ts b/superset-frontend/cypress-base/cypress/utils/urls.ts
index 1a585f40479..66110bcc64b 100644
--- a/superset-frontend/cypress-base/cypress/utils/urls.ts
+++ b/superset-frontend/cypress-base/cypress/utils/urls.ts
@@ -25,8 +25,3 @@ export const SUPPORTED_CHARTS_DASHBOARD =
'/superset/dashboard/supported_charts_dash/';
export const TABBED_DASHBOARD = '/superset/dashboard/tabbed_dash/';
export const DATABASE_LIST = '/databaseview/list';
-export const DATASET_LIST_PATH = 'tablemodelview/list';
-export const ALERT_LIST = '/alert/list/';
-export const REPORT_LIST = '/report/list/';
-export const LOGIN = '/login/';
-export const REGISTER = '/register/';
diff --git a/superset-frontend/playwright/components/modals/index.ts b/superset-frontend/playwright/components/modals/index.ts
index a8f8f1576f3..41074401a7d 100644
--- a/superset-frontend/playwright/components/modals/index.ts
+++ b/superset-frontend/playwright/components/modals/index.ts
@@ -18,6 +18,9 @@
*/
// Specific modal implementations
+export { ChartPropertiesModal } from './ChartPropertiesModal';
+export { ConfirmDialog } from './ConfirmDialog';
export { DeleteConfirmationModal } from './DeleteConfirmationModal';
export { DuplicateDatasetModal } from './DuplicateDatasetModal';
+export { EditDatasetModal } from './EditDatasetModal';
export { ImportDatasetModal } from './ImportDatasetModal';
diff --git a/superset-frontend/playwright/pages/ChartListPage.ts b/superset-frontend/playwright/pages/ChartListPage.ts
index 74f75181d24..49c3578cfb1 100644
--- a/superset-frontend/playwright/pages/ChartListPage.ts
+++ b/superset-frontend/playwright/pages/ChartListPage.ts
@@ -47,7 +47,7 @@ export class ChartListPage {
}
/**
- * Navigate to the chart list page.
+ * Navigate to the chart list page in table view.
* Forces table view via URL parameter to avoid card view default
* (ListviewsDefaultCardView feature flag may enable card view).
*/
@@ -55,6 +55,13 @@ export class ChartListPage {
await this.page.goto(`${URL.CHART_LIST}?viewMode=table`);
}
+ /**
+ * Navigate to the chart list page in card view.
+ */
+ async gotoCardView(): Promise<void> {
+ await this.page.goto(`${URL.CHART_LIST}?viewMode=card`);
+ }
+
/**
* Wait for the table to load
* @param options - Optional wait options
@@ -63,6 +70,16 @@ export class ChartListPage {
await this.table.waitForVisible(options);
}
+ /**
+ * Wait for card view to finish loading.
+ */
+ async waitForCardLoad(options?: { timeout?: number }): Promise<void> {
+ await this.page
+ .locator('[data-test="styled-card"]')
+ .first()
+ .waitFor({ state: 'visible', ...options });
+ }
+
/**
* Gets a chart row locator by name.
* Returns a Locator that tests can use with expect().toBeVisible(), etc.
@@ -129,4 +146,24 @@ export class ChartListPage {
async clickBulkAction(actionName: string): Promise<void> {
await this.bulkSelect.clickAction(actionName);
}
+
+ // --- Card view methods ---
+
+ /**
+ * Gets a chart card locator by name (card view).
+ */
+ getChartCard(chartName: string): Locator {
+ return this.page
+ .locator('[data-test="styled-card"]')
+ .filter({ hasText: chartName });
+ }
+
+ /**
+ * Clicks the edit option in a chart card's dropdown menu (card view).
+ */
+ async clickCardEditAction(chartName: string): Promise<void> {
+ const card = this.getChartCard(chartName);
+ await card.locator('[aria-label="more"]').click();
+ await this.page.locator('[data-test="chart-list-edit-option"]').click();
+ }
}
diff --git a/superset-frontend/playwright/tests/experimental/chart/chart-list.spec.ts b/superset-frontend/playwright/tests/chart/chart-list.spec.ts
similarity index 79%
rename from superset-frontend/playwright/tests/experimental/chart/chart-list.spec.ts
rename to superset-frontend/playwright/tests/chart/chart-list.spec.ts
index b1476db4f8f..57f7b2dd2ea 100644
--- a/superset-frontend/playwright/tests/experimental/chart/chart-list.spec.ts
+++ b/superset-frontend/playwright/tests/chart/chart-list.spec.ts
@@ -17,21 +17,20 @@
* under the License.
*/
+import { testWithAssets, expect } from '../../helpers/fixtures';
+import { ChartListPage } from '../../pages/ChartListPage';
import {
- test as testWithAssets,
- expect,
-} from '../../../helpers/fixtures/testAssets';
-import { ChartListPage } from '../../../pages/ChartListPage';
-import { ChartPropertiesModal } from '../../../components/modals/ChartPropertiesModal';
-import { DeleteConfirmationModal } from '../../../components/modals/DeleteConfirmationModal';
-import { Toast } from '../../../components/core/Toast';
-import { apiGetChart, ENDPOINTS } from '../../../helpers/api/chart';
+ ChartPropertiesModal,
+ DeleteConfirmationModal,
+} from '../../components/modals';
+import { Toast } from '../../components/core';
+import { apiGetChart, ENDPOINTS } from '../../helpers/api/chart';
import { createTestChart } from './chart-test-helpers';
-import { waitForGet, waitForPut } from '../../../helpers/api/intercepts';
+import { waitForGet, waitForPut } from '../../helpers/api/intercepts';
import {
expectStatusOneOf,
expectValidExportZip,
-} from '../../../helpers/api/assertions';
+} from '../../helpers/api/assertions';
/**
* Extend testWithAssets with chartListPage navigation (beforeEach equivalent).
@@ -261,6 +260,60 @@ test('should bulk delete multiple charts', async ({
}
});
+test('should edit chart name from card view', async ({ page, testAssets }) => {
+ // Create throwaway chart for editing
+ const { id: chartId, name: chartName } = await createTestChart(
+ page,
+ testAssets,
+ test.info(),
+ { prefix: 'test_card_edit' },
+ );
+
+ // Navigate to card view (not table view)
+ const cardListPage = new ChartListPage(page);
+ await cardListPage.gotoCardView();
+ await cardListPage.waitForCardLoad();
+
+ // Verify chart card is visible
+ await expect(cardListPage.getChartCard(chartName)).toBeVisible();
+
+ // Open card dropdown and click edit
+ await cardListPage.clickCardEditAction(chartName);
+
+ // Wait for properties modal to be ready
+ const propertiesModal = new ChartPropertiesModal(page);
+ await propertiesModal.waitForReady();
+
+ // Edit the chart name
+ const newName = `card_renamed_${Date.now()}_${test.info().parallelIndex}`;
+ await propertiesModal.fillName(newName);
+
+ // Set up response intercept for save
+ const saveResponsePromise = waitForPut(page, `${ENDPOINTS.CHART}${chartId}`);
+
+ // Click Save button
+ await propertiesModal.clickSave();
+
+ // Wait for save to complete and verify success
+ expectStatusOneOf(await saveResponsePromise, [200, 201]);
+
+ // Modal should close
+ await propertiesModal.waitForHidden();
+
+ // Verify success toast appears
+ const toast = new Toast(page);
+ await expect(toast.getSuccess()).toBeVisible();
+
+ // Verify the renamed card appears in card view and old name is gone
+ await expect(cardListPage.getChartCard(newName)).toBeVisible();
+ await expect(cardListPage.getChartCard(chartName)).not.toBeVisible();
+
+ // Backend verification: API returns updated name
+ const response = await apiGetChart(page, chartId);
+ const chart = (await response.json()).result;
+ expect(chart.slice_name).toBe(newName);
+});
+
test('should bulk export multiple charts', async ({
page,
chartListPage,
diff --git a/superset-frontend/playwright/tests/experimental/chart/chart-test-helpers.ts b/superset-frontend/playwright/tests/chart/chart-test-helpers.ts
similarity index 92%
rename from superset-frontend/playwright/tests/experimental/chart/chart-test-helpers.ts
rename to superset-frontend/playwright/tests/chart/chart-test-helpers.ts
index fa0dc55e036..5cae0d5f58f 100644
--- a/superset-frontend/playwright/tests/experimental/chart/chart-test-helpers.ts
+++ b/superset-frontend/playwright/tests/chart/chart-test-helpers.ts
@@ -18,9 +18,9 @@
*/
import type { Page, TestInfo } from '@playwright/test';
-import type { TestAssets } from '../../../helpers/fixtures/testAssets';
-import { apiPostChart } from '../../../helpers/api/chart';
-import { getDatasetByName } from '../../../helpers/api/dataset';
+import type { TestAssets } from '../../helpers/fixtures';
+import { apiPostChart } from '../../helpers/api/chart';
+import { getDatasetByName } from '../../helpers/api/dataset';
interface TestChartResult {
id: number;
diff --git a/superset-frontend/playwright/tests/experimental/dashboard/dashboard-list.spec.ts b/superset-frontend/playwright/tests/dashboard/dashboard-list.spec.ts
similarity index 95%
rename from superset-frontend/playwright/tests/experimental/dashboard/dashboard-list.spec.ts
rename to superset-frontend/playwright/tests/dashboard/dashboard-list.spec.ts
index 0ed0c49769d..a305b65ffa0 100644
--- a/superset-frontend/playwright/tests/experimental/dashboard/dashboard-list.spec.ts
+++ b/superset-frontend/playwright/tests/dashboard/dashboard-list.spec.ts
@@ -17,28 +17,27 @@
* under the License.
*/
+import { testWithAssets, expect } from '../../helpers/fixtures';
+import { DashboardListPage } from '../../pages/DashboardListPage';
import {
- test as testWithAssets,
- expect,
-} from '../../../helpers/fixtures/testAssets';
-import { DashboardListPage } from '../../../pages/DashboardListPage';
-import { DeleteConfirmationModal } from '../../../components/modals/DeleteConfirmationModal';
-import { ImportDatasetModal } from '../../../components/modals/ImportDatasetModal';
-import { Toast } from '../../../components/core/Toast';
+ DeleteConfirmationModal,
+ ImportDatasetModal,
+} from '../../components/modals';
+import { Toast } from '../../components/core';
import {
apiGetDashboard,
apiDeleteDashboard,
apiExportDashboards,
getDashboardByName,
ENDPOINTS,
-} from '../../../helpers/api/dashboard';
+} from '../../helpers/api/dashboard';
import { createTestDashboard } from './dashboard-test-helpers';
-import { waitForGet, waitForPost } from '../../../helpers/api/intercepts';
+import { waitForGet, waitForPost } from '../../helpers/api/intercepts';
import {
expectStatusOneOf,
expectValidExportZip,
-} from '../../../helpers/api/assertions';
-import { TIMEOUT } from '../../../utils/constants';
+} from '../../helpers/api/assertions';
+import { TIMEOUT } from '../../utils/constants';
/**
* Extend testWithAssets with dashboardListPage navigation (beforeEach equivalent).
diff --git a/superset-frontend/playwright/tests/experimental/dashboard/dashboard-test-helpers.ts b/superset-frontend/playwright/tests/dashboard/dashboard-test-helpers.ts
similarity index 93%
rename from superset-frontend/playwright/tests/experimental/dashboard/dashboard-test-helpers.ts
rename to superset-frontend/playwright/tests/dashboard/dashboard-test-helpers.ts
index fcbb07601eb..9f45661342e 100644
--- a/superset-frontend/playwright/tests/experimental/dashboard/dashboard-test-helpers.ts
+++ b/superset-frontend/playwright/tests/dashboard/dashboard-test-helpers.ts
@@ -18,8 +18,8 @@
*/
import type { Page, TestInfo } from '@playwright/test';
-import type { TestAssets } from '../../../helpers/fixtures/testAssets';
-import { apiPostDashboard } from '../../../helpers/api/dashboard';
+import type { TestAssets } from '../../helpers/fixtures';
+import { apiPostDashboard } from '../../helpers/api/dashboard';
interface TestDashboardResult {
id: number;
diff --git a/superset-frontend/playwright/tests/experimental/dashboard/export.spec.ts b/superset-frontend/playwright/tests/dashboard/export.spec.ts
similarity index 94%
rename from superset-frontend/playwright/tests/experimental/dashboard/export.spec.ts
rename to superset-frontend/playwright/tests/dashboard/export.spec.ts
index 992aaca5097..1687bf2ecac 100644
--- a/superset-frontend/playwright/tests/experimental/dashboard/export.spec.ts
+++ b/superset-frontend/playwright/tests/dashboard/export.spec.ts
@@ -18,9 +18,9 @@
*/
import { test, expect } from '@playwright/test';
-import { DashboardPage } from '../../../pages/DashboardPage';
-import { Toast } from '../../../components/core';
-import { TIMEOUT } from '../../../utils/constants';
+import { DashboardPage } from '../../pages/DashboardPage';
+import { Toast } from '../../components/core';
+import { TIMEOUT } from '../../utils/constants';
/**
* Dashboard Export E2E tests.
diff --git a/superset-frontend/playwright/tests/experimental/dashboard/theme.spec.ts b/superset-frontend/playwright/tests/dashboard/theme.spec.ts
similarity index 93%
rename from superset-frontend/playwright/tests/experimental/dashboard/theme.spec.ts
rename to superset-frontend/playwright/tests/dashboard/theme.spec.ts
index edec236e6ca..79d431cb85c 100644
--- a/superset-frontend/playwright/tests/experimental/dashboard/theme.spec.ts
+++ b/superset-frontend/playwright/tests/dashboard/theme.spec.ts
@@ -18,16 +18,16 @@
*/
import { test, expect } from '@playwright/test';
-import { AuthPage } from '../../../pages/AuthPage';
-import { DashboardPage } from '../../../pages/DashboardPage';
-import { apiPostTheme, apiDeleteTheme } from '../../../helpers/api/theme';
+import { AuthPage } from '../../pages/AuthPage';
+import { DashboardPage } from '../../pages/DashboardPage';
+import { apiPostTheme, apiDeleteTheme } from '../../helpers/api/theme';
import {
apiPostDashboard,
apiPutDashboard,
apiDeleteDashboard,
-} from '../../../helpers/api/dashboard';
-import { apiGet } from '../../../helpers/api/requests';
-import { TIMEOUT } from '../../../utils/constants';
+} from '../../helpers/api/dashboard';
+import { apiGet } from '../../helpers/api/requests';
+import { TIMEOUT } from '../../utils/constants';
/**
* Dashboard Theme E2E tests.
diff --git a/superset-frontend/playwright/tests/experimental/dataset/create-dataset.spec.ts b/superset-frontend/playwright/tests/dataset/create-dataset.spec.ts
similarity index 91%
rename from superset-frontend/playwright/tests/experimental/dataset/create-dataset.spec.ts
rename to superset-frontend/playwright/tests/dataset/create-dataset.spec.ts
index 4250ddcb674..a1a69e54a93 100644
--- a/superset-frontend/playwright/tests/experimental/dataset/create-dataset.spec.ts
+++ b/superset-frontend/playwright/tests/dataset/create-dataset.spec.ts
@@ -17,17 +17,17 @@
* under the License.
*/
-import { test, expect } from '../../../helpers/fixtures/testAssets';
-import type { TestAssets } from '../../../helpers/fixtures/testAssets';
+import { testWithAssets as test, expect } from '../../helpers/fixtures';
+import type { TestAssets } from '../../helpers/fixtures';
import type { Page, TestInfo } from '@playwright/test';
-import { ExplorePage } from '../../../pages/ExplorePage';
-import { CreateDatasetPage } from '../../../pages/CreateDatasetPage';
-import { DatasetListPage } from '../../../pages/DatasetListPage';
-import { ChartCreationPage } from '../../../pages/ChartCreationPage';
-import { ENDPOINTS } from '../../../helpers/api/dataset';
-import { waitForPost } from '../../../helpers/api/intercepts';
-import { expectStatusOneOf } from '../../../helpers/api/assertions';
-import { apiPostDatabase } from '../../../helpers/api/database';
+import { ExplorePage } from '../../pages/ExplorePage';
+import { CreateDatasetPage } from '../../pages/CreateDatasetPage';
+import { DatasetListPage } from '../../pages/DatasetListPage';
+import { ChartCreationPage } from '../../pages/ChartCreationPage';
+import { ENDPOINTS } from '../../helpers/api/dataset';
+import { waitForPost } from '../../helpers/api/intercepts';
+import { expectStatusOneOf } from '../../helpers/api/assertions';
+import { apiPostDatabase } from '../../helpers/api/database';
interface GsheetsSetupResult {
sheetName: string;
diff --git a/superset-frontend/playwright/tests/experimental/dataset/dataset-list.spec.ts b/superset-frontend/playwright/tests/dataset/dataset-list.spec.ts
similarity index 92%
rename from superset-frontend/playwright/tests/experimental/dataset/dataset-list.spec.ts
rename to superset-frontend/playwright/tests/dataset/dataset-list.spec.ts
index a31e6db4e98..d9b781507ea 100644
--- a/superset-frontend/playwright/tests/experimental/dataset/dataset-list.spec.ts
+++ b/superset-frontend/playwright/tests/dataset/dataset-list.spec.ts
@@ -17,37 +17,36 @@
* under the License.
*/
-import {
- test as testWithAssets,
- expect,
-} from '../../../helpers/fixtures/testAssets';
+import { testWithAssets, expect } from '../../helpers/fixtures';
import path from 'path';
-import { DatasetListPage } from '../../../pages/DatasetListPage';
-import { ExplorePage } from '../../../pages/ExplorePage';
-import { ConfirmDialog } from '../../../components/modals/ConfirmDialog';
-import { DeleteConfirmationModal } from '../../../components/modals/DeleteConfirmationModal';
-import { ImportDatasetModal } from '../../../components/modals/ImportDatasetModal';
-import { DuplicateDatasetModal } from '../../../components/modals/DuplicateDatasetModal';
-import { EditDatasetModal } from '../../../components/modals/EditDatasetModal';
-import { Toast } from '../../../components/core/Toast';
+import { DatasetListPage } from '../../pages/DatasetListPage';
+import { ExplorePage } from '../../pages/ExplorePage';
+import {
+ ConfirmDialog,
+ DeleteConfirmationModal,
+ DuplicateDatasetModal,
+ EditDatasetModal,
+ ImportDatasetModal,
+} from '../../components/modals';
+import { Toast } from '../../components/core';
import {
apiDeleteDataset,
apiGetDataset,
apiPostVirtualDataset,
getDatasetByName,
ENDPOINTS,
-} from '../../../helpers/api/dataset';
+} from '../../helpers/api/dataset';
import { createTestDataset } from './dataset-test-helpers';
import {
waitForGet,
waitForPost,
waitForPut,
-} from '../../../helpers/api/intercepts';
+} from '../../helpers/api/intercepts';
import {
expectStatusOneOf,
expectValidExportZip,
-} from '../../../helpers/api/assertions';
-import { TIMEOUT } from '../../../utils/constants';
+} from '../../helpers/api/assertions';
+import { TIMEOUT } from '../../utils/constants';
/**
* Extend testWithAssets with datasetListPage navigation (beforeEach equivalent).
@@ -458,11 +457,12 @@ test.describe('import dataset', () => {
testAssets,
}) => {
// Dataset name from fixture (test_netflix_1768502050965)
- // Note: Fixture contains a Google Sheets dataset - test will skip if gsheets connector unavailable
+ // Note: Fixture contains a Google Sheets dataset backed by shillelagh[gsheetsapi],
+ // which is a base dependency — import failure fails the test hard (no skip).
const importedDatasetName = 'test_netflix_1768502050965';
const fixturePath = path.resolve(
__dirname,
- '../../../fixtures/dataset_export.zip',
+ '../../fixtures/dataset_export.zip',
);
// Cleanup: Delete any existing dataset with the same name from previous runs
@@ -518,25 +518,12 @@ test.describe('import dataset', () => {
importResponse = await importResponsePromise;
}
- // Check final import response for gsheets connector errors
+ // Fail hard if dataset import fails.
+ // The fixture contains a gsheets dataset; shillelagh[gsheetsapi] is a base
+ // dependency (pyproject.toml), so the engine is always available in CI.
if (!importResponse.ok()) {
const errorBody = await importResponse.json().catch(() => ({}));
- const errorText = JSON.stringify(errorBody);
- // Skip test if gsheets connector not installed
- if (
- errorText.includes('gsheets') ||
- errorText.includes('No such DB engine') ||
- errorText.includes('Could not load database driver')
- ) {
- await test.info().attach('skip-reason', {
- body: `Import failed due to missing gsheets connector: ${errorText}`,
- contentType: 'text/plain',
- });
- test.skip();
- return;
- }
- // Re-throw other errors
- throw new Error(`Import failed: ${errorText}`);
+ throw new Error(`Import failed: ${JSON.stringify(errorBody)}`);
}
// Modal should close on success
diff --git a/superset-frontend/playwright/tests/experimental/dataset/dataset-test-helpers.ts b/superset-frontend/playwright/tests/dataset/dataset-test-helpers.ts
similarity index 93%
rename from superset-frontend/playwright/tests/experimental/dataset/dataset-test-helpers.ts
rename to superset-frontend/playwright/tests/dataset/dataset-test-helpers.ts
index 8f619580ae8..2bff43f8b28 100644
--- a/superset-frontend/playwright/tests/experimental/dataset/dataset-test-helpers.ts
+++ b/superset-frontend/playwright/tests/dataset/dataset-test-helpers.ts
@@ -18,8 +18,8 @@
*/
import type { Page, TestInfo } from '@playwright/test';
-import type { TestAssets } from '../../../helpers/fixtures/testAssets';
-import { createTestVirtualDataset } from '../../../helpers/api/dataset';
+import type { TestAssets } from '../../helpers/fixtures';
+import { createTestVirtualDataset } from '../../helpers/api/dataset';
interface TestDatasetResult {
id: number;