mirror of https://github.com/grafana/grafana
e2e: creates a separate package for selectors (#23858)
* Initial commit * Chore: fixes after merge * Chore: removes todos * Chore: uncomment test * Chore: adds missing externals to rollup config * Refactor: selectors is master for everything * Docs: updates Docs * Chore: adds e2e-selectors to publishpull/23931/head
parent
9ac7263e66
commit
b09b49fb37
@ -0,0 +1,2 @@ |
||||
|
||||
|
@ -0,0 +1,3 @@ |
||||
# Grafana End-to-End Test Selectors library |
||||
|
||||
> **@grafana/e2e-selectors is currently in ALPHA**. Core API is unstable and can be a subject of breaking changes! |
@ -0,0 +1,3 @@ |
||||
{ |
||||
"extends": "../../api-extractor.json" |
||||
} |
@ -0,0 +1,7 @@ |
||||
'use strict'; |
||||
|
||||
if (process.env.NODE_ENV === 'production') { |
||||
module.exports = require('./index.production.js'); |
||||
} else { |
||||
module.exports = require('./index.development.js'); |
||||
} |
@ -0,0 +1,50 @@ |
||||
{ |
||||
"author": "Grafana Labs", |
||||
"license": "Apache-2.0", |
||||
"name": "@grafana/e2e-selectors", |
||||
"version": "7.0.0-pre.0", |
||||
"description": "Grafana End-to-End Test Selectors Library", |
||||
"keywords": [ |
||||
"cli", |
||||
"grafana", |
||||
"e2e", |
||||
"typescript" |
||||
], |
||||
"repository": { |
||||
"type": "git", |
||||
"url": "http://github.com/grafana/grafana.git", |
||||
"directory": "packages/grafana-e2e-selectors" |
||||
}, |
||||
"main": "src/index.ts", |
||||
"scripts": { |
||||
"build": "grafana-toolkit package:build --scope=e2e-selectors", |
||||
"bundle": "rollup -c rollup.config.ts", |
||||
"clean": "rimraf ./dist ./compiled", |
||||
"docsExtract": "mkdir -p ../../reports/docs && api-extractor run 2>&1 | tee ../../reports/docs/$(basename $(pwd)).log", |
||||
"lint": "eslint src/ --ext=.js,.ts,.tsx", |
||||
"typecheck": "tsc --noEmit" |
||||
}, |
||||
"devDependencies": { |
||||
"@types/node": "13.7.7", |
||||
"@rollup/plugin-commonjs": "11.0.2", |
||||
"@rollup/plugin-node-resolve": "7.1.1", |
||||
"@types/rollup-plugin-visualizer": "2.6.0", |
||||
"@types/systemjs": "^0.20.6", |
||||
"pretty-format": "25.1.0", |
||||
"rollup": "2.0.6", |
||||
"rollup-plugin-sourcemaps": "0.5.0", |
||||
"rollup-plugin-terser": "5.3.0", |
||||
"rollup-plugin-typescript2": "0.26.0", |
||||
"rollup-plugin-visualizer": "3.3.1", |
||||
"ts-loader": "6.2.1", |
||||
"ts-node": "8.8.1" |
||||
}, |
||||
"types": "src/index.ts", |
||||
"dependencies": { |
||||
"@grafana/tsconfig": "^1.0.0-rc1", |
||||
"commander": "5.0.0", |
||||
"execa": "4.0.0", |
||||
"typescript": "3.7.5", |
||||
"yaml": "^1.8.3" |
||||
} |
||||
} |
@ -0,0 +1,25 @@ |
||||
import resolve from '@rollup/plugin-node-resolve'; |
||||
import sourceMaps from 'rollup-plugin-sourcemaps'; |
||||
import { terser } from 'rollup-plugin-terser'; |
||||
|
||||
const pkg = require('./package.json'); |
||||
|
||||
const libraryName = pkg.name; |
||||
|
||||
const buildCjsPackage = ({ env }) => { |
||||
return { |
||||
input: `compiled/index.js`, |
||||
output: [ |
||||
{ |
||||
file: `dist/index.${env}.js`, |
||||
name: libraryName, |
||||
format: 'cjs', |
||||
sourcemap: true, |
||||
exports: 'named', |
||||
globals: {}, |
||||
}, |
||||
], |
||||
plugins: [resolve(), sourceMaps(), env === 'production' && terser()], |
||||
}; |
||||
}; |
||||
export default [buildCjsPackage({ env: 'development' }), buildCjsPackage({ env: 'production' })]; |
@ -0,0 +1,7 @@ |
||||
/** |
||||
* A library containing the different design components of the Grafana ecosystem. |
||||
* |
||||
* @packageDocumentation |
||||
*/ |
||||
export * from './selectors'; |
||||
export * from './types'; |
@ -0,0 +1,108 @@ |
||||
import { Pages } from './pages'; |
||||
|
||||
export const Components = { |
||||
DataSource: { |
||||
TestData: { |
||||
QueryTab: { |
||||
scenarioSelect: 'Test Data Query scenario select', |
||||
max: 'TestData max', |
||||
min: 'TestData min', |
||||
noise: 'TestData noise', |
||||
seriesCount: 'TestData series count', |
||||
spread: 'TestData spread', |
||||
startValue: 'TestData start value', |
||||
}, |
||||
}, |
||||
}, |
||||
Panels: { |
||||
Panel: { |
||||
title: (title: string) => `Panel header title item ${title}`, |
||||
headerItems: (item: string) => `Panel header item ${item}`, |
||||
}, |
||||
Visualization: { |
||||
Graph: { |
||||
VisualizationTab: { |
||||
legendSection: 'Legend section', |
||||
}, |
||||
Legend: { |
||||
legendItemAlias: (name: string) => `gpl alias ${name}`, |
||||
showLegendSwitch: 'gpl show legend', |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
Drawer: { |
||||
General: { |
||||
title: (title: string) => `Drawer title ${title}`, |
||||
expand: 'Drawer expand', |
||||
contract: 'Drawer contract', |
||||
close: 'Drawer close', |
||||
rcContentWrapper: () => '.drawer-content-wrapper', |
||||
}, |
||||
}, |
||||
PanelEditor: { |
||||
General: { |
||||
content: 'Panel editor content', |
||||
}, |
||||
OptionsPane: { |
||||
content: 'Panel editor option pane content', |
||||
close: Pages.Dashboard.Toolbar.toolbarItems('Close options pane'), |
||||
open: Pages.Dashboard.Toolbar.toolbarItems('Open options pane'), |
||||
select: 'Panel editor option pane select', |
||||
}, |
||||
// not sure about the naming *DataPane*
|
||||
DataPane: { |
||||
content: 'Panel editor data pane content', |
||||
}, |
||||
}, |
||||
PanelInspector: { |
||||
Data: { |
||||
content: 'Panel inspector Data content', |
||||
}, |
||||
Stats: { |
||||
content: 'Panel inspector Stats content', |
||||
}, |
||||
Json: { |
||||
content: 'Panel inspector Json content', |
||||
}, |
||||
Query: { |
||||
content: 'Panel inspector Query content', |
||||
}, |
||||
}, |
||||
Tab: { |
||||
title: (title: string) => `Tab ${title}`, |
||||
active: () => '[class*="-activeTabStyle"]', |
||||
}, |
||||
QueryTab: { |
||||
content: 'Query editor tab content', |
||||
queryInspectorButton: 'Query inspector button', |
||||
}, |
||||
AlertTab: { |
||||
content: 'Alert editor tab content', |
||||
}, |
||||
TransformTab: { |
||||
content: 'Transform editor tab content', |
||||
}, |
||||
QueryEditorToolbarItem: { |
||||
button: (title: string) => `QueryEditor toolbar item button ${title}`, |
||||
}, |
||||
BackButton: { |
||||
backArrow: 'Go Back button', |
||||
}, |
||||
OptionsGroup: { |
||||
toggle: (title: string) => `Options group ${title}`, |
||||
}, |
||||
PluginVisualization: { |
||||
item: (title: string) => `Plugin visualization item ${title}`, |
||||
current: () => '[class*="-currentVisualizationItem"]', |
||||
}, |
||||
Select: { |
||||
option: 'Select option', |
||||
}, |
||||
FieldConfigEditor: { |
||||
content: 'Field config editor content', |
||||
}, |
||||
OverridesConfigEditor: { |
||||
content: 'Field overrides editor content', |
||||
}, |
||||
}; |
@ -0,0 +1,8 @@ |
||||
import { Pages } from './pages'; |
||||
import { Components } from './components'; |
||||
import { E2ESelectors } from '../types'; |
||||
|
||||
export const selectors: { pages: E2ESelectors<typeof Pages>; components: E2ESelectors<typeof Components> } = { |
||||
pages: Pages, |
||||
components: Components, |
||||
}; |
@ -0,0 +1,121 @@ |
||||
export const Pages = { |
||||
Login: { |
||||
url: '/login', |
||||
username: 'Username input field', |
||||
password: 'Password input field', |
||||
submit: 'Login button', |
||||
skip: 'Skip change password button', |
||||
}, |
||||
DataSource: { |
||||
name: 'Data source settings page name input field', |
||||
delete: 'Data source settings page Delete button', |
||||
saveAndTest: 'Data source settings page Save and Test button', |
||||
alert: 'Data source settings page Alert', |
||||
alertMessage: 'Data source settings page Alert message', |
||||
}, |
||||
DataSources: { |
||||
url: '/datasources', |
||||
dataSources: (dataSourceName: string) => `Data source list item ${dataSourceName}`, |
||||
}, |
||||
AddDataSource: { |
||||
url: '/datasources/new', |
||||
dataSourcePlugins: (pluginName: string) => `Data source plugin item ${pluginName}`, |
||||
}, |
||||
ConfirmModal: { |
||||
delete: 'Confirm Modal Danger Button', |
||||
}, |
||||
AddDashboard: { |
||||
url: '/dashboard/new', |
||||
addNewPanel: 'Add new panel', |
||||
}, |
||||
Dashboard: { |
||||
url: (uid: string) => `/d/${uid}`, |
||||
Toolbar: { |
||||
toolbarItems: (button: string) => `Dashboard navigation bar button ${button}`, |
||||
navBar: () => '.navbar', |
||||
}, |
||||
SubMenu: { |
||||
submenuItem: 'Dashboard template variables submenu item', |
||||
submenuItemLabels: (item: string) => `Dashboard template variables submenu Label ${item}`, |
||||
submenuItemValueDropDownValueLinkTexts: (item: string) => |
||||
`Dashboard template variables Variable Value DropDown value link text ${item}`, |
||||
submenuItemValueDropDownDropDown: 'Dashboard template variables Variable Value DropDown DropDown', |
||||
submenuItemValueDropDownOptionTexts: (item: string) => |
||||
`Dashboard template variables Variable Value DropDown option text ${item}`, |
||||
}, |
||||
Settings: { |
||||
General: { |
||||
deleteDashBoard: 'Dashboard settings page delete dashboard button', |
||||
sectionItems: (item: string) => `Dashboard settings section item ${item}`, |
||||
saveDashBoard: 'Dashboard settings aside actions Save button', |
||||
saveAsDashBoard: 'Dashboard settings aside actions Save As button', |
||||
}, |
||||
Variables: { |
||||
List: { |
||||
addVariableCTA: 'Call to action button Add variable', |
||||
newButton: 'Variable editor New variable button', |
||||
table: 'Variable editor Table', |
||||
tableRowNameFields: (variableName: string) => `Variable editor Table Name field ${variableName}`, |
||||
tableRowDefinitionFields: (variableName: string) => `Variable editor Table Definition field ${variableName}`, |
||||
tableRowArrowUpButtons: (variableName: string) => `Variable editor Table ArrowUp button ${variableName}`, |
||||
tableRowArrowDownButtons: (variableName: string) => `Variable editor Table ArrowDown button ${variableName}`, |
||||
tableRowDuplicateButtons: (variableName: string) => `Variable editor Table Duplicate button ${variableName}`, |
||||
tableRowRemoveButtons: (variableName: string) => `Variable editor Table Remove button ${variableName}`, |
||||
}, |
||||
Edit: { |
||||
General: { |
||||
headerLink: 'Variable editor Header link', |
||||
modeLabelNew: 'Variable editor Header mode New', |
||||
modeLabelEdit: 'Variable editor Header mode Edit', |
||||
generalNameInput: 'Variable editor Form Name field', |
||||
generalTypeSelect: 'Variable editor Form Type select', |
||||
generalLabelInput: 'Variable editor Form Label field', |
||||
generalHideSelect: 'Variable editor Form Hide select', |
||||
selectionOptionsMultiSwitch: 'Variable editor Form Multi switch', |
||||
selectionOptionsIncludeAllSwitch: 'Variable editor Form IncludeAll switch', |
||||
selectionOptionsCustomAllInput: 'Variable editor Form IncludeAll field', |
||||
previewOfValuesOption: 'Variable editor Preview of Values option', |
||||
addButton: 'Variable editor Add button', |
||||
updateButton: 'Variable editor Update button', |
||||
}, |
||||
QueryVariable: { |
||||
queryOptionsDataSourceSelect: 'Variable editor Form Query DataSource select', |
||||
queryOptionsRefreshSelect: 'Variable editor Form Query Refresh select', |
||||
queryOptionsRegExInput: 'Variable editor Form Query RegEx field', |
||||
queryOptionsSortSelect: 'Variable editor Form Query Sort select', |
||||
queryOptionsQueryInput: 'Variable editor Form Default Variable Query Editor textarea', |
||||
valueGroupsTagsEnabledSwitch: 'Variable editor Form Query UseTags switch', |
||||
valueGroupsTagsTagsQueryInput: 'Variable editor Form Query TagsQuery field', |
||||
valueGroupsTagsTagsValuesQueryInput: 'Variable editor Form Query TagsValuesQuery field', |
||||
}, |
||||
ConstantVariable: { |
||||
constantOptionsQueryInput: 'Variable editor Form Constant Query field', |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
Dashboards: { |
||||
url: '/dashboards', |
||||
dashboards: (title: string) => `Dashboard search item ${title}`, |
||||
}, |
||||
SaveDashboardAsModal: { |
||||
newName: 'Save dashboard title field', |
||||
save: 'Save dashboard button', |
||||
}, |
||||
SaveDashboardModal: { |
||||
save: 'Dashboard settings Save Dashboard Modal Save button', |
||||
saveVariables: 'Dashboard settings Save Dashboard Modal Save variables checkbox', |
||||
saveTimerange: 'Dashboard settings Save Dashboard Modal Save timerange checkbox', |
||||
}, |
||||
SharePanelModal: { |
||||
linkToRenderedImage: 'Link to rendered image', |
||||
}, |
||||
Explore: { |
||||
url: '/explore', |
||||
General: { |
||||
container: 'Explore', |
||||
runButton: 'Run button', |
||||
}, |
||||
}, |
||||
}; |
@ -0,0 +1 @@ |
||||
export * from './selectors'; |
@ -0,0 +1,15 @@ |
||||
export type StringSelector = string; |
||||
export type FunctionSelector = (id: string) => string; |
||||
export type CssSelector = () => string; |
||||
|
||||
export interface Selectors { |
||||
[key: string]: StringSelector | FunctionSelector | CssSelector | UrlSelector | Selectors; |
||||
} |
||||
|
||||
export type E2ESelectors<S extends Selectors> = { |
||||
[P in keyof S]: S[P]; |
||||
}; |
||||
|
||||
export interface UrlSelector extends Selectors { |
||||
url: string | FunctionSelector; |
||||
} |
@ -0,0 +1,4 @@ |
||||
{ |
||||
"exclude": ["dist", "node_modules", "**/*.test.ts*"], |
||||
"extends": "./tsconfig.json" |
||||
} |
@ -0,0 +1,11 @@ |
||||
{ |
||||
"compilerOptions": { |
||||
"declarationDir": "dist", |
||||
"outDir": "compiled", |
||||
"rootDirs": ["."], |
||||
"typeRoots": ["node_modules/@types"] |
||||
}, |
||||
"exclude": ["dist", "node_modules"], |
||||
"extends": "@grafana/tsconfig", |
||||
"include": ["src/**/*.ts"] |
||||
} |
@ -1,129 +0,0 @@ |
||||
import { TestData } from '../pages/testdata'; |
||||
import { Panel } from '../pages/panel'; |
||||
import { Graph } from '../pages/graph'; |
||||
import { componentFactory } from '../support'; |
||||
import { Dashboard } from '../pages/dashboard'; |
||||
|
||||
export const Components = { |
||||
DataSource: { |
||||
TestData, |
||||
}, |
||||
Panels: { |
||||
Panel, |
||||
Visualization: { |
||||
Graph, |
||||
}, |
||||
}, |
||||
Drawer: { |
||||
General: componentFactory({ |
||||
selectors: { |
||||
title: (title: string) => `Drawer title ${title}`, |
||||
expand: 'Drawer expand', |
||||
contract: 'Drawer contract', |
||||
close: 'Drawer close', |
||||
rcContentWrapper: () => '.drawer-content-wrapper', |
||||
}, |
||||
}), |
||||
}, |
||||
PanelEditor: { |
||||
General: componentFactory({ |
||||
selectors: { |
||||
content: 'Panel editor content', |
||||
}, |
||||
}), |
||||
OptionsPane: componentFactory({ |
||||
selectors: { |
||||
content: 'Panel editor option pane content', |
||||
close: Dashboard.selectors.toolbarItems('Close options pane'), |
||||
open: Dashboard.selectors.toolbarItems('Open options pane'), |
||||
select: 'Panel editor option pane select', |
||||
}, |
||||
}), |
||||
// not sure about the naming *DataPane*
|
||||
DataPane: componentFactory({ |
||||
selectors: { |
||||
content: 'Panel editor data pane content', |
||||
}, |
||||
}), |
||||
}, |
||||
PanelInspector: { |
||||
Data: componentFactory({ |
||||
selectors: { |
||||
content: 'Panel inspector Data content', |
||||
}, |
||||
}), |
||||
Stats: componentFactory({ |
||||
selectors: { |
||||
content: 'Panel inspector Stats content', |
||||
}, |
||||
}), |
||||
Json: componentFactory({ |
||||
selectors: { |
||||
content: 'Panel inspector Json content', |
||||
}, |
||||
}), |
||||
Query: componentFactory({ |
||||
selectors: { |
||||
content: 'Panel inspector Query content', |
||||
}, |
||||
}), |
||||
}, |
||||
Tab: componentFactory({ |
||||
selectors: { |
||||
title: (title: string) => `Tab ${title}`, |
||||
active: () => '[class*="-activeTabStyle"]', |
||||
}, |
||||
}), |
||||
QueryTab: componentFactory({ |
||||
selectors: { |
||||
content: 'Query editor tab content', |
||||
queryInspectorButton: 'Query inspector button', |
||||
}, |
||||
}), |
||||
AlertTab: componentFactory({ |
||||
selectors: { |
||||
content: 'Alert editor tab content', |
||||
}, |
||||
}), |
||||
TransformTab: componentFactory({ |
||||
selectors: { |
||||
content: 'Transform editor tab content', |
||||
}, |
||||
}), |
||||
QueryEditorToolbarItem: componentFactory({ |
||||
selectors: { |
||||
button: (title: string) => `QueryEditor toolbar item button ${title}`, |
||||
}, |
||||
}), |
||||
BackButton: componentFactory({ |
||||
selectors: { |
||||
backArrow: 'Go Back button', |
||||
}, |
||||
}), |
||||
OptionsGroup: componentFactory({ |
||||
selectors: { |
||||
toggle: (title: string) => `Options group ${title}`, |
||||
}, |
||||
}), |
||||
PluginVisualization: componentFactory({ |
||||
selectors: { |
||||
item: (title: string) => `Plugin visualization item ${title}`, |
||||
current: () => '[class*="-currentVisualizationItem"]', |
||||
}, |
||||
}), |
||||
Select: componentFactory({ |
||||
selectors: { |
||||
option: 'Select option', |
||||
}, |
||||
}), |
||||
FieldConfigEditor: componentFactory({ |
||||
selectors: { |
||||
content: 'Field config editor content', |
||||
}, |
||||
}), |
||||
OverridesConfigEditor: componentFactory({ |
||||
selectors: { |
||||
content: 'Field overrides editor content', |
||||
}, |
||||
}), |
||||
}; |
@ -1,28 +0,0 @@ |
||||
// @ts-nocheck
|
||||
// importing the e2e package in Grafana will cause transpile errors because
|
||||
// Cypress is an unknown type. Adding the Cypress types would overwrite all jest test types like
|
||||
// toBe, toEqual and so forth. That's why this file is not type checked and will be so until we
|
||||
// can solve the above mentioned issue with Cypress/Jest.
|
||||
import { e2eScenario, ScenarioArguments } from './support/scenario'; |
||||
import { Pages } from './pages'; |
||||
import { Components } from './components'; |
||||
import { Flows } from './flows'; |
||||
import { getScenarioContext, setScenarioContext } from './support/scenarioContext'; |
||||
|
||||
export type SelectorFunction = (text?: string) => Cypress.Chainable<JQuery<HTMLElement>>; |
||||
export type VisitFunction = (args?: string) => Cypress.Chainable<Window>; |
||||
|
||||
const e2eObject = { |
||||
env: (args: string) => Cypress.env(args), |
||||
config: () => Cypress.config(), |
||||
blobToBase64String: (blob: any) => Cypress.Blob.blobToBase64String(blob), |
||||
imgSrcToBlob: (url: string) => Cypress.Blob.imgSrcToBlob(url), |
||||
scenario: (args: ScenarioArguments) => e2eScenario(args), |
||||
pages: Pages, |
||||
components: Components, |
||||
flows: Flows, |
||||
getScenarioContext, |
||||
setScenarioContext, |
||||
}; |
||||
|
||||
export const e2e: (() => Cypress.cy) & typeof e2eObject = Object.assign(() => cy, e2eObject); |
@ -1,8 +0,0 @@ |
||||
import { pageFactory } from '../support'; |
||||
|
||||
export const AddDashboard = pageFactory({ |
||||
url: '/dashboard/new', |
||||
selectors: { |
||||
addNewPanel: 'Add new panel', |
||||
}, |
||||
}); |
@ -1,8 +0,0 @@ |
||||
import { pageFactory } from '../support'; |
||||
|
||||
export const AddDataSource = pageFactory({ |
||||
url: '/datasources/new', |
||||
selectors: { |
||||
dataSourcePlugins: (pluginName: string) => `Data source plugin item ${pluginName}`, |
||||
}, |
||||
}); |
@ -1,8 +0,0 @@ |
||||
import { pageFactory } from '../support'; |
||||
|
||||
export const ConfirmModal = pageFactory({ |
||||
url: '', |
||||
selectors: { |
||||
delete: 'Confirm Modal Danger Button', |
||||
}, |
||||
}); |
@ -1,9 +0,0 @@ |
||||
import { pageFactory } from '../support'; |
||||
|
||||
export const Dashboard = pageFactory({ |
||||
url: (uid: string) => `/d/${uid}`, |
||||
selectors: { |
||||
toolbarItems: (button: string) => `Dashboard navigation bar button ${button}`, |
||||
navBar: () => '.navbar', |
||||
}, |
||||
}); |
@ -1,11 +0,0 @@ |
||||
import { pageFactory } from '../support'; |
||||
|
||||
export const DashboardSettings = pageFactory({ |
||||
url: '', |
||||
selectors: { |
||||
deleteDashBoard: 'Dashboard settings page delete dashboard button', |
||||
sectionItems: (item: string) => `Dashboard settings section item ${item}`, |
||||
saveDashBoard: 'Dashboard settings aside actions Save button', |
||||
saveAsDashBoard: 'Dashboard settings aside actions Save As button', |
||||
}, |
||||
}); |
@ -1,8 +0,0 @@ |
||||
import { pageFactory } from '../support'; |
||||
|
||||
export const Dashboards = pageFactory({ |
||||
url: '/dashboards', |
||||
selectors: { |
||||
dashboards: (title: string) => `Dashboard search item ${title}`, |
||||
}, |
||||
}); |
@ -1,12 +0,0 @@ |
||||
import { pageFactory } from '../support'; |
||||
|
||||
export const DataSource = pageFactory({ |
||||
url: '', |
||||
selectors: { |
||||
name: 'Data source settings page name input field', |
||||
delete: 'Data source settings page Delete button', |
||||
saveAndTest: 'Data source settings page Save and Test button', |
||||
alert: 'Data source settings page Alert', |
||||
alertMessage: 'Data source settings page Alert message', |
||||
}, |
||||
}); |
@ -1,8 +0,0 @@ |
||||
import { pageFactory } from '../support'; |
||||
|
||||
export const DataSources = pageFactory({ |
||||
url: '/datasources', |
||||
selectors: { |
||||
dataSources: (dataSourceName: string) => `Data source list item ${dataSourceName}`, |
||||
}, |
||||
}); |
@ -1,9 +0,0 @@ |
||||
import { pageFactory } from '../support'; |
||||
|
||||
export const Explore = pageFactory({ |
||||
url: '/explore', |
||||
selectors: { |
||||
container: 'Explore', |
||||
runButton: 'Run button', |
||||
}, |
||||
}); |
@ -1,13 +0,0 @@ |
||||
import { VisualizationTab } from './visualizationTab'; |
||||
import { pageFactory } from '../../support'; |
||||
|
||||
export const Graph = { |
||||
VisualizationTab, |
||||
Legend: pageFactory({ |
||||
url: '', |
||||
selectors: { |
||||
legendItemAlias: (name: string) => `gpl alias ${name}`, |
||||
showLegendSwitch: 'gpl show legend', |
||||
}, |
||||
}), |
||||
}; |
@ -1,11 +0,0 @@ |
||||
import { pageFactory } from '../../support'; |
||||
|
||||
export const VisualizationTab = pageFactory({ |
||||
url: '', |
||||
selectors: { |
||||
xAxisSection: 'X-Axis section', |
||||
axesSection: 'Axes section', |
||||
legendSection: 'Legend section', |
||||
displaySection: 'Display section', |
||||
}, |
||||
}); |
@ -1,47 +0,0 @@ |
||||
import { Login } from './login'; |
||||
import { AddDataSource } from './addDataSource'; |
||||
import { DataSource } from './datasource'; |
||||
import { DataSources } from './datasources'; |
||||
import { ConfirmModal } from './confirmModal'; |
||||
import { AddDashboard } from './addDashboard'; |
||||
import { Dashboard } from './dashboard'; |
||||
import { SaveDashboardAsModal } from './saveDashboardAsModal'; |
||||
import { Dashboards } from './dashboards'; |
||||
import { DashboardSettings } from './dashboardSettings'; |
||||
import { Explore } from './explore'; |
||||
import { SaveDashboardModal } from './saveDashboardModal'; |
||||
import { SharePanelModal } from './sharePanelModal'; |
||||
import { ConstantVariable, QueryVariable, VariableGeneral, Variables, VariablesSubMenu } from './variables'; |
||||
|
||||
export const Pages = { |
||||
Login, |
||||
DataSource, |
||||
DataSources, |
||||
AddDataSource, |
||||
ConfirmModal, |
||||
AddDashboard, |
||||
Dashboard: { |
||||
visit: (uid: string) => Dashboard.visit(uid), |
||||
Toolbar: Dashboard, |
||||
SubMenu: VariablesSubMenu, |
||||
Settings: { |
||||
General: DashboardSettings, |
||||
Variables: { |
||||
List: Variables, |
||||
Edit: { |
||||
General: VariableGeneral, |
||||
QueryVariable: QueryVariable, |
||||
ConstantVariable: ConstantVariable, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
Dashboards, |
||||
SaveDashboardAsModal, |
||||
SaveDashboardModal, |
||||
SharePanelModal, |
||||
Explore: { |
||||
visit: () => Explore.visit(), |
||||
General: Explore, |
||||
}, |
||||
}; |
@ -1,11 +0,0 @@ |
||||
import { pageFactory } from '../support'; |
||||
|
||||
export const Login = pageFactory({ |
||||
url: '/login', |
||||
selectors: { |
||||
username: 'Username input field', |
||||
password: 'Password input field', |
||||
submit: 'Login button', |
||||
skip: 'Skip change password button', |
||||
}, |
||||
}); |
@ -1,9 +0,0 @@ |
||||
import { pageFactory } from '../support'; |
||||
|
||||
export const Panel = pageFactory({ |
||||
url: '', |
||||
selectors: { |
||||
title: (title: string) => `Panel header title item ${title}`, |
||||
headerItems: (item: string) => `Panel header item ${item}`, |
||||
}, |
||||
}); |
@ -1,9 +0,0 @@ |
||||
import { pageFactory } from '../support'; |
||||
|
||||
export const SaveDashboardAsModal = pageFactory({ |
||||
url: '', |
||||
selectors: { |
||||
newName: 'Save dashboard title field', |
||||
save: 'Save dashboard button', |
||||
}, |
||||
}); |
@ -1,10 +0,0 @@ |
||||
import { pageFactory } from '../support'; |
||||
|
||||
export const SaveDashboardModal = pageFactory({ |
||||
url: '', |
||||
selectors: { |
||||
save: 'Dashboard settings Save Dashboard Modal Save button', |
||||
saveVariables: 'Dashboard settings Save Dashboard Modal Save variables checkbox', |
||||
saveTimerange: 'Dashboard settings Save Dashboard Modal Save timerange checkbox', |
||||
}, |
||||
}); |
@ -1,8 +0,0 @@ |
||||
import { pageFactory } from '../support'; |
||||
|
||||
export const SharePanelModal = pageFactory({ |
||||
url: '', |
||||
selectors: { |
||||
linkToRenderedImage: 'Link to rendered image', |
||||
}, |
||||
}); |
@ -1,5 +0,0 @@ |
||||
import { QueryTab } from './queryTab'; |
||||
|
||||
export const TestData = { |
||||
QueryTab, |
||||
}; |
@ -1,13 +0,0 @@ |
||||
import { componentFactory } from '../../support'; |
||||
|
||||
export const QueryTab = componentFactory({ |
||||
selectors: { |
||||
scenarioSelect: 'Test Data Query scenario select', |
||||
max: 'TestData max', |
||||
min: 'TestData min', |
||||
noise: 'TestData noise', |
||||
seriesCount: 'TestData series count', |
||||
spread: 'TestData spread', |
||||
startValue: 'TestData start value', |
||||
}, |
||||
}); |
@ -1,69 +0,0 @@ |
||||
import { pageFactory } from '../support'; |
||||
|
||||
export const Variables = pageFactory({ |
||||
url: '', |
||||
selectors: { |
||||
addVariableCTA: 'Call to action button Add variable', |
||||
newButton: 'Variable editor New variable button', |
||||
table: 'Variable editor Table', |
||||
tableRowNameFields: (variableName: string) => `Variable editor Table Name field ${variableName}`, |
||||
tableRowDefinitionFields: (variableName: string) => `Variable editor Table Definition field ${variableName}`, |
||||
tableRowArrowUpButtons: (variableName: string) => `Variable editor Table ArrowUp button ${variableName}`, |
||||
tableRowArrowDownButtons: (variableName: string) => `Variable editor Table ArrowDown button ${variableName}`, |
||||
tableRowDuplicateButtons: (variableName: string) => `Variable editor Table Duplicate button ${variableName}`, |
||||
tableRowRemoveButtons: (variableName: string) => `Variable editor Table Remove button ${variableName}`, |
||||
}, |
||||
}); |
||||
|
||||
export const VariablesSubMenu = pageFactory({ |
||||
url: '', |
||||
selectors: { |
||||
submenuItem: 'Dashboard template variables submenu item', |
||||
submenuItemLabels: (item: string) => `Dashboard template variables submenu Label ${item}`, |
||||
submenuItemValueDropDownValueLinkTexts: (item: string) => |
||||
`Dashboard template variables Variable Value DropDown value link text ${item}`, |
||||
submenuItemValueDropDownDropDown: 'Dashboard template variables Variable Value DropDown DropDown', |
||||
submenuItemValueDropDownOptionTexts: (item: string) => |
||||
`Dashboard template variables Variable Value DropDown option text ${item}`, |
||||
}, |
||||
}); |
||||
|
||||
export const VariableGeneral = pageFactory({ |
||||
url: '', |
||||
selectors: { |
||||
headerLink: 'Variable editor Header link', |
||||
modeLabelNew: 'Variable editor Header mode New', |
||||
modeLabelEdit: 'Variable editor Header mode Edit', |
||||
generalNameInput: 'Variable editor Form Name field', |
||||
generalTypeSelect: 'Variable editor Form Type select', |
||||
generalLabelInput: 'Variable editor Form Label field', |
||||
generalHideSelect: 'Variable editor Form Hide select', |
||||
selectionOptionsMultiSwitch: 'Variable editor Form Multi switch', |
||||
selectionOptionsIncludeAllSwitch: 'Variable editor Form IncludeAll switch', |
||||
selectionOptionsCustomAllInput: 'Variable editor Form IncludeAll field', |
||||
previewOfValuesOption: 'Variable editor Preview of Values option', |
||||
addButton: 'Variable editor Add button', |
||||
updateButton: 'Variable editor Update button', |
||||
}, |
||||
}); |
||||
|
||||
export const QueryVariable = pageFactory({ |
||||
url: '', |
||||
selectors: { |
||||
queryOptionsDataSourceSelect: 'Variable editor Form Query DataSource select', |
||||
queryOptionsRefreshSelect: 'Variable editor Form Query Refresh select', |
||||
queryOptionsRegExInput: 'Variable editor Form Query RegEx field', |
||||
queryOptionsSortSelect: 'Variable editor Form Query Sort select', |
||||
queryOptionsQueryInput: 'Variable editor Form Default Variable Query Editor textarea', |
||||
valueGroupsTagsEnabledSwitch: 'Variable editor Form Query UseTags switch', |
||||
valueGroupsTagsTagsQueryInput: 'Variable editor Form Query TagsQuery field', |
||||
valueGroupsTagsTagsValuesQueryInput: 'Variable editor Form Query TagsValuesQuery field', |
||||
}, |
||||
}); |
||||
|
||||
export const ConstantVariable = pageFactory({ |
||||
url: '', |
||||
selectors: { |
||||
constantOptionsQueryInput: 'Variable editor Form Constant Query field', |
||||
}, |
||||
}); |
@ -1,76 +1,99 @@ |
||||
import { CssSelector, FunctionSelector, Selectors, StringSelector, UrlSelector } from '@grafana/e2e-selectors'; |
||||
import { e2e } from '../index'; |
||||
import { Selector } from './selector'; |
||||
import { fromBaseUrl } from './url'; |
||||
import { e2e } from '../index'; |
||||
import { SelectorFunction, VisitFunction } from '../noTypeCheck'; |
||||
|
||||
export type Selectors = Record<string, string | Function>; |
||||
export type SelectorFunctions<S> = { [P in keyof S]: SelectorFunction }; |
||||
export type VisitFunction = (args?: string) => Cypress.Chainable<Window>; |
||||
export type E2EVisit = { visit: VisitFunction }; |
||||
export type E2EFunction = (text?: string) => Cypress.Chainable<JQuery<HTMLElement>>; |
||||
|
||||
export type Page<S> = SelectorFunctions<S> & { |
||||
selectors: S; |
||||
visit: VisitFunction; |
||||
export type TypeSelectors<S> = S extends StringSelector |
||||
? E2EFunction |
||||
: S extends FunctionSelector |
||||
? E2EFunction |
||||
: S extends CssSelector |
||||
? E2EFunction |
||||
: S extends UrlSelector |
||||
? E2EVisit & Omit<E2EFunctions<S>, 'url'> |
||||
: S extends Record<any, any> |
||||
? E2EFunctions<S> |
||||
: S; |
||||
|
||||
export type E2EFunctions<S extends Selectors> = { |
||||
[P in keyof S]: TypeSelectors<S[P]>; |
||||
}; |
||||
export interface PageFactoryArgs<S> { |
||||
selectors: S; |
||||
url?: string | Function; |
||||
} |
||||
|
||||
export const pageFactory = <S extends Selectors>({ url, selectors }: PageFactoryArgs<S>): Page<S> => { |
||||
const visit = (args?: string) => { |
||||
if (!url) { |
||||
return e2e().visit(''); |
||||
} |
||||
|
||||
let parsedUrl = ''; |
||||
if (typeof url === 'string') { |
||||
parsedUrl = fromBaseUrl(url); |
||||
} |
||||
export type E2EObjects<S extends Selectors> = E2EFunctions<S>; |
||||
|
||||
if (typeof url === 'function' && args) { |
||||
parsedUrl = fromBaseUrl(url(args)); |
||||
} |
||||
export type E2EFactoryArgs<S extends Selectors> = { selectors: S }; |
||||
|
||||
e2e().logToConsole('Visiting', parsedUrl); |
||||
return e2e().visit(parsedUrl); |
||||
}; |
||||
const pageObjects: SelectorFunctions<S> = {} as SelectorFunctions<S>; |
||||
const processSelectors = <S extends Selectors>(e2eObjects: E2EFunctions<S>, selectors: S): E2EFunctions<S> => { |
||||
const logOutput = (data: any) => e2e().logToConsole('Retrieving Selector:', data); |
||||
const keys = Object.keys(selectors); |
||||
|
||||
keys.forEach(key => { |
||||
for (let index = 0; index < keys.length; index++) { |
||||
const key = keys[index]; |
||||
const value = selectors[key]; |
||||
|
||||
if (key === 'url') { |
||||
// @ts-ignore
|
||||
e2eObjects['visit'] = (args?: string) => { |
||||
let parsedUrl = ''; |
||||
if (typeof value === 'string') { |
||||
parsedUrl = fromBaseUrl(value); |
||||
} |
||||
|
||||
if (typeof value === 'function' && args) { |
||||
parsedUrl = fromBaseUrl(value(args)); |
||||
} |
||||
|
||||
e2e().logToConsole('Visiting', parsedUrl); |
||||
return e2e().visit(parsedUrl); |
||||
}; |
||||
|
||||
continue; |
||||
} |
||||
|
||||
if (typeof value === 'string') { |
||||
// @ts-ignore
|
||||
pageObjects[key] = () => { |
||||
e2e().logToConsole('Retrieving Selector:', value); |
||||
e2eObjects[key] = () => { |
||||
logOutput(value); |
||||
return e2e().get(Selector.fromAriaLabel(value)); |
||||
}; |
||||
|
||||
continue; |
||||
} |
||||
|
||||
if (typeof value === 'function') { |
||||
// @ts-ignore
|
||||
pageObjects[key] = (text?: string) => { |
||||
e2eObjects[key] = (text?: string) => { |
||||
if (!text) { |
||||
const selector = value(); |
||||
e2e().logToConsole('Retrieving Selector:', selector); |
||||
const selector = value((undefined as unknown) as string); |
||||
|
||||
logOutput(selector); |
||||
return e2e().get(selector); |
||||
} |
||||
|
||||
const selector = value(text); |
||||
e2e().logToConsole('Retrieving Selector:', selector); |
||||
|
||||
logOutput(selector); |
||||
return e2e().get(Selector.fromAriaLabel(selector)); |
||||
}; |
||||
|
||||
continue; |
||||
} |
||||
|
||||
if (typeof value === 'object') { |
||||
// @ts-ignore
|
||||
e2eObjects[key] = processSelectors({}, value); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
return { |
||||
visit, |
||||
...pageObjects, |
||||
selectors, |
||||
}; |
||||
return e2eObjects; |
||||
}; |
||||
|
||||
type Component<S> = Omit<Page<S>, 'visit'>; |
||||
type ComponentFactoryArgs<S> = Omit<PageFactoryArgs<S>, 'url'>; |
||||
export const e2eFactory = <S extends Selectors>({ selectors }: E2EFactoryArgs<S>): E2EObjects<S> => { |
||||
const e2eObjects: E2EFunctions<S> = {} as E2EFunctions<S>; |
||||
processSelectors(e2eObjects, selectors); |
||||
|
||||
export const componentFactory = <S extends Selectors>(args: ComponentFactoryArgs<S>): Component<S> => { |
||||
const { visit, ...rest } = pageFactory(args); |
||||
return rest; |
||||
return { ...e2eObjects }; |
||||
}; |
||||
|
@ -1,6 +1,6 @@ |
||||
{ |
||||
"extends": ["@grafana/eslint-config"], |
||||
"rules": { |
||||
"no-restricted-imports": [2, "^@grafana/runtime.*", "^@grafana/ui.*"] |
||||
"no-restricted-imports": [2, "^@grafana/runtime.*", "^@grafana/ui.*", "^@grafana/e2e.*"] |
||||
} |
||||
} |
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue