You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by kg...@apache.org on 2023/04/28 15:33:57 UTC
[superset] branch master updated: chore: Add Cypress tests for drill by (#23849)
This is an automated email from the ASF dual-hosted git repository.
kgabryje 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 60046ca1cc chore: Add Cypress tests for drill by (#23849)
60046ca1cc is described below
commit 60046ca1ccd99a2c2b80e500289dc9762556c3a5
Author: Kamil Gabryjelski <ka...@gmail.com>
AuthorDate: Fri Apr 28 17:33:45 2023 +0200
chore: Add Cypress tests for drill by (#23849)
---
.../cypress/e2e/dashboard/drillby.test.ts | 705 +++++++++++++++++++++
.../cypress/e2e/dashboard/drilltodetail.test.ts | 14 +-
.../cypress-base/cypress/e2e/dashboard/utils.ts | 18 +
.../cypress-base/cypress/e2e/explore/utils.ts | 14 +-
.../src/components/Chart/DrillBy/DrillByChart.tsx | 1 +
.../Chart/DrillBy/useDisplayModeToggle.tsx | 1 +
.../Chart/DrillBy/useResultsTableView.tsx | 4 +-
superset/examples/supported_charts_dashboard.py | 2 +-
tests/integration_tests/superset_test_config.py | 3 +-
9 files changed, 746 insertions(+), 16 deletions(-)
diff --git a/superset-frontend/cypress-base/cypress/e2e/dashboard/drillby.test.ts b/superset-frontend/cypress-base/cypress/e2e/dashboard/drillby.test.ts
new file mode 100644
index 0000000000..c365f66b4a
--- /dev/null
+++ b/superset-frontend/cypress-base/cypress/e2e/dashboard/drillby.test.ts
@@ -0,0 +1,705 @@
+/**
+ * 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.
+ */
+// eslint-disable-next-line import/no-extraneous-dependencies
+import { Interception } from 'cypress/types/net-stubbing';
+import { waitForChartLoad } from 'cypress/utils';
+import { SUPPORTED_CHARTS_DASHBOARD } from 'cypress/utils/urls';
+import {
+ openTopLevelTab,
+ SUPPORTED_TIER1_CHARTS,
+ SUPPORTED_TIER2_CHARTS,
+} from './utils';
+import {
+ interceptExploreJson,
+ interceptV1ChartData,
+ interceptFormDataKey,
+} from '../explore/utils';
+
+const closeModal = () => {
+ cy.get('body').then($body => {
+ if ($body.find('[data-test="close-drill-by-modal"]').length) {
+ cy.getBySel('close-drill-by-modal').click({ force: true });
+ }
+ });
+};
+
+const openTableContextMenu = (
+ cellContent: string,
+ tableSelector = "[data-test-viz-type='table']",
+) => {
+ cy.get(tableSelector)
+ .scrollIntoView()
+ .contains(cellContent)
+ .first()
+ .rightclick();
+};
+
+const drillBy = (targetDrillByColumn: string, isLegacy = false) => {
+ if (isLegacy) {
+ interceptExploreJson('legacyData');
+ } else {
+ interceptV1ChartData();
+ }
+
+ cy.get('.ant-dropdown:not(.ant-dropdown-hidden)')
+ .first()
+ .find("[role='menu'] [role='menuitem'] [title='Drill by']")
+ .trigger('mouseover');
+ cy.get(
+ '.ant-dropdown-menu-submenu:not(.ant-dropdown-menu-hidden) [data-test="drill-by-submenu"]',
+ )
+ .find('[role="menuitem"]')
+ .contains(new RegExp(`^${targetDrillByColumn}$`))
+ .first()
+ .click({ force: true });
+
+ if (isLegacy) {
+ return cy.wait('@legacyData');
+ }
+ return cy.wait('@v1Data');
+};
+
+const verifyExpectedFormData = (
+ interceptedRequest: Interception,
+ expectedFormData: Record<string, any>,
+) => {
+ const actualFormData = interceptedRequest.request.body?.form_data;
+ Object.entries(expectedFormData).forEach(([key, val]) => {
+ expect(actualFormData?.[key]).to.eql(val);
+ });
+};
+
+const testEchart = (
+ vizType: string,
+ chartName: string,
+ drillClickCoordinates: [[number, number], [number, number]],
+ furtherDrillDimension = 'name',
+) => {
+ cy.get(`[data-test-viz-type='${vizType}'] canvas`).then($canvas => {
+ // click 'boy'
+ cy.wrap($canvas)
+ .scrollIntoView()
+ .trigger(
+ 'mouseover',
+ drillClickCoordinates[0][0],
+ drillClickCoordinates[0][1],
+ )
+ .rightclick(drillClickCoordinates[0][0], drillClickCoordinates[0][1]);
+
+ drillBy('state').then(intercepted => {
+ verifyExpectedFormData(intercepted, {
+ groupby: ['state'],
+ adhoc_filters: [
+ {
+ clause: 'WHERE',
+ comparator: 'boy',
+ expressionType: 'SIMPLE',
+ operator: '==',
+ operatorId: 'EQUALS',
+ subject: 'gender',
+ },
+ ],
+ });
+ });
+
+ cy.getBySel(`"Drill by: ${chartName}-modal"`).as('drillByModal');
+
+ cy.get('@drillByModal')
+ .find('.draggable-trigger')
+ .should('contain', chartName);
+
+ cy.get('@drillByModal')
+ .find('.ant-breadcrumb')
+ .should('be.visible')
+ .and('contain', 'gender (boy)')
+ .and('contain', '/')
+ .and('contain', 'state');
+
+ cy.get('@drillByModal')
+ .find('[data-test="drill-by-chart"]')
+ .should('be.visible');
+
+ // further drill
+ cy.get(`[data-test="drill-by-chart"] canvas`).then($canvas => {
+ // click 'other'
+ cy.wrap($canvas)
+ .scrollIntoView()
+ .trigger(
+ 'mouseover',
+ drillClickCoordinates[1][0],
+ drillClickCoordinates[1][1],
+ )
+ .rightclick(drillClickCoordinates[1][0], drillClickCoordinates[1][1]);
+
+ drillBy(furtherDrillDimension).then(intercepted => {
+ verifyExpectedFormData(intercepted, {
+ groupby: [furtherDrillDimension],
+ adhoc_filters: [
+ {
+ clause: 'WHERE',
+ comparator: 'boy',
+ expressionType: 'SIMPLE',
+ operator: '==',
+ operatorId: 'EQUALS',
+ subject: 'gender',
+ },
+ {
+ clause: 'WHERE',
+ comparator: 'other',
+ expressionType: 'SIMPLE',
+ operator: '==',
+ operatorId: 'EQUALS',
+ subject: 'state',
+ },
+ ],
+ });
+ });
+
+ cy.get('@drillByModal')
+ .find('[data-test="drill-by-chart"]')
+ .should('be.visible');
+
+ // undo - back to drill by state
+ interceptV1ChartData('drillByUndo');
+ cy.get('@drillByModal')
+ .find('.ant-breadcrumb')
+ .should('be.visible')
+ .and('contain', 'gender (boy)')
+ .and('contain', '/')
+ .and('contain', 'state (other)')
+ .and('contain', furtherDrillDimension)
+ .contains('state (other)')
+ .click();
+ cy.wait('@drillByUndo').then(intercepted => {
+ verifyExpectedFormData(intercepted, {
+ groupby: ['state'],
+ adhoc_filters: [
+ {
+ clause: 'WHERE',
+ comparator: 'boy',
+ expressionType: 'SIMPLE',
+ operator: '==',
+ operatorId: 'EQUALS',
+ subject: 'gender',
+ },
+ ],
+ });
+ });
+
+ cy.get('@drillByModal')
+ .find('.ant-breadcrumb')
+ .should('be.visible')
+ .and('contain', 'gender (boy)')
+ .and('contain', '/')
+ .and('not.contain', 'state (other)')
+ .and('not.contain', furtherDrillDimension)
+ .and('contain', 'state');
+
+ cy.get('@drillByModal')
+ .find('[data-test="drill-by-chart"]')
+ .should('be.visible');
+ });
+ });
+};
+
+describe('Drill by modal', () => {
+ beforeEach(() => {
+ closeModal();
+ });
+ before(() => {
+ cy.visit(SUPPORTED_CHARTS_DASHBOARD);
+ });
+
+ describe('Modal actions + Table', () => {
+ before(() => {
+ closeModal();
+ openTopLevelTab('Tier 1');
+ SUPPORTED_TIER1_CHARTS.forEach(waitForChartLoad);
+ });
+
+ it('opens the modal from the context menu', () => {
+ openTableContextMenu('boy');
+ drillBy('state').then(intercepted => {
+ verifyExpectedFormData(intercepted, {
+ groupby: ['state'],
+ adhoc_filters: [
+ {
+ clause: 'WHERE',
+ comparator: 'boy',
+ expressionType: 'SIMPLE',
+ operator: '==',
+ operatorId: 'EQUALS',
+ subject: 'gender',
+ },
+ ],
+ });
+ });
+
+ cy.getBySel('"Drill by: Table-modal"').as('drillByModal');
+
+ cy.get('@drillByModal')
+ .find('.draggable-trigger')
+ .should('contain', 'Drill by: Table');
+
+ cy.get('@drillByModal')
+ .find('[data-test="metadata-bar"]')
+ .should('be.visible');
+
+ cy.get('@drillByModal')
+ .find('.ant-breadcrumb')
+ .should('be.visible')
+ .and('contain', 'gender (boy)')
+ .and('contain', '/')
+ .and('contain', 'state');
+
+ cy.get('@drillByModal')
+ .find('[data-test="drill-by-chart"]')
+ .should('be.visible')
+ .and('contain', 'state')
+ .and('contain', 'sum__num');
+
+ // further drilling
+ openTableContextMenu('CA', '[data-test="drill-by-chart"]');
+ drillBy('name').then(intercepted => {
+ verifyExpectedFormData(intercepted, {
+ groupby: ['name'],
+ adhoc_filters: [
+ {
+ clause: 'WHERE',
+ comparator: 'boy',
+ expressionType: 'SIMPLE',
+ operator: '==',
+ operatorId: 'EQUALS',
+ subject: 'gender',
+ },
+ {
+ clause: 'WHERE',
+ comparator: 'CA',
+ expressionType: 'SIMPLE',
+ operator: '==',
+ operatorId: 'EQUALS',
+ subject: 'state',
+ },
+ ],
+ });
+ });
+
+ cy.get('@drillByModal')
+ .find('[data-test="drill-by-chart"]')
+ .should('be.visible')
+ .and('not.contain', 'state')
+ .and('contain', 'name')
+ .and('contain', 'sum__num');
+
+ // undo - back to drill by state
+ interceptV1ChartData('drillByUndo');
+ interceptFormDataKey();
+ cy.get('@drillByModal')
+ .find('.ant-breadcrumb')
+ .should('be.visible')
+ .and('contain', 'gender (boy)')
+ .and('contain', '/')
+ .and('contain', 'state (CA)')
+ .and('contain', 'name')
+ .contains('state (CA)')
+ .click();
+ cy.wait('@drillByUndo').then(intercepted => {
+ verifyExpectedFormData(intercepted, {
+ groupby: ['state'],
+ adhoc_filters: [
+ {
+ clause: 'WHERE',
+ comparator: 'boy',
+ expressionType: 'SIMPLE',
+ operator: '==',
+ operatorId: 'EQUALS',
+ subject: 'gender',
+ },
+ ],
+ });
+ });
+
+ cy.get('@drillByModal')
+ .find('[data-test="drill-by-chart"]')
+ .should('be.visible')
+ .and('not.contain', 'name')
+ .and('contain', 'state')
+ .and('contain', 'sum__num');
+
+ cy.get('@drillByModal')
+ .find('.ant-breadcrumb')
+ .should('be.visible')
+ .and('contain', 'gender (boy)')
+ .and('contain', '/')
+ .and('not.contain', 'state (CA)')
+ .and('not.contain', 'name')
+ .and('contain', 'state');
+
+ cy.get('@drillByModal')
+ .find('[data-test="drill-by-display-toggle"]')
+ .contains('Table')
+ .click();
+
+ cy.getBySel('drill-by-chart').should('not.exist');
+
+ cy.get('@drillByModal')
+ .find('[data-test="drill-by-results-table"]')
+ .should('be.visible');
+
+ cy.wait('@formDataKey').then(intercept => {
+ cy.get('@drillByModal')
+ .contains('Edit chart')
+ .should('have.attr', 'href')
+ .and(
+ 'contain',
+ `/explore/?form_data_key=${intercept.response?.body?.key}`,
+ );
+ });
+ });
+ });
+
+ describe('Tier 1 charts', () => {
+ before(() => {
+ closeModal();
+ openTopLevelTab('Tier 1');
+ SUPPORTED_TIER1_CHARTS.forEach(waitForChartLoad);
+ });
+
+ it('Pivot Table', () => {
+ openTableContextMenu('boy', "[data-test-viz-type='pivot_table_v2']");
+ drillBy('name').then(intercepted => {
+ verifyExpectedFormData(intercepted, {
+ groupbyRows: ['state'],
+ groupbyColumns: ['name'],
+ adhoc_filters: [
+ {
+ clause: 'WHERE',
+ comparator: 'boy',
+ expressionType: 'SIMPLE',
+ operator: '==',
+ operatorId: 'EQUALS',
+ subject: 'gender',
+ },
+ ],
+ });
+ });
+
+ cy.getBySel('"Drill by: Pivot Table-modal"').as('drillByModal');
+
+ cy.get('@drillByModal')
+ .find('.draggable-trigger')
+ .should('contain', 'Drill by: Pivot Table');
+
+ cy.get('@drillByModal')
+ .find('.ant-breadcrumb')
+ .should('be.visible')
+ .and('contain', 'gender (boy)')
+ .and('contain', '/')
+ .and('contain', 'name');
+
+ cy.get('@drillByModal')
+ .find('[data-test="drill-by-chart"]')
+ .should('be.visible')
+ .and('contain', 'state')
+ .and('contain', 'name')
+ .and('contain', 'sum__num')
+ .and('not.contain', 'Gender');
+
+ openTableContextMenu('CA', '[data-test="drill-by-chart"]');
+ drillBy('ds').then(intercepted => {
+ verifyExpectedFormData(intercepted, {
+ groupbyColumns: ['name'],
+ groupbyRows: ['ds'],
+ adhoc_filters: [
+ {
+ clause: 'WHERE',
+ comparator: 'boy',
+ expressionType: 'SIMPLE',
+ operator: '==',
+ operatorId: 'EQUALS',
+ subject: 'gender',
+ },
+ {
+ clause: 'WHERE',
+ comparator: 'CA',
+ expressionType: 'SIMPLE',
+ operator: '==',
+ operatorId: 'EQUALS',
+ subject: 'state',
+ },
+ ],
+ });
+ });
+
+ cy.get('@drillByModal')
+ .find('[data-test="drill-by-chart"]')
+ .should('be.visible')
+ .and('contain', 'name')
+ .and('contain', 'ds')
+ .and('contain', 'sum__num')
+ .and('not.contain', 'state');
+
+ interceptV1ChartData('drillByUndo');
+
+ cy.get('@drillByModal')
+ .find('.ant-breadcrumb')
+ .should('be.visible')
+ .and('contain', 'gender (boy)')
+ .and('contain', '/')
+ .and('contain', 'name (CA)')
+ .and('contain', 'ds')
+ .contains('name (CA)')
+ .click();
+ cy.wait('@drillByUndo').then(intercepted => {
+ verifyExpectedFormData(intercepted, {
+ groupbyRows: ['state'],
+ groupbyColumns: ['name'],
+ adhoc_filters: [
+ {
+ clause: 'WHERE',
+ comparator: 'boy',
+ expressionType: 'SIMPLE',
+ operator: '==',
+ operatorId: 'EQUALS',
+ subject: 'gender',
+ },
+ ],
+ });
+ });
+
+ cy.get('@drillByModal')
+ .find('[data-test="drill-by-chart"]')
+ .should('be.visible')
+ .and('not.contain', 'ds')
+ .and('contain', 'state')
+ .and('contain', 'name')
+ .and('contain', 'sum__num');
+
+ cy.get('@drillByModal')
+ .find('.ant-breadcrumb')
+ .should('be.visible')
+ .and('contain', 'gender (boy)')
+ .and('contain', '/')
+ .and('not.contain', 'name (CA)')
+ .and('not.contain', 'ds')
+ .and('contain', 'name');
+ });
+
+ it('Line chart', () => {
+ testEchart('echarts_timeseries_line', 'Time-Series Line Chart', [
+ [70, 93],
+ [70, 93],
+ ]);
+ });
+
+ it('Area Chart', () => {
+ testEchart('echarts_area', 'Time-Series Area Chart', [
+ [70, 93],
+ [70, 93],
+ ]);
+ });
+
+ it('Time-Series Scatter Chart', () => {
+ testEchart('echarts_timeseries_scatter', 'Time-Series Scatter Chart', [
+ [70, 93],
+ [70, 93],
+ ]);
+ });
+
+ it('Time-Series Bar Chart V2', () => {
+ testEchart('echarts_timeseries_bar', 'Time-Series Bar Chart V2', [
+ [70, 94],
+ [362, 68],
+ ]);
+ });
+
+ it('Pie Chart', () => {
+ testEchart('pie', 'Pie Chart', [
+ [243, 167],
+ [534, 248],
+ ]);
+ });
+ });
+
+ describe('Tier 2 charts', () => {
+ before(() => {
+ closeModal();
+ openTopLevelTab('Tier 2');
+ SUPPORTED_TIER2_CHARTS.forEach(waitForChartLoad);
+ });
+
+ it('Box Plot Chart', () => {
+ testEchart(
+ 'box_plot',
+ 'Box Plot Chart',
+ [
+ [139, 277],
+ [787, 441],
+ ],
+ 'ds',
+ );
+ });
+
+ it('Time-Series Generic Chart', () => {
+ testEchart('echarts_timeseries', 'Time-Series Generic Chart', [
+ [70, 93],
+ [70, 93],
+ ]);
+ });
+
+ it('Time-Series Smooth Line Chart', () => {
+ testEchart('echarts_timeseries_smooth', 'Time-Series Smooth Line Chart', [
+ [70, 93],
+ [70, 93],
+ ]);
+ });
+
+ it('Time-Series Step Line Chart', () => {
+ testEchart('echarts_timeseries_step', 'Time-Series Step Line Chart', [
+ [70, 93],
+ [70, 93],
+ ]);
+ });
+
+ it('Funnel Chart', () => {
+ testEchart('funnel', 'Funnel Chart', [
+ [154, 80],
+ [421, 39],
+ ]);
+ });
+
+ it('Gauge Chart', () => {
+ testEchart('gauge_chart', 'Gauge Chart', [
+ [151, 95],
+ [300, 143],
+ ]);
+ });
+
+ it('Radar Chart', () => {
+ testEchart('radar', 'Radar Chart', [
+ [182, 49],
+ [423, 91],
+ ]);
+ });
+
+ it('Treemap V2 Chart', () => {
+ testEchart('treemap_v2', 'Treemap V2 Chart', [
+ [145, 84],
+ [220, 105],
+ ]);
+ });
+
+ it('Mixed Chart', () => {
+ cy.get('[data-test-viz-type="mixed_timeseries"] canvas').then($canvas => {
+ // click 'boy'
+ cy.wrap($canvas)
+ .scrollIntoView()
+ .trigger('mouseover', 70, 93)
+ .rightclick(70, 93);
+
+ drillBy('name').then(intercepted => {
+ const { queries } = intercepted.request.body;
+ expect(queries[0].columns).to.eql(['name']);
+ expect(queries[0].filters).to.eql([
+ { col: 'gender', op: '==', val: 'boy' },
+ ]);
+ expect(queries[1].columns).to.eql(['state']);
+ expect(queries[1].filters).to.eql([]);
+ });
+
+ cy.getBySel('"Drill by: Mixed Chart-modal"').as('drillByModal');
+
+ cy.get('@drillByModal')
+ .find('.draggable-trigger')
+ .should('contain', 'Mixed Chart');
+
+ cy.get('@drillByModal')
+ .find('.ant-breadcrumb')
+ .should('be.visible')
+ .and('contain', 'gender (boy)')
+ .and('contain', '/')
+ .and('contain', 'name');
+
+ cy.get('@drillByModal')
+ .find('[data-test="drill-by-chart"]')
+ .should('be.visible');
+
+ // further drill
+ cy.get(`[data-test="drill-by-chart"] canvas`).then($canvas => {
+ // click second query
+ cy.wrap($canvas)
+ .scrollIntoView()
+ .trigger('mouseover', 246, 114)
+ .rightclick(246, 114);
+
+ drillBy('ds').then(intercepted => {
+ const { queries } = intercepted.request.body;
+ expect(queries[0].columns).to.eql(['name']);
+ expect(queries[0].filters).to.eql([
+ { col: 'gender', op: '==', val: 'boy' },
+ ]);
+ expect(queries[1].columns).to.eql(['ds']);
+ expect(queries[1].filters).to.eql([
+ { col: 'state', op: '==', val: 'other' },
+ ]);
+ });
+
+ cy.get('@drillByModal')
+ .find('[data-test="drill-by-chart"]')
+ .should('be.visible');
+
+ // undo - back to drill by state
+ interceptV1ChartData('drillByUndo');
+ cy.get('@drillByModal')
+ .find('.ant-breadcrumb')
+ .should('be.visible')
+ .and('contain', 'gender (boy)')
+ .and('contain', '/')
+ .and('contain', 'name (other)')
+ .and('contain', 'ds')
+ .contains('name (other)')
+ .click();
+
+ cy.wait('@drillByUndo').then(intercepted => {
+ const { queries } = intercepted.request.body;
+ expect(queries[0].columns).to.eql(['name']);
+ expect(queries[0].filters).to.eql([
+ { col: 'gender', op: '==', val: 'boy' },
+ ]);
+ expect(queries[1].columns).to.eql(['state']);
+ expect(queries[1].filters).to.eql([]);
+ });
+
+ cy.get('@drillByModal')
+ .find('.ant-breadcrumb')
+ .should('be.visible')
+ .and('contain', 'gender (boy)')
+ .and('contain', '/')
+ .and('not.contain', 'name (other)')
+ .and('not.contain', 'ds')
+ .and('contain', 'name');
+
+ cy.get('@drillByModal')
+ .find('[data-test="drill-by-chart"]')
+ .should('be.visible');
+ });
+ });
+ });
+ });
+});
diff --git a/superset-frontend/cypress-base/cypress/e2e/dashboard/drilltodetail.test.ts b/superset-frontend/cypress-base/cypress/e2e/dashboard/drilltodetail.test.ts
index 2ab4966d57..ff1872333b 100644
--- a/superset-frontend/cypress-base/cypress/e2e/dashboard/drilltodetail.test.ts
+++ b/superset-frontend/cypress-base/cypress/e2e/dashboard/drilltodetail.test.ts
@@ -18,7 +18,11 @@
*/
import { waitForChartLoad } from 'cypress/utils';
import { SUPPORTED_CHARTS_DASHBOARD } from 'cypress/utils/urls';
-import { SUPPORTED_TIER1_CHARTS, SUPPORTED_TIER2_CHARTS } from './utils';
+import {
+ openTopLevelTab,
+ SUPPORTED_TIER1_CHARTS,
+ SUPPORTED_TIER2_CHARTS,
+} from './utils';
function interceptSamples() {
cy.intercept(`/datasource/samples*`).as('samples');
@@ -77,10 +81,6 @@ function closeModal() {
});
}
-function setTopLevelTab(tabName: string) {
- cy.get("div#TABS-TOP div[role='tab']").contains(tabName).click();
-}
-
function testTimeChart(vizType: string) {
interceptSamples();
@@ -139,7 +139,7 @@ describe('Drill to detail modal', () => {
describe('Tier 1 charts', () => {
before(() => {
cy.visit(SUPPORTED_CHARTS_DASHBOARD);
- setTopLevelTab('Tier 1');
+ openTopLevelTab('Tier 1');
SUPPORTED_TIER1_CHARTS.forEach(waitForChartLoad);
});
@@ -438,7 +438,7 @@ describe('Drill to detail modal', () => {
describe('Tier 2 charts', () => {
before(() => {
cy.visit(SUPPORTED_CHARTS_DASHBOARD);
- setTopLevelTab('Tier 2');
+ openTopLevelTab('Tier 2');
SUPPORTED_TIER2_CHARTS.forEach(waitForChartLoad);
});
diff --git a/superset-frontend/cypress-base/cypress/e2e/dashboard/utils.ts b/superset-frontend/cypress-base/cypress/e2e/dashboard/utils.ts
index 211ae88ff8..159e9368ec 100644
--- a/superset-frontend/cypress-base/cypress/e2e/dashboard/utils.ts
+++ b/superset-frontend/cypress-base/cypress/e2e/dashboard/utils.ts
@@ -37,10 +37,24 @@ export const SUPPORTED_TIER1_CHARTS = [
{ name: 'Big Number', viz: 'big_number_total' },
{ name: 'Big Number with Trendline', viz: 'big_number' },
{ name: 'Pie Chart', viz: 'pie' },
+ { name: 'Table', viz: 'table' },
+ { name: 'Pivot Table', viz: 'pivot_table_v2' },
+ { name: 'Time-Series Line Chart', viz: 'echarts_timeseries_line' },
+ { name: 'Time-Series Area Chart', viz: 'echarts_area' },
+ { name: 'Time-Series Scatter Chart', viz: 'echarts_timeseries_scatter' },
+ { name: 'Time-Series Bar Chart V2', viz: 'echarts_timeseries_bar' },
] as ChartSpec[];
export const SUPPORTED_TIER2_CHARTS = [
{ name: 'Box Plot Chart', viz: 'box_plot' },
+ { name: 'Time-Series Generic Chart', viz: 'echarts_timeseries' },
+ { name: 'Time-Series Smooth Line Chart', viz: 'echarts_timeseries_smooth' },
+ { name: 'Time-Series Step Line Chart', viz: 'echarts_timeseries_step' },
+ { name: 'Funnel Chart', viz: 'funnel' },
+ { name: 'Gauge Chart', viz: 'gauge_chart' },
+ { name: 'Radar Chart', viz: 'radar' },
+ { name: 'Treemap V2 Chart', viz: 'treemap_v2' },
+ { name: 'Mixed Chart', viz: 'mixed_timeseries' },
] as ChartSpec[];
export const testItems = {
@@ -515,3 +529,7 @@ export function openTab(tabComponentIndex: number, tabIndex: number) {
.eq(tabIndex)
.click();
}
+
+export const openTopLevelTab = (tabName: string) => {
+ cy.get("div#TABS-TOP div[role='tab']").contains(tabName).click();
+};
diff --git a/superset-frontend/cypress-base/cypress/e2e/explore/utils.ts b/superset-frontend/cypress-base/cypress/e2e/explore/utils.ts
index 0a1dc50faa..95af89db5f 100644
--- a/superset-frontend/cypress-base/cypress/e2e/explore/utils.ts
+++ b/superset-frontend/cypress-base/cypress/e2e/explore/utils.ts
@@ -35,14 +35,18 @@ export function interceptUpdate() {
cy.intercept('PUT', `/api/v1/chart/*`).as('update');
}
-export function interceptPost() {
- cy.intercept('POST', `/api/v1/chart/`).as('post');
-}
+export const interceptV1ChartData = (alias = 'v1Data') => {
+ cy.intercept('/api/v1/chart/data*').as(alias);
+};
-export function interceptExploreJson() {
- cy.intercept('POST', `/superset/explore_json/**`).as('getJson');
+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() {
cy.intercept({
method: 'GET',
diff --git a/superset-frontend/src/components/Chart/DrillBy/DrillByChart.tsx b/superset-frontend/src/components/Chart/DrillBy/DrillByChart.tsx
index 91faa05c9c..f58a646db9 100644
--- a/superset-frontend/src/components/Chart/DrillBy/DrillByChart.tsx
+++ b/superset-frontend/src/components/Chart/DrillBy/DrillByChart.tsx
@@ -54,6 +54,7 @@ export default function DrillByChart({
height: 100%;
min-height: 0;
`}
+ data-test="drill-by-chart"
>
<SuperChart
disableErrorBoundary
diff --git a/superset-frontend/src/components/Chart/DrillBy/useDisplayModeToggle.tsx b/superset-frontend/src/components/Chart/DrillBy/useDisplayModeToggle.tsx
index 5e7b812cc4..9ca1351544 100644
--- a/superset-frontend/src/components/Chart/DrillBy/useDisplayModeToggle.tsx
+++ b/superset-frontend/src/components/Chart/DrillBy/useDisplayModeToggle.tsx
@@ -36,6 +36,7 @@ export const useDisplayModeToggle = () => {
box-shadow: none;
}
`}
+ data-test="drill-by-display-toggle"
>
<Radio.Group
onChange={({ target: { value } }) => {
diff --git a/superset-frontend/src/components/Chart/DrillBy/useResultsTableView.tsx b/superset-frontend/src/components/Chart/DrillBy/useResultsTableView.tsx
index 2778fab72c..b424b95ea5 100644
--- a/superset-frontend/src/components/Chart/DrillBy/useResultsTableView.tsx
+++ b/superset-frontend/src/components/Chart/DrillBy/useResultsTableView.tsx
@@ -40,7 +40,7 @@ export const useResultsTableView = (
}
if (chartDataResult.length === 1) {
return (
- <PaginationContainer>
+ <PaginationContainer data-test="drill-by-results-table">
<SingleQueryResultPane
colnames={chartDataResult[0].colnames}
coltypes={chartDataResult[0].coltypes}
@@ -53,7 +53,7 @@ export const useResultsTableView = (
);
}
return (
- <Tabs fullWidth={false}>
+ <Tabs fullWidth={false} data-test="drill-by-results-tabs">
{chartDataResult.map((res, index) => (
<Tabs.TabPane tab={t('Results %s', index + 1)} key={index}>
<PaginationContainer>
diff --git a/superset/examples/supported_charts_dashboard.py b/superset/examples/supported_charts_dashboard.py
index 54aa650d50..e6d7557deb 100644
--- a/superset/examples/supported_charts_dashboard.py
+++ b/superset/examples/supported_charts_dashboard.py
@@ -335,7 +335,7 @@ def create_slices(tbl: SqlaTable) -> List[Slice]:
viz_type="mixed_timeseries",
metrics=["sum__num"],
groupby=["gender"],
- metrics_b=["count"],
+ metrics_b=["sum__num"],
groupby_b=["state"],
),
),
diff --git a/tests/integration_tests/superset_test_config.py b/tests/integration_tests/superset_test_config.py
index 19c2cc000f..c3f9b350f8 100644
--- a/tests/integration_tests/superset_test_config.py
+++ b/tests/integration_tests/superset_test_config.py
@@ -61,7 +61,7 @@ PRESTO_POLL_INTERVAL = 0.1
HIVE_POLL_INTERVAL = 0.1
SQL_MAX_ROW = 10000
-SQLLAB_CTAS_NO_LIMIT = True # SQL_MAX_ROW will not take affect for the CTA queries
+SQLLAB_CTAS_NO_LIMIT = True # SQL_MAX_ROW will not take effect for the CTA queries
FEATURE_FLAGS = {
**FEATURE_FLAGS,
"foo": "bar",
@@ -71,6 +71,7 @@ FEATURE_FLAGS = {
"ALERT_REPORTS": True,
"DASHBOARD_NATIVE_FILTERS": True,
"DRILL_TO_DETAIL": True,
+ "DRILL_BY": True,
"HORIZONTAL_FILTER_BAR": True,
}