e2e: Uses should on first element after visit to prevent flakiness (#21077)

This commit is contained in:
Hugo Häggmark 2019-12-13 08:39:12 +01:00 committed by GitHub
parent 1aa39ee458
commit e96f962076
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 37 additions and 12 deletions

View File

@ -4,7 +4,10 @@ export const addDataSource = (pluginName?: string): string => {
pluginName = pluginName || 'TestData DB'; pluginName = pluginName || 'TestData DB';
e2e().logToConsole('Adding data source with pluginName:', pluginName); e2e().logToConsole('Adding data source with pluginName:', pluginName);
e2e.pages.AddDataSource.visit(); e2e.pages.AddDataSource.visit();
e2e.pages.AddDataSource.dataSourcePlugins(pluginName).click(); e2e.pages.AddDataSource.dataSourcePlugins(pluginName)
.scrollIntoView()
.should('be.visible') // prevents flakiness
.click();
const dataSourceName = `e2e-${new Date().getTime()}`; const dataSourceName = `e2e-${new Date().getTime()}`;
e2e.pages.DataSource.name().clear(); e2e.pages.DataSource.name().clear();

View File

@ -3,7 +3,9 @@ import { e2e } from '../index';
export const login = (username: string, password: string) => { export const login = (username: string, password: string) => {
e2e().logToConsole('Trying to login with:', { username, password }); e2e().logToConsole('Trying to login with:', { username, password });
e2e.pages.Login.visit(); e2e.pages.Login.visit();
e2e.pages.Login.username().type(username); e2e.pages.Login.username()
.should('be.visible') // prevents flakiness
.type(username);
e2e.pages.Login.password().type(password); e2e.pages.Login.password().type(password);
e2e.pages.Login.submit().click(); e2e.pages.Login.submit().click();
e2e().logToConsole('Logged in with', { username, password }); e2e().logToConsole('Logged in with', { username, password });

View File

@ -1,6 +1,5 @@
import { e2e } from '../index'; import { e2e } from '../index';
export const openDashboard = (dashboardTitle: string) => { export const openDashboard = (dashboardUid: string) => {
e2e.pages.Dashboards.visit(); e2e.pages.Dashboard.visit(dashboardUid);
e2e.pages.Dashboards.dashboards(dashboardTitle).click();
}; };

View File

@ -9,7 +9,7 @@ import { Flows } from './flows';
export type SelectorFunction = (text?: string) => Cypress.Chainable<any>; export type SelectorFunction = (text?: string) => Cypress.Chainable<any>;
export type SelectorObject<S> = { export type SelectorObject<S> = {
visit: () => Cypress.Chainable<any>; visit: (args?: string) => Cypress.Chainable<any>;
selectors: S; selectors: S;
}; };

View File

@ -1,7 +1,7 @@
import { pageFactory } from '../support'; import { pageFactory } from '../support';
export const Dashboard = pageFactory({ export const Dashboard = pageFactory({
url: '', url: (uid: string) => `/d/${uid}`,
selectors: { selectors: {
toolbarItems: (button: string) => `Dashboard navigation bar button ${button}`, toolbarItems: (button: string) => `Dashboard navigation bar button ${button}`,
backArrow: 'Dashboard settings Go Back button', backArrow: 'Dashboard settings Go Back button',

View File

@ -7,12 +7,28 @@ export type Selectors = Record<string, string | Function>;
export type PageObjects<S> = { [P in keyof S]: SelectorFunction }; export type PageObjects<S> = { [P in keyof S]: SelectorFunction };
export type PageFactory<S> = PageObjects<S> & SelectorObject<S>; export type PageFactory<S> = PageObjects<S> & SelectorObject<S>;
export interface PageFactoryArgs<S extends Selectors> { export interface PageFactoryArgs<S extends Selectors> {
url?: string; url?: string | Function;
selectors: S; selectors: S;
} }
export const pageFactory = <S extends Selectors>({ url, selectors }: PageFactoryArgs<S>): PageFactory<S> => { export const pageFactory = <S extends Selectors>({ url, selectors }: PageFactoryArgs<S>): PageFactory<S> => {
const visit = () => e2e().visit(Url.fromBaseUrl(url)); const visit = (args?: string) => {
if (!url) {
return e2e().visit('');
}
let parsedUrl = '';
if (typeof url === 'string') {
parsedUrl = Url.fromBaseUrl(url);
}
if (typeof url === 'function' && args) {
parsedUrl = Url.fromBaseUrl(url(args));
}
e2e().logToConsole('Visiting', parsedUrl);
return e2e().visit(parsedUrl);
};
const pageObjects: PageObjects<S> = {} as PageObjects<S>; const pageObjects: PageObjects<S> = {} as PageObjects<S>;
const keys = Object.keys(selectors); const keys = Object.keys(selectors);

View File

@ -8,8 +8,10 @@ e2e.scenario({
addScenarioDashBoard: true, addScenarioDashBoard: true,
skipScenario: false, skipScenario: false,
scenario: ({ dataSourceName, dashboardTitle, dashboardUid }: ScenarioContext) => { scenario: ({ dataSourceName, dashboardTitle, dashboardUid }: ScenarioContext) => {
e2e.flows.openDashboard(dashboardTitle); e2e.flows.openDashboard(dashboardUid);
e2e.pages.Dashboard.toolbarItems('Add panel').click(); e2e.pages.Dashboard.toolbarItems('Add panel')
.should('be.visible') // prevents flakiness
.click();
e2e.pages.AddDashboard.ctaButtons('Add Query').click(); e2e.pages.AddDashboard.ctaButtons('Add Query').click();
e2e.pages.Panels.EditPanel.tabItems('Queries').click(); e2e.pages.Panels.EditPanel.tabItems('Queries').click();

View File

@ -1,4 +1,7 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"include": ["**/*.ts"] "compilerOptions": {
"types": ["cypress"]
},
"include": ["**/*.ts", "../../packages/grafana-e2e/cypress/support/index.d.ts"]
} }