| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456 |
- /**
- * 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.
- */
- import '@cypress/code-coverage/support';
- import '@applitools/eyes-cypress/commands';
- import { expect } from 'chai';
- import rison from 'rison';
- /* eslint-disable @typescript-eslint/no-explicit-any */
- require('cy-verify-downloads').addCustomCommand();
- // fail on console error, allow config to override individual tests
- // these exceptions are a little pile of tech debt
- //
- // DISABLING FOR NOW
- /*
- const { getConfig, setConfig } = failOnConsoleError({
- consoleMessages: [
- /\[webpack-dev-server\]/,
- 'The pseudo class ":first-child" is potentially unsafe when doing server-side rendering. Try changing it to ":first-of-type".',
- 'The pseudo class ":nth-child" is potentially unsafe when doing server-side rendering. Try changing it to ":nth-of-type".',
- 'Error: Unknown Error',
- /Unable to infer path to ace from script src/,
- ],
- includeConsoleTypes: ['error'],
- });
- */
- // Set individual tests to allow certain console errors to NOT fail, e.g
- // cy.allowConsoleErrors(['foo', /^some bar-regex.*/]);
- // This will be reset between tests.
- Cypress.Commands.addAll({
- getConsoleMessages: () => cy.wrap(getConfig()?.consoleMessages),
- allowConsoleErrors: (consoleMessages: (string | RegExp)[]) =>
- setConfig({ ...getConfig(), consoleMessages }),
- });
- const BASE_EXPLORE_URL = '/explore/?form_data=';
- let DASHBOARD_FIXTURES: Record<string, any>[] = [];
- let CHART_FIXTURES: Record<string, any>[] = [];
- Cypress.Commands.add('loadChartFixtures', () =>
- cy.fixture('charts.json').then(charts => {
- CHART_FIXTURES = charts;
- }),
- );
- Cypress.Commands.add('loadDashboardFixtures', () =>
- cy.fixture('dashboards.json').then(dashboards => {
- DASHBOARD_FIXTURES = dashboards;
- }),
- );
- const PATHS_TO_SKIP_LOGIN = ['login', 'register'];
- const skipLogin = () => {
- for (const path of PATHS_TO_SKIP_LOGIN) {
- if (Cypress.currentTest.title.toLowerCase().includes(path)) {
- return true;
- }
- }
- return false;
- };
- before(() => {
- if (skipLogin()) {
- return;
- }
- cy.login();
- Cypress.Cookies.defaults({ preserve: 'session' });
- cy.loadChartFixtures();
- cy.loadDashboardFixtures();
- });
- beforeEach(() => {
- if (skipLogin()) {
- return;
- }
- cy.cleanDashboards();
- cy.cleanCharts();
- });
- Cypress.Commands.add('cleanDashboards', () => {
- cy.getDashboards().then((sampleDashboards?: Record<string, any>[]) => {
- const deletableDashboards = [];
- for (let i = 0; i < DASHBOARD_FIXTURES.length; i += 1) {
- const fixture = DASHBOARD_FIXTURES[i];
- const isInDb = sampleDashboards?.find(
- d => d.dashboard_title === fixture.dashboard_title,
- );
- if (isInDb) {
- deletableDashboards.push(isInDb.id);
- }
- }
- if (deletableDashboards.length) {
- cy.request({
- failOnStatusCode: false,
- method: 'DELETE',
- url: `api/v1/dashboard/?q=!(${deletableDashboards.join(',')})`,
- headers: {
- Cookie: `csrf_access_token=${window.localStorage.getItem(
- 'access_token',
- )}`,
- 'Content-Type': 'application/json',
- 'X-CSRFToken': `${window.localStorage.getItem('access_token')}`,
- Referer: `${Cypress.config().baseUrl}/`,
- },
- }).then(resp => resp);
- }
- });
- });
- Cypress.Commands.add('cleanCharts', () => {
- cy.getCharts().then((sampleCharts?: Record<string, any>[]) => {
- const deletableCharts = [];
- for (let i = 0; i < CHART_FIXTURES.length; i += 1) {
- const fixture = CHART_FIXTURES[i];
- const isInDb = sampleCharts?.find(
- c => c.slice_name === fixture.slice_name,
- );
- if (isInDb) {
- deletableCharts.push(isInDb.id);
- }
- }
- if (deletableCharts.length) {
- cy.request({
- failOnStatusCode: false,
- method: 'DELETE',
- url: `api/v1/chart/?q=!(${deletableCharts.join(',')})`,
- headers: {
- Cookie: `csrf_access_token=${window.localStorage.getItem(
- 'access_token',
- )}`,
- 'Content-Type': 'application/json',
- 'X-CSRFToken': `${window.localStorage.getItem('access_token')}`,
- Referer: `${Cypress.config().baseUrl}/`,
- },
- }).then(resp => resp);
- }
- });
- });
- Cypress.Commands.add('getBySel', (selector, ...args) =>
- cy.get(`[data-test=${selector}]`, ...args),
- );
- Cypress.Commands.add('getBySelLike', (selector, ...args) =>
- cy.get(`[data-test*=${selector}]`, ...args),
- );
- /* eslint-disable consistent-return */
- Cypress.on('uncaught:exception', err => {
- // ignore ResizeObserver client errors, as they are unrelated to operation
- // and causing flaky test failures in CI
- if (err.message && /ResizeObserver loop limit exceeded/.test(err.message)) {
- // returning false here prevents Cypress from failing the test
- return false;
- }
- return false; // TODO:@geido remove
- });
- /* eslint-enable consistent-return */
- Cypress.Commands.add('login', () => {
- cy.request({
- method: 'POST',
- url: '/login/',
- body: { username: 'admin', password: 'general' },
- }).then(response => {
- if (response.status === 302) {
- // If there's a redirect, follow it manually
- const redirectUrl = response.headers.location;
- cy.request({
- method: 'GET',
- url: redirectUrl,
- }).then(finalResponse => {
- expect(finalResponse.status).to.eq(200);
- });
- } else {
- expect(response.status).to.eq(200);
- }
- });
- });
- Cypress.Commands.add('visitChartByName', name => {
- const query = rison.encode({
- columns: ['id'],
- filters: [{ col: 'slice_name', opr: 'eq', value: name }],
- });
- cy.request(`/api/v1/chart?q=${query}`).then(response => {
- cy.visit(`${BASE_EXPLORE_URL}{"slice_id": ${response.body.result[0].id}}`);
- });
- });
- Cypress.Commands.add('visitChartById', chartId =>
- cy.visit(`${BASE_EXPLORE_URL}{"slice_id": ${chartId}}`),
- );
- Cypress.Commands.add(
- 'visitChartByParams',
- (formData: {
- datasource?: string;
- datasource_id?: number;
- datasource_type?: string;
- [key: string]: unknown;
- }) => {
- let datasource_id;
- let datasource_type;
- if (formData.datasource_id && formData.datasource_type) {
- ({ datasource_id, datasource_type } = formData);
- } else {
- [datasource_id, datasource_type] = formData.datasource?.split('__') || [];
- }
- const accessToken = window.localStorage.getItem('access_token');
- cy.request({
- method: 'POST',
- url: 'api/v1/explore/form_data',
- body: {
- datasource_id,
- datasource_type,
- form_data: JSON.stringify(formData),
- },
- headers: {
- ...(accessToken && {
- Cookie: `csrf_access_token=${accessToken}`,
- 'X-CSRFToken': accessToken,
- }),
- 'Content-Type': 'application/json',
- Referer: `${Cypress.config().baseUrl}/`,
- },
- }).then(response => {
- const formDataKey = response.body.key;
- const url = `/explore/?form_data_key=${formDataKey}`;
- cy.visit(url);
- });
- },
- );
- Cypress.Commands.add('verifySliceContainer', chartSelector => {
- // After a wait response check for valid slice container
- cy.get('.slice_container')
- .should('be.visible')
- .within(() => {
- if (chartSelector) {
- cy.get(chartSelector)
- .should('be.visible')
- .then(chart => {
- expect(chart[0].clientWidth).greaterThan(0);
- expect(chart[0].clientHeight).greaterThan(0);
- });
- }
- });
- return cy;
- });
- Cypress.Commands.add(
- 'verifySliceSuccess',
- ({
- waitAlias,
- querySubstring,
- chartSelector,
- }: {
- waitAlias: string;
- chartSelector: JQuery.Selector;
- querySubstring?: string | RegExp;
- }) => {
- cy.wait(waitAlias).then(({ response }) => {
- cy.verifySliceContainer(chartSelector);
- const responseBody = response?.body;
- if (querySubstring) {
- const query: string =
- responseBody.query || responseBody.result[0].query || '';
- if (querySubstring instanceof RegExp) {
- expect(query).to.match(querySubstring);
- } else {
- expect(query).to.contain(querySubstring);
- }
- }
- });
- return cy;
- },
- );
- Cypress.Commands.add('createSampleDashboards', (indexes?: number[]) =>
- cy.cleanDashboards().then(() => {
- for (let i = 0; i < DASHBOARD_FIXTURES.length; i += 1) {
- if (indexes?.includes(i) || !indexes) {
- cy.request({
- method: 'POST',
- url: `/api/v1/dashboard/`,
- body: DASHBOARD_FIXTURES[i],
- failOnStatusCode: false,
- headers: {
- Cookie: `csrf_access_token=${window.localStorage.getItem(
- 'access_token',
- )}`,
- 'Content-Type': 'application/json',
- 'X-CSRFToken': `${window.localStorage.getItem('access_token')}`,
- Referer: `${Cypress.config().baseUrl}/`,
- },
- });
- }
- }
- }),
- );
- Cypress.Commands.add('createSampleCharts', (indexes?: number[]) =>
- cy.cleanCharts().then(() => {
- for (let i = 0; i < CHART_FIXTURES.length; i += 1) {
- if (indexes?.includes(i) || !indexes) {
- cy.request({
- method: 'POST',
- url: `/api/v1/chart/`,
- body: CHART_FIXTURES[i],
- failOnStatusCode: false,
- headers: {
- Cookie: `csrf_access_token=${window.localStorage.getItem(
- 'access_token',
- )}`,
- 'Content-Type': 'application/json',
- 'X-CSRFToken': `${window.localStorage.getItem('access_token')}`,
- Referer: `${Cypress.config().baseUrl}/`,
- },
- });
- }
- }
- }),
- );
- Cypress.Commands.add(
- 'deleteDashboardByName',
- (dashboardName: string, failOnStatusCode = false) =>
- cy.getDashboards().then((sampleDashboards?: Record<string, any>[]) => {
- const dashboard = sampleDashboards?.find(
- d => d.dashboard_title === dashboardName,
- );
- if (dashboard) {
- cy.deleteDashboard(dashboard.id, failOnStatusCode);
- }
- }),
- );
- Cypress.Commands.add(
- 'deleteDashboard',
- (id: number, failOnStatusCode = false) =>
- cy
- .request({
- failOnStatusCode,
- method: 'DELETE',
- url: `api/v1/dashboard/${id}`,
- headers: {
- Cookie: `csrf_access_token=${window.localStorage.getItem(
- 'access_token',
- )}`,
- 'Content-Type': 'application/json',
- 'X-CSRFToken': `${window.localStorage.getItem('access_token')}`,
- Referer: `${Cypress.config().baseUrl}/`,
- },
- })
- .then(resp => resp),
- );
- Cypress.Commands.add('getDashboards', () => {
- cy.request({
- method: 'GET',
- url: `api/v1/dashboard/`,
- headers: {
- 'Content-Type': 'application/json',
- },
- }).then(resp => resp.body.result);
- });
- Cypress.Commands.add('getDashboard', (dashboardId: string | number) =>
- cy
- .request({
- method: 'GET',
- url: `api/v1/dashboard/${dashboardId}`,
- headers: {
- 'Content-Type': 'application/json',
- },
- })
- .then(resp => resp.body.result),
- );
- Cypress.Commands.add(
- 'updateDashboard',
- (dashboardId: number, body: Record<string, any>) =>
- cy
- .request({
- method: 'PUT',
- url: `api/v1/dashboard/${dashboardId}`,
- body,
- headers: {
- 'Content-Type': 'application/json',
- },
- })
- .then(resp => resp.body.result),
- );
- Cypress.Commands.add('deleteChart', (id: number, failOnStatusCode = false) =>
- cy
- .request({
- failOnStatusCode,
- method: 'DELETE',
- url: `api/v1/chart/${id}`,
- headers: {
- Cookie: `csrf_access_token=${window.localStorage.getItem(
- 'access_token',
- )}`,
- 'Content-Type': 'application/json',
- 'X-CSRFToken': `${window.localStorage.getItem('access_token')}`,
- Referer: `${Cypress.config().baseUrl}/`,
- },
- })
- .then(resp => resp),
- );
- Cypress.Commands.add('getCharts', () =>
- cy
- .request({
- method: 'GET',
- url: `api/v1/chart/`,
- headers: {
- 'Content-Type': 'application/json',
- },
- })
- .then(resp => resp.body.result),
- );
- Cypress.Commands.add(
- 'deleteChartByName',
- (sliceName: string, failOnStatusCode = false) =>
- cy.getCharts().then((sampleCharts?: Record<string, any>[]) => {
- const chart = sampleCharts?.find(c => c.slice_name === sliceName);
- if (chart) {
- cy.deleteChart(chart.id, failOnStatusCode);
- }
- }),
- );
|