mirror of https://github.com/apache/superset.git
chore: Dashboard cypress refactor (#11280)
* moved dashboard tests to use data-test attributes * linter * fix for unstable save test
This commit is contained in:
parent
9266f0a4a8
commit
55ae259b13
|
@ -23,47 +23,81 @@ describe('Dashboard edit mode', () => {
|
|||
cy.server();
|
||||
cy.login();
|
||||
cy.visit(WORLD_HEALTH_DASHBOARD);
|
||||
cy.get('.dashboard-header [data-test=edit-alt]').click();
|
||||
cy.get('[data-test="dashboard-header"]')
|
||||
.find('[data-test=edit-alt]')
|
||||
.click();
|
||||
});
|
||||
|
||||
xit('remove, and add chart flow', () => {
|
||||
it('remove, and add chart flow', () => {
|
||||
// wait for box plot to appear
|
||||
cy.get('.grid-container .box_plot');
|
||||
cy.get('[data-test="grid-container"]').find('.box_plot', {
|
||||
timeout: 10000,
|
||||
});
|
||||
const elementsCount = 10;
|
||||
|
||||
cy.get('.fa.fa-trash')
|
||||
cy.get('[data-test="dashboard-component-chart-holder"]')
|
||||
.find('[data-test="dashboard-delete-component-button"]')
|
||||
.last()
|
||||
.then($el => {
|
||||
cy.wrap($el).invoke('show').click();
|
||||
// box plot should be gone
|
||||
cy.get('.grid-container .box_plot').should('not.exist');
|
||||
cy.get('[data-test="grid-container"]')
|
||||
.find('.box_plot')
|
||||
.should('not.be.visible');
|
||||
});
|
||||
|
||||
cy.get('.tabs-components .nav-tabs li a').contains('Charts').click();
|
||||
|
||||
// wait for tab-switching animation to complete
|
||||
cy.wait(1000);
|
||||
cy.get('[data-test="dashboard-builder-component-pane-tabs-navigation"]')
|
||||
.children()
|
||||
.last()
|
||||
.click();
|
||||
|
||||
// find box plot is available from list
|
||||
cy.get('.tabs-components')
|
||||
.find('.chart-card-container')
|
||||
.contains('Box plot');
|
||||
cy.get('[data-test="dashboard-charts-filter-search-input"]').type(
|
||||
'Box plot',
|
||||
);
|
||||
cy.get('[data-test="card-title"]').should('have.length', 1);
|
||||
|
||||
drag('.chart-card', 'Box plot').to(
|
||||
drag('[data-test="card-title"]', 'Box plot').to(
|
||||
'.grid-row.background--transparent:last',
|
||||
);
|
||||
|
||||
// add back to dashboard
|
||||
cy.get('.grid-container .box_plot').should('be.exist');
|
||||
cy.get('[data-test="grid-container"]')
|
||||
.find('.box_plot')
|
||||
.should('be.visible');
|
||||
|
||||
// should show Save changes button
|
||||
cy.get('.dashboard-header .button-container').contains('Save');
|
||||
cy.get('[data-test="header-save-button"]').should('be.visible');
|
||||
|
||||
// undo 2 steps
|
||||
cy.get('.dashboard-header .undo-action').click().click();
|
||||
// undo first step and expect deleted item
|
||||
cy.get('[data-test="undo-action"]').click();
|
||||
cy.get('[data-test="grid-container"]')
|
||||
.find('[data-test="chart-container"]')
|
||||
.should('have.length', elementsCount - 1);
|
||||
|
||||
// Box plot chart should be gone
|
||||
cy.get('[data-test="grid-container"]')
|
||||
.find('.box_plot')
|
||||
.should('not.be.visible');
|
||||
|
||||
// undo second step and expect initial items count
|
||||
cy.get('[data-test="undo-action"]').click();
|
||||
cy.get('[data-test="grid-container"]')
|
||||
.find('[data-test="chart-container"]')
|
||||
.should('have.length', elementsCount);
|
||||
cy.get('[data-test="card-title"]').contains('Box plot', { timeout: 5000 });
|
||||
|
||||
// save changes button should be disabled
|
||||
cy.get('[data-test="header-save-button"]').should('be.disabled');
|
||||
|
||||
// no changes, can switch to view mode
|
||||
cy.get('.dashboard-header .button-container')
|
||||
.contains('Discard Changes')
|
||||
cy.get('[data-test="dashboard-edit-actions"]')
|
||||
.find('[data-test="discard-changes-button"]')
|
||||
.should('be.visible')
|
||||
.click();
|
||||
cy.get('[data-test="dashboard-header"]').within(() => {
|
||||
cy.get('[data-test="dashboard-edit-actions"]').should('not.be.visible');
|
||||
cy.get('[data-test="edit-alt"]').should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -38,27 +38,27 @@ describe('Dashboard add to favorite', () => {
|
|||
|
||||
it('should allow favor/unfavor', () => {
|
||||
if (!isFavoriteDashboard) {
|
||||
cy.get('a.fave-unfave-icon')
|
||||
cy.get('[data-test="fave-unfave-icon"]')
|
||||
.find('svg')
|
||||
.should('have.attr', 'data-test', 'favorite-unselected');
|
||||
cy.get('a.fave-unfave-icon').trigger('click');
|
||||
cy.get('a.fave-unfave-icon')
|
||||
cy.get('[data-test="fave-unfave-icon"]').trigger('click');
|
||||
cy.get('[data-test="fave-unfave-icon"]')
|
||||
.find('svg')
|
||||
.should('have.attr', 'data-test', 'favorite-selected')
|
||||
.and('not.have.attr', 'data-test', 'favorite-unselected');
|
||||
} else {
|
||||
cy.get('a.fave-unfave-icon')
|
||||
cy.get('[data-test="fave-unfave-icon"]')
|
||||
.find('svg')
|
||||
.should('have.attr', 'data-test', 'favorite-unselected')
|
||||
.and('not.have.attr', 'data-test', 'favorite-selected');
|
||||
cy.get('a.fave-unfave-icon').trigger('click');
|
||||
cy.get('a.fave-unfave-icon')
|
||||
cy.get('[data-test="fave-unfave-icon"]').trigger('click');
|
||||
cy.get('[data-test="fave-unfave-icon"]')
|
||||
.find('svg')
|
||||
.should('have.attr', 'data-test', 'favorite-unselected')
|
||||
.and('not.have.attr', 'data-test', 'favorite-selected');
|
||||
}
|
||||
|
||||
// reset to original fav state
|
||||
cy.get('a.fave-unfave-icon').trigger('click');
|
||||
cy.get('[data-test="fave-unfave-icon"]').trigger('click');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -51,7 +51,9 @@ describe('Dashboard load', () => {
|
|||
expect(responseBody).to.have.property('errors');
|
||||
expect(responseBody.errors.length).to.eq(0);
|
||||
const sliceId = responseBody.form_data.slice_id;
|
||||
cy.get(`#chart-id-${sliceId}`).should('be.visible');
|
||||
cy.get('[data-test="grid-content"]')
|
||||
.find(`#chart-id-${sliceId}`)
|
||||
.should('be.visible');
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
|
|
@ -30,27 +30,35 @@ describe('Dashboard edit markdown', () => {
|
|||
cy.get('script').then(nodes => {
|
||||
numScripts = nodes.length;
|
||||
});
|
||||
cy.get('.dashboard-header [data-test=edit-alt]').click();
|
||||
cy.get('[data-test="dashboard-header"]')
|
||||
.find('[data-test="edit-alt"]')
|
||||
.click();
|
||||
cy.get('script').then(nodes => {
|
||||
// load 5 new script chunks for css editor
|
||||
expect(nodes.length).to.greaterThan(numScripts);
|
||||
numScripts = nodes.length;
|
||||
});
|
||||
|
||||
cy.get('[data-test="grid-row-background--transparent"]')
|
||||
.first()
|
||||
.as('component-background-first');
|
||||
// add new markdown component
|
||||
drag('.new-component', 'Markdown').to(
|
||||
'.grid-row.background--transparent:first',
|
||||
drag('[data-test="new-component"]', 'Markdown').to(
|
||||
'@component-background-first',
|
||||
);
|
||||
cy.get('script').then(nodes => {
|
||||
// load more scripts for markdown editor
|
||||
expect(nodes.length).to.greaterThan(numScripts);
|
||||
numScripts = nodes.length;
|
||||
});
|
||||
|
||||
cy.contains('h3', '✨Markdown').click();
|
||||
cy.get('.ace_content').contains(
|
||||
'Click here to edit [markdown](https://bit.ly/1dQOfRK)',
|
||||
);
|
||||
cy.get('[data-test="dashboard-markdown-editor"]')
|
||||
.should(
|
||||
'have.text',
|
||||
'✨Markdown✨Markdown✨MarkdownClick here to edit markdown',
|
||||
)
|
||||
.click();
|
||||
cy.get('[data-test="dashboard-component-chart-holder"]')
|
||||
.find('.ace_content')
|
||||
.contains('Click here to edit [markdown](https://bit.ly/1dQOfRK)');
|
||||
|
||||
// entering edit mode does not add new scripts
|
||||
// (though scripts may still be removed by others)
|
||||
|
@ -58,7 +66,9 @@ describe('Dashboard edit markdown', () => {
|
|||
expect(nodes.length).to.most(numScripts);
|
||||
});
|
||||
|
||||
cy.get('.grid-row.background--transparent:first').click('right');
|
||||
cy.get('.ace_content').should('not.exist');
|
||||
cy.get('@component-background-first').click('right');
|
||||
cy.get('[data-test="dashboard-component-chart-holder"]')
|
||||
.find('.ace_content')
|
||||
.should('not.be.visible');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -34,9 +34,11 @@ describe('Dashboard save action', () => {
|
|||
cy.route('POST', `/superset/copy_dash/${dashboardId}/`).as('copyRequest');
|
||||
});
|
||||
|
||||
cy.get('#save-dash-split-button').trigger('click', { force: true });
|
||||
cy.contains('Save as').trigger('click', { force: true });
|
||||
cy.get('.modal-footer').contains('Save').trigger('click', { force: true });
|
||||
cy.get('[data-test="more-horiz"]').trigger('click', { force: true });
|
||||
cy.get('[data-test="save-as-menu-item"]').trigger('click', { force: true });
|
||||
cy.get('[data-test="modal-save-dashboard-button"]').trigger('click', {
|
||||
force: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should save as new dashboard', () => {
|
||||
|
@ -50,21 +52,32 @@ describe('Dashboard save action', () => {
|
|||
|
||||
it('should save/overwrite dashboard', () => {
|
||||
// should have box_plot chart
|
||||
cy.get('.grid-container .box_plot', { timeout: 5000 }); // wait for 5 secs
|
||||
cy.get('[data-test="grid-row-background--transparent"]').within(() => {
|
||||
cy.get('.box_plot', { timeout: 10000 }).should('be.visible');
|
||||
});
|
||||
|
||||
// remove box_plot chart from dashboard
|
||||
cy.get('.dashboard-header [data-test=edit-alt]').click();
|
||||
cy.get('.fa.fa-trash').last().trigger('click', { force: true });
|
||||
cy.get('.grid-container .box_plot').should('not.exist');
|
||||
cy.get('[data-test="edit-alt"]').click({ timeout: 5000 });
|
||||
cy.get('[data-test="dashboard-delete-component-button"]')
|
||||
.should('be.visible', { timeout: 10000 })
|
||||
.last()
|
||||
.trigger('click');
|
||||
cy.get('[data-test="grid-container"]')
|
||||
.find('.box_plot')
|
||||
.should('not.be.visible');
|
||||
|
||||
cy.route('POST', '/superset/save_dash/**/').as('saveRequest');
|
||||
cy.get('.dashboard-header')
|
||||
cy.get('[data-test="dashboard-header"]')
|
||||
.find('[data-test="header-save-button"]')
|
||||
.contains('Save')
|
||||
.trigger('click', { force: true });
|
||||
|
||||
// go back to view mode
|
||||
cy.wait('@saveRequest');
|
||||
cy.get('.dashboard-header [data-test=edit-alt]').click();
|
||||
cy.get('.grid-container .box_plot').should('not.exist');
|
||||
cy.get('[data-test="dashboard-header"]')
|
||||
.find('[data-test="edit-alt"]')
|
||||
.click();
|
||||
cy.get('[data-test="grid-container"]')
|
||||
.find('.box_plot', { timeout: 20000 })
|
||||
.should('not.be.visible');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -95,46 +95,60 @@ describe('Dashboard tabs', () => {
|
|||
cy.wait('@filterRequest');
|
||||
cy.wait('@treemapRequest');
|
||||
|
||||
cy.get('.dashboard-component-tabs')
|
||||
cy.get('[data-test="dashboard-component-tabs"]')
|
||||
.first()
|
||||
.find('ul.nav.nav-tabs li')
|
||||
.as('tabs');
|
||||
.find('[data-test="nav-list"]')
|
||||
.children()
|
||||
.as('top-level-tabs');
|
||||
|
||||
cy.get('@tabs').first().click().should('have.class', 'active');
|
||||
cy.get('@tabs').last().should('not.have.class', 'active');
|
||||
cy.get('@top-level-tabs').first().click().should('have.class', 'active');
|
||||
cy.get('@top-level-tabs').last().should('not.have.class', 'active');
|
||||
|
||||
cy.get('@tabs').last().click().should('have.class', 'active');
|
||||
cy.get('@tabs').first().should('not.have.class', 'active');
|
||||
cy.get('@top-level-tabs').last().click().should('have.class', 'active');
|
||||
cy.get('@top-level-tabs').first().should('not.have.class', 'active');
|
||||
});
|
||||
|
||||
it('should load charts when tab is visible', () => {
|
||||
// landing in first tab, should see 2 charts
|
||||
cy.wait('@filterRequest');
|
||||
cy.get('.grid-container .filter_box').should('be.exist');
|
||||
cy.get('[data-test="grid-container"]')
|
||||
.find('.filter_box')
|
||||
.should('be.visible');
|
||||
cy.wait('@treemapRequest');
|
||||
cy.get('.grid-container .treemap').should('be.exist');
|
||||
cy.get('.grid-container .box_plot').should('not.be.exist');
|
||||
cy.get('.grid-container .line').should('not.be.exist');
|
||||
cy.get('[data-test="grid-container"]')
|
||||
.find('.treemap')
|
||||
.should('be.visible');
|
||||
cy.get('[data-test="grid-container"]')
|
||||
.find('.box_plot')
|
||||
.should('not.be.visible');
|
||||
cy.get('[data-test="grid-container"]')
|
||||
.find('.line')
|
||||
.should('not.be.visible');
|
||||
|
||||
// click row level tab, see 1 more chart
|
||||
cy.get('.tab-content ul.nav.nav-tabs li')
|
||||
cy.get('[data-test="dashboard-component-tabs"]')
|
||||
.last()
|
||||
.find('.editable-title input')
|
||||
.click();
|
||||
.find('[data-test="nav-list"]')
|
||||
.children()
|
||||
.as('row-level-tabs');
|
||||
|
||||
cy.get('@row-level-tabs').last().click();
|
||||
|
||||
cy.wait('@linechartRequest');
|
||||
cy.get('.grid-container .line').should('be.exist');
|
||||
cy.get('[data-test="grid-container"]').find('.line').should('be.visible');
|
||||
|
||||
// click top level tab, see 1 more chart
|
||||
handleException();
|
||||
cy.get('.dashboard-component-tabs')
|
||||
cy.get('[data-test="dashboard-component-tabs"]')
|
||||
.first()
|
||||
.find('ul.nav.nav-tabs li')
|
||||
.last()
|
||||
.find('.editable-title input')
|
||||
.click();
|
||||
.find('[data-test="nav-list"]')
|
||||
.children()
|
||||
.as('top-level-tabs');
|
||||
|
||||
cy.get('@top-level-tabs').last().click();
|
||||
|
||||
// should exist a visible box_plot element
|
||||
cy.get('.grid-container .box_plot');
|
||||
cy.get('[data-test="grid-container"]').find('.box_plot');
|
||||
});
|
||||
|
||||
it('should send new queries when tab becomes visible', () => {
|
||||
|
@ -162,7 +176,13 @@ describe('Dashboard tabs', () => {
|
|||
});
|
||||
|
||||
// click row level tab, send 1 more query
|
||||
cy.get('.tab-content ul.nav.nav-tabs li').last().click();
|
||||
cy.get('[data-test="dashboard-component-tabs"]')
|
||||
.last()
|
||||
.find('[data-test="nav-list"]')
|
||||
.children()
|
||||
.as('row-level-tabs');
|
||||
cy.get('@row-level-tabs').last().click();
|
||||
|
||||
cy.wait('@linechartRequest').then(xhr => {
|
||||
const requestFormData = xhr.request.body;
|
||||
const requestParams = JSON.parse(requestFormData.get('form_data'));
|
||||
|
@ -174,13 +194,13 @@ describe('Dashboard tabs', () => {
|
|||
});
|
||||
|
||||
// click top level tab, send 1 more query
|
||||
handleException();
|
||||
cy.get('.dashboard-component-tabs')
|
||||
cy.get('[data-test="dashboard-component-tabs"]')
|
||||
.first()
|
||||
.find('ul.nav.nav-tabs li')
|
||||
.last()
|
||||
.find('.editable-title input')
|
||||
.click();
|
||||
.find('[data-test="nav-list"]')
|
||||
.children()
|
||||
.as('top-level-tabs');
|
||||
|
||||
cy.get('@top-level-tabs').last().click();
|
||||
|
||||
cy.wait('@boxplotRequest').then(xhr => {
|
||||
const requestFormData = xhr.request.body;
|
||||
|
@ -193,15 +213,10 @@ describe('Dashboard tabs', () => {
|
|||
});
|
||||
|
||||
// navigate to filter and clear filter
|
||||
cy.get('.dashboard-component-tabs')
|
||||
.first()
|
||||
.find('ul.nav.nav-tabs li')
|
||||
.first()
|
||||
.click();
|
||||
cy.get('.tab-content ul.nav.nav-tabs li')
|
||||
.first()
|
||||
.should('be.visible')
|
||||
.click();
|
||||
cy.get('@top-level-tabs').first().click();
|
||||
|
||||
cy.get('@top-level-tabs').first().click();
|
||||
|
||||
cy.get('.Select__clear-indicator').click();
|
||||
|
||||
// trigger 1 new query
|
||||
|
|
|
@ -50,7 +50,7 @@ class BuilderComponentPane extends React.PureComponent {
|
|||
<Tabs
|
||||
className="m-t-10 tabs-components"
|
||||
id="tabs"
|
||||
data-test="tabs-component"
|
||||
data-test="dashboard-builder-component-pane-tabs-navigation"
|
||||
>
|
||||
<Tab eventKey={1} title={t('Components')}>
|
||||
<NewTabs />
|
||||
|
|
|
@ -197,7 +197,7 @@ class SaveModal extends React.PureComponent {
|
|||
modalFooter={
|
||||
<div>
|
||||
<Button
|
||||
data-test="save-modal-save-button"
|
||||
data-test="modal-save-dashboard-button"
|
||||
buttonStyle="primary"
|
||||
onClick={this.saveDashboard}
|
||||
>
|
||||
|
|
|
@ -214,6 +214,7 @@ class SliceAdder extends React.Component {
|
|||
className="search-input"
|
||||
onChange={this.searchUpdated}
|
||||
onKeyPress={this.handleKeyPress}
|
||||
data-test="dashboard-charts-filter-search-input"
|
||||
/>
|
||||
<DropdownButton
|
||||
title={`Sort by ${KEYS_TO_SORT[this.state.sortBy].label}`}
|
||||
|
|
|
@ -237,6 +237,7 @@ class ChartHolder extends React.Component {
|
|||
>
|
||||
<div
|
||||
ref={dragSourceRef}
|
||||
data-test="dashboard-component-chart-holder"
|
||||
className={`dashboard-component dashboard-component-chart-holder ${
|
||||
this.state.outlinedComponentId ? 'fade-in' : 'fade-out'
|
||||
} ${this.state.isFullSize ? 'full-size' : ''}`}
|
||||
|
@ -270,10 +271,11 @@ class ChartHolder extends React.Component {
|
|||
)}
|
||||
{editMode && (
|
||||
<HoverMenu position="top">
|
||||
<DeleteComponentButton
|
||||
data-test="chart-delete-button"
|
||||
onDelete={this.handleDeleteComponent}
|
||||
/>
|
||||
<div data-test="dashboard-delete-component-button">
|
||||
<DeleteComponentButton
|
||||
onDelete={this.handleDeleteComponent}
|
||||
/>
|
||||
</div>
|
||||
</HoverMenu>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -172,7 +172,7 @@ function PropertiesModal({ slice, onHide, onSave }: InternalProps) {
|
|||
</FormLabel>
|
||||
<FormControl
|
||||
name="name"
|
||||
data-test="properties-name-input"
|
||||
data-test="properties-modal-name-input"
|
||||
type="text"
|
||||
bsSize="sm"
|
||||
value={name}
|
||||
|
@ -260,7 +260,7 @@ function PropertiesModal({ slice, onHide, onSave }: InternalProps) {
|
|||
{t('Cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
data-test="properties-save-button"
|
||||
data-test="properties-modal-save-button"
|
||||
type="submit"
|
||||
buttonSize="sm"
|
||||
buttonStyle="primary"
|
||||
|
|
Loading…
Reference in New Issue