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

suddjian pushed a commit to branch behavior-driven-cypress
in repository https://gitbox.apache.org/repos/asf/superset.git

commit cda0f2405ff7f1f85aec7f3959bf390f31618d4a
Author: David Aaron Suddjian <[email protected]>
AuthorDate: Wed Mar 24 11:36:54 2021 -0700

    remove bootstrap usage from controls test, + new utils
---
 .../cypress/integration/dashboard/controls.test.ts | 110 ++++++++++-----------
 .../integration/dashboard/dashboard.helper.ts      |  69 +++++++++++++
 .../cypress/integration/dashboard/load.test.ts     |  20 +---
 .../cypress-base/cypress/utils/vizPlugins.ts       |  33 +++----
 4 files changed, 143 insertions(+), 89 deletions(-)

diff --git 
a/superset-frontend/cypress-base/cypress/integration/dashboard/controls.test.ts 
b/superset-frontend/cypress-base/cypress/integration/dashboard/controls.test.ts
index 1be8f51..0727a07 100644
--- 
a/superset-frontend/cypress-base/cypress/integration/dashboard/controls.test.ts
+++ 
b/superset-frontend/cypress-base/cypress/integration/dashboard/controls.test.ts
@@ -16,79 +16,79 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { WORLD_HEALTH_DASHBOARD } from './dashboard.helper';
 import {
+  WORLD_HEALTH_CHARTS,
+  WORLD_HEALTH_DASHBOARD,
+  waitForChartLoad,
+  ChartSpec,
   getChartAliases,
-  isLegacyResponse,
-  DASHBOARD_CHART_ALIAS_PREFIX,
-} from '../../utils/vizPlugins';
+} from './dashboard.helper';
+import { isLegacyResponse } from '../../utils/vizPlugins';
 
 describe('Dashboard top-level controls', () => {
-  let mapId: string;
-  let aliases: string[];
-
   beforeEach(() => {
     cy.login();
     cy.visit(WORLD_HEALTH_DASHBOARD);
-
-    cy.get('#app').then(data => {
-      const bootstrapData = JSON.parse(data[0].dataset.bootstrap || '');
-      const dashboard = bootstrapData.dashboard_data;
-      mapId = dashboard.slices.find(
-        (slice: { form_data: { viz_type: string }; slice_id: number }) =>
-          slice.form_data.viz_type === 'world_map',
-      ).slice_id;
-      aliases = getChartAliases(dashboard.slices);
-    });
   });
 
   // flaky test
   xit('should allow chart level refresh', () => {
-    cy.wait(aliases);
-    cy.get('[data-test="grid-container"]').find('.world_map').should('exist');
-    cy.get(`#slice_${mapId}-controls`).click();
-    cy.get(`[data-test="slice_${mapId}-menu"]`)
-      .find('[data-test="refresh-chart-menu-item"]')
-      .click({ force: true });
-    cy.get('[data-test="refresh-chart-menu-item"]').should(
-      'have.class',
-      'ant-dropdown-menu-item-disabled',
-    );
-
-    cy.wait(`@${DASHBOARD_CHART_ALIAS_PREFIX}${mapId}`);
-    cy.get('[data-test="refresh-chart-menu-item"]').should(
-      'not.have.class',
-      'ant-dropdown-menu-item-disabled',
-    );
+    const mapSpec = WORLD_HEALTH_CHARTS.find(
+      ({ viz }) => viz === 'world_map',
+    ) as ChartSpec;
+    waitForChartLoad(mapSpec).then(gridComponent => {
+      const mapId = gridComponent.attr('data-test-chart-id');
+      
cy.get('[data-test="grid-container"]').find('.world_map').should('exist');
+      cy.get(`#slice_${mapId}-controls`).click();
+      cy.get(`[data-test="slice_${mapId}-menu"]`)
+        .find('[data-test="refresh-chart-menu-item"]')
+        .click({ force: true });
+      // likely cause for flakiness:
+      // The query completes before this assertion happens.
+      // Solution: pause the network before clicking, assert, then unpause 
network.
+      cy.get('[data-test="refresh-chart-menu-item"]').should(
+        'have.class',
+        'ant-dropdown-menu-item-disabled',
+      );
+      waitForChartLoad(mapSpec);
+      cy.get('[data-test="refresh-chart-menu-item"]').should(
+        'not.have.class',
+        'ant-dropdown-menu-item-disabled',
+      );
+    });
   });
 
   it('should allow dashboard level force refresh', () => {
-    cy.wait(aliases);
     // when charts are not start loading, for example, under a secondary tab,
     // should allow force refresh
-    cy.get('[data-test="more-horiz"]').click();
-    cy.get('[data-test="refresh-dashboard-menu-item"]').should(
-      'not.have.class',
-      'ant-dropdown-menu-item-disabled',
-    );
+    getChartAliases(WORLD_HEALTH_CHARTS).then(aliases => {
+      cy.get('[data-test="more-horiz"]').click();
+      cy.get('[data-test="refresh-dashboard-menu-item"]').should(
+        'not.have.class',
+        'ant-dropdown-menu-item-disabled',
+      );
 
-    cy.get('[data-test="refresh-dashboard-menu-item"]').click({ force: true });
-    cy.get('[data-test="refresh-dashboard-menu-item"]').should(
-      'have.class',
-      'ant-dropdown-menu-item-disabled',
-    );
+      cy.get('[data-test="refresh-dashboard-menu-item"]').click({
+        force: true,
+      });
+      cy.get('[data-test="refresh-dashboard-menu-item"]').should(
+        'have.class',
+        'ant-dropdown-menu-item-disabled',
+      );
+
+      // wait all charts force refreshed.
 
-    // wait all charts force refreshed.
-    cy.wait(aliases).then(xhrs => {
-      xhrs.forEach(async ({ response, request }) => {
-        const responseBody = response?.body;
-        const isCached = isLegacyResponse(responseBody)
-          ? responseBody.is_cached
-          : responseBody.result[0].is_cached;
-        // request url should indicate force-refresh operation
-        expect(request.url).to.have.string('force=true');
-        // is_cached in response should be false
-        expect(isCached).to.equal(false);
+      cy.wait(aliases).then(xhrs => {
+        xhrs.forEach(async ({ response, request }) => {
+          const responseBody = response?.body;
+          const isCached = isLegacyResponse(responseBody)
+            ? responseBody.is_cached
+            : responseBody.result[0].is_cached;
+          // request url should indicate force-refresh operation
+          expect(request.url).to.have.string('force=true');
+          // is_cached in response should be false
+          expect(isCached).to.equal(false);
+        });
       });
     });
     cy.get('[data-test="more-horiz"]').click();
diff --git 
a/superset-frontend/cypress-base/cypress/integration/dashboard/dashboard.helper.ts
 
b/superset-frontend/cypress-base/cypress/integration/dashboard/dashboard.helper.ts
index e9d8cd0..7bd2be5 100644
--- 
a/superset-frontend/cypress-base/cypress/integration/dashboard/dashboard.helper.ts
+++ 
b/superset-frontend/cypress-base/cypress/integration/dashboard/dashboard.helper.ts
@@ -1,3 +1,5 @@
+import { getChartAlias, Slice } from 'cypress/utils/vizPlugins';
+
 /**
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -35,6 +37,73 @@ export const WORLD_HEALTH_CHARTS = [
   { name: 'Box plot', viz: 'box_plot' },
 ] as const;
 
+export const BIRTH_NAMES_CHARTS = [
+  { name: 'Participants', viz: 'blah' },
+  { name: 'Genders', viz: 'blah' },
+  { name: 'Trends', viz: 'blah' },
+  { name: 'Genders by State', viz: 'blah' },
+  { name: 'Girls', viz: 'blah' },
+  { name: 'Girl Name Cloud', viz: 'blah' },
+  { name: 'Top 10 Girl Name Share', viz: 'blah' },
+  { name: 'Boys', viz: 'blah' },
+  { name: 'Boy Name Cloud', viz: 'blah' },
+  { name: 'Top 10 Boy Name Share', viz: 'blah' },
+] as const;
+
+/** Used to specify charts expected by the test suite */
+export interface ChartSpec {
+  name: string;
+  viz: string;
+}
+
+export function getChartGridComponent({ name, viz }: ChartSpec) {
+  return (
+    cy
+      .get('[data-test="grid-content"] [data-test="editable-title"]')
+      .contains(name)
+      // parentsUntil returns the child of the element matching the selector
+      .parentsUntil('[data-test="chart-grid-component"]')
+      .parent()
+      .should('have.attr', 'data-test-viz-type', viz)
+  );
+}
+
+export function waitForChartLoad(chart: ChartSpec) {
+  return getChartGridComponent(chart).then(gridComponent => {
+    const chartId = gridComponent.attr('data-test-chart-id');
+    // the chart should load in under half a minute
+    return (
+      cy
+        // this id only becomes visible when the chart is loaded
+        .wrap(gridComponent)
+        .find(`#chart-id-${chartId}`, { timeout: 30000 })
+        .should('be.visible')
+        // return the chart grid component
+        .then(() => gridComponent)
+    );
+  });
+}
+
+const toSlicelike = ($chart: JQuery<HTMLElement>): Slice => ({
+  slice_id: parseInt($chart.attr('data-test-chart-id')!, 10),
+  form_data: {
+    viz_type: $chart.attr('data-test-viz-type')!,
+  },
+});
+
+export function getChartAliases(charts: readonly ChartSpec[]) {
+  const aliases: string[] = [];
+  charts.forEach(chart =>
+    getChartGridComponent(chart).then($chart => {
+      aliases.push(getChartAlias(toSlicelike($chart)));
+    }),
+  );
+  // Wrapping the aliases is key.
+  // That way callers can chain off this function
+  // and actually get the list of aliases.
+  return cy.wrap(aliases);
+}
+
 /**
  * Drag an element and drop it to another element.
  * Usage:
diff --git 
a/superset-frontend/cypress-base/cypress/integration/dashboard/load.test.ts 
b/superset-frontend/cypress-base/cypress/integration/dashboard/load.test.ts
index 4522494..b03cdd2 100644
--- a/superset-frontend/cypress-base/cypress/integration/dashboard/load.test.ts
+++ b/superset-frontend/cypress-base/cypress/integration/dashboard/load.test.ts
@@ -17,32 +17,18 @@
  * under the License.
  */
 import {
+  waitForChartLoad,
   WORLD_HEALTH_CHARTS,
   WORLD_HEALTH_DASHBOARD,
 } from './dashboard.helper';
 
 describe('Dashboard load', () => {
-  beforeEach(() => {
+  before(() => {
     cy.login();
     cy.visit(WORLD_HEALTH_DASHBOARD);
   });
 
   it('should load dashboard', () => {
-    // wait and verify one-by-one
-    WORLD_HEALTH_CHARTS.forEach(({ name, viz }) => {
-      // prettier-ignore
-      cy.get('[data-test="grid-content"] 
[data-test="editable-title"]').contains(name)
-        // use the chart title to find the chart grid component,
-        // which has the chart id and viz type info
-        .parentsUntil('[data-test="chart-grid-component"]').parent()
-        .should('have.attr', 'data-test-viz-type', viz)
-        .then(chartElement => {
-          const chartId = chartElement.attr('data-test-chart-id');
-          // the chart should load in under a minute
-          // (big timeout so that it works in CI)
-          cy.wrap(chartElement).find(`#chart-id-${chartId}`, { timeout: 30000 
})
-            .should('be.visible');
-        });
-    });
+    WORLD_HEALTH_CHARTS.forEach(waitForChartLoad);
   });
 });
diff --git a/superset-frontend/cypress-base/cypress/utils/vizPlugins.ts 
b/superset-frontend/cypress-base/cypress/utils/vizPlugins.ts
index 9450a30..04075e9 100644
--- a/superset-frontend/cypress-base/cypress/utils/vizPlugins.ts
+++ b/superset-frontend/cypress-base/cypress/utils/vizPlugins.ts
@@ -57,24 +57,23 @@ export function getSliceIdFromRequestUrl(url: string) {
   return query?.match(/\d+/)?.[0];
 }
 
+export function getChartAlias(slice: Slice): string {
+  const vizType = slice.form_data.viz_type;
+  const isLegacy = isLegacyChart(vizType);
+  const alias = `${DASHBOARD_CHART_ALIAS_PREFIX}${slice.slice_id}`;
+  const formData = encodeURIComponent(`{"slice_id":${slice.slice_id}}`);
+  if (isLegacy) {
+    const route = `/superset/explore_json/?*${formData}*`;
+    cy.intercept('POST', `${route}`).as(alias);
+    return `@${alias}`;
+  }
+  const route = `/api/v1/chart/data?*${formData}*`;
+  cy.intercept('POST', `${route}`).as(alias);
+  return `@${alias}`;
+}
+
 export function getChartAliases(slices: Slice[]): string[] {
-  const aliases: string[] = [];
-  Array.from(slices).forEach(slice => {
-    const vizType = slice.form_data.viz_type;
-    const isLegacy = isLegacyChart(vizType);
-    const alias = `${DASHBOARD_CHART_ALIAS_PREFIX}${slice.slice_id}`;
-    const formData = encodeURIComponent(`{"slice_id":${slice.slice_id}}`);
-    if (isLegacy) {
-      const route = `/superset/explore_json/?*${formData}*`;
-      cy.intercept('POST', `${route}`).as(alias);
-      aliases.push(`@${alias}`);
-    } else {
-      const route = `/api/v1/chart/data?*${formData}*`;
-      cy.intercept('POST', `${route}`).as(alias);
-      aliases.push(`@${alias}`);
-    }
-  });
-  return aliases;
+  return Array.from(slices).map(getChartAlias);
 }
 
 export function interceptChart({

Reply via email to