未验证 提交 29ad78e1 编写于 作者: J Jesse Yang 提交者: GitHub

chore: upgrade Cypress to 6.2.1 (#12605)

上级 1b2611c2
......@@ -21,7 +21,6 @@ import { CHART_LIST } from './chart_list.helper';
describe('chart card view', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.visit(CHART_LIST);
cy.get('[data-test="card-view"]').click();
});
......
......@@ -21,7 +21,6 @@ import { CHART_LIST } from './chart_list.helper';
describe('chart card view filters', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.visit(CHART_LIST);
cy.get('[data-test="card-view"]').click();
});
......@@ -89,7 +88,6 @@ describe('chart card view filters', () => {
describe('chart list view filters', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.visit(CHART_LIST);
cy.get('[data-test="list-view"]').click();
});
......
......@@ -21,7 +21,6 @@ import { CHART_LIST } from './chart_list.helper';
describe('chart list view', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.visit(CHART_LIST);
cy.get('[data-test="list-view"]').click();
});
......
......@@ -17,7 +17,6 @@
* under the License.
*/
import { WORLD_HEALTH_DASHBOARD } from './dashboard.helper';
import readResponseBlob from '../../utils/readResponseBlob';
import {
getChartAliases,
isLegacyResponse,
......@@ -25,19 +24,19 @@ import {
} from '../../utils/vizPlugins';
describe('Dashboard top-level controls', () => {
let mapId;
let aliases;
let mapId: string;
let aliases: string[];
beforeEach(() => {
cy.server();
cy.login();
cy.visit(WORLD_HEALTH_DASHBOARD);
cy.get('#app').then(data => {
const bootstrapData = JSON.parse(data[0].dataset.bootstrap);
const bootstrapData = JSON.parse(data[0].dataset.bootstrap || '');
const dashboard = bootstrapData.dashboard_data;
mapId = dashboard.slices.find(
slice => slice.form_data.viz_type === 'world_map',
(slice: { form_data: { viz_type: string }; slice_id: number }) =>
slice.form_data.viz_type === 'world_map',
).slice_id;
aliases = getChartAliases(dashboard.slices);
});
......@@ -50,10 +49,11 @@ describe('Dashboard top-level controls', () => {
cy.get(`#slice_${mapId}-controls`).click();
cy.get(`[data-test="slice_${mapId}-menu"]`)
.find('[data-test="refresh-chart-menu-item"]')
.click({ force: true })
.then($el => {
cy.get($el).should('have.class', 'ant-dropdown-menu-item-disabled');
});
.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(
......@@ -63,7 +63,6 @@ describe('Dashboard top-level controls', () => {
});
it('should allow dashboard level force refresh', () => {
// wait the all dash finish loading.
cy.wait(aliases);
// when charts are not start loading, for example, under a secondary tab,
// should allow force refresh
......@@ -80,14 +79,14 @@ describe('Dashboard top-level controls', () => {
);
// wait all charts force refreshed.
cy.wait(aliases, { responseTimeout: 15000 }).then(xhrs => {
xhrs.forEach(async xhr => {
const responseBody = await readResponseBlob(xhr.response.body);
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(xhr.url).to.have.string('force=true');
expect(request.url).to.have.string('force=true');
// is_cached in response should be false
expect(isCached).to.equal(false);
});
......
......@@ -20,7 +20,6 @@ import { WORLD_HEALTH_DASHBOARD, drag } from './dashboard.helper';
describe('Dashboard edit mode', () => {
beforeEach(() => {
cy.server();
cy.login();
cy.visit(WORLD_HEALTH_DASHBOARD);
cy.get('[data-test="dashboard-header"]')
......@@ -43,7 +42,7 @@ describe('Dashboard edit mode', () => {
// box plot should be gone
cy.get('[data-test="grid-container"]')
.find('.box_plot')
.should('not.be.visible');
.should('not.exist');
});
cy.get('[data-test="dashboard-builder-component-pane-tabs-navigation"]')
......@@ -78,7 +77,7 @@ describe('Dashboard edit mode', () => {
// Box plot chart should be gone
cy.get('[data-test="grid-container"]')
.find('.box_plot')
.should('not.be.visible');
.should('not.exist');
// undo second step and expect initial items count
cy.get('[data-test="undo-action"]').click();
......
......@@ -71,10 +71,9 @@ function openDashboardEditProperties() {
describe('Dashboard edit action', () => {
beforeEach(() => {
cy.server();
cy.login();
cy.visit(WORLD_HEALTH_DASHBOARD);
cy.route(`/api/v1/dashboard/1`).as('dashboardGet');
cy.intercept(`/api/v1/dashboard/1`).as('dashboardGet');
cy.get('.dashboard-grid', { timeout: 50000 })
.should('be.visible') // wait for 50 secs to load dashboard
.then(() => {
......
......@@ -25,10 +25,9 @@ describe('Dashboard add to favorite', () => {
let isFavoriteDashboard = false;
beforeEach(() => {
cy.server();
cy.login();
cy.route(CHECK_DASHBOARD_FAVORITE_ENDPOINT).as('countFavStar');
cy.intercept(CHECK_DASHBOARD_FAVORITE_ENDPOINT).as('countFavStar');
cy.visit(WORLD_HEALTH_DASHBOARD);
cy.wait('@countFavStar').then(xhr => {
......
......@@ -16,13 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
import { WORLD_HEALTH_DASHBOARD } from './dashboard.helper';
import {
getChartAliases,
DASHBOARD_CHART_ALIAS_PREFIX,
isLegacyResponse,
} from '../../utils/vizPlugins';
import readResponseBlob from '../../utils/readResponseBlob';
parsePostForm,
} from 'cypress/utils';
import { WORLD_HEALTH_DASHBOARD } from './dashboard.helper';
interface Slice {
slice_id: number;
......@@ -43,7 +43,6 @@ describe('Dashboard filter', () => {
const getAlias = (id: number) => `@${DASHBOARD_CHART_ALIAS_PREFIX}${id}`;
beforeEach(() => {
cy.server();
cy.login();
cy.visit(WORLD_HEALTH_DASHBOARD);
......@@ -87,18 +86,17 @@ describe('Dashboard filter', () => {
cy.get('.filter_box button').click({ force: true });
cy.wait(aliases.filter(x => x !== getAlias(filterId))).then(requests =>
Promise.all(
requests.map(async xhr => {
expect(xhr.status).to.eq(200);
const responseBody = await readResponseBlob(xhr.response.body);
requests.map(async ({ response, request }) => {
const responseBody = response?.body;
let requestFilter;
if (isLegacyResponse(responseBody)) {
const requestFormData = xhr.request.body as FormData;
const requestFormData = parsePostForm(request.body);
const requestParams = JSON.parse(
requestFormData.get('form_data') as string,
requestFormData.form_data as string,
);
requestFilter = requestParams.extra_filters[0];
} else {
requestFilter = xhr.request.body.queries[0].filters[0];
requestFilter = request.body.queries[0].filters[0];
}
expect(requestFilter).deep.eq({
col: 'region',
......
......@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
import readResponseBlob from '../../utils/readResponseBlob';
import {
getChartAliases,
isLegacyResponse,
......@@ -28,7 +27,6 @@ describe('Dashboard load', () => {
let dashboard;
let aliases;
beforeEach(() => {
cy.server();
cy.login();
cy.visit(WORLD_HEALTH_DASHBOARD);
......@@ -46,16 +44,15 @@ describe('Dashboard load', () => {
// wait and verify one-by-one
cy.wait(aliases).then(requests =>
Promise.all(
requests.map(async xhr => {
expect(xhr.status).to.eq(200);
const responseBody = await readResponseBlob(xhr.response.body);
requests.map(async ({ response, request }) => {
const responseBody = response?.body;
let sliceId;
if (isLegacyResponse(responseBody)) {
expect(responseBody).to.have.property('errors');
expect(responseBody.errors.length).to.eq(0);
sliceId = responseBody.form_data.slice_id;
} else {
sliceId = getSliceIdFromRequestUrl(xhr.url);
sliceId = getSliceIdFromRequestUrl(request.url);
responseBody.result.forEach(element => {
expect(element).to.have.property('error', null);
expect(element).to.have.property('status', 'success');
......
......@@ -20,7 +20,6 @@ import { TABBED_DASHBOARD, drag, resize } from './dashboard.helper';
describe('Dashboard edit markdown', () => {
beforeEach(() => {
cy.server();
cy.login();
cy.visit(TABBED_DASHBOARD);
});
......@@ -85,6 +84,6 @@ describe('Dashboard edit markdown', () => {
cy.get('@component-background-first').click('right');
cy.get('[data-test="dashboard-component-chart-holder"]')
.find('.ace_content')
.should('not.be.visible');
.should('not.exist');
});
});
......@@ -21,7 +21,6 @@ import { TABBED_DASHBOARD } from './dashboard.helper';
describe('Nativefilters', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.visit(TABBED_DASHBOARD);
});
it('should show filter bar and allow user to create filters ', () => {
......
......@@ -28,14 +28,15 @@ function openDashboardEditProperties() {
describe('Dashboard save action', () => {
beforeEach(() => {
cy.server();
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;
const dashboardId = dashboard.id;
cy.route('POST', `/superset/copy_dash/${dashboardId}/`).as('copyRequest');
cy.intercept('POST', `/superset/copy_dash/${dashboardId}/`).as(
'copyRequest',
);
cy.get('[data-test="more-horiz"]').trigger('click', { force: true });
cy.get('[data-test="save-as-menu-item"]').trigger('click', {
......@@ -56,35 +57,37 @@ describe('Dashboard save action', () => {
});
it('should save/overwrite dashboard', () => {
cy.get('[data-test="grid-row-background--transparent"]').within(() => {
cy.get('.box_plot', { timeout: 10000 }).should('be.visible');
});
// should load chart
cy.get('.dashboard-grid', { timeout: 50000 }); // wait for 50 secs
cy.get('.dashboard-grid', { timeout: 30000 });
cy.get('.box_plot').should('be.visible');
// remove box_plot chart from dashboard
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');
.trigger('moustenter')
.click();
cy.get('[data-test="grid-container"]')
.find('.box_plot')
.should('not.be.visible');
.should('not.exist');
cy.route('POST', '/superset/save_dash/**/').as('saveRequest');
cy.intercept('POST', '/superset/save_dash/**/').as('saveRequest');
cy.get('[data-test="dashboard-header"]')
.find('[data-test="header-save-button"]')
.contains('Save')
.trigger('click', { force: true });
.click();
// go back to view mode
cy.wait('@saveRequest');
cy.get('[data-test="dashboard-header"]')
.find('[data-test="edit-alt"]')
.click();
// deleted boxplot should still not exist
cy.get('[data-test="grid-container"]')
.find('.box_plot', { timeout: 20000 })
.should('not.be.visible');
.should('not.exist');
});
// TODO: Fix broken test
......
......@@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import { interceptChart, parsePostForm } from 'cypress/utils';
import { TABBED_DASHBOARD } from './dashboard.helper';
describe('Dashboard tabs', () => {
......@@ -23,7 +24,6 @@ describe('Dashboard tabs', () => {
let treemapId;
let linechartId;
let boxplotId;
let dashboardId;
// cypress can not handle window.scrollTo
// https://github.com/cypress-io/cypress/issues/2761
......@@ -35,7 +35,6 @@ describe('Dashboard tabs', () => {
};
beforeEach(() => {
cy.server();
cy.login();
cy.visit(TABBED_DASHBOARD);
......@@ -43,7 +42,6 @@ describe('Dashboard tabs', () => {
cy.get('#app').then(data => {
const bootstrapData = JSON.parse(data[0].dataset.bootstrap);
const dashboard = bootstrapData.dashboard_data;
dashboardId = dashboard.id;
filterId = dashboard.slices.find(
slice => slice.form_data.viz_type === 'filter_box',
).slice_id;
......@@ -56,38 +54,10 @@ describe('Dashboard tabs', () => {
linechartId = dashboard.slices.find(
slice => slice.form_data.viz_type === 'line',
).slice_id;
const filterFormdata = {
slice_id: filterId,
};
const filterRequest = `/superset/explore_json/?form_data=${JSON.stringify(
filterFormdata,
)}&dashboard_id=${dashboardId}`;
cy.route('POST', filterRequest).as('filterRequest');
const treemapFormdata = {
slice_id: treemapId,
};
const treemapRequest = `/superset/explore_json/?form_data=${JSON.stringify(
treemapFormdata,
)}&dashboard_id=${dashboardId}`;
cy.route('POST', treemapRequest).as('treemapRequest');
const linechartFormdata = {
slice_id: linechartId,
};
const linechartRequest = `/superset/explore_json/?form_data=${JSON.stringify(
linechartFormdata,
)}&dashboard_id=${dashboardId}`;
cy.route('POST', linechartRequest).as('linechartRequest');
const boxplotFormdata = {
slice_id: boxplotId,
};
const boxplotRequest = `/superset/explore_json/?form_data=${JSON.stringify(
boxplotFormdata,
)}&dashboard_id=${dashboardId}`;
cy.route('POST', boxplotRequest).as('boxplotRequest');
interceptChart(filterId).as('filterRequest');
interceptChart(treemapId).as('treemapRequest');
interceptChart(linechartId).as('linechartRequest');
interceptChart(boxplotId, false).as('boxplotRequest');
});
});
......@@ -129,10 +99,8 @@ describe('Dashboard tabs', () => {
.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');
.should('not.exist');
cy.get('[data-test="grid-container"]').find('.line').should('not.exist');
// click row level tab, see 1 more chart
cy.get('[data-test="dashboard-component-tabs"]')
......@@ -164,67 +132,54 @@ describe('Dashboard tabs', () => {
cy.wait('@treemapRequest');
// apply filter
cy.get('.Select__control').first().should('be.visible');
cy.get('.Select__control').first().click({ force: true });
cy.get('.Select__control input[type=text]')
.first()
.should('be.visible')
.type('South Asia{enter}', { force: true });
cy.get('.Select__control').first().should('be.visible').click();
cy.get('.Select__control input[type=text]').first().focus().type('South');
cy.get('.Select__option').contains('South Asia').click();
cy.get('.filter_box button:not(:disabled)').contains('Apply').click();
// send new query from same tab
cy.wait('@treemapRequest').then(xhr => {
const requestFormData = xhr.request.body;
const requestParams = JSON.parse(requestFormData.get('form_data'));
cy.wait('@treemapRequest').then(({ request }) => {
const requestBody = parsePostForm(request.body);
const requestParams = JSON.parse(requestBody.form_data);
expect(requestParams.extra_filters[0]).deep.eq({
col: 'region',
op: 'IN',
val: ['South Asia'],
op: '==',
val: 'South Asia',
});
});
// click row level tab, send 1 more query
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.get('.ant-tabs-tab').contains('row tab 2').click();
cy.wait('@linechartRequest').then(xhr => {
const requestFormData = xhr.request.body;
const requestParams = JSON.parse(requestFormData.get('form_data'));
cy.wait('@linechartRequest').then(({ request }) => {
const requestBody = parsePostForm(request.body);
const requestParams = JSON.parse(requestBody.form_data);
expect(requestParams.extra_filters[0]).deep.eq({
col: 'region',
op: 'IN',
val: ['South Asia'],
op: '==',
val: 'South Asia',
});
});
// click top level tab, send 1 more query
cy.get('[data-test="dashboard-component-tabs"]')
.first()
.find('[data-test="nav-list"]')
.children()
.as('top-level-tabs');
cy.get('.ant-tabs-tab').contains('Tab B').click();
cy.get('@top-level-tabs').last().click();
cy.wait('@boxplotRequest').then(xhr => {
const requestFormData = xhr.request.body;
const requestParams = JSON.parse(requestFormData.get('form_data'));
expect(requestParams.extra_filters[0]).deep.eq({
cy.wait('@boxplotRequest').then(({ request }) => {
const requestBody = request.body;
const requestParams = requestBody.queries[0];
expect(requestParams.filters[0]).deep.eq({
col: 'region',
op: 'IN',
val: ['South Asia'],
op: '==',
val: 'South Asia',
});
});
// navigate to filter and clear filter
cy.get('@top-level-tabs').first().click();
cy.get('@top-level-tabs').first().click();
cy.get('.ant-tabs-tab').contains('Tab A').click();
cy.get('.ant-tabs-tab').contains('row tab 1').click();
cy.get('.Select__clear-indicator').click();
cy.get('.filter_box button:not(:disabled)').contains('Apply').click();
// trigger 1 new query
cy.wait('@treemapRequest');
......
......@@ -16,16 +16,18 @@
* specific language governing permissions and limitations
* under the License.
*/
import {
isLegacyResponse,
getChartAliases,
parsePostForm,
} from 'cypress/utils';
import { WORLD_HEALTH_DASHBOARD } from './dashboard.helper';
import { isLegacyResponse, getChartAliases } from '../../utils/vizPlugins';
import readResponseBlob from '../../utils/readResponseBlob';
describe('Dashboard form data', () => {
const urlParams = { param1: '123', param2: 'abc' };
let dashboard;
beforeEach(() => {
cy.server();
cy.login();
cy.visit(WORLD_HEALTH_DASHBOARD, { qs: urlParams });
......@@ -41,16 +43,15 @@ describe('Dashboard form data', () => {
// wait and verify one-by-one
cy.wait(aliases, { timeout: 18000 }).then(requests =>
Promise.all(
requests.map(async xhr => {
expect(xhr.status).to.eq(200);
const responseBody = await readResponseBlob(xhr.response.body);
requests.map(async ({ response, request }) => {
const responseBody = response?.body;
if (isLegacyResponse(responseBody)) {
const requestFormData = xhr.request.body;
const requestParams = JSON.parse(requestFormData.get('form_data'));
const requestParams = JSON.parse(
parsePostForm(request.body).form_data,
);
expect(requestParams.url_params).deep.eq(urlParams);
} else {
xhr.request.body.queries.forEach(query => {
request.body.queries.forEach(query => {
expect(query.url_params).deep.eq(urlParams);
});
}
......
......@@ -21,7 +21,6 @@ import { DASHBOARD_LIST } from './dashboard_list.helper';
describe('Dashboard card view', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.visit(DASHBOARD_LIST);
cy.get('[data-test="card-view"]').click();
});
......
......@@ -21,7 +21,6 @@ import { DASHBOARD_LIST } from './dashboard_list.helper';
describe('dashboard filters card view', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.visit(DASHBOARD_LIST);
cy.get('[data-test="card-view"]').click();
});
......@@ -74,7 +73,6 @@ describe('dashboard filters card view', () => {
describe('dashboard filters list view', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.visit(DASHBOARD_LIST);
cy.get('[data-test="list-view"]').click();
});
......
......@@ -21,7 +21,6 @@ import { DASHBOARD_LIST } from './dashboard_list.helper';
describe('dashboard list view', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.visit(DASHBOARD_LIST);
cy.get('[data-test="list-view"]').click();
});
......
......@@ -20,7 +20,6 @@ import { DATABASE_LIST } from './helper';
describe('Add database', () => {
beforeEach(() => {
cy.server();
cy.login();
});
......
......@@ -19,10 +19,9 @@
describe('AdhocFilters', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.route('GET', '/superset/explore_json/**').as('getJson');
cy.route('POST', '/superset/explore_json/**').as('postJson');
cy.route('GET', '/superset/filter/table/*/name').as('filterValues');
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
cy.intercept('GET', '/superset/filter/table/*/name').as('filterValues');
cy.visitChartByName('Boys'); // a table chart
cy.verifySliceSuccess({ waitAlias: '@postJson' });
});
......
......@@ -19,9 +19,8 @@
describe('AdhocMetrics', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.route('GET', '/superset/explore_json/**').as('getJson');
cy.route('POST', '/superset/explore_json/**').as('postJson');
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
cy.visitChartByName('Num Births Trend');
cy.verifySliceSuccess({ waitAlias: '@postJson' });
});
......
......@@ -19,9 +19,8 @@
describe('Advanced analytics', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.route('GET', '/superset/explore_json/**').as('getJson');
cy.route('POST', '/superset/explore_json/**').as('postJson');
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
});
it('Create custom time compare', () => {
......@@ -60,9 +59,8 @@ describe('Advanced analytics', () => {
describe('Annotations', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.route('GET', '/superset/explore_json/**').as('getJson');
cy.route('POST', '/superset/explore_json/**').as('postJson');
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
});
it('Create formula annotation y-axis goal line', () => {
......
......@@ -21,8 +21,7 @@ import { FORM_DATA_DEFAULTS, NUM_METRIC } from './visualizations/shared.helper';
describe('No Results', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.route('POST', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
it('No results message shows up', () => {
......@@ -43,9 +42,7 @@ describe('No Results', () => {
};
cy.visitChartByParams(JSON.stringify(formData));
cy.wait('@getJson').then(async xhr => {
expect(xhr.status).to.eq(200);
});
cy.wait('@getJson').its('response.statusCode').should('eq', 200);
cy.get('div.chart-container').contains('No Results');
});
});
......@@ -29,9 +29,8 @@ describe('Datasource control', () => {
let numScripts = 0;
cy.login();
cy.server();
cy.route('GET', '/superset/explore_json/**').as('getJson');
cy.route('POST', '/superset/explore_json/**').as('postJson');
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
cy.visitChartByName('Num Births Trend');
cy.verifySliceSuccess({ waitAlias: '@postJson' });
......@@ -91,9 +90,8 @@ describe('Datasource control', () => {
describe('VizType control', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.route('GET', '/superset/explore_json/**').as('getJson');
cy.route('POST', '/superset/explore_json/**').as('postJson');
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
});
it('Can change vizType', () => {
......@@ -123,9 +121,8 @@ describe('VizType control', () => {
describe('Time range filter', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.route('GET', '/superset/explore_json/**').as('getJson');
cy.route('POST', '/superset/explore_json/**').as('postJson');
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
});
it('Advanced time_range params', () => {
......@@ -237,10 +234,9 @@ describe('Time range filter', () => {
describe('Groupby control', () => {
it('Set groupby', () => {
cy.server();
cy.login();
cy.route('GET', '/superset/explore_json/**').as('getJson');
cy.route('POST', '/superset/explore_json/**').as('postJson');
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
cy.visitChartByName('Num Births Trend');
cy.verifySliceSuccess({ waitAlias: '@postJson' });
......
......@@ -27,9 +27,8 @@ describe('Edit FilterBox Chart', () => {
}
beforeEach(() => {
cy.server();
cy.login();
cy.route('POST', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
it('should work with default date filter', () => {
......
......@@ -30,9 +30,8 @@ const apiURL = (endpoint, queryObject) =>
describe('Test explore links', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.route('GET', '/superset/explore_json/**').as('getJson');
cy.route('POST', '/superset/explore_json/**').as('postJson');
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
});
it('Open and close view query modal', () => {
......@@ -50,7 +49,7 @@ describe('Test explore links', () => {
});
it('Visit short link', () => {
cy.route('POST', 'r/shortner/').as('getShortUrl');
cy.intercept('POST', 'r/shortner/').as('getShortUrl');
cy.visitChartByName('Growth Rate');
cy.verifySliceSuccess({ waitAlias: '@postJson' });
......
......@@ -16,8 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
import readResponseBlob from '../../../utils/readResponseBlob';
describe('Visualization > Area', () => {
const AREA_FORM_DATA = {
datasource: '2__table',
......@@ -58,9 +56,8 @@ describe('Visualization > Area', () => {
}
beforeEach(() => {
cy.server();
cy.login();
cy.route('POST', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
it('should work without groupby', () => {
......@@ -96,11 +93,8 @@ describe('Visualization > Area', () => {
}),
);
cy.wait('@getJson').then(async xhr => {
cy.verifyResponseCodes(xhr);
const responseBody = await readResponseBlob(xhr.response.body);
cy.wait('@getJson').then(async ({ response }) => {
const responseBody = response?.body;
// Make sure data is sorted correctly
const firstRow = responseBody.data[0].values;
const secondRow = responseBody.data[1].values;
......
......@@ -49,8 +49,7 @@ describe('Visualization > Big Number with Trendline', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.route('POST', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
it('should work', () => {
......
......@@ -17,9 +17,6 @@
* under the License.
*/
import { FORM_DATA_DEFAULTS, NUM_METRIC } from './shared.helper';
import readResponseBlob from '../../../utils/readResponseBlob';
// Big Number Total
describe('Visualization > Big Number Total', () => {
const BIG_NUMBER_DEFAULTS = {
......@@ -29,8 +26,7 @@ describe('Visualization > Big Number Total', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.route('POST', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
it('Test big number chart with adhoc metric', () => {
......@@ -74,11 +70,9 @@ describe('Visualization > Big Number Total', () => {
};
cy.visitChartByParams(JSON.stringify(formData));
cy.wait(['@getJson']).then(async xhr => {
cy.verifyResponseCodes(xhr);
cy.wait(['@getJson']).then(async ({ response }) => {
cy.verifySliceContainer();
const responseBody = await readResponseBlob(xhr.response.body);
const responseBody = response?.body;
expect(responseBody.query).not.contains(formData.groupby[0]);
});
});
......
......@@ -38,9 +38,8 @@ describe('Visualization > Box Plot', () => {
}
beforeEach(() => {
cy.server();
cy.login();
cy.route('POST', '/api/v1/chart/data*').as('getJson');
cy.intercept('POST', '/api/v1/chart/data*').as('getJson');
});
it('should work', () => {
......
......@@ -52,9 +52,8 @@ describe('Visualization > Bubble', () => {
}
beforeEach(() => {
cy.server();
cy.login();
cy.route('POST', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
// Number of circles are pretty unstable when there are a lot of circles
......
......@@ -52,9 +52,8 @@ describe('Visualization > Compare', () => {
}
beforeEach(() => {
cy.server();
cy.login();
cy.route('POST', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
it('should work without groupby', () => {
......
......@@ -23,8 +23,7 @@ describe('Visualization > Distribution bar chart', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.route('POST', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
it('should work with adhoc metric', () => {
......
......@@ -40,9 +40,8 @@ describe('Visualization > Dual Line', () => {
}
beforeEach(() => {
cy.server();
cy.login();
cy.route('POST', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
it('should work', () => {
......
......@@ -42,9 +42,8 @@ describe('Visualization > Histogram', () => {
}
beforeEach(() => {
cy.server();
cy.login();
cy.route('POST', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
it('should work without groupby', () => {
......
......@@ -23,8 +23,7 @@ describe('Visualization > Line', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.route('POST', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
it('should show validator error when no metric', () => {
......
......@@ -42,9 +42,8 @@ describe('Visualization > Pie', () => {
}
beforeEach(() => {
cy.server();
cy.login();
cy.route('POST', '/api/v1/chart/data*').as('getJson');
cy.intercept('POST', '/api/v1/chart/data*').as('getJson');
});
it('should work with ad-hoc metric', () => {
......
......@@ -59,9 +59,8 @@ describe('Visualization > Pivot Table', () => {
}
beforeEach(() => {
cy.server();
cy.login();
cy.route('POST', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
it('should work with single groupby', () => {
......
......@@ -38,9 +38,8 @@ describe('Visualization > Sankey', () => {
}
beforeEach(() => {
cy.server();
cy.login();
cy.route('POST', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
it('should work', () => {
......
......@@ -37,9 +37,8 @@ describe('Visualization > Sunburst', () => {
}
beforeEach(() => {
cy.server();
cy.login();
cy.route('POST', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
it('should work without secondary metric', () => {
......
......@@ -23,11 +23,14 @@ import {
MAX_STATE,
SIMPLE_FILTER,
} from './shared.helper';
import readResponseBlob from '../../../utils/readResponseBlob';
// Table
describe('Visualization > Table', () => {
const VIZ_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'table' };
const VIZ_DEFAULTS = {
...FORM_DATA_DEFAULTS,
viz_type: 'table',
row_limit: 1000,
};
const PERCENT_METRIC = {
expressionType: 'SQL',
......@@ -41,8 +44,7 @@ describe('Visualization > Table', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.route('POST', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
it('Use default time column', () => {
......@@ -98,7 +100,7 @@ describe('Visualization > Table', () => {
});
cy.verifySliceSuccess({
waitAlias: '@getJson',
querySubstring: /groupby.*name/,
querySubstring: /group by.*name/i,
chartSelector: 'table',
});
});
......@@ -114,37 +116,34 @@ describe('Visualization > Table', () => {
});
cy.verifySliceSuccess({
waitAlias: '@getJson',
querySubstring: /groupby.*name/,
querySubstring: /group by.*name/i,
chartSelector: 'table',
});
});
it('Handle sorting correctly', () => {
// should handle sorting correctly
cy.get('.chart-container th').contains('name').click();
cy.get('.chart-container td:nth-child(2):eq(0)').contains('Aaron');
cy.get('.chart-container td:nth-child(2):eq(0)').contains('Abigail');
cy.get('.chart-container th').contains('Time').click().click();
cy.get('.chart-container td:nth-child(1):eq(0)').contains('2008');
});
it('Test table with percent metrics and groupby', () => {
const formData = {
cy.visitChartByParams({
...VIZ_DEFAULTS,
percent_metrics: PERCENT_METRIC,
metrics: [],
groupby: ['name'],
};
cy.visitChartByParams(JSON.stringify(formData));
});
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'table' });
});
it('Test table with groupby order desc', () => {
const formData = {
cy.visitChartByParams({
...VIZ_DEFAULTS,
metrics: NUM_METRIC,
groupby: ['name'],
order_desc: true,
};
cy.visitChartByParams(JSON.stringify(formData));
});
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'table' });
});
......@@ -157,37 +156,34 @@ describe('Visualization > Table', () => {
row_limit: limit,
};
cy.visitChartByParams(JSON.stringify(formData));
cy.wait('@getJson').then(async xhr => {
cy.verifyResponseCodes(xhr);
cy.wait('@getJson').then(({ response }) => {
cy.verifySliceContainer('table');
const responseBody = await readResponseBlob(xhr.response.body);
expect(responseBody.data.records.length).to.eq(limit);
expect(response?.body.data.records.length).to.eq(limit);
});
cy.get('span.label-danger').contains('10 rows');
});
it('Test table with columns and row limit', () => {
const formData = {
cy.visitChartByParams({
...VIZ_DEFAULTS,
// should still work when query_mode is not-set/invalid
query_mode: undefined,
all_columns: ['name'],
metrics: [],
row_limit: 10,
};
cy.visitChartByParams(JSON.stringify(formData));
});
// should display in raw records mode
cy.get('div[data-test="query_mode"] .btn.active').contains('Raw Records');
cy.get('div[data-test="all_columns"]').should('be.visible');
cy.get('div[data-test="groupby"]').should('not.be.visible');
cy.get('div[data-test="groupby"]').should('not.exist');
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'table' });
// should allow switch to aggregate mode
cy.get('div[data-test="query_mode"] .btn').contains('Aggregate').click();
cy.get('div[data-test="query_mode"] .btn.active').contains('Aggregate');
cy.get('div[data-test="all_columns"]').should('not.be.visible');
cy.get('div[data-test="all_columns"]').should('not.exist');
cy.get('div[data-test="groupby"]').should('be.visible');
});
......@@ -204,10 +200,9 @@ describe('Visualization > Table', () => {
};
cy.visitChartByParams(JSON.stringify(formData));
cy.wait('@getJson').then(async xhr => {
cy.verifyResponseCodes(xhr);
cy.wait('@getJson').then(({ response }) => {
cy.verifySliceContainer('table');
const responseBody = await readResponseBlob(xhr.response.body);
const responseBody = response?.body;
const { records } = responseBody.data;
expect(records[0].num).greaterThan(records[records.length - 1].num);
});
......@@ -233,7 +228,7 @@ describe('Visualization > Table', () => {
cy.visitChartByParams(JSON.stringify(formData));
cy.verifySliceSuccess({
waitAlias: '@getJson',
querySubstring: formData.groupby[0],
querySubstring: /group by.*state/i,
chartSelector: 'table',
});
cy.get('td').contains(/\d*%/);
......
......@@ -23,8 +23,7 @@ describe('Visualization > Time TableViz', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.route('POST', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
it('Test time series table multiple metrics last year total', () => {
......
......@@ -43,9 +43,8 @@ describe('Visualization > Treemap', () => {
}
beforeEach(() => {
cy.server();
cy.login();
cy.route('POST', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
it('should work', () => {
......
......@@ -40,9 +40,8 @@ describe('Visualization > World Map', () => {
}
beforeEach(() => {
cy.server();
cy.login();
cy.route('POST', '/superset/explore_json/**').as('getJson');
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
it('should work with ad-hoc metric', () => {
......
......@@ -26,7 +26,6 @@ function parseClockStr(node: JQuery) {
describe('SqlLab query panel', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.visit('/superset/sqllab');
});
......@@ -43,7 +42,7 @@ describe('SqlLab query panel', () => {
expanded_columns: [],
};
cy.route({
cy.intercept({
method: 'POST',
url: '/superset/sql_json/',
delay: 1000,
......@@ -93,8 +92,8 @@ describe('SqlLab query panel', () => {
});
it.skip('successfully saves a query', () => {
cy.route('savedqueryviewapi/**').as('getSavedQuery');
cy.route('superset/tables/**').as('getTables');
cy.intercept('savedqueryviewapi/**').as('getSavedQuery');
cy.intercept('superset/tables/**').as('getTables');
const query =
'SELECT ds, gender, name, num FROM main.birth_names ORDER BY name LIMIT 3';
......
......@@ -21,14 +21,13 @@ import { selectResultsTab } from './sqllab.helper';
describe('SqlLab datasource panel', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.visit('/superset/sqllab');
});
// TODO the test bellow is flaky, and has been disabled for the time being
// (notice the `it.skip`)
it.skip('creates a table preview when a database, schema, and table are selected', () => {
cy.route('/superset/table/**').as('tableMetadata');
cy.intercept('/superset/table/**').as('tableMetadata');
// it should have dropdowns to select database, schema, and table
cy.get('.sql-toolbar .Select').should('have.length', 3);
......
......@@ -19,7 +19,6 @@
describe('SqlLab query tabs', () => {
beforeEach(() => {
cy.login();
cy.server();
cy.visit('/superset/sqllab');
});
......
......@@ -34,14 +34,6 @@ declare namespace Cypress {
visitChartByName(name: string): cy;
visitChartById(id: number): cy;
/**
* Verify a waitXHR response and parse response JSON.
*/
verifyResponseCodes(
xhr: WaitXHR,
callback?: (result: JSONValue) => void,
): cy;
/**
* Verify slice container renders.
*/
......
......@@ -17,7 +17,6 @@
* under the License.
*/
import '@cypress/code-coverage/support';
import readResponseBlob from '../utils/readResponseBlob';
const BASE_EXPLORE_URL = '/superset/explore/?form_data=';
......@@ -55,19 +54,8 @@ Cypress.Commands.add('visitChartById', chartId =>
Cypress.Commands.add('visitChartByParams', params => {
const queryString =
typeof params === 'string' ? params : JSON.stringify(params);
return cy.visit(`${BASE_EXPLORE_URL}${queryString}`);
});
Cypress.Commands.add('verifyResponseCodes', (xhr: XMLHttpRequest, callback) => {
// After a wait response check for valid response
expect(xhr.status).to.eq(200);
readResponseBlob(xhr.response.body).then(res => {
expect(res).to.not.be.instanceOf(Error);
if (callback) {
callback(res);
}
});
return cy;
const url = `${BASE_EXPLORE_URL}${queryString}`;
return cy.visit(url);
});
Cypress.Commands.add('verifySliceContainer', chartSelector => {
......@@ -98,20 +86,19 @@ Cypress.Commands.add(
chartSelector: JQuery.Selector;
querySubstring?: string | RegExp;
}) => {
cy.wait(waitAlias).then(xhr => {
cy.wait(waitAlias).then(({ response }) => {
cy.verifySliceContainer(chartSelector);
cy.verifyResponseCodes(xhr, responseBody => {
if (querySubstring) {
const query = responseBody
? (responseBody as { query: string }).query
: '';
if (querySubstring instanceof RegExp) {
expect(query).to.match(querySubstring);
} else {
expect(query).to.contain(querySubstring);
}
const responseBody = response?.body;
if (querySubstring) {
const query = responseBody
? (responseBody as { query: string }).query
: '';
if (querySubstring instanceof RegExp) {
expect(query).to.match(querySubstring);
} else {
expect(query).to.contain(querySubstring);
}
});
}
});
return cy;
},
......
......@@ -16,17 +16,5 @@
* specific language governing permissions and limitations
* under the License.
*/
/**
* Read XHR response and parse it as JSON.
*/
export default function readResponseBlob(blob: Blob | JSONValue) {
return new Promise<ReturnType<JSON['parse']>>(resolve => {
if (blob instanceof Blob) {
const reader = new FileReader();
reader.onload = () => resolve(JSON.parse(String(reader.result || '')));
reader.readAsText(blob);
} else {
resolve(blob);
}
});
}
export * from './vizPlugins';
export { default as parsePostForm } from './parsePostForm';
/**
* 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.
*/
/**
* Parse multipart form data sent via POST requests.
*/
export default function parsePostForm(requestBody: ArrayBuffer) {
type ParsedFields = Record<string, string[] | string>;
if (requestBody.constructor.name !== 'ArrayBuffer') {
return (requestBody as unknown) as ParsedFields;
}
const lines = new TextDecoder('utf-8').decode(requestBody).split('\n');
const fields: ParsedFields = {};
let key = '';
let value: string[] = [];
function addField(key: string, value: string) {
if (key in fields) {
if (Array.isArray(fields[key])) {
(fields[key] as string[]).push(value);
} else {
fields[key] = [fields[key] as string, value];
}
} else {
fields[key] = value;
}
}
lines.forEach(line => {
const nameMatch = line.match(/Content-Disposition: form-data; name="(.*)"/);
if (nameMatch) {
if (key) {
addField(key, value.join('\n'));
}
key = nameMatch[1];
value = [];
} else if (!/----.*FormBoundary/.test(line)) {
value.push(line);
}
});
if (key && value) {
addField(key, value.join('\n'));
}
return fields;
}
......@@ -23,30 +23,42 @@ export const DASHBOARD_CHART_ALIAS_PREFIX = 'getJson_';
export function isLegacyChart(vizType: string): boolean {
return !V1_PLUGINS.includes(vizType);
}
export function isLegacyResponse(response: any): boolean {
return !response.result;
}
export function getSliceIdFromRequestUrl(url: string): string {
export function getSliceIdFromRequestUrl(url: string) {
const address = new URL(url);
const query = address.searchParams.get('form_data');
return query?.match(/\d+/)[0];
return query?.match(/\d+/)?.[0];
}
export function getChartAliases(slices: any[]): 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 = `{"slice_id":${slice.slice_id}}`;
const formData = encodeURIComponent(`{"slice_id":${slice.slice_id}}`);
if (isLegacy) {
const route = `/superset/explore_json/?*${formData}*`;
cy.route('POST', `${route}`).as(alias);
cy.intercept('POST', `${route}`).as(alias);
aliases.push(`@${alias}`);
} else {
const route = `/api/v1/chart/data?*${formData}*`;
cy.route('POST', `${route}`).as(alias);
cy.intercept('POST', `${route}`).as(alias);
aliases.push(`@${alias}`);
}
});
return aliases;
}
export function interceptChart(sliceId: number, isLegacy = true) {
const formData = { slice_id: sliceId };
const encodedFormData = encodeURIComponent(JSON.stringify(formData));
const url = isLegacy
? `**/superset/explore_json/?form_data=${encodedFormData}*`
: `**/api/v1/chart/data?form_data=${encodedFormData}*`;
return cy.intercept('POST', url);
}
......@@ -10,13 +10,13 @@
"author": "Apcahe",
"license": "Apache-2.0",
"dependencies": {
"@cypress/code-coverage": "^3.8.3",
"@cypress/code-coverage": "^3.9.2",
"rison": "^0.1.1",
"shortid": "^2.2.15"
},
"devDependencies": {
"cypress": "^5.5.0",
"eslint-plugin-cypress": "^2.11.1"
"cypress": "^6.3.0",
"eslint-plugin-cypress": "^2.11.2"
},
"nyc": {
"reporter": [
......
{
"compilerOptions": {
"baseUrl": ".",
"allowSyntheticDefaultImports": true,
"moduleResolution": "Node",
"strict": true,
"target": "ES5",
"lib": ["ES5", "ES2015", "DOM"],
"target": "es2019",
"lib": ["es2019", "DOM"],
"types": ["cypress"],
"allowJs": true,
"noEmit": true,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册