Skip to content

Commit

Permalink
chore: E2E tests for the Drill to detail modal (#21187)
Browse files Browse the repository at this point in the history
* Add example ECharts Dashboard

* [WIP] E2E test

* Add echarts interactions

* Lint

* DRY
  • Loading branch information
geido authored Aug 29, 2022
1 parent ccb293a commit f017f98
Show file tree
Hide file tree
Showing 9 changed files with 548 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const WORLD_HEALTH_DASHBOARD = '/superset/dashboard/world_health/';
export const USA_BIRTH_NAMES_DASHBOARD = '/superset/dashboard/births/';
export const testDashboard = '/superset/dashboard/538/';
export const TABBED_DASHBOARD = '/superset/dashboard/tabbed_dash/';
export const ECHARTS_DASHBOARD = '/superset/dashboard/echarts_dash/';

export const testItems = {
dashboard: 'Cypress test Dashboard',
Expand Down Expand Up @@ -73,6 +74,14 @@ export const WORLD_HEALTH_CHARTS = [
{ name: 'Box plot', viz: 'box_plot' },
] as const;

export const ECHARTS_CHARTS = [
{ name: 'Number of Girls', viz: 'big_number_total' },
{ name: 'Participants', viz: 'big_number' },
{ name: 'Box plot', viz: 'box_plot' },
{ name: 'Genders', viz: 'pie' },
{ name: 'Energy Force Layout', viz: 'graph_chart' },
] as const;

/** Used to specify charts expected by the test suite */
export interface ChartSpec {
name: string;
Expand All @@ -81,7 +90,7 @@ export interface ChartSpec {

export function getChartGridComponent({ name, viz }: ChartSpec) {
return cy
.get(`[data-test="chart-grid-component"][data-test-chart-name="${name}"]`)
.get(`[data-test-chart-name="${name}"]`)
.should('have.attr', 'data-test-viz-type', viz);
}

Expand All @@ -92,7 +101,7 @@ export function waitForChartLoad(chart: ChartSpec) {
return (
cy
// this id only becomes visible when the chart is loaded
.get(`[data-test="chart-grid-component"] #chart-id-${chartId}`, {
.get(`#chart-id-${chartId}`, {
timeout: 30000,
})
.should('be.visible')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
/**
* 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 {
waitForChartLoad,
ECHARTS_CHARTS,
ECHARTS_DASHBOARD,
} from './dashboard.helper';

function interceptSamples() {
cy.intercept(`/datasource/samples*`).as('samples');
}

function openModalFromMenu(chartType: string) {
interceptSamples();

cy.get(
`[data-test-viz-type='${chartType}'] [aria-label='More Options']`,
).click();
cy.get('.ant-dropdown')
.not('.ant-dropdown-hidden')
.find("[role='menu'] [role='menuitem']")
.eq(5)
.should('contain', 'Drill to detail')
.click();
cy.wait('@samples');
}

function openModalFromChartContext(targetMenuItem: string) {
interceptSamples();

cy.get('.ant-dropdown')
.not('.ant-dropdown-hidden')
.find("[role='menu'] [role='menuitem']")
.should('contain', targetMenuItem)
.click();
cy.wait('@samples');
}

describe('Drill to detail modal', () => {
beforeEach(() => {
cy.login();
cy.visit(ECHARTS_DASHBOARD);
ECHARTS_CHARTS.forEach(waitForChartLoad);
});

it('opens the modal from the context menu', () => {
openModalFromMenu('big_number_total');

cy.get("[role='dialog'] .draggable-trigger").should(
'contain',
'Drill to detail: Number of Girls',
);
});

it('refreshes the data', () => {
openModalFromMenu('big_number_total');
// move to the last page
cy.get(".pagination-container [role='navigation'] [role='button']")
.eq(7)
.click();
cy.wait('@samples');
// reload
cy.get("[aria-label='reload']").click();
cy.wait('@samples');
// make sure it started back from first page
cy.get(".pagination-container [role='navigation'] li.active").should(
'contain',
'1',
);
});

it('paginates', () => {
openModalFromMenu('big_number_total');
// checking the data
cy.get("[data-test='row-count-label']").should('contain', '36.4k rows');
cy.get("[role='rowgroup'] [role='row']")
.should('have.length', 50)
.then($rows => {
expect($rows).to.contain('Amy');
});
// checking the paginated data
cy.get(".pagination-container [role='navigation'] [role='button']")
.should('have.length', 9)
.then($pages => {
expect($pages).to.contain('1');
expect($pages).to.contain('729');
});
cy.get(".pagination-container [role='navigation'] [role='button']")
.eq(7)
.click();
cy.wait('@samples');
cy.get("[role='rowgroup'] [role='row']")
.should('have.length', 46)
.then($rows => {
expect($rows).to.contain('Victoria');
});
});

it('clears filters', () => {
interceptSamples();

// opens the modal by clicking on the box on the chart
cy.get("[data-test-viz-type='box_plot'] canvas").then($canvas => {
const canvasWidth = $canvas.width() || 0;
const canvasHeight = $canvas.height() || 0;
const canvasCenterX = canvasWidth / 6;
const canvasCenterY = canvasHeight / 6;

cy.wrap($canvas)
.scrollIntoView()
.rightclick(canvasCenterX, canvasCenterY, { force: true });

openModalFromChartContext('Drill to detail by East Asia & Pacific');

// checking the filter
cy.get("[data-test='filter-val']").should(
'contain',
'East Asia & Pacific',
);
cy.get("[data-test='row-count-label']").should('contain', '1.98k rows');
cy.get(".pagination-container [role='navigation'] [role='button']")
.should('have.length', 9)
.then($pages => {
expect($pages).to.contain('1');
expect($pages).to.contain('40');
});

// close the filter and test that data was reloaded
cy.get("[data-test='filter-col']").find("[aria-label='close']").click();
cy.wait('@samples');
cy.get("[data-test='row-count-label']").should('contain', '11.8k rows');
cy.get(".pagination-container [role='navigation'] li.active").should(
'contain',
'1',
);
cy.get(".pagination-container [role='navigation'] [role='button']")
.should('have.length', 9)
.then($pages => {
expect($pages).to.contain('1');
expect($pages).to.contain('236');
});
});
});

describe('Time-series Bar Chart V2', () => {
it('opens the modal with the correct filters', () => {
interceptSamples();

cy.get("[data-test-viz-type='echarts_timeseries_bar'] canvas").then(
$canvas => {
cy.wrap($canvas)
.scrollIntoView()
.rightclick(70, 100, { force: true });
cy.get('.ant-dropdown')
.not('.ant-dropdown-hidden')
.find("[role='menu'] [role='menuitem']")
.should('have.length', 3)
.then($menuitems => {
expect($menuitems).to.contain('Drill to detail by 1965');
expect($menuitems).to.contain('Drill to detail by boy');
expect($menuitems).to.contain('Drill to detail by all');
})
.eq(2)
.click();
cy.wait('@samples');

cy.get("[data-test='filter-val']").then($filters => {
expect($filters).to.contain('1965');
expect($filters).to.contain('boy');
});
},
);
});
});

describe('Box plot', () => {
it('opens the modal with the correct filters', () => {
interceptSamples();

// opens the modal by clicking on the box on the chart
cy.get("[data-test-viz-type='box_plot'] canvas").then($canvas => {
const canvasWidth = $canvas.width() || 0;
const canvasHeight = $canvas.height() || 0;
const canvasCenterX = canvasWidth / 6;
const canvasCenterY = canvasHeight / 6;

cy.wrap($canvas)
.scrollIntoView()
.rightclick(canvasCenterX, canvasCenterY, { force: true });

openModalFromChartContext('Drill to detail by East Asia & Pacific');

// checking the filter
cy.get("[data-test='filter-val']").should(
'contain',
'East Asia & Pacific',
);
});
});
});

describe('Pie', () => {
it('opens the modal with the correct filters', () => {
interceptSamples();

// opens the modal by clicking on the slice of the Pie chart
cy.get("[data-test-viz-type='pie'] canvas").then($canvas => {
const canvasWidth = $canvas.width() || 0;
const canvasHeight = $canvas.height() || 0;
const canvasCenterX = canvasWidth / 2;
const canvasCenterY = canvasHeight / 2;

cy.wrap($canvas)
.scrollIntoView()
.rightclick(canvasCenterX, canvasCenterY, { force: true });

openModalFromChartContext('Drill to detail by boy');

// checking the filtered and paginated data
cy.get("[data-test='filter-val']").should('contain', 'boy');
});
});
});

describe('Big number total', () => {
it('opens the modal with no filters', () => {
interceptSamples();

// opens the modal by clicking on the number on the chart
cy.get(
"[data-test-viz-type='big_number_total'] .header-line",
).rightclick();

openModalFromChartContext('Drill to detail');

cy.get("[data-test='filter-val']").should('not.exist');
});
});

describe('Big number with trendline', () => {
it('opens the modal with the correct data', () => {
interceptSamples();

// opens the modal by clicking on the number
cy.get("[data-test-viz-type='big_number'] .header-line").rightclick();

openModalFromChartContext('Drill to detail');

cy.get("[data-test='filter-val']").should('not.exist');

// TODO: test clicking on a trendline
// Cypress is refusing to rightclick on the dot
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ export default function transformProps(
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 10,
showSymbol: false,
color: mainColor,
areaStyle: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export default function TableControls({
margin-bottom: ${theme.gridUnit * 4}px;
line-height: 1.2;
`}
data-test="filter-col"
>
<span
css={css`
Expand All @@ -113,7 +114,7 @@ export default function TableControls({
>
{colName}
</span>
<strong>{val}</strong>
<strong data-test="filter-val">{val}</strong>
</Tag>
))}
</div>
Expand Down
12 changes: 8 additions & 4 deletions superset-frontend/src/explore/components/RowCountLabel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,14 @@ export default function RowCountLabel(props: RowCountLabelProps) {
limitReached || (rowcount === 0 && !loading) ? 'danger' : 'default';
const formattedRowCount = getNumberFormatter()(rowcount);
const label = (
<Label type={type} data-test="row-count-label">
{loading
? t('Loading...')
: tn('%s row', '%s rows', rowcount, formattedRowCount)}
<Label type={type}>
{loading ? (
t('Loading...')
) : (
<span data-test="row-count-label">
{tn('%s row', '%s rows', rowcount, formattedRowCount)}
</span>
)}
</Label>
);
return limitReached ? (
Expand Down
3 changes: 3 additions & 0 deletions superset/cli/examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ def load_examples_run(
if load_test_data:
print("Loading [Tabbed dashboard]")
examples.load_tabbed_dashboard(only_metadata)

print("Loading [ECharts Dashboard]")
examples.load_echarts_dashboard()
else:
print("Loading [Random long/lat data]")
examples.load_long_lat_data(only_metadata, force)
Expand Down
1 change: 1 addition & 0 deletions superset/examples/data_loading.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from .country_map import load_country_map_data
from .css_templates import load_css_templates
from .deck import load_deck_dash
from .echarts_dashboard import load_echarts_dashboard
from .energy import load_energy
from .flights import load_flights
from .long_lat import load_long_lat_data
Expand Down
Loading

0 comments on commit f017f98

Please sign in to comment.