Skip to content

Commit 664cb5f

Browse files
authored
e2e: Adds ScenarioContext and video recordings to e2e (grafana#21110)
* Refactor: Adds ScenarioContext * Refactor: Removes async * Refactor: Adds video and reverts CIRCLE_SHA2 to CIRCLE_SHA1 * Refactor: Adds videos to release job as well
1 parent fcc74ad commit 664cb5f

File tree

10 files changed

+62
-46
lines changed

10 files changed

+62
-46
lines changed

.circleci/config.yml

+8-2
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,17 @@ jobs:
125125
- node_modules
126126
- run:
127127
name: run end-to-end tests
128-
command: 'env BASE_URL=http://127.0.0.1:3000 yarn e2e-tests'
128+
command: 'env BASE_URL=http://127.0.0.1:3000 yarn e2e-tests:ci'
129129
no_output_timeout: 5m
130130
- store_artifacts:
131131
path: public/e2e-tests/screenShots/theTruth
132132
destination: expected-screenshots
133133
- store_artifacts:
134134
path: public/e2e-tests/screenShots/theOutput
135135
destination: output-screenshots
136+
- store_artifacts:
137+
path: public/e2e-tests/videos
138+
destination: output-videos
136139
- run:
137140
name: ci job failed
138141
command: './scripts/ci-job-failed.sh'
@@ -164,14 +167,17 @@ jobs:
164167
- node_modules
165168
- run:
166169
name: run end-to-end tests
167-
command: 'env BASE_URL=http://127.0.0.1:3000 yarn e2e-tests'
170+
command: 'env BASE_URL=http://127.0.0.1:3000 yarn e2e-tests:ci'
168171
no_output_timeout: 5m
169172
- store_artifacts:
170173
path: public/e2e-tests/screenShots/theTruth
171174
destination: expected-screenshots
172175
- store_artifacts:
173176
path: public/e2e-tests/screenShots/theOutput
174177
destination: output-screenshots
178+
- store_artifacts:
179+
path: public/e2e-tests/videos
180+
destination: output-videos
175181
- run:
176182
name: ci job failed
177183
command: './scripts/ci-job-failed.sh'

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,4 @@ compilation-stats.json
101101
/packages/grafana-e2e/cypress/logs
102102
/public/e2e-test/screenShots/theOutput
103103
/public/e2e-tests/screenShots/theOutput/*.png
104-
104+
public/e2e-tests/videos

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,9 @@
162162
"typecheckPackages": "yarn workspaces run typecheck",
163163
"jest": "jest --notify --watch",
164164
"jest-ci": "mkdir -p reports/junit && export JEST_JUNIT_OUTPUT_DIR=reports/junit && jest --ci --reporters=default --reporters=jest-junit --maxWorkers 2",
165-
"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",
165+
"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",
166166
"e2e-tests": "yarn e2e",
167+
"e2e-tests:ci": "yarn e2e --record",
167168
"e2e-tests:debug": "SLOWMO=1 yarn e2e --headed --no-exit",
168169
"api-tests": "jest --notify --watch --config=devenv/e2e-api-tests/jest.js",
169170
"storybook": "cd packages/grafana-ui && yarn storybook --ci",
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
import { e2e } from '../index';
22
import { Url } from '../support/url';
33

4-
export const addDashboard = async (): Promise<{ dashboardTitle: string; uid: string }> => {
4+
export const addDashboard = () => {
55
e2e().logToConsole('Adding dashboard');
66
e2e.pages.AddDashboard.visit();
77

88
const dashboardTitle = e2e.flows.saveNewDashboard();
99
e2e().logToConsole('Added dashboard with title:', dashboardTitle);
1010

11-
return new Promise(resolve => {
12-
e2e()
13-
.url()
14-
.then((url: string) => {
15-
resolve({
16-
dashboardTitle,
17-
uid: Url.getDashboardUid(url),
18-
});
19-
});
20-
});
11+
e2e()
12+
.url()
13+
.then((url: string) => {
14+
e2e.context().set('lastAddedDashboard', dashboardTitle);
15+
e2e.context().set('lastAddedDashboardUid', Url.getDashboardUid(url));
16+
});
2117
};

packages/grafana-e2e/src/flows/addDataSource.ts

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const addDataSource = (pluginName?: string): string => {
1616
e2e.pages.DataSource.alert().should('exist');
1717
e2e.pages.DataSource.alertMessage().should('contain.text', 'Data source is working');
1818
e2e().logToConsole('Added data source with name:', dataSourceName);
19+
e2e.context().set('lastAddedDataSource', dataSourceName);
1920

2021
return dataSourceName;
2122
};

packages/grafana-e2e/src/noTypeCheck.ts

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import { e2eScenario, ScenarioArguments } from './support/scenario';
77
import { Pages } from './pages';
88
import { Flows } from './flows';
9+
import { scenarioContext } from './support/scenarioContext';
910

1011
export type SelectorFunction = (text?: string) => Cypress.Chainable<any>;
1112
export type SelectorObject<S> = {
@@ -19,6 +20,7 @@ const e2eObject = {
1920
blobToBase64String: (blob: any) => Cypress.Blob.blobToBase64String(blob),
2021
imgSrcToBlob: (url: string) => Cypress.Blob.imgSrcToBlob(url),
2122
scenario: (args: ScenarioArguments) => e2eScenario(args),
23+
context: scenarioContext,
2224
pages: Pages,
2325
flows: Flows,
2426
};
+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { ScenarioContext } from './scenario';
2-
3-
export { ScenarioContext };
41
export * from './types';
52
export * from './selector';
3+
export * from './scenarioContext';
+9-25
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
11
import { e2e } from '../index';
22

3-
export interface ScenarioContext {
4-
dataSourceName?: string;
5-
dashboardTitle?: string;
6-
dashboardUid?: string;
7-
}
8-
93
export interface ScenarioArguments {
104
describeName: string;
115
itName: string;
12-
scenario: (context: ScenarioContext) => void;
6+
scenario: () => void;
137
skipScenario?: boolean;
148
addScenarioDataSource?: boolean;
159
addScenarioDashBoard?: boolean;
@@ -32,37 +26,27 @@ export const e2eScenario = ({
3226
return;
3327
}
3428

35-
let scenarioDataSource: string;
36-
let scenarioDashBoardTitle: string;
37-
let scenarioDashBoardUid: string;
38-
39-
beforeEach(async () => {
29+
beforeEach(() => {
4030
e2e.flows.login('admin', 'admin');
4131
if (addScenarioDataSource) {
42-
scenarioDataSource = e2e.flows.addDataSource('TestData DB');
32+
e2e.flows.addDataSource('TestData DB');
4333
}
4434
if (addScenarioDashBoard) {
45-
const { dashboardTitle, uid } = await e2e.flows.addDashboard();
46-
scenarioDashBoardTitle = dashboardTitle;
47-
scenarioDashBoardUid = uid;
35+
e2e.flows.addDashboard();
4836
}
4937
});
5038

5139
afterEach(() => {
52-
if (scenarioDataSource) {
53-
e2e.flows.deleteDataSource(scenarioDataSource);
40+
if (e2e.context().get('lastAddedDataSource')) {
41+
e2e.flows.deleteDataSource(e2e.context().get('lastAddedDataSource'));
5442
}
55-
if (scenarioDashBoardUid) {
56-
e2e.flows.deleteDashboard(scenarioDashBoardUid);
43+
if (e2e.context().get('lastAddedDashboardUid')) {
44+
e2e.flows.deleteDashboard(e2e.context().get('lastAddedDashboardUid'));
5745
}
5846
});
5947

6048
it(itName, () => {
61-
scenario({
62-
dashboardTitle: scenarioDashBoardTitle,
63-
dashboardUid: scenarioDashBoardUid,
64-
dataSourceName: scenarioDataSource,
65-
});
49+
scenario();
6650
});
6751
});
6852
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
export interface ScenarioContext {
2+
lastAddedDataSource: string;
3+
lastAddedDashboard: string;
4+
lastAddedDashboardUid: string;
5+
[key: string]: any;
6+
}
7+
8+
const scenarioContexts: ScenarioContext = {
9+
lastAddedDataSource: '',
10+
lastAddedDashboard: '',
11+
lastAddedDashboardUid: '',
12+
};
13+
14+
export interface ScenarioContextApi {
15+
get: <T>(name: string | keyof ScenarioContext) => T;
16+
set: <T>(name: string | keyof ScenarioContext, value: T) => void;
17+
}
18+
19+
export const scenarioContext = (): ScenarioContextApi => {
20+
const get = <T>(name: string | keyof ScenarioContext): T => scenarioContexts[name] as T;
21+
const set = <T>(name: string | keyof ScenarioContext, value: T): void => {
22+
scenarioContexts[name] = value;
23+
};
24+
25+
return {
26+
get,
27+
set,
28+
};
29+
};

public/e2e-tests/integration/smoketests.spec.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { e2e } from '@grafana/e2e';
2-
import { ScenarioContext } from '@grafana/e2e/src/support';
32

43
e2e.scenario({
54
describeName: 'Smoke tests',
65
itName: 'Login scenario, create test data source, dashboard, panel, and export scenario',
76
addScenarioDataSource: true,
87
addScenarioDashBoard: true,
98
skipScenario: false,
10-
scenario: ({ dataSourceName, dashboardTitle, dashboardUid }: ScenarioContext) => {
11-
e2e.flows.openDashboard(dashboardUid);
9+
scenario: () => {
10+
e2e.flows.openDashboard(e2e.context().get('lastAddedDashboardUid'));
1211
e2e.pages.Dashboard.toolbarItems('Add panel')
1312
.should('be.visible') // prevents flakiness
1413
.click();

0 commit comments

Comments
 (0)