Skip to content

Commit 9f415e8

Browse files
authored
Refactor: move end-to-end test infrastructure to @grafana/toolkit (grafana#18012)
1 parent ccf11fb commit 9f415e8

23 files changed

+71
-60
lines changed

jest.config.e2e.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ module.exports = {
1111
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
1212
setupFiles: [],
1313
globals: { 'ts-jest': { isolatedModules: true } },
14-
setupFilesAfterEnv: ['expect-puppeteer', '<rootDir>/public/e2e-test/install/install.ts'],
15-
};
14+
setupFilesAfterEnv: ['expect-puppeteer', '<rootDir>/packages/grafana-toolkit/src/e2e/install.ts'],
15+
};

packages/grafana-toolkit/package.json

+8
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,17 @@
1919
},
2020
"author": "Grafana Labs",
2121
"license": "Apache-2.0",
22+
"main": "src/index.ts",
2223
"dependencies": {
2324
"@babel/core": "7.4.5",
2425
"@babel/preset-env": "7.4.5",
2526
"@types/execa": "^0.9.0",
27+
"@types/expect-puppeteer": "3.3.1",
2628
"@types/inquirer": "^6.0.3",
2729
"@types/jest": "24.0.13",
2830
"@types/jest-cli": "^23.6.0",
2931
"@types/node": "^12.0.4",
32+
"@types/puppeteer-core": "1.9.0",
3033
"@types/react-dev-utils": "^9.0.1",
3134
"@types/semver": "^6.0.0",
3235
"@types/tmp": "^0.1.0",
@@ -40,6 +43,7 @@
4043
"copy-webpack-plugin": "5.0.3",
4144
"css-loader": "^3.0.0",
4245
"execa": "^1.0.0",
46+
"expect-puppeteer": "4.1.1",
4347
"file-loader": "^4.0.0",
4448
"glob": "^7.1.4",
4549
"html-loader": "0.5.5",
@@ -57,6 +61,7 @@
5761
"postcss-loader": "3.0.0",
5862
"postcss-preset-env": "6.6.0",
5963
"prettier": "^1.18.2",
64+
"puppeteer-core": "1.18.1",
6065
"react-dev-utils": "^9.0.1",
6166
"replace-in-file": "^4.1.0",
6267
"replace-in-file-webpack-plugin": "^1.0.6",
@@ -78,5 +83,8 @@
7883
"devDependencies": {
7984
"@types/glob": "^7.1.1",
8085
"@types/prettier": "^1.16.4"
86+
},
87+
"_moduleAliases": {
88+
"puppeteer": "node_modules/puppeteer-core"
8189
}
8290
}

public/e2e-test/core/images.ts packages/grafana-toolkit/src/e2e/images.ts

+12-12
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,17 @@ export const compareScreenShots = async (fileName: string) =>
2525

2626
if (screenShotFromTest.width !== screenShotFromTruth.width) {
2727
throw new Error(
28-
`The screenshot:[${fileName}] taken during the test has a width:[${
29-
screenShotFromTest.width
30-
}] that differs from the expected: [${screenShotFromTruth.width}].`
28+
`The screenshot:[${fileName}] taken during the test has a ` +
29+
`width:[${screenShotFromTest.width}] that differs from the ` +
30+
`expected: [${screenShotFromTruth.width}].`
3131
);
3232
}
3333

3434
if (screenShotFromTest.height !== screenShotFromTruth.height) {
3535
throw new Error(
36-
`The screenshot:[${fileName}] taken during the test has a width:[${
37-
screenShotFromTest.height
38-
}] that differs from the expected: [${screenShotFromTruth.height}].`
36+
`The screenshot:[${fileName}] taken during the test has a ` +
37+
`height:[${screenShotFromTest.height}] that differs from the ` +
38+
`expected: [${screenShotFromTruth.height}].`
3939
);
4040
}
4141

@@ -50,14 +50,14 @@ export const compareScreenShots = async (fileName: string) =>
5050
);
5151

