diff --git a/.circleci/config.yml b/.circleci/config.yml index 0dc313ec893..1b6c9ded369 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -125,7 +125,7 @@ jobs: - node_modules - run: name: run end-to-end tests - command: 'env BASE_URL=http://127.0.0.1:3000 yarn e2e-tests' + command: 'env BASE_URL=http://127.0.0.1:3000 yarn e2e-tests:ci' no_output_timeout: 5m - store_artifacts: path: public/e2e-tests/screenShots/theTruth @@ -133,6 +133,9 @@ jobs: - store_artifacts: path: public/e2e-tests/screenShots/theOutput destination: output-screenshots + - store_artifacts: + path: public/e2e-tests/videos + destination: output-videos - run: name: ci job failed command: './scripts/ci-job-failed.sh' @@ -164,7 +167,7 @@ jobs: - node_modules - run: name: run end-to-end tests - command: 'env BASE_URL=http://127.0.0.1:3000 yarn e2e-tests' + command: 'env BASE_URL=http://127.0.0.1:3000 yarn e2e-tests:ci' no_output_timeout: 5m - store_artifacts: path: public/e2e-tests/screenShots/theTruth @@ -172,6 +175,9 @@ jobs: - store_artifacts: path: public/e2e-tests/screenShots/theOutput destination: output-screenshots + - store_artifacts: + path: public/e2e-tests/videos + destination: output-videos - run: name: ci job failed command: './scripts/ci-job-failed.sh' diff --git a/.gitignore b/.gitignore index 65cafd94694..1005c547675 100644 --- a/.gitignore +++ b/.gitignore @@ -101,4 +101,4 @@ compilation-stats.json /packages/grafana-e2e/cypress/logs /public/e2e-test/screenShots/theOutput /public/e2e-tests/screenShots/theOutput/*.png - +public/e2e-tests/videos diff --git a/package.json b/package.json index 44ffd24a5d9..a7f7405433d 100644 --- a/package.json +++ b/package.json @@ -162,8 +162,9 @@ "typecheckPackages": "yarn workspaces run typecheck", "jest": "jest --notify --watch", "jest-ci": "mkdir -p reports/junit && export JEST_JUNIT_OUTPUT_DIR=reports/junit && jest --ci --reporters=default --reporters=jest-junit --maxWorkers 2", - "e2e": "cd packages/grafana-e2e && yarn start --env BASE_URL=$BASE_URL,CIRCLE_SHA2=$CIRCLE_SHA2,SLOWMO=$SLOWMO --record --config integrationFolder=../../public/e2e-tests/integration,screenshotsFolder=../../public/e2e-tests/screenShots,fileServerFolder=./cypress,video=false,viewportWidth=1920,viewportHeight=1080,trashAssetsBeforeRuns=false", + "e2e": "cd packages/grafana-e2e && yarn start --env BASE_URL=$BASE_URL,CIRCLE_SHA1=$CIRCLE_SHA1,SLOWMO=$SLOWMO --config integrationFolder=../../public/e2e-tests/integration,screenshotsFolder=../../public/e2e-tests/screenShots,videosFolder=../../public/e2e-tests/videos,fileServerFolder=./cypress,viewportWidth=1920,viewportHeight=1080,trashAssetsBeforeRuns=false", "e2e-tests": "yarn e2e", + "e2e-tests:ci": "yarn e2e --record", "e2e-tests:debug": "SLOWMO=1 yarn e2e --headed --no-exit", "api-tests": "jest --notify --watch --config=devenv/e2e-api-tests/jest.js", "storybook": "cd packages/grafana-ui && yarn storybook --ci", diff --git a/packages/grafana-e2e/src/flows/addDashboard.ts b/packages/grafana-e2e/src/flows/addDashboard.ts index f1e5758d369..f67f269ab24 100644 --- a/packages/grafana-e2e/src/flows/addDashboard.ts +++ b/packages/grafana-e2e/src/flows/addDashboard.ts @@ -1,21 +1,17 @@ import { e2e } from '../index'; import { Url } from '../support/url'; -export const addDashboard = async (): Promise<{ dashboardTitle: string; uid: string }> => { +export const addDashboard = () => { e2e().logToConsole('Adding dashboard'); e2e.pages.AddDashboard.visit(); const dashboardTitle = e2e.flows.saveNewDashboard(); e2e().logToConsole('Added dashboard with title:', dashboardTitle); - return new Promise(resolve => { - e2e() - .url() - .then((url: string) => { - resolve({ - dashboardTitle, - uid: Url.getDashboardUid(url), - }); - }); - }); + e2e() + .url() + .then((url: string) => { + e2e.context().set('lastAddedDashboard', dashboardTitle); + e2e.context().set('lastAddedDashboardUid', Url.getDashboardUid(url)); + }); }; diff --git a/packages/grafana-e2e/src/flows/addDataSource.ts b/packages/grafana-e2e/src/flows/addDataSource.ts index 95f863123db..713d06e09e5 100644 --- a/packages/grafana-e2e/src/flows/addDataSource.ts +++ b/packages/grafana-e2e/src/flows/addDataSource.ts @@ -16,6 +16,7 @@ export const addDataSource = (pluginName?: string): string => { e2e.pages.DataSource.alert().should('exist'); e2e.pages.DataSource.alertMessage().should('contain.text', 'Data source is working'); e2e().logToConsole('Added data source with name:', dataSourceName); + e2e.context().set('lastAddedDataSource', dataSourceName); return dataSourceName; }; diff --git a/packages/grafana-e2e/src/noTypeCheck.ts b/packages/grafana-e2e/src/noTypeCheck.ts index 1f5557f2fe7..0dd517ec2c8 100644 --- a/packages/grafana-e2e/src/noTypeCheck.ts +++ b/packages/grafana-e2e/src/noTypeCheck.ts @@ -6,6 +6,7 @@ import { e2eScenario, ScenarioArguments } from './support/scenario'; import { Pages } from './pages'; import { Flows } from './flows'; +import { scenarioContext } from './support/scenarioContext'; export type SelectorFunction = (text?: string) => Cypress.Chainable; export type SelectorObject = { @@ -19,6 +20,7 @@ const e2eObject = { blobToBase64String: (blob: any) => Cypress.Blob.blobToBase64String(blob), imgSrcToBlob: (url: string) => Cypress.Blob.imgSrcToBlob(url), scenario: (args: ScenarioArguments) => e2eScenario(args), + context: scenarioContext, pages: Pages, flows: Flows, }; diff --git a/packages/grafana-e2e/src/support/index.ts b/packages/grafana-e2e/src/support/index.ts index 74ba6812b5b..2b3cee22367 100644 --- a/packages/grafana-e2e/src/support/index.ts +++ b/packages/grafana-e2e/src/support/index.ts @@ -1,5 +1,3 @@ -import { ScenarioContext } from './scenario'; - -export { ScenarioContext }; export * from './types'; export * from './selector'; +export * from './scenarioContext'; diff --git a/packages/grafana-e2e/src/support/scenario.ts b/packages/grafana-e2e/src/support/scenario.ts index 894f1c9ff7b..fccf104a321 100644 --- a/packages/grafana-e2e/src/support/scenario.ts +++ b/packages/grafana-e2e/src/support/scenario.ts @@ -1,15 +1,9 @@ import { e2e } from '../index'; -export interface ScenarioContext { - dataSourceName?: string; - dashboardTitle?: string; - dashboardUid?: string; -} - export interface ScenarioArguments { describeName: string; itName: string; - scenario: (context: ScenarioContext) => void; + scenario: () => void; skipScenario?: boolean; addScenarioDataSource?: boolean; addScenarioDashBoard?: boolean; @@ -32,37 +26,27 @@ export const e2eScenario = ({ return; } - let scenarioDataSource: string; - let scenarioDashBoardTitle: string; - let scenarioDashBoardUid: string; - - beforeEach(async () => { + beforeEach(() => { e2e.flows.login('admin', 'admin'); if (addScenarioDataSource) { - scenarioDataSource = e2e.flows.addDataSource('TestData DB'); + e2e.flows.addDataSource('TestData DB'); } if (addScenarioDashBoard) { - const { dashboardTitle, uid } = await e2e.flows.addDashboard(); - scenarioDashBoardTitle = dashboardTitle; - scenarioDashBoardUid = uid; + e2e.flows.addDashboard(); } }); afterEach(() => { - if (scenarioDataSource) { - e2e.flows.deleteDataSource(scenarioDataSource); + if (e2e.context().get('lastAddedDataSource')) { + e2e.flows.deleteDataSource(e2e.context().get('lastAddedDataSource')); } - if (scenarioDashBoardUid) { - e2e.flows.deleteDashboard(scenarioDashBoardUid); + if (e2e.context().get('lastAddedDashboardUid')) { + e2e.flows.deleteDashboard(e2e.context().get('lastAddedDashboardUid')); } }); it(itName, () => { - scenario({ - dashboardTitle: scenarioDashBoardTitle, - dashboardUid: scenarioDashBoardUid, - dataSourceName: scenarioDataSource, - }); + scenario(); }); }); }; diff --git a/packages/grafana-e2e/src/support/scenarioContext.ts b/packages/grafana-e2e/src/support/scenarioContext.ts new file mode 100644 index 00000000000..cc8803e3802 --- /dev/null +++ b/packages/grafana-e2e/src/support/scenarioContext.ts @@ -0,0 +1,29 @@ +export interface ScenarioContext { + lastAddedDataSource: string; + lastAddedDashboard: string; + lastAddedDashboardUid: string; + [key: string]: any; +} + +const scenarioContexts: ScenarioContext = { + lastAddedDataSource: '', + lastAddedDashboard: '', + lastAddedDashboardUid: '', +}; + +export interface ScenarioContextApi { + get: (name: string | keyof ScenarioContext) => T; + set: (name: string | keyof ScenarioContext, value: T) => void; +} + +export const scenarioContext = (): ScenarioContextApi => { + const get = (name: string | keyof ScenarioContext): T => scenarioContexts[name] as T; + const set = (name: string | keyof ScenarioContext, value: T): void => { + scenarioContexts[name] = value; + }; + + return { + get, + set, + }; +}; diff --git a/public/e2e-tests/integration/smoketests.spec.ts b/public/e2e-tests/integration/smoketests.spec.ts index 6732b68496f..d9bc5210b33 100644 --- a/public/e2e-tests/integration/smoketests.spec.ts +++ b/public/e2e-tests/integration/smoketests.spec.ts @@ -1,5 +1,4 @@ import { e2e } from '@grafana/e2e'; -import { ScenarioContext } from '@grafana/e2e/src/support'; e2e.scenario({ describeName: 'Smoke tests', @@ -7,8 +6,8 @@ e2e.scenario({ addScenarioDataSource: true, addScenarioDashBoard: true, skipScenario: false, - scenario: ({ dataSourceName, dashboardTitle, dashboardUid }: ScenarioContext) => { - e2e.flows.openDashboard(dashboardUid); + scenario: () => { + e2e.flows.openDashboard(e2e.context().get('lastAddedDashboardUid')); e2e.pages.Dashboard.toolbarItems('Add panel') .should('be.visible') // prevents flakiness .click();