E2E: Adds tests for QueryVariable CRUD (#20448)
* WIP: Adds basic template variables CRUD start * e2eTests: Adds aria-labels in VariableEditorCtrl * Refactor: Simplifies a bit * e2eTests: Adds first Template Variable CRUD for QueryVariable * Tests: Adds ArrayPageOjbectType * Tests: Adds createQueryVariable method * Tests: Refactor CRUD test * Tests: Adds datasource and dashboard to scenario * Refactor: Fixes type errors * Refactor: Move pages to toolkit
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { Page } from 'puppeteer-core';
|
||||
import { constants } from './constants';
|
||||
import { PageObject } from './pageObjects';
|
||||
import { PageObject, Selector } from './pageObjects';
|
||||
|
||||
export interface ExpectSelectorConfig {
|
||||
selector: string;
|
||||
@@ -22,22 +22,34 @@ export interface TestPageType<T> {
|
||||
}
|
||||
|
||||
type PageObjects<T> = { [P in keyof T]: T[P] };
|
||||
type SelectorFunc = () => string;
|
||||
|
||||
export interface TestPageConfig<T> {
|
||||
url?: string;
|
||||
pageObjects: PageObjects<T>;
|
||||
pageObjects: { [P in keyof T]: string | SelectorFunc };
|
||||
}
|
||||
|
||||
export class TestPage<T> implements TestPageType<T> {
|
||||
pageObjects: PageObjects<T>;
|
||||
private page?: Page;
|
||||
private pageUrl?: string;
|
||||
private readonly pageUrl?: string;
|
||||
|
||||
constructor(config: TestPageConfig<T>) {
|
||||
if (config.url) {
|
||||
this.pageUrl = `${constants.baseUrl}${config.url}`;
|
||||
}
|
||||
this.pageObjects = config.pageObjects;
|
||||
|
||||
this.pageObjects = {} as PageObjects<T>;
|
||||
Object.keys(config.pageObjects).map(async key => {
|
||||
const selector = (config.pageObjects as any)[key];
|
||||
if (typeof selector === 'function') {
|
||||
(this.pageObjects as any)[key] = new PageObject(selector());
|
||||
}
|
||||
|
||||
if (typeof selector === 'string') {
|
||||
(this.pageObjects as any)[key] = new PageObject(Selector.fromAriaLabel(selector));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
init = async (page: Page): Promise<void> => {
|
||||
|
||||
@@ -5,6 +5,10 @@ export class Selector {
|
||||
return `[aria-label="${selector}"]`;
|
||||
};
|
||||
|
||||
static fromSwitchLabel = (selector: string) => {
|
||||
return `${Selector.fromAriaLabel(selector)} .gf-form-switch input`;
|
||||
};
|
||||
|
||||
static fromSelector = (selector: string) => {
|
||||
return selector;
|
||||
};
|
||||
@@ -14,6 +18,7 @@ export interface PageObjectType {
|
||||
init: (page: Page) => Promise<void>;
|
||||
exists: () => Promise<void>;
|
||||
containsText: (text: string) => Promise<void>;
|
||||
waitForSelector: (timeoutInMs?: number) => Promise<void>;
|
||||
}
|
||||
|
||||
export interface ClickablePageObjectType extends PageObjectType {
|
||||
@@ -22,13 +27,36 @@ export interface ClickablePageObjectType extends PageObjectType {
|
||||
|
||||
export interface InputPageObjectType extends PageObjectType {
|
||||
enter: (text: string) => Promise<void>;
|
||||
containsPlaceholder: (text: string) => Promise<void>;
|
||||
blur: () => Promise<void>;
|
||||
}
|
||||
|
||||
export interface SelectPageObjectType extends PageObjectType {
|
||||
select: (text: string) => Promise<void>;
|
||||
selectedTextIs: (text: string) => Promise<void>;
|
||||
}
|
||||
|
||||
export class PageObject implements PageObjectType {
|
||||
export interface SwitchPageObjectType extends PageObjectType {
|
||||
toggle: () => Promise<void>;
|
||||
isSwitchedOn: () => Promise<void>;
|
||||
isSwitchedOff: () => Promise<void>;
|
||||
}
|
||||
|
||||
export interface ArrayPageObjectType {
|
||||
hasLength: (length: number) => Promise<void>;
|
||||
clickAtPos: (index: number) => Promise<void>;
|
||||
containsTextAtPos: (text: string, index: number) => Promise<void>;
|
||||
waitForSelector: (timeoutInMs?: number) => Promise<void>;
|
||||
}
|
||||
|
||||
export class PageObject
|
||||
implements
|
||||
PageObjectType,
|
||||
ClickablePageObjectType,
|
||||
InputPageObjectType,
|
||||
SelectPageObjectType,
|
||||
SwitchPageObjectType,
|
||||
ArrayPageObjectType {
|
||||
protected page?: Page;
|
||||
|
||||
constructor(protected selector: string) {}
|
||||
@@ -38,50 +66,109 @@ export class PageObject implements PageObjectType {
|
||||
};
|
||||
|
||||
exists = async (): Promise<void> => {
|
||||
console.log('Checking for existence of:', this.selector);
|
||||
const options = { visible: true } as any;
|
||||
await expect(this.page).not.toBeNull();
|
||||
await expect(this.page).toMatchElement(this.selector, options);
|
||||
};
|
||||
|
||||
containsText = async (text: string): Promise<void> => {
|
||||
console.log(`Checking for existence of '${text}' for:`, this.selector);
|
||||
const options = { visible: true, text } as any;
|
||||
await expect(this.page).not.toBeNull();
|
||||
await expect(this.page).toMatchElement(this.selector, options);
|
||||
};
|
||||
}
|
||||
|
||||
export class ClickablePageObject extends PageObject implements ClickablePageObjectType {
|
||||
constructor(selector: string) {
|
||||
super(selector);
|
||||
}
|
||||
containsPlaceholder = async (expectedPlaceholder: string): Promise<void> => {
|
||||
console.log(`Checking for placeholder '${expectedPlaceholder}' in:`, this.selector);
|
||||
await expect(this.page).not.toBeNull();
|
||||
const placeholder = await this.page!.$eval(this.selector, (input: any) => input.placeholder);
|
||||
await expect(placeholder).toEqual(expectedPlaceholder);
|
||||
};
|
||||
|
||||
hasLength = async (length: number): Promise<void> => {
|
||||
console.log('Checking for length of', this.selector);
|
||||
const result = await this.page!.$$eval(this.selector, elements => elements.length);
|
||||
await expect(result).toEqual(length);
|
||||
};
|
||||
|
||||
containsTextAtPos = async (text: string, index: number): Promise<void> => {
|
||||
console.log(`Checking for text ${text} at position ${index} of`, this.selector);
|
||||
await expect(this.page).not.toBeNull();
|
||||
const result = await this.page!.$$eval(this.selector, elements => elements.map((el: any) => el.innerText));
|
||||
await expect(result[index]!.trim()).toEqual(text);
|
||||
};
|
||||
|
||||
click = async (): Promise<void> => {
|
||||
console.log('Trying to click on:', this.selector);
|
||||
await expect(this.page).not.toBeNull();
|
||||
await expect(this.page).toClick(this.selector);
|
||||
};
|
||||
}
|
||||
|
||||
export class InputPageObject extends PageObject implements InputPageObjectType {
|
||||
constructor(selector: string) {
|
||||
super(selector);
|
||||
}
|
||||
clickAtPos = async (index: number): Promise<void> => {
|
||||
console.log(`Trying to clicking at position:${index} on:`, this.selector);
|
||||
await expect(this.page).not.toBeNull();
|
||||
const elements = await this.page!.$$(this.selector);
|
||||
const element = await elements[index];
|
||||
await element.click();
|
||||
};
|
||||
|
||||
toggle = async (): Promise<void> => {
|
||||
const switchSelector = this.selector.replace(' .gf-form-switch input', '');
|
||||
console.log('Trying to toggle:', switchSelector);
|
||||
await expect(this.page).not.toBeNull();
|
||||
await expect(this.page).toClick(switchSelector);
|
||||
};
|
||||
|
||||
enter = async (text: string): Promise<void> => {
|
||||
console.log(`Trying to enter text:${text} into:`, this.selector);
|
||||
await expect(this.page).not.toBeNull();
|
||||
await expect(this.page).toFill(this.selector, text);
|
||||
};
|
||||
}
|
||||
|
||||
export class SelectPageObject extends PageObject implements SelectPageObjectType {
|
||||
constructor(selector: string) {
|
||||
super(selector);
|
||||
}
|
||||
|
||||
select = async (text: string): Promise<void> => {
|
||||
console.log(`Trying to select text:${text} in dropdown:`, this.selector);
|
||||
await expect(this.page).not.toBeNull();
|
||||
await this.page!.select(this.selector, text);
|
||||
};
|
||||
|
||||
selectedTextIs = async (text: string): Promise<void> => {
|
||||
console.log(`Trying to get selected text from dropdown:`, this.selector);
|
||||
await expect(this.page).not.toBeNull();
|
||||
const selectedText = await this.page!.$eval(this.selector, (select: any) => {
|
||||
if (select.selectedIndex === -1) {
|
||||
return '';
|
||||
}
|
||||
return select.options[select.selectedIndex].innerText;
|
||||
});
|
||||
await expect(selectedText).toEqual(text);
|
||||
};
|
||||
|
||||
waitForSelector = async (timeoutInMs?: number): Promise<void> => {
|
||||
console.log('Waiting for', this.selector);
|
||||
await expect(this.page).not.toBeNull();
|
||||
await this.page!.waitForSelector(this.selector, { timeout: timeoutInMs || 1000 });
|
||||
};
|
||||
|
||||
isSwitchedOn = async (): Promise<void> => {
|
||||
const checked = await this.getChecked();
|
||||
await expect(checked).toBe(true);
|
||||
};
|
||||
|
||||
isSwitchedOff = async (): Promise<void> => {
|
||||
const checked = await this.getChecked();
|
||||
await expect(checked).toBe(false);
|
||||
};
|
||||
|
||||
blur = async (): Promise<void> => {
|
||||
console.log('Trying to blur:', this.selector);
|
||||
await expect(this.page).not.toBeNull();
|
||||
await this.page!.$eval(this.selector, (input: any) => input.blur());
|
||||
};
|
||||
|
||||
private getChecked = async (): Promise<boolean> => {
|
||||
console.log('Trying get switch status for:', this.selector);
|
||||
await expect(this.page).not.toBeNull();
|
||||
return await this.page!.$eval(this.selector, (input: any) => input.checked);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { Page } from 'puppeteer-core';
|
||||
|
||||
import { ClickablePageObjectType } from '../../pageObjects';
|
||||
import { TestPage } from '../../pageInfo';
|
||||
import { dashboardPage } from './dashboardPage';
|
||||
import { dashboardSettingsPage } from './dashboardSettingsPage';
|
||||
import { saveDashboardModal } from './saveDashboardModal';
|
||||
import { dashboardsPageFactory } from './dashboardsPage';
|
||||
import { confirmModal } from '../modals/confirmModal';
|
||||
|
||||
export interface CreateDashboardPage {
|
||||
addQuery: ClickablePageObjectType;
|
||||
saveDashboard: ClickablePageObjectType;
|
||||
}
|
||||
|
||||
export const createDashboardPage = new TestPage<CreateDashboardPage>({
|
||||
url: '/dashboard/new',
|
||||
pageObjects: {
|
||||
addQuery: 'Add Query CTA button',
|
||||
saveDashboard: 'Save dashboard navbar button',
|
||||
},
|
||||
});
|
||||
|
||||
export const createEmptyDashboardPage = async (page: Page, dashboardTitle: string) => {
|
||||
await createDashboardPage.init(page);
|
||||
await createDashboardPage.navigateTo();
|
||||
await createDashboardPage.pageObjects.saveDashboard.click();
|
||||
|
||||
await saveDashboardModal.init(page);
|
||||
await saveDashboardModal.expectSelector({ selector: 'save-dashboard-as-modal' });
|
||||
await saveDashboardModal.pageObjects.name.enter(dashboardTitle);
|
||||
await saveDashboardModal.pageObjects.save.click();
|
||||
await saveDashboardModal.pageObjects.success.exists();
|
||||
|
||||
await dashboardPage.init(page);
|
||||
return dashboardPage;
|
||||
};
|
||||
|
||||
export const cleanDashboard = async (page: Page, dashboardTitle: string) => {
|
||||
const dashboardsPage = dashboardsPageFactory(dashboardTitle);
|
||||
await dashboardsPage.init(page);
|
||||
await dashboardsPage.navigateTo();
|
||||
await dashboardsPage.pageObjects.dashboard.exists();
|
||||
await dashboardsPage.pageObjects.dashboard.click();
|
||||
|
||||
await dashboardPage.init(page);
|
||||
await dashboardPage.pageObjects.settings.click();
|
||||
|
||||
await dashboardSettingsPage.init(page);
|
||||
await dashboardSettingsPage.pageObjects.deleteDashBoard.click();
|
||||
|
||||
await confirmModal.init(page);
|
||||
await confirmModal.pageObjects.delete.click();
|
||||
await confirmModal.pageObjects.success.exists();
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
import { ArrayPageObjectType, ClickablePageObjectType, PageObjectType } from '../../pageObjects';
|
||||
import { TestPage } from '../../pageInfo';
|
||||
|
||||
export interface DashboardPage {
|
||||
settings: ClickablePageObjectType;
|
||||
submenuItemLabel: ArrayPageObjectType;
|
||||
submenuItemValueDropDownValueLink: ArrayPageObjectType;
|
||||
submenuItemValueDropDownDropDown: PageObjectType;
|
||||
submenuItemValueDropDownSelectedLink: PageObjectType;
|
||||
submenuItemValueDropDownOptionText: ArrayPageObjectType;
|
||||
}
|
||||
|
||||
export const dashboardPage = new TestPage<DashboardPage>({
|
||||
pageObjects: {
|
||||
settings: 'Dashboard settings navbar button',
|
||||
submenuItemLabel: 'Dashboard template variables submenu LabelName label',
|
||||
submenuItemValueDropDownValueLink: 'Dashboard template variables Variable Value DropDown value link',
|
||||
submenuItemValueDropDownDropDown: 'Dashboard template variables Variable Value DropDown DropDown',
|
||||
submenuItemValueDropDownSelectedLink: 'Dashboard template variables Variable Value DropDown Selected link',
|
||||
submenuItemValueDropDownOptionText: 'Dashboard template variables Variable Value DropDown option text',
|
||||
},
|
||||
});
|
||||
|
||||
export interface AssertVariableLabelsAndComponentsArguments {
|
||||
label: string;
|
||||
options: string[];
|
||||
}
|
||||
|
||||
export const assertVariableLabelsAndComponents = async (
|
||||
page: TestPage<DashboardPage>,
|
||||
args: AssertVariableLabelsAndComponentsArguments[]
|
||||
) => {
|
||||
console.log('Asserting variable components and labels');
|
||||
await page.pageObjects.submenuItemLabel.waitForSelector();
|
||||
await page.pageObjects.submenuItemLabel.hasLength(args.length);
|
||||
await page.pageObjects.submenuItemValueDropDownValueLink.hasLength(args.length);
|
||||
|
||||
for (let index = 0; index < args.length; index++) {
|
||||
const { label, options } = args[index];
|
||||
await page.pageObjects.submenuItemLabel.containsTextAtPos(label, index);
|
||||
await page.pageObjects.submenuItemValueDropDownValueLink.containsTextAtPos(options[1], index);
|
||||
await page.pageObjects.submenuItemValueDropDownValueLink.clickAtPos(index);
|
||||
await page.pageObjects.submenuItemValueDropDownOptionText.hasLength(options.length);
|
||||
for (let optionIndex = 0; optionIndex < options.length; optionIndex++) {
|
||||
await page.pageObjects.submenuItemValueDropDownOptionText.containsTextAtPos(options[optionIndex], optionIndex);
|
||||
}
|
||||
}
|
||||
console.log('Asserting variable components and labels, Ok');
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
import { ClickablePageObjectType } from '../../pageObjects';
|
||||
import { TestPage } from '../../pageInfo';
|
||||
|
||||
export interface DashboardSettingsPage {
|
||||
deleteDashBoard: ClickablePageObjectType;
|
||||
variablesSection: ClickablePageObjectType;
|
||||
saveDashBoard: ClickablePageObjectType;
|
||||
}
|
||||
|
||||
export const dashboardSettingsPage = new TestPage<DashboardSettingsPage>({
|
||||
pageObjects: {
|
||||
deleteDashBoard: 'Dashboard settings page delete dashboard button',
|
||||
variablesSection: 'Dashboard settings section Variables',
|
||||
saveDashBoard: 'Dashboard settings aside actions Save button',
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
import { ClickablePageObjectType } from '../../pageObjects';
|
||||
import { TestPage } from '../../pageInfo';
|
||||
|
||||
export interface DashboardsPage {
|
||||
dashboard: ClickablePageObjectType;
|
||||
}
|
||||
|
||||
export const dashboardsPageFactory = (dashboardTitle: string) =>
|
||||
new TestPage<DashboardsPage>({
|
||||
url: '/dashboards',
|
||||
pageObjects: {
|
||||
dashboard: dashboardTitle,
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
import { ClickablePageObjectType, PageObject, Selector } from '../../pageObjects';
|
||||
import { TestPage } from '../../pageInfo';
|
||||
|
||||
export interface SaveChangesDashboardModal {
|
||||
save: ClickablePageObjectType;
|
||||
success: PageObject;
|
||||
}
|
||||
|
||||
export const saveChangesDashboardModal = new TestPage<SaveChangesDashboardModal>({
|
||||
pageObjects: {
|
||||
save: 'Dashboard settings Save Dashboard Modal Save button',
|
||||
success: () => Selector.fromSelector('.alert-success'),
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
import { ClickablePageObjectType, InputPageObjectType, PageObject, Selector } from '../../pageObjects';
|
||||
import { TestPage } from '../../pageInfo';
|
||||
|
||||
export interface SaveDashboardModal {
|
||||
name: InputPageObjectType;
|
||||
save: ClickablePageObjectType;
|
||||
success: PageObject;
|
||||
}
|
||||
|
||||
export const saveDashboardModal = new TestPage<SaveDashboardModal>({
|
||||
pageObjects: {
|
||||
name: 'Save dashboard title field',
|
||||
save: 'Save dashboard button',
|
||||
success: () => Selector.fromSelector('.alert-success'),
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
import { ClickablePageObjectType } from '../../pageObjects';
|
||||
import { TestPage } from '../../pageInfo';
|
||||
|
||||
export interface AddDataSourcePage {
|
||||
testDataDB: ClickablePageObjectType;
|
||||
}
|
||||
|
||||
export const addDataSourcePage = new TestPage<AddDataSourcePage>({
|
||||
url: '/datasources/new',
|
||||
pageObjects: {
|
||||
testDataDB: 'TestData DB datasource plugin',
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,62 @@
|
||||
import { Page } from 'puppeteer-core';
|
||||
|
||||
import { ClickablePageObjectType } from '../../pageObjects';
|
||||
import { TestPage } from '../../pageInfo';
|
||||
import { editDataSourcePage } from './editDataSourcePage';
|
||||
import { addDataSourcePage } from './addDataSourcePage';
|
||||
import { confirmModal } from '../modals/confirmModal';
|
||||
|
||||
export interface DataSourcesPage {
|
||||
testData: ClickablePageObjectType;
|
||||
}
|
||||
|
||||
export const dataSourcesPageFactory = (testDataSourceName: string) =>
|
||||
new TestPage<DataSourcesPage>({
|
||||
url: '/datasources',
|
||||
pageObjects: {
|
||||
testData: `Data source list item for ${testDataSourceName}`,
|
||||
},
|
||||
});
|
||||
|
||||
export const addTestDataSourceAndVerify = async (page: Page) => {
|
||||
// Add TestData DB
|
||||
const testDataSourceName = `e2e - TestData-${new Date().getTime()}`;
|
||||
await addDataSourcePage.init(page);
|
||||
await addDataSourcePage.navigateTo();
|
||||
await addDataSourcePage.pageObjects.testDataDB.exists();
|
||||
await addDataSourcePage.pageObjects.testDataDB.click();
|
||||
|
||||
await editDataSourcePage.init(page);
|
||||
await editDataSourcePage.waitForNavigation();
|
||||
await editDataSourcePage.pageObjects.name.enter(testDataSourceName);
|
||||
await editDataSourcePage.pageObjects.saveAndTest.click();
|
||||
await editDataSourcePage.pageObjects.alert.exists();
|
||||
await editDataSourcePage.pageObjects.alertMessage.containsText('Data source is working');
|
||||
|
||||
// Verify that data source is listed
|
||||
const url = await editDataSourcePage.getUrlWithoutBaseUrl();
|
||||
const expectedUrl = url.substring(1, url.length - 1);
|
||||
const selector = `a[href="${expectedUrl}"]`;
|
||||
|
||||
const dataSourcesPage = dataSourcesPageFactory(testDataSourceName);
|
||||
await dataSourcesPage.init(page);
|
||||
await dataSourcesPage.navigateTo();
|
||||
await dataSourcesPage.expectSelector({ selector });
|
||||
|
||||
return testDataSourceName;
|
||||
};
|
||||
|
||||
export const cleanUpTestDataSource = async (page: Page, testDataSourceName: string) => {
|
||||
const dataSourcesPage = dataSourcesPageFactory(testDataSourceName);
|
||||
await dataSourcesPage.init(page);
|
||||
await dataSourcesPage.navigateTo();
|
||||
await dataSourcesPage.pageObjects.testData.click();
|
||||
|
||||
await editDataSourcePage.init(page);
|
||||
await editDataSourcePage.pageObjects.delete.exists();
|
||||
await editDataSourcePage.pageObjects.delete.click();
|
||||
|
||||
await confirmModal.init(page);
|
||||
await confirmModal.pageObjects.delete.click();
|
||||
await confirmModal.pageObjects.success.exists();
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
import { ClickablePageObjectType, InputPageObjectType, PageObjectType } from '../../pageObjects';
|
||||
import { TestPage } from '../../pageInfo';
|
||||
|
||||
export interface EditDataSourcePage {
|
||||
name: InputPageObjectType;
|
||||
delete: ClickablePageObjectType;
|
||||
saveAndTest: ClickablePageObjectType;
|
||||
alert: PageObjectType;
|
||||
alertMessage: PageObjectType;
|
||||
}
|
||||
|
||||
export const editDataSourcePage = new TestPage<EditDataSourcePage>({
|
||||
pageObjects: {
|
||||
name: 'Datasource settings page name input field',
|
||||
delete: 'Delete button',
|
||||
saveAndTest: 'Save and Test button',
|
||||
alert: 'Datasource settings page Alert',
|
||||
alertMessage: 'Datasource settings page Alert message',
|
||||
},
|
||||
});
|
||||
@@ -1,2 +1,12 @@
|
||||
export * from './loginPage';
|
||||
export * from './pluginsPage';
|
||||
export * from './dashboards/createDashboardPage';
|
||||
export * from './dashboards/dashboardPage';
|
||||
export * from './dashboards/dashboardSettingsPage';
|
||||
export * from './dashboards/dashboardsPage';
|
||||
export * from './dashboards/saveChangesDashboardModal';
|
||||
export * from './dashboards/saveDashboardModal';
|
||||
export * from './datasources/addDataSourcePage';
|
||||
export * from './datasources/dataSources';
|
||||
export * from './datasources/editDataSourcePage';
|
||||
export * from './modals/confirmModal';
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
import { TestPage } from '../pageInfo';
|
||||
import {
|
||||
Selector,
|
||||
InputPageObject,
|
||||
InputPageObjectType,
|
||||
ClickablePageObjectType,
|
||||
ClickablePageObject,
|
||||
} from '../pageObjects';
|
||||
import { ClickablePageObjectType, InputPageObjectType } from '../pageObjects';
|
||||
|
||||
export interface LoginPage {
|
||||
username: InputPageObjectType;
|
||||
@@ -16,8 +10,8 @@ export interface LoginPage {
|
||||
export const loginPage = new TestPage<LoginPage>({
|
||||
url: '/login',
|
||||
pageObjects: {
|
||||
username: new InputPageObject(Selector.fromAriaLabel('Username input field')),
|
||||
password: new InputPageObject(Selector.fromAriaLabel('Password input field')),
|
||||
submit: new ClickablePageObject(Selector.fromAriaLabel('Login button')),
|
||||
username: 'Username input field',
|
||||
password: 'Password input field',
|
||||
submit: 'Login button',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { ClickablePageObjectType, PageObject, Selector } from '../../pageObjects';
|
||||
import { TestPage } from '../../pageInfo';
|
||||
|
||||
export interface ConfirmModal {
|
||||
delete: ClickablePageObjectType;
|
||||
success: PageObject;
|
||||
}
|
||||
|
||||
export const confirmModal = new TestPage<ConfirmModal>({
|
||||
pageObjects: {
|
||||
delete: 'Confirm Modal Danger Button',
|
||||
success: () => Selector.fromSelector('.alert-success'),
|
||||
},
|
||||
});
|
||||
@@ -1,30 +1,69 @@
|
||||
import { Browser, Page } from 'puppeteer-core';
|
||||
import { launchBrowser } from './launcher';
|
||||
import { ensureLoggedIn } from './login';
|
||||
import { cleanDashboard, createEmptyDashboardPage } from './pages/dashboards/createDashboardPage';
|
||||
import { DashboardPage } from './pages/dashboards/dashboardPage';
|
||||
import { TestPage } from './pageInfo';
|
||||
import { addTestDataSourceAndVerify, cleanUpTestDataSource } from './pages/datasources/dataSources';
|
||||
|
||||
export interface ScenarioArguments {
|
||||
describeName: string;
|
||||
itName: string;
|
||||
scenario: (browser: Browser, page: Page, datasourceName?: string, dashboardPage?: TestPage<DashboardPage>) => void;
|
||||
skipScenario?: boolean;
|
||||
createTestDataSource?: boolean;
|
||||
createTestDashboard?: boolean;
|
||||
}
|
||||
|
||||
export const e2eScenario = ({
|
||||
describeName,
|
||||
itName,
|
||||
scenario,
|
||||
skipScenario = false,
|
||||
createTestDataSource = false,
|
||||
createTestDashboard = false,
|
||||
}: ScenarioArguments) => {
|
||||
describe(describeName, () => {
|
||||
if (skipScenario) {
|
||||
it.skip(itName, async () => {
|
||||
expect(false).toBe(true);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
export const e2eScenario = (
|
||||
title: string,
|
||||
testDescription: string,
|
||||
callback: (browser: Browser, page: Page) => void
|
||||
) => {
|
||||
describe(title, () => {
|
||||
let browser: Browser;
|
||||
let page: Page;
|
||||
let testDataSourceName: string;
|
||||
let testDashboardTitle: string;
|
||||
let dashboardPage: TestPage<DashboardPage>;
|
||||
|
||||
beforeAll(async () => {
|
||||
browser = await launchBrowser();
|
||||
page = await browser.newPage();
|
||||
await ensureLoggedIn(page);
|
||||
if (createTestDataSource) {
|
||||
testDataSourceName = await addTestDataSourceAndVerify(page);
|
||||
}
|
||||
if (createTestDashboard) {
|
||||
testDashboardTitle = `e2e - ${new Date().getTime()}`;
|
||||
dashboardPage = await createEmptyDashboardPage(page, testDashboardTitle);
|
||||
}
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
if (testDataSourceName) {
|
||||
await cleanUpTestDataSource(page, testDataSourceName);
|
||||
}
|
||||
if (testDashboardTitle && dashboardPage) {
|
||||
await cleanDashboard(page, testDashboardTitle);
|
||||
}
|
||||
if (browser) {
|
||||
await browser.close();
|
||||
}
|
||||
});
|
||||
|
||||
it(testDescription, async () => {
|
||||
await callback(browser, page);
|
||||
it(itName, async () => {
|
||||
await scenario(browser, page, testDataSourceName, dashboardPage);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Browser, Page } from 'puppeteer-core';
|
||||
|
||||
import { e2eScenario, takeScreenShot, pages } from '@grafana/toolkit/src/e2e';
|
||||
import { e2eScenario, pages, takeScreenShot } from '@grafana/toolkit/src/e2e';
|
||||
import { getEndToEndSettings } from '@grafana/toolkit/src/plugins';
|
||||
|
||||
// ****************************************************************
|
||||
@@ -11,14 +11,18 @@ const sleep = (milliseconds: number) => {
|
||||
return new Promise(resolve => setTimeout(resolve, milliseconds));
|
||||
};
|
||||
|
||||
e2eScenario('Common Plugin Test', 'should pass', async (browser: Browser, page: Page) => {
|
||||
const settings = getEndToEndSettings();
|
||||
const pluginPage = pages.getPluginPage(settings.plugin.id);
|
||||
await pluginPage.init(page);
|
||||
await pluginPage.navigateTo();
|
||||
// TODO: find a better way to avoid the 'loading' page
|
||||
await sleep(500);
|
||||
e2eScenario({
|
||||
describeName: 'Common Plugin Test',
|
||||
itName: 'should pass',
|
||||
scenario: async (browser: Browser, page: Page) => {
|
||||
const settings = getEndToEndSettings();
|
||||
const pluginPage = pages.getPluginPage(settings.plugin.id);
|
||||
await pluginPage.init(page);
|
||||
await pluginPage.navigateTo();
|
||||
// TODO: find a better way to avoid the 'loading' page
|
||||
await sleep(500);
|
||||
|
||||
const fileName = 'plugin-page';
|
||||
await takeScreenShot(page, fileName);
|
||||
const fileName = 'plugin-page';
|
||||
await takeScreenShot(page, fileName);
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user