@grafana/e2e: improvements (#26939)
* Minor changes * Added an `editPanel` flow function ... and moved the internals of `addPanel` to a common function for use by both * Added optional template variables to `addDashboard` config * Use latest Cypress 4.x version * Updated lockfile
This commit is contained in:
@@ -49,7 +49,7 @@
|
||||
"@mochajs/json-file-reporter": "^1.2.0",
|
||||
"blink-diff": "1.0.13",
|
||||
"commander": "5.0.0",
|
||||
"cypress": "^4.9.0",
|
||||
"cypress": "^4.12.1",
|
||||
"cypress-file-upload": "^4.0.7",
|
||||
"execa": "4.0.0",
|
||||
"resolve-as-bin": "2.1.0",
|
||||
|
||||
@@ -8,8 +8,21 @@ export interface AddDashboardConfig {
|
||||
timeRange: DashboardTimeRangeConfig;
|
||||
timezone: string;
|
||||
title: string;
|
||||
variables: Partial<AddVariableConfig>[];
|
||||
}
|
||||
|
||||
export interface AddVariableConfig {
|
||||
constantValue?: string;
|
||||
dataSource?: string;
|
||||
hide?: string;
|
||||
label?: string;
|
||||
name: string;
|
||||
query?: string;
|
||||
regex?: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
// @todo improve config input/output: https://stackoverflow.com/a/63507459/923745
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
export const addDashboard = (config?: Partial<AddDashboardConfig>): any => {
|
||||
const fullConfig = {
|
||||
@@ -19,10 +32,11 @@ export const addDashboard = (config?: Partial<AddDashboardConfig>): any => {
|
||||
},
|
||||
timezone: 'Coordinated Universal Time',
|
||||
title: `e2e-${Date.now()}`,
|
||||
variables: [],
|
||||
...config,
|
||||
} as AddDashboardConfig;
|
||||
|
||||
const { timeRange, timezone, title } = fullConfig;
|
||||
const { timeRange, timezone, title, variables } = fullConfig;
|
||||
|
||||
e2e().logToConsole('Adding dashboard with title:', title);
|
||||
|
||||
@@ -33,11 +47,11 @@ export const addDashboard = (config?: Partial<AddDashboardConfig>): any => {
|
||||
// @todo use the time range picker's time zone control
|
||||
selectOption(e2e.pages.Dashboard.Settings.General.timezone(), timezone);
|
||||
|
||||
addVariables(variables);
|
||||
|
||||
e2e.components.BackButton.backArrow().click();
|
||||
|
||||
if (timeRange) {
|
||||
setDashboardTimeRange(timeRange);
|
||||
}
|
||||
setDashboardTimeRange(timeRange);
|
||||
|
||||
e2e.pages.Dashboard.Toolbar.toolbarItems('Save dashboard').click();
|
||||
|
||||
@@ -62,9 +76,79 @@ export const addDashboard = (config?: Partial<AddDashboardConfig>): any => {
|
||||
});
|
||||
|
||||
// @todo remove `wrap` when possible
|
||||
return e2e().wrap({
|
||||
config: fullConfig,
|
||||
uid,
|
||||
});
|
||||
return e2e().wrap(
|
||||
{
|
||||
config: fullConfig,
|
||||
uid,
|
||||
},
|
||||
{ log: false }
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
export const VARIABLE_TYPE_AD_HOC_FILTERS = 'Ad hoc filters';
|
||||
export const VARIABLE_TYPE_CONSTANT = 'Constant';
|
||||
export const VARIABLE_TYPE_DATASOURCE = 'Datasource';
|
||||
export const VARIABLE_TYPE_QUERY = 'Query';
|
||||
|
||||
const addVariable = (config: Partial<AddVariableConfig>, isFirst: boolean): any => {
|
||||
const fullConfig = {
|
||||
type: VARIABLE_TYPE_QUERY,
|
||||
...config,
|
||||
} as AddVariableConfig;
|
||||
|
||||
if (isFirst) {
|
||||
e2e.pages.Dashboard.Settings.Variables.List.addVariableCTA().click();
|
||||
} else {
|
||||
e2e.pages.Dashboard.Settings.Variables.List.newButton().click();
|
||||
}
|
||||
|
||||
const { constantValue, dataSource, hide, label, name, query, regex, type } = fullConfig;
|
||||
|
||||
if (hide) {
|
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.generalHideSelect().select(hide);
|
||||
}
|
||||
|
||||
if (label) {
|
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.generalLabelInput().type(label);
|
||||
}
|
||||
|
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.generalNameInput().type(name);
|
||||
|
||||
if (type !== VARIABLE_TYPE_QUERY) {
|
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.generalTypeSelect().select(type);
|
||||
}
|
||||
|
||||
if (
|
||||
dataSource &&
|
||||
(type === VARIABLE_TYPE_AD_HOC_FILTERS || type === VARIABLE_TYPE_DATASOURCE || type === VARIABLE_TYPE_QUERY)
|
||||
) {
|
||||
e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsDataSourceSelect().select(dataSource);
|
||||
}
|
||||
|
||||
if (constantValue && type === VARIABLE_TYPE_CONSTANT) {
|
||||
e2e.pages.Dashboard.Settings.Variables.Edit.ConstantVariable.constantOptionsQueryInput().type(constantValue);
|
||||
}
|
||||
|
||||
if (type === VARIABLE_TYPE_QUERY) {
|
||||
if (query) {
|
||||
e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsQueryInput().type(query);
|
||||
}
|
||||
|
||||
if (regex) {
|
||||
e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsRegExInput().type(regex);
|
||||
}
|
||||
}
|
||||
|
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.addButton().click();
|
||||
|
||||
return fullConfig;
|
||||
};
|
||||
|
||||
const addVariables = (configs: Partial<AddVariableConfig>[]): any => {
|
||||
if (configs.length > 0) {
|
||||
e2e.pages.Dashboard.Settings.General.sectionItems('Variables').click();
|
||||
}
|
||||
|
||||
return configs.map((config, i) => addVariable(config, i === 0));
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ export interface AddDataSourceConfig {
|
||||
type: string;
|
||||
}
|
||||
|
||||
// @todo improve config input/output: https://stackoverflow.com/a/63507459/923745
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
export const addDataSource = (config?: Partial<AddDataSourceConfig>): any => {
|
||||
const fullConfig = {
|
||||
@@ -110,9 +111,12 @@ export const addDataSource = (config?: Partial<AddDataSourceConfig>): any => {
|
||||
}
|
||||
|
||||
// @todo remove `wrap` when possible
|
||||
return e2e().wrap({
|
||||
config: fullConfig,
|
||||
id,
|
||||
});
|
||||
return e2e().wrap(
|
||||
{
|
||||
config: fullConfig,
|
||||
id,
|
||||
},
|
||||
{ log: false }
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,169 +1,24 @@
|
||||
import { e2e } from '../index';
|
||||
import { getLocalStorage, requireLocalStorage } from '../support/localStorage';
|
||||
import { configurePanel, ConfigurePanelConfig } from './configurePanel';
|
||||
import { getScenarioContext } from '../support/scenarioContext';
|
||||
import { selectOption } from './selectOption';
|
||||
|
||||
export interface AddPanelConfig {
|
||||
chartData: {
|
||||
method: string;
|
||||
route: string | RegExp;
|
||||
};
|
||||
dashboardUid: string;
|
||||
export interface AddPanelConfig extends ConfigurePanelConfig {
|
||||
dataSourceName: string;
|
||||
matchScreenshot: boolean;
|
||||
queriesForm: (config: AddPanelConfig) => void;
|
||||
panelTitle: string;
|
||||
screenshotName: string;
|
||||
visualizationName: string;
|
||||
}
|
||||
|
||||
// @todo improve config input/output: https://stackoverflow.com/a/63507459/923745
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
export const addPanel = (config?: Partial<AddPanelConfig>): any =>
|
||||
getScenarioContext().then(({ lastAddedDashboardUid, lastAddedDataSource }: any) => {
|
||||
const fullConfig = {
|
||||
chartData: {
|
||||
method: 'POST',
|
||||
route: '/api/ds/query',
|
||||
},
|
||||
dashboardUid: lastAddedDashboardUid,
|
||||
dataSourceName: lastAddedDataSource,
|
||||
matchScreenshot: false,
|
||||
panelTitle: `e2e-${Date.now()}`,
|
||||
queriesForm: () => {},
|
||||
screenshotName: 'chart',
|
||||
visualizationName: 'Table',
|
||||
...config,
|
||||
} as AddPanelConfig;
|
||||
|
||||
const {
|
||||
chartData,
|
||||
dashboardUid,
|
||||
dataSourceName,
|
||||
matchScreenshot,
|
||||
panelTitle,
|
||||
queriesForm,
|
||||
screenshotName,
|
||||
visualizationName,
|
||||
} = fullConfig;
|
||||
|
||||
e2e.flows.openDashboard({ uid: dashboardUid });
|
||||
e2e.pages.Dashboard.Toolbar.toolbarItems('Add panel').click();
|
||||
e2e.pages.AddDashboard.addNewPanel().click();
|
||||
|
||||
e2e().server();
|
||||
|
||||
// @todo alias '/**/*.js*' as '@pluginModule' when possible: https://github.com/cypress-io/cypress/issues/1296
|
||||
|
||||
e2e()
|
||||
.route(chartData.method, chartData.route)
|
||||
.as('chartData');
|
||||
|
||||
selectOption(e2e.components.DataSourcePicker.container(), dataSourceName);
|
||||
|
||||
// @todo instead wait for '@pluginModule'
|
||||
e2e().wait(2000);
|
||||
|
||||
openOptions();
|
||||
|
||||
openOptionsGroup('settings');
|
||||
getOptionsGroup('settings')
|
||||
.find('[value="Panel Title"]')
|
||||
.scrollIntoView()
|
||||
.clear()
|
||||
.type(panelTitle);
|
||||
closeOptionsGroup('settings');
|
||||
|
||||
openOptionsGroup('type');
|
||||
e2e.components.PluginVisualization.item(visualizationName)
|
||||
.scrollIntoView()
|
||||
.click();
|
||||
closeOptionsGroup('type');
|
||||
|
||||
closeOptions();
|
||||
|
||||
queriesForm(fullConfig);
|
||||
|
||||
e2e().wait('@chartData');
|
||||
|
||||
// @todo enable when plugins have this implemented
|
||||
//e2e.components.QueryEditorRow.actionButton('Disable/enable query').click();
|
||||
//e2e.components.Panels.Panel.containerByTitle(panelTitle).find('.panel-content').contains('No data');
|
||||
//e2e.components.QueryEditorRow.actionButton('Disable/enable query').click();
|
||||
|
||||
e2e()
|
||||
.get('button[title="Apply changes and go back to dashboard"]')
|
||||
.click();
|
||||
|
||||
e2e().wait('@chartData');
|
||||
|
||||
// Wait for RxJS
|
||||
e2e().wait(500);
|
||||
|
||||
if (matchScreenshot) {
|
||||
e2e.components.Panels.Panel.containerByTitle(panelTitle)
|
||||
.find('.panel-content')
|
||||
.screenshot(screenshotName);
|
||||
e2e().compareScreenshots(screenshotName);
|
||||
}
|
||||
|
||||
// @todo remove `wrap` when possible
|
||||
return e2e().wrap({ config: fullConfig });
|
||||
});
|
||||
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
const closeOptions = (): any =>
|
||||
isOptionsOpen().then((isOpen: any) => {
|
||||
if (isOpen) {
|
||||
e2e.components.PanelEditor.OptionsPane.close().click();
|
||||
}
|
||||
});
|
||||
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
const closeOptionsGroup = (name: string): any =>
|
||||
isOptionsGroupOpen(name).then((isOpen: any) => {
|
||||
if (isOpen) {
|
||||
toggleOptionsGroup(name);
|
||||
}
|
||||
});
|
||||
|
||||
const getOptionsGroup = (name: string) => e2e().get(`.options-group:has([aria-label="Options group Panel ${name}"])`);
|
||||
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
const isOptionsGroupOpen = (name: string): any =>
|
||||
requireLocalStorage(`grafana.dashboard.editor.ui.optionGroup[Panel ${name}]`).then(({ defaultToClosed }: any) => {
|
||||
// @todo remove `wrap` when possible
|
||||
return e2e().wrap(!defaultToClosed);
|
||||
});
|
||||
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
const isOptionsOpen = (): any =>
|
||||
getLocalStorage('grafana.dashboard.editor.ui').then((data: any) => {
|
||||
if (data) {
|
||||
// @todo remove `wrap` when possible
|
||||
return e2e().wrap(data.isPanelOptionsVisible);
|
||||
} else {
|
||||
// @todo remove `wrap` when possible
|
||||
return e2e().wrap(true);
|
||||
}
|
||||
});
|
||||
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
const openOptions = (): any =>
|
||||
isOptionsOpen().then((isOpen: any) => {
|
||||
if (!isOpen) {
|
||||
e2e.components.PanelEditor.OptionsPane.open().click();
|
||||
}
|
||||
});
|
||||
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
const openOptionsGroup = (name: string): any =>
|
||||
isOptionsGroupOpen(name).then((isOpen: any) => {
|
||||
if (!isOpen) {
|
||||
toggleOptionsGroup(name);
|
||||
}
|
||||
});
|
||||
|
||||
const toggleOptionsGroup = (name: string) =>
|
||||
getOptionsGroup(name)
|
||||
.find('.editor-options-group-toggle')
|
||||
.click();
|
||||
getScenarioContext().then(({ lastAddedDataSource }: any) =>
|
||||
configurePanel(
|
||||
{
|
||||
dataSourceName: lastAddedDataSource,
|
||||
panelTitle: `e2e-${Date.now()}`,
|
||||
visualizationName: 'Table',
|
||||
...config,
|
||||
} as AddPanelConfig,
|
||||
false
|
||||
)
|
||||
);
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
import { e2e } from '../index';
|
||||
import { getLocalStorage, requireLocalStorage } from '../support/localStorage';
|
||||
import { getScenarioContext } from '../support/scenarioContext';
|
||||
import { selectOption } from './selectOption';
|
||||
|
||||
export interface ConfigurePanelConfig {
|
||||
chartData: {
|
||||
method: string;
|
||||
route: string | RegExp;
|
||||
};
|
||||
dashboardUid: string;
|
||||
dataSourceName?: string;
|
||||
matchScreenshot: boolean;
|
||||
queriesForm?: (config: any) => void;
|
||||
panelTitle: string;
|
||||
screenshotName: string;
|
||||
visitDashboardAtStart: boolean; // @todo remove when possible
|
||||
visualizationName?: string;
|
||||
}
|
||||
|
||||
// @todo improve config input/output: https://stackoverflow.com/a/63507459/923745
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
export const configurePanel = (config: Partial<ConfigurePanelConfig>, edit: boolean): any =>
|
||||
getScenarioContext().then(({ lastAddedDashboardUid }: any) => {
|
||||
const fullConfig = {
|
||||
chartData: {
|
||||
method: 'POST',
|
||||
route: '/api/ds/query',
|
||||
},
|
||||
dashboardUid: lastAddedDashboardUid,
|
||||
matchScreenshot: false,
|
||||
saveDashboard: true,
|
||||
screenshotName: 'chart',
|
||||
visitDashboardAtStart: true,
|
||||
...config,
|
||||
} as ConfigurePanelConfig;
|
||||
|
||||
const {
|
||||
chartData,
|
||||
dashboardUid,
|
||||
dataSourceName,
|
||||
matchScreenshot,
|
||||
panelTitle,
|
||||
queriesForm,
|
||||
screenshotName,
|
||||
visitDashboardAtStart,
|
||||
visualizationName,
|
||||
} = fullConfig;
|
||||
|
||||
if (visitDashboardAtStart) {
|
||||
e2e.flows.openDashboard({ uid: dashboardUid });
|
||||
}
|
||||
|
||||
if (edit) {
|
||||
e2e.components.Panels.Panel.title(panelTitle).click();
|
||||
e2e.components.Panels.Panel.headerItems('Edit').click();
|
||||
} else {
|
||||
e2e.pages.Dashboard.Toolbar.toolbarItems('Add panel').click();
|
||||
e2e.pages.AddDashboard.addNewPanel().click();
|
||||
}
|
||||
|
||||
e2e().server();
|
||||
|
||||
// @todo alias '/**/*.js*' as '@pluginModule' when possible: https://github.com/cypress-io/cypress/issues/1296
|
||||
|
||||
e2e()
|
||||
.route(chartData.method, chartData.route)
|
||||
.as('chartData');
|
||||
|
||||
if (dataSourceName) {
|
||||
selectOption(e2e.components.DataSourcePicker.container(), dataSourceName);
|
||||
}
|
||||
|
||||
// @todo instead wait for '@pluginModule'
|
||||
e2e().wait(2000);
|
||||
|
||||
e2e().wait('@chartData');
|
||||
|
||||
// `panelTitle` is needed to edit the panel, and unlikely to have its value changed at that point
|
||||
const changeTitle = panelTitle && !edit;
|
||||
|
||||
if (changeTitle || visualizationName) {
|
||||
openOptions();
|
||||
|
||||
if (changeTitle) {
|
||||
openOptionsGroup('settings');
|
||||
getOptionsGroup('settings')
|
||||
.find('[value="Panel Title"]')
|
||||
.scrollIntoView()
|
||||
.clear()
|
||||
.type(panelTitle);
|
||||
closeOptionsGroup('settings');
|
||||
}
|
||||
|
||||
if (visualizationName) {
|
||||
openOptionsGroup('type');
|
||||
e2e.components.PluginVisualization.item(visualizationName)
|
||||
.scrollIntoView()
|
||||
.click();
|
||||
closeOptionsGroup('type');
|
||||
}
|
||||
|
||||
closeOptions();
|
||||
} else {
|
||||
// Options are consistently closed
|
||||
closeOptions();
|
||||
}
|
||||
|
||||
if (queriesForm) {
|
||||
queriesForm(fullConfig);
|
||||
e2e().wait('@chartData');
|
||||
}
|
||||
|
||||
// @todo enable when plugins have this implemented
|
||||
//e2e.components.QueryEditorRow.actionButton('Disable/enable query').click();
|
||||
//e2e().wait('@chartData');
|
||||
//e2e.components.Panels.Panel.containerByTitle(panelTitle).find('.panel-content').contains('No data');
|
||||
//e2e.components.QueryEditorRow.actionButton('Disable/enable query').click();
|
||||
//e2e().wait('@chartData');
|
||||
|
||||
e2e()
|
||||
.get('button[title="Apply changes and go back to dashboard"]')
|
||||
.click();
|
||||
|
||||
e2e()
|
||||
.url()
|
||||
.should('include', `/d/${dashboardUid}`);
|
||||
|
||||
e2e().wait('@chartData');
|
||||
|
||||
// Wait for RxJS
|
||||
e2e().wait(500);
|
||||
|
||||
if (matchScreenshot) {
|
||||
e2e.components.Panels.Panel.containerByTitle(panelTitle)
|
||||
.find('.panel-content')
|
||||
.screenshot(screenshotName);
|
||||
e2e().compareScreenshots(screenshotName);
|
||||
}
|
||||
|
||||
// @todo remove `wrap` when possible
|
||||
return e2e().wrap({ config: fullConfig }, { log: false });
|
||||
});
|
||||
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
const closeOptions = (): any =>
|
||||
isOptionsOpen().then((isOpen: any) => {
|
||||
if (isOpen) {
|
||||
e2e.components.PanelEditor.OptionsPane.close().click();
|
||||
}
|
||||
});
|
||||
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
const closeOptionsGroup = (name: string): any =>
|
||||
isOptionsGroupOpen(name).then((isOpen: any) => {
|
||||
if (isOpen) {
|
||||
toggleOptionsGroup(name);
|
||||
}
|
||||
});
|
||||
|
||||
const getOptionsGroup = (name: string) => e2e().get(`.options-group:has([aria-label="Options group Panel ${name}"])`);
|
||||
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
const isOptionsGroupOpen = (name: string): any =>
|
||||
requireLocalStorage(`grafana.dashboard.editor.ui.optionGroup[Panel ${name}]`).then(({ defaultToClosed }: any) => {
|
||||
// @todo remove `wrap` when possible
|
||||
return e2e().wrap(!defaultToClosed, { log: false });
|
||||
});
|
||||
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
const isOptionsOpen = (): any =>
|
||||
getLocalStorage('grafana.dashboard.editor.ui').then((data: any) => {
|
||||
if (data) {
|
||||
// @todo remove `wrap` when possible
|
||||
return e2e().wrap(data.isPanelOptionsVisible, { log: false });
|
||||
} else {
|
||||
// @todo remove `wrap` when possible
|
||||
return e2e().wrap(true, { log: false });
|
||||
}
|
||||
});
|
||||
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
const openOptions = (): any =>
|
||||
isOptionsOpen().then((isOpen: any) => {
|
||||
if (!isOpen) {
|
||||
e2e.components.PanelEditor.OptionsPane.open().click();
|
||||
}
|
||||
});
|
||||
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
const openOptionsGroup = (name: string): any =>
|
||||
isOptionsGroupOpen(name).then((isOpen: any) => {
|
||||
if (!isOpen) {
|
||||
toggleOptionsGroup(name);
|
||||
}
|
||||
});
|
||||
|
||||
const toggleOptionsGroup = (name: string) =>
|
||||
getOptionsGroup(name)
|
||||
.find('.editor-options-group-toggle')
|
||||
.click();
|
||||
@@ -0,0 +1,9 @@
|
||||
import { configurePanel, ConfigurePanelConfig } from './configurePanel';
|
||||
|
||||
export interface EditPanelConfig extends ConfigurePanelConfig {
|
||||
queriesForm?: (config: EditPanelConfig) => void;
|
||||
}
|
||||
|
||||
// @todo improve config input/output: https://stackoverflow.com/a/63507459/923745
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
export const editPanel = (config: Partial<EditPanelConfig>): any => configurePanel(config, true);
|
||||
@@ -1,28 +1,13 @@
|
||||
import { addDashboard } from './addDashboard';
|
||||
import { addDataSource } from './addDataSource';
|
||||
import { addPanel } from './addPanel';
|
||||
import { assertSuccessNotification } from './assertSuccessNotification';
|
||||
import { deleteDashboard } from './deleteDashboard';
|
||||
import { deleteDataSource } from './deleteDataSource';
|
||||
import { login } from './login';
|
||||
import { openDashboard } from './openDashboard';
|
||||
import { saveDashboard } from './saveDashboard';
|
||||
import { openPanelMenuItem, PanelMenuItems } from './openPanelMenuItem';
|
||||
import { revertAllChanges } from './revertAllChanges';
|
||||
import { selectOption } from './selectOption';
|
||||
|
||||
export const Flows = {
|
||||
addDashboard,
|
||||
addDataSource,
|
||||
addPanel,
|
||||
assertSuccessNotification,
|
||||
deleteDashboard,
|
||||
deleteDataSource,
|
||||
login,
|
||||
openDashboard,
|
||||
saveDashboard,
|
||||
openPanelMenuItem,
|
||||
PanelMenuItems,
|
||||
revertAllChanges,
|
||||
selectOption,
|
||||
};
|
||||
export * from './addDashboard';
|
||||
export * from './addDataSource';
|
||||
export * from './addPanel';
|
||||
export * from './assertSuccessNotification';
|
||||
export * from './deleteDashboard';
|
||||
export * from './deleteDataSource';
|
||||
export * from './editPanel';
|
||||
export * from './login';
|
||||
export * from './openDashboard';
|
||||
export * from './openPanelMenuItem';
|
||||
export * from './revertAllChanges';
|
||||
export * from './saveDashboard';
|
||||
export * from './selectOption';
|
||||
|
||||
@@ -7,6 +7,7 @@ export interface OpenDashboardConfig {
|
||||
uid: string;
|
||||
}
|
||||
|
||||
// @todo improve config input/output: https://stackoverflow.com/a/63507459/923745
|
||||
export const openDashboard = (config?: Partial<OpenDashboardConfig>) =>
|
||||
getScenarioContext().then(({ lastAddedDashboardUid }: any) => {
|
||||
const fullConfig = {
|
||||
@@ -23,5 +24,5 @@ export const openDashboard = (config?: Partial<OpenDashboardConfig>) =>
|
||||
}
|
||||
|
||||
// @todo remove `wrap` when possible
|
||||
return e2e().wrap({ config: fullConfig });
|
||||
return e2e().wrap({ config: fullConfig }, { log: false });
|
||||
});
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
* @packageDocumentation
|
||||
*/
|
||||
import { e2eScenario, ScenarioArguments } from './support/scenario';
|
||||
import { Flows } from './flows';
|
||||
import { getScenarioContext, setScenarioContext } from './support/scenarioContext';
|
||||
import { e2eFactory } from './support';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import * as flows from './flows';
|
||||
|
||||
const e2eObject = {
|
||||
env: (args: string) => Cypress.env(args),
|
||||
@@ -17,7 +17,7 @@ const e2eObject = {
|
||||
scenario: (args: ScenarioArguments) => e2eScenario(args),
|
||||
pages: e2eFactory({ selectors: selectors.pages }),
|
||||
components: e2eFactory({ selectors: selectors.components }),
|
||||
flows: Flows,
|
||||
flows,
|
||||
getScenarioContext,
|
||||
setScenarioContext,
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import { e2e } from '../index';
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
const get = (key: string): any =>
|
||||
e2e()
|
||||
.wrap({ getLocalStorage: () => localStorage.getItem(key) })
|
||||
.wrap({ getLocalStorage: () => localStorage.getItem(key) }, { log: false })
|
||||
.invoke('getLocalStorage');
|
||||
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { e2e } from '../';
|
||||
import { Flows } from '../flows';
|
||||
|
||||
export interface ScenarioArguments {
|
||||
describeName: string;
|
||||
@@ -22,20 +21,20 @@ export const e2eScenario = ({
|
||||
if (skipScenario) {
|
||||
it.skip(itName, () => scenario());
|
||||
} else {
|
||||
before(() => Flows.login(e2e.env('USERNAME'), e2e.env('PASSWORD')));
|
||||
before(() => e2e.flows.login(e2e.env('USERNAME'), e2e.env('PASSWORD')));
|
||||
|
||||
beforeEach(() => {
|
||||
Cypress.Cookies.preserveOnce('grafana_session');
|
||||
|
||||
if (addScenarioDataSource) {
|
||||
Flows.addDataSource();
|
||||
e2e.flows.addDataSource();
|
||||
}
|
||||
if (addScenarioDashBoard) {
|
||||
Flows.addDashboard();
|
||||
e2e.flows.addDashboard();
|
||||
}
|
||||
});
|
||||
|
||||
afterEach(() => Flows.revertAllChanges());
|
||||
afterEach(() => e2e.flows.revertAllChanges());
|
||||
after(() => e2e().clearCookies());
|
||||
|
||||
it(itName, () => scenario());
|
||||
|
||||
@@ -37,19 +37,25 @@ const lastProperty = <T extends DeleteDashboardConfig | DeleteDataSourceConfig,
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
export const getScenarioContext = (): any =>
|
||||
e2e()
|
||||
.wrap({
|
||||
getScenarioContext: () => ({ ...scenarioContext } as ScenarioContext),
|
||||
})
|
||||
.invoke('getScenarioContext');
|
||||
.wrap(
|
||||
{
|
||||
getScenarioContext: () => ({ ...scenarioContext } as ScenarioContext),
|
||||
},
|
||||
{ log: false }
|
||||
)
|
||||
.invoke({ log: false }, 'getScenarioContext');
|
||||
|
||||
// @todo this actually returns type `Cypress.Chainable`
|
||||
export const setScenarioContext = (newContext: Partial<ScenarioContext>): any =>
|
||||
e2e()
|
||||
.wrap({
|
||||
setScenarioContext: () => {
|
||||
Object.entries(newContext).forEach(([key, value]) => {
|
||||
scenarioContext[key] = value;
|
||||
});
|
||||
.wrap(
|
||||
{
|
||||
setScenarioContext: () => {
|
||||
Object.entries(newContext).forEach(([key, value]) => {
|
||||
scenarioContext[key] = value;
|
||||
});
|
||||
},
|
||||
},
|
||||
})
|
||||
.invoke('setScenarioContext');
|
||||
{ log: false }
|
||||
)
|
||||
.invoke({ log: false }, 'setScenarioContext');
|
||||
|
||||
Reference in New Issue
Block a user