5252
if (numDiffPixels !== 0) {
53-
const localMessage = `\nCompare the output from expected:[${constants.screenShotsTruthDir}] with outcome:[${
54-
constants.screenShotsOutputDir
55-
}]`;
53+
const localMessage =
54+
`\nCompare the output from expected:[${constants.screenShotsTruthDir}] ` +
55+
`with outcome:[${constants.screenShotsOutputDir}]`;
5656
const circleCIMessage = '\nCheck the Artifacts tab in the CircleCi build output for the actual screenshots.';
5757
const checkMessage = process.env.CIRCLE_SHA1 ? circleCIMessage : localMessage;
58-
let msg = `\nThe screenshot:[${
59-
constants.screenShotsOutputDir
60-
}/${fileName}.png] taken during the test differs by:[${numDiffPixels}] pixels from the expected.`;
58+
let msg =
59+
`\nThe screenshot:[${constants.screenShotsOutputDir}/${fileName}.png] ` +
60+
`taken during the test differs by:[${numDiffPixels}] pixels from the expected.`;
6161
msg += '\n';
6262
msg += checkMessage;
6363
msg += '\n';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export * from './constants';
2+
export * from './images';
3+
export * from './install';
4+
export * from './launcher';
5+
export * from './login';
6+
export * from './pageObjects';
7+
export * from './pages';
8+
export * from './scenario';

public/e2e-test/install/install.ts packages/grafana-toolkit/src/e2e/install.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import puppeteer from 'puppeteer-core';
2-
import { constants } from 'e2e-test/core/constants';
2+
import { constants } from './constants';
33

44
export const downloadBrowserIfNeeded = async (): Promise<void> => {
55
const browserFetcher = puppeteer.createBrowserFetcher();
File renamed without changes.

public/e2e-test/core/login.ts packages/grafana-toolkit/src/e2e/login.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import { Page } from 'puppeteer-core';
22

33
import { constants } from './constants';
4-
import { loginPage } from 'e2e-test/pages/start/loginPage';
4+
import { loginPage } from './start/loginPage';
55

66
export const login = async (page: Page) => {
77
await loginPage.init(page);
88
await loginPage.navigateTo();
99

10-
await loginPage.pageObjects.username.enter('admin');
11-
await loginPage.pageObjects.password.enter('admin');
12-
await loginPage.pageObjects.submit.click();
10+
await loginPage.pageObjects!.username.enter('admin');
11+
await loginPage.pageObjects!.password.enter('admin');
12+
await loginPage.pageObjects!.submit.click();
1313
await loginPage.waitForResponse();
1414
};
1515

public/e2e-test/core/pageObjects.ts packages/grafana-toolkit/src/e2e/pageObjects.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export interface SelectPageObjectType extends PageObjectType {
2929
}
3030

3131
export class PageObject implements PageObjectType {
32-
protected page: Page = null;
32+
protected page?: Page;
3333

3434
constructor(protected selector: string) {}
3535

@@ -82,6 +82,6 @@ export class SelectPageObject extends PageObject implements SelectPageObjectType
8282
select = async (text: string): Promise<void> => {
8383
console.log(`Trying to select text:${text} in dropdown:`, this.selector);
8484
await expect(this.page).not.toBeNull();
85-
await this.page.select(this.selector, text);
85+
await this.page!.select(this.selector, text);
8686
};
8787
}

public/e2e-test/core/pages.ts packages/grafana-toolkit/src/e2e/pages.ts

+11-12
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ export interface TestPageType<T> {
1717
waitForResponse: () => Promise<void>;
1818
waitForNavigation: () => Promise<void>;
1919
waitFor: (milliseconds: number) => Promise<void>;
20-
pageObjects: PageObjects<T>;
20+
21+
pageObjects?: PageObjects<T>;
2122
}
2223

2324
type PageObjects<T> = { [P in keyof T]: T[P] };
@@ -28,17 +29,15 @@ export interface TestPageConfig<T> {
2829
}
2930

3031
export class TestPage<T> implements TestPageType<T> {
31-
pageObjects: PageObjects<T> = null;
32-
private page: Page = null;
33-
private pageUrl: string = null;
32+
pageObjects?: PageObjects<T>;
33+
private page?: Page;
34+
private pageUrl?: string;
3435

3536
constructor(config: TestPageConfig<T>) {
3637
if (config.url) {
3738
this.pageUrl = `${constants.baseUrl}${config.url}`;
3839
}
39-
if (config.pageObjects) {
40-
this.pageObjects = config.pageObjects;
41-
}
40+
this.pageObjects = config.pageObjects;
4241
}
4342

4443
init = async (page: Page): Promise<void> => {
@@ -59,7 +58,7 @@ export class TestPage<T> implements TestPageType<T> {
5958
this.throwIfNotInitialized();
6059

6160
console.log('Trying to navigate to:', this.pageUrl);
62-
await this.page.goto(this.pageUrl);
61+
await this.page!.goto(this.pageUrl!);
6362
};
6463

6564
expectSelector = async (config: ExpectSelectorConfig): Promise<void> => {
@@ -75,19 +74,19 @@ export class TestPage<T> implements TestPageType<T> {
7574
waitForResponse = async (): Promise<void> => {
7675
this.throwIfNotInitialized();
7776

78-
await this.page.waitForResponse(response => response.url() === this.pageUrl && response.status() === 200);
77+
await this.page!.waitForResponse(response => response.url() === this.pageUrl && response.status() === 200);
7978
};
8079

8180
waitForNavigation = async (): Promise<void> => {
8281
this.throwIfNotInitialized();
8382

84-
await this.page.waitForNavigation();
83+
await this.page!.waitForNavigation();
8584
};
8685

8786
getUrl = async (): Promise<string> => {
8887
this.throwIfNotInitialized();
8988

90-
return await this.page.url();
89+
return await this.page!.url();
9190
};
9291

9392
getUrlWithoutBaseUrl = async (): Promise<string> => {
@@ -101,7 +100,7 @@ export class TestPage<T> implements TestPageType<T> {
101100
waitFor = async (milliseconds: number) => {
102101
this.throwIfNotInitialized();
103102

104-
await this.page.waitFor(milliseconds);
103+
await this.page!.waitFor(milliseconds);
105104
};
106105

107106
private throwIfNotInitialized = () => {

public/e2e-test/core/scenario.ts packages/grafana-toolkit/src/e2e/scenario.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ export const e2eScenario = (
88
callback: (browser: Browser, page: Page) => void
99
) => {
1010
describe(title, () => {
11-
let browser: Browser = null;
12-
let page: Page = null;
11+
let browser: Browser;
12+
let page: Page;
1313

1414
beforeAll(async () => {
1515
browser = await launchBrowser();

public/e2e-test/pages/start/loginPage.ts packages/grafana-toolkit/src/e2e/start/loginPage.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1+
import { TestPage } from '../pages';
12
import {
2-
InputPageObject,
3-
ClickablePageObject,
43
Selector,
4+
InputPageObject,
55
InputPageObjectType,
66
ClickablePageObjectType,
7-
} from 'e2e-test/core/pageObjects';
8-
import { TestPage } from 'e2e-test/core/pages';
7+
ClickablePageObject,
8+
} from '../pageObjects';
99

1010
export interface LoginPage {
1111
username: InputPageObjectType;

packages/grafana-toolkit/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './e2e';

public/e2e-test/pages/dashboards/createDashboardPage.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { ClickablePageObjectType, ClickablePageObject, Selector } from 'e2e-test/core/pageObjects';
2-
import { TestPage } from 'e2e-test/core/pages';
1+
import { TestPage, ClickablePageObjectType, ClickablePageObject, Selector } from '@grafana/toolkit';
32

43
export interface CreateDashboardPage {
54
addQuery: ClickablePageObjectType;

public/e2e-test/pages/dashboards/dashboardsPage.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { ClickablePageObjectType, ClickablePageObject, Selector } from 'e2e-test/core/pageObjects';
2-
import { TestPage } from 'e2e-test/core/pages';
1+
import { TestPage, ClickablePageObjectType, ClickablePageObject, Selector } from '@grafana/toolkit';
32

43
export interface DashboardsPage {
54
dashboard: ClickablePageObjectType;

public/e2e-test/pages/dashboards/saveDashboardModal.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import {
2+
TestPage,
23
ClickablePageObjectType,
34
ClickablePageObject,
45
Selector,
56
InputPageObjectType,
67
InputPageObject,
78
PageObject,
8-
} from 'e2e-test/core/pageObjects';
9-
import { TestPage } from 'e2e-test/core/pages';
9+
} from '@grafana/toolkit';
1010

1111
export interface SaveDashboardModal {
1212
name: InputPageObjectType;

public/e2e-test/pages/datasources/addDataSourcePage.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { ClickablePageObject, Selector, ClickablePageObjectType } from 'e2e-test/core/pageObjects';
2-
import { TestPage } from 'e2e-test/core/pages';
1+
import { TestPage, ClickablePageObject, Selector, ClickablePageObjectType } from '@grafana/toolkit';
32

43
export interface AddDataSourcePage {
54
testDataDB: ClickablePageObjectType;

public/e2e-test/pages/datasources/dataSources.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { TestPage } from 'e2e-test/core/pages';
1+
import { TestPage } from '@grafana/toolkit';
22

33
export interface DataSourcesPage {}
44

public/e2e-test/pages/datasources/editDataSourcePage.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import {
2+
TestPage,
23
ClickablePageObjectType,
34
PageObjectType,
45
ClickablePageObject,
56
PageObject,
67
Selector,
7-
} from 'e2e-test/core/pageObjects';
8-
import { TestPage } from 'e2e-test/core/pages';
8+
} from '@grafana/toolkit';
99

1010
export interface EditDataSourcePage {
1111
saveAndTest: ClickablePageObjectType;

public/e2e-test/pages/panels/editPanel.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import {
2+
TestPage,
23
SelectPageObjectType,
34
SelectPageObject,
45
Selector,
56
ClickablePageObjectType,
67
ClickablePageObject,
7-
} from 'e2e-test/core/pageObjects';
8-
import { TestPage } from 'e2e-test/core/pages';
8+
} from '@grafana/toolkit';
99

1010
export interface EditPanelPage {
1111
queriesTab: ClickablePageObjectType;
@@ -20,7 +20,9 @@ export const editPanelPage = new TestPage<EditPanelPage>({
2020
queriesTab: new ClickablePageObject(Selector.fromAriaLabel('Queries tab button')),
2121
saveDashboard: new ClickablePageObject(Selector.fromAriaLabel('Save dashboard navbar button')),
2222
scenarioSelect: new SelectPageObject(Selector.fromAriaLabel('Scenario Select')),
23-
showXAxis: new ClickablePageObject(Selector.fromSelector('[aria-label="X-Axis section"] > gf-form-switch')),
23+
showXAxis: new ClickablePageObject(
24+
Selector.fromSelector('[aria-label="X-Axis section"] [label=Show] .gf-form-switch')
25+
),
2426
visualizationTab: new ClickablePageObject(Selector.fromAriaLabel('Visualization tab button')),
2527
},
2628
});

public/e2e-test/pages/panels/panel.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { ClickablePageObjectType, ClickablePageObject, Selector } from 'e2e-test/core/pageObjects';
2-
import { TestPage } from 'e2e-test/core/pages';
1+
import { TestPage, ClickablePageObjectType, ClickablePageObject, Selector } from '@grafana/toolkit';
32

43
export interface Panel {
54
panelTitle: ClickablePageObjectType;

public/e2e-test/pages/panels/sharePanelModal.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { ClickablePageObjectType, ClickablePageObject, Selector } from 'e2e-test/core/pageObjects';
2-
import { TestPage } from 'e2e-test/core/pages';
1+
import { TestPage, ClickablePageObjectType, ClickablePageObject, Selector } from '@grafana/toolkit';
32

43
export interface SharePanelModal {
54
directLinkRenderedImage: ClickablePageObjectType;

public/e2e-test/scenarios/smoke.test.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Browser, Page, Target } from 'puppeteer-core';
22

3-
import { e2eScenario } from 'e2e-test/core/scenario';
3+
import { e2eScenario, constants, takeScreenShot, compareScreenShots } from '@grafana/toolkit';
44
import { addDataSourcePage } from 'e2e-test/pages/datasources/addDataSourcePage';
55
import { editDataSourcePage } from 'e2e-test/pages/datasources/editDataSourcePage';
66
import { dataSourcesPage } from 'e2e-test/pages/datasources/dataSources';
@@ -9,9 +9,7 @@ import { saveDashboardModal } from 'e2e-test/pages/dashboards/saveDashboardModal
99
import { dashboardsPageFactory } from 'e2e-test/pages/dashboards/dashboardsPage';
1010
import { panel } from 'e2e-test/pages/panels/panel';
1111
import { editPanelPage } from 'e2e-test/pages/panels/editPanel';
12-
import { constants } from 'e2e-test/core/constants';
1312
import { sharePanelModal } from 'e2e-test/pages/panels/sharePanelModal';
14-
import { takeScreenShot, compareScreenShots } from 'e2e-test/core/images';
1513

1614
e2eScenario(
1715
'Login scenario, create test data source, dashboard, panel, and export scenario',

0 commit comments

Comments
 (0)