From 6c5a0421fe8aa575e7609a328be2655a10405c75 Mon Sep 17 00:00:00 2001 From: Steven Vachon Date: Wed, 2 Sep 2020 20:37:23 -0400 Subject: [PATCH] @grafana/e2e: improve types (#27348) --- .../grafana-e2e/src/flows/addDashboard.ts | 51 +++++++++------- .../grafana-e2e/src/flows/addDataSource.ts | 11 ++-- packages/grafana-e2e/src/flows/addPanel.ts | 28 +++------ .../grafana-e2e/src/flows/configurePanel.ts | 60 +++++++++++++++---- packages/grafana-e2e/src/flows/editPanel.ts | 16 +++-- packages/grafana-e2e/src/flows/explore.ts | 39 +++++------- .../grafana-e2e/src/flows/openDashboard.ts | 18 ++++-- .../src/support/scenarioContext.ts | 2 +- 8 files changed, 125 insertions(+), 100 deletions(-) diff --git a/packages/grafana-e2e/src/flows/addDashboard.ts b/packages/grafana-e2e/src/flows/addDashboard.ts index 06c8afaba5c..f0c3093259e 100644 --- a/packages/grafana-e2e/src/flows/addDashboard.ts +++ b/packages/grafana-e2e/src/flows/addDashboard.ts @@ -15,24 +15,32 @@ export interface AddDashboardConfig { annotations: AddAnnotationConfig[]; timeRange: TimeRangeConfig; title: string; - variables: Array>; + variables: PartialAddVariableConfig[]; } -export interface AddVariableConfig { - constantValue?: string; - dataSource?: string; +interface AddVariableDefault { 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): any => { - const fullConfig = { +interface AddVariableOptional { + constantValue?: string; + dataSource?: string; + label?: string; + query?: string; + regex?: string; +} + +interface AddVariableRequired { + name: string; +} + +export type PartialAddVariableConfig = Partial & AddVariableOptional & AddVariableRequired; +export type AddVariableConfig = AddVariableDefault & AddVariableOptional & AddVariableRequired; + +// @todo this actually returns type `Cypress.Chainable` +export const addDashboard = (config?: Partial) => { + const fullConfig: AddDashboardConfig = { annotations: [], title: `e2e-${uuidv4()}`, variables: [], @@ -43,7 +51,7 @@ export const addDashboard = (config?: Partial): any => { zone: 'Coordinated Universal Time', ...config?.timeRange, }, - } as AddDashboardConfig; + }; const { annotations, timeRange, title, variables } = fullConfig; @@ -54,7 +62,9 @@ export const addDashboard = (config?: Partial): any => { if (annotations.length > 0 || variables.length > 0) { e2e.pages.Dashboard.Toolbar.toolbarItems('Dashboard settings').click(); addAnnotations(annotations); - addVariables(variables); + + fullConfig.variables = addVariables(variables); + e2e.components.BackButton.backArrow().click(); } @@ -137,13 +147,12 @@ const addAnnotation = (config: AddAnnotationConfig, isFirst: boolean) => { .click(); }; -// @todo this actually returns type `Cypress.Chainable` -const addAnnotations = (configs: AddAnnotationConfig[]): any => { +const addAnnotations = (configs: AddAnnotationConfig[]) => { if (configs.length > 0) { e2e.pages.Dashboard.Settings.General.sectionItems('Annotations').click(); } - return configs.map((config, i) => addAnnotation(config, i === 0)); + return configs.forEach((config, i) => addAnnotation(config, i === 0)); }; export const VARIABLE_HIDE_LABEL = 'Label'; @@ -155,13 +164,12 @@ export const VARIABLE_TYPE_CONSTANT = 'Constant'; export const VARIABLE_TYPE_DATASOURCE = 'Datasource'; export const VARIABLE_TYPE_QUERY = 'Query'; -// @todo this actually returns type `Cypress.Chainable` -const addVariable = (config: Partial, isFirst: boolean): any => { +const addVariable = (config: PartialAddVariableConfig, isFirst: boolean): AddVariableConfig => { const fullConfig = { hide: VARIABLE_HIDE_NOTHING, type: VARIABLE_TYPE_QUERY, ...config, - } as AddVariableConfig; + }; if (isFirst) { e2e.pages.Dashboard.Settings.Variables.List.addVariableCTA().click(); @@ -227,8 +235,7 @@ const addVariable = (config: Partial, isFirst: boolean): any return fullConfig; }; -// @todo this actually returns type `Cypress.Chainable` -const addVariables = (configs: Array>): any => { +const addVariables = (configs: PartialAddVariableConfig[]): AddVariableConfig[] => { if (configs.length > 0) { e2e.pages.Dashboard.Settings.General.sectionItems('Variables').click(); } diff --git a/packages/grafana-e2e/src/flows/addDataSource.ts b/packages/grafana-e2e/src/flows/addDataSource.ts index 321c693250f..d6b2353e820 100644 --- a/packages/grafana-e2e/src/flows/addDataSource.ts +++ b/packages/grafana-e2e/src/flows/addDataSource.ts @@ -9,16 +9,15 @@ export interface AddDataSourceConfig { basicAuthUser: string; checkHealth: boolean; expectedAlertMessage: string | RegExp; - form: Function; + form: () => void; name: string; skipTlsVerify: boolean; 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): any => { - const fullConfig = { +// @todo this actually returns type `Cypress.Chainable` +export const addDataSource = (config?: Partial) => { + const fullConfig: AddDataSourceConfig = { basicAuth: false, basicAuthPassword: '', basicAuthUser: '', @@ -29,7 +28,7 @@ export const addDataSource = (config?: Partial): any => { skipTlsVerify: false, type: 'TestData DB', ...config, - } as AddDataSourceConfig; + }; const { basicAuth, diff --git a/packages/grafana-e2e/src/flows/addPanel.ts b/packages/grafana-e2e/src/flows/addPanel.ts index 0dd3f1b8a8d..9e1907f09bb 100644 --- a/packages/grafana-e2e/src/flows/addPanel.ts +++ b/packages/grafana-e2e/src/flows/addPanel.ts @@ -1,24 +1,14 @@ -import { configurePanel, ConfigurePanelConfig } from './configurePanel'; +import { configurePanel, PartialAddPanelConfig } from './configurePanel'; import { getScenarioContext } from '../support/scenarioContext'; import { v4 as uuidv4 } from 'uuid'; -// @todo `Omit` 'isExplore' -export interface AddPanelConfig extends ConfigurePanelConfig { - dataSourceName: string; - queriesForm: (config: AddPanelConfig) => void; - 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): any => +export const addPanel = (config?: Partial) => getScenarioContext().then(({ lastAddedDataSource }: any) => - configurePanel( - { - dataSourceName: lastAddedDataSource, - panelTitle: `e2e-${uuidv4()}`, - ...config, - } as AddPanelConfig, - false - ) + configurePanel({ + dataSourceName: lastAddedDataSource, + panelTitle: `e2e-${uuidv4()}`, + ...config, + isEdit: false, + isExplore: false, + }) ); diff --git a/packages/grafana-e2e/src/flows/configurePanel.ts b/packages/grafana-e2e/src/flows/configurePanel.ts index 5b2f592a34d..3e57ca4ef5f 100644 --- a/packages/grafana-e2e/src/flows/configurePanel.ts +++ b/packages/grafana-e2e/src/flows/configurePanel.ts @@ -5,45 +5,75 @@ import { selectOption } from './selectOption'; import { setDashboardTimeRange } from './setDashboardTimeRange'; import { setTimeRange, TimeRangeConfig } from './setTimeRange'; -export interface ConfigurePanelConfig { +interface AddPanelOverrides { + dataSourceName: string; + queriesForm: (config: AddPanelConfig) => void; + panelTitle: string; +} + +interface EditPanelOverrides { + queriesForm?: (config: EditPanelConfig) => void; + panelTitle: string; +} + +interface ConfigurePanelDefault { chartData: { method: string; route: string | RegExp; }; dashboardUid: string; - dataSourceName?: string; - isExplore: boolean; matchScreenshot: boolean; - queriesForm?: (config: any) => void; - panelTitle: string; + saveDashboard: boolean; screenshotName: string; - timeRange?: TimeRangeConfig; visitDashboardAtStart: boolean; // @todo remove when possible +} + +interface ConfigurePanelOptional { + dataSourceName?: string; + queriesForm?: (config: ConfigurePanelConfig) => void; + panelTitle?: string; + timeRange?: TimeRangeConfig; 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, isEdit: boolean): any => +interface ConfigurePanelRequired { + isEdit: boolean; + isExplore: boolean; +} + +export type PartialConfigurePanelConfig = Partial & + ConfigurePanelOptional & + ConfigurePanelRequired; + +export type ConfigurePanelConfig = ConfigurePanelDefault & ConfigurePanelOptional & ConfigurePanelRequired; + +export type PartialAddPanelConfig = PartialConfigurePanelConfig & AddPanelOverrides; +export type AddPanelConfig = ConfigurePanelConfig & AddPanelOverrides; + +export type PartialEditPanelConfig = PartialConfigurePanelConfig & EditPanelOverrides; +export type EditPanelConfig = ConfigurePanelConfig & EditPanelOverrides; + +// @todo this actually returns type `Cypress.Chainable` +export const configurePanel = (config: PartialAddPanelConfig | PartialEditPanelConfig | PartialConfigurePanelConfig) => getScenarioContext().then(({ lastAddedDashboardUid }: any) => { - const fullConfig = { + const fullConfig: AddPanelConfig | EditPanelConfig | ConfigurePanelConfig = { chartData: { method: 'POST', route: '/api/ds/query', }, dashboardUid: lastAddedDashboardUid, - isExplore: false, matchScreenshot: false, saveDashboard: true, screenshotName: 'panel-visualization', visitDashboardAtStart: true, ...config, - } as ConfigurePanelConfig; + }; const { chartData, dashboardUid, dataSourceName, + isEdit, isExplore, matchScreenshot, panelTitle, @@ -54,6 +84,10 @@ export const configurePanel = (config: Partial, isEdit: bo visualizationName, } = fullConfig; + if (isEdit && isExplore) { + throw new TypeError('Invalid configuration'); + } + if (isExplore) { e2e.pages.Explore.visit(); } else { @@ -108,7 +142,7 @@ export const configurePanel = (config: Partial, isEdit: bo .find('[value="Panel Title"]') .scrollIntoView() .clear() - .type(panelTitle); + .type(panelTitle as string); } if (visualizationName) { diff --git a/packages/grafana-e2e/src/flows/editPanel.ts b/packages/grafana-e2e/src/flows/editPanel.ts index fcf4a04e46d..c003d4729a5 100644 --- a/packages/grafana-e2e/src/flows/editPanel.ts +++ b/packages/grafana-e2e/src/flows/editPanel.ts @@ -1,10 +1,8 @@ -import { configurePanel, ConfigurePanelConfig } from './configurePanel'; +import { configurePanel, PartialEditPanelConfig } from './configurePanel'; -// @todo `Omit` 'isExplore' -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): any => configurePanel(config, true); +export const editPanel = (config: Partial) => + configurePanel({ + ...config, + isEdit: true, + isExplore: false, + }); diff --git a/packages/grafana-e2e/src/flows/explore.ts b/packages/grafana-e2e/src/flows/explore.ts index 515e4728a82..cc9dd1047c2 100644 --- a/packages/grafana-e2e/src/flows/explore.ts +++ b/packages/grafana-e2e/src/flows/explore.ts @@ -1,28 +1,19 @@ -import { configurePanel, ConfigurePanelConfig } from './configurePanel'; +import { configurePanel, PartialConfigurePanelConfig } from './configurePanel'; import { getScenarioContext } from '../support/scenarioContext'; -// @todo `Omit` 'dashboardUid' and 'panelTitle' -export interface ExploreConfig extends ConfigurePanelConfig { - queriesForm: (config: ExploreConfig) => void; -} - -// @todo improve config input/output: https://stackoverflow.com/a/63507459/923745 -// @todo this actually returns type `Cypress.Chainable` -export const explore = (config: Partial): any => +export const explore = (config: Partial) => getScenarioContext().then(({ lastAddedDataSource }: any) => - configurePanel( - { - dataSourceName: lastAddedDataSource, - isExplore: true, - screenshotName: 'explore-graph', - ...config, - timeRange: { - from: '2020-01-01 00:00:00', - to: '2020-01-01 06:00:00', - zone: 'Coordinated Universal Time', - ...config.timeRange, - }, - } as ExploreConfig, - false - ) + configurePanel({ + dataSourceName: lastAddedDataSource, + screenshotName: 'explore-graph', + ...config, + isEdit: false, + isExplore: true, + timeRange: { + from: '2020-01-01 00:00:00', + to: '2020-01-01 06:00:00', + zone: 'Coordinated Universal Time', + ...config.timeRange, + }, + }) ); diff --git a/packages/grafana-e2e/src/flows/openDashboard.ts b/packages/grafana-e2e/src/flows/openDashboard.ts index b379691f328..3bbcec024c5 100644 --- a/packages/grafana-e2e/src/flows/openDashboard.ts +++ b/packages/grafana-e2e/src/flows/openDashboard.ts @@ -2,18 +2,24 @@ import { e2e } from '../index'; import { getScenarioContext } from '../support/scenarioContext'; import { setDashboardTimeRange, TimeRangeConfig } from './setDashboardTimeRange'; -export interface OpenDashboardConfig { - timeRange?: TimeRangeConfig; +interface OpenDashboardDefault { uid: string; } -// @todo improve config input/output: https://stackoverflow.com/a/63507459/923745 -export const openDashboard = (config?: Partial) => +interface OpenDashboardOptional { + timeRange?: TimeRangeConfig; +} + +export type PartialOpenDashboardConfig = Partial & OpenDashboardOptional; +export type OpenDashboardConfig = OpenDashboardDefault & OpenDashboardOptional; + +// @todo this actually returns type `Cypress.Chainable` +export const openDashboard = (config?: PartialOpenDashboardConfig) => getScenarioContext().then(({ lastAddedDashboardUid }: any) => { - const fullConfig = { + const fullConfig: OpenDashboardConfig = { uid: lastAddedDashboardUid, ...config, - } as OpenDashboardConfig; + }; const { timeRange, uid } = fullConfig; diff --git a/packages/grafana-e2e/src/support/scenarioContext.ts b/packages/grafana-e2e/src/support/scenarioContext.ts index 974c621cfd3..eeba3776c6e 100644 --- a/packages/grafana-e2e/src/support/scenarioContext.ts +++ b/packages/grafana-e2e/src/support/scenarioContext.ts @@ -39,7 +39,7 @@ export const getScenarioContext = (): any => e2e() .wrap( { - getScenarioContext: () => ({ ...scenarioContext } as ScenarioContext), + getScenarioContext: (): ScenarioContext => ({ ...scenarioContext }), }, { log: false } )