chore: Dashboard cypress refactor (#11280)

* moved dashboard tests to use data-test attributes

* linter

* fix for unstable save test
This commit is contained in:
adam-stasiak-polidea 2020-10-20 06:36:20 +02:00 committed by GitHub
parent 9266f0a4a8
commit 55ae259b13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 171 additions and 94 deletions

View File

@ -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');
});
});
});

View File

@ -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');
});
});

View File

@ -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');
}),
);
});

View File

@ -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');
});
});

View File

@ -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');
});
});

View File

@ -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

View File

@ -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 />

View File

@ -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}
>

View File

@ -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}`}

View File

@ -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>

View File

@ -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"