You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ru...@apache.org on 2020/10/20 04:36:56 UTC

[incubator-superset] branch master updated: chore: Dashboard cypress refactor (#11280)

This is an automated email from the ASF dual-hosted git repository.

rusackas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 55ae259  chore: Dashboard cypress refactor (#11280)
55ae259 is described below

commit 55ae259b1362cfe19a0a9524d1e39f063ed9c62a
Author: adam-stasiak-polidea <ad...@polidea.com>
AuthorDate: Tue Oct 20 06:36:20 2020 +0200

    chore: Dashboard cypress refactor (#11280)
    
    * moved dashboard tests to use data-test attributes
    
    * linter
    
    * fix for unstable save test
---
 .../integration/dashboard/edit_mode.test.js        | 72 ++++++++++++-----
 .../cypress/integration/dashboard/fav_star.test.js | 14 ++--
 .../cypress/integration/dashboard/load.test.js     |  4 +-
 .../cypress/integration/dashboard/markdown.test.ts | 32 +++++---
 .../cypress/integration/dashboard/save.test.js     | 35 ++++++---
 .../cypress/integration/dashboard/tabs.test.js     | 89 +++++++++++++---------
 .../dashboard/components/BuilderComponentPane.jsx  |  2 +-
 .../src/dashboard/components/SaveModal.jsx         |  2 +-
 .../src/dashboard/components/SliceAdder.jsx        |  1 +
 .../components/gridComponents/ChartHolder.jsx      | 10 ++-
 .../src/explore/components/PropertiesModal.tsx     |  4 +-
 11 files changed, 171 insertions(+), 94 deletions(-)

diff --git a/superset-frontend/cypress-base/cypress/integration/dashboard/edit_mode.test.js b/superset-frontend/cypress-base/cypress/integration/dashboard/edit_mode.test.js
index ab4d8db..c628837 100644
--- a/superset-frontend/cypress-base/cypress/integration/dashboard/edit_mode.test.js
+++ b/superset-frontend/cypress-base/cypress/integration/dashboard/edit_mode.test.js
@@ -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 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 });
 
-    // undo 2 steps
-    cy.get('.dashboard-header .undo-action').click().click();
+    // 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');
+    });
   });
 });
diff --git a/superset-frontend/cypress-base/cypress/integration/dashboard/fav_star.test.js b/superset-frontend/cypress-base/cypress/integration/dashboard/fav_star.test.js
index 7d66a0b..3a6ffcd 100644
--- a/superset-frontend/cypress-base/cypress/integration/dashboard/fav_star.test.js
+++ b/superset-frontend/cypress-base/cypress/integration/dashboard/fav_star.test.js
@@ -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');
   });
 });
diff --git a/superset-frontend/cypress-base/cypress/integration/dashboard/load.test.js b/superset-frontend/cypress-base/cypress/integration/dashboard/load.test.js
index 6e33eb5..7b46ffa 100644
--- a/superset-frontend/cypress-base/cypress/integration/dashboard/load.test.js
+++ b/superset-frontend/cypress-base/cypress/integration/dashboard/load.test.js
@@ -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');
         }),
       );
     });
diff --git a/superset-frontend/cypress-base/cypress/integration/dashboard/markdown.test.ts b/superset-frontend/cypress-base/cypress/integration/dashboard/markdown.test.ts
index 4f8fb84..929f9e6 100644
--- a/superset-frontend/cypress-base/cypress/integration/dashboard/markdown.test.ts
+++ b/superset-frontend/cypress-base/cypress/integration/dashboard/markdown.test.ts
@@ -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');
   });
 });
diff --git a/superset-frontend/cypress-base/cypress/integration/dashboard/save.test.js b/superset-frontend/cypress-base/cypress/integration/dashboard/save.test.js
index 811e7c0..6b7ff92 100644
--- a/superset-frontend/cypress-base/cypress/integration/dashboard/save.test.js
+++ b/superset-frontend/cypress-base/cypress/integration/dashboard/save.test.js
@@ -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');
   });
 });
diff --git a/superset-frontend/cypress-base/cypress/integration/dashboard/tabs.test.js b/superset-frontend/cypress-base/cypress/integration/dashboard/tabs.test.js
index 94b0bb0..a842264 100644
--- a/superset-frontend/cypress-base/cypress/integration/dashboard/tabs.test.js
+++ b/superset-frontend/cypress-base/cypress/integration/dashboard/tabs.test.js
@@ -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
diff --git a/superset-frontend/src/dashboard/components/BuilderComponentPane.jsx b/superset-frontend/src/dashboard/components/BuilderComponentPane.jsx
index 87545f8..df18290 100644
--- a/superset-frontend/src/dashboard/components/BuilderComponentPane.jsx
+++ b/superset-frontend/src/dashboard/components/BuilderComponentPane.jsx
@@ -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 />
diff --git a/superset-frontend/src/dashboard/components/SaveModal.jsx b/superset-frontend/src/dashboard/components/SaveModal.jsx
index 40b29c29..e3a85b5 100644
--- a/superset-frontend/src/dashboard/components/SaveModal.jsx
+++ b/superset-frontend/src/dashboard/components/SaveModal.jsx
@@ -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}
             >
diff --git a/superset-frontend/src/dashboard/components/SliceAdder.jsx b/superset-frontend/src/dashboard/components/SliceAdder.jsx
index fbb8ac7..f9fc471 100644
--- a/superset-frontend/src/dashboard/components/SliceAdder.jsx
+++ b/superset-frontend/src/dashboard/components/SliceAdder.jsx
@@ -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}`}
diff --git a/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.jsx b/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.jsx
index b43684e..f1f4f91 100644
--- a/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.jsx
+++ b/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.jsx
@@ -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>
diff --git a/superset-frontend/src/explore/components/PropertiesModal.tsx b/superset-frontend/src/explore/components/PropertiesModal.tsx
index e1e1bed..3c83e0b 100644
--- a/superset-frontend/src/explore/components/PropertiesModal.tsx
+++ b/superset-frontend/src/explore/components/PropertiesModal.tsx
@@ -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"