From 5c85ff134eb1bb35e36b28c0d660659a990a2476 Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Tue, 26 Mar 2024 10:06:50 +0100 Subject: [PATCH] Plugin E2E: Change package imports and exports (#838) --- packages/plugin-e2e/src/api.ts | 295 ------------- packages/plugin-e2e/src/auth/auth.setup.ts | 2 +- .../src/fixtures/annotationEditPage.ts | 15 +- .../src/fixtures/commands/createDataSource.ts | 10 +- .../commands/createDataSourceConfigPage.ts | 12 +- .../src/fixtures/commands/createUser.ts | 9 +- .../commands/gotoAnnotationEditPage.ts | 12 +- .../fixtures/commands/gotoAppConfigPage.ts | 11 +- .../src/fixtures/commands/gotoAppPage.ts | 10 +- .../fixtures/commands/gotoDashboardPage.ts | 19 +- .../commands/gotoDataSourceConfigPage.ts | 15 +- .../fixtures/commands/gotoPanelEditPage.ts | 12 +- .../fixtures/commands/gotoVariableEditPage.ts | 12 +- .../plugin-e2e/src/fixtures/commands/login.ts | 11 +- .../commands/readProvisionedDashboard.ts | 10 +- .../commands/readProvisionedDataSource.ts | 10 +- .../plugin-e2e/src/fixtures/dashboardPage.ts | 15 +- .../plugin-e2e/src/fixtures/explorePage.ts | 9 +- .../plugin-e2e/src/fixtures/grafanaVersion.ts | 4 +- packages/plugin-e2e/src/fixtures/index.ts | 49 --- .../src/fixtures/isFeatureToggleEnabled.ts | 12 +- packages/plugin-e2e/src/fixtures/page.ts | 9 +- .../plugin-e2e/src/fixtures/panelEditPage.ts | 11 +- packages/plugin-e2e/src/fixtures/selectors.ts | 9 +- packages/plugin-e2e/src/fixtures/types.ts | 11 - .../src/fixtures/variableEditPage.ts | 12 +- packages/plugin-e2e/src/index.ts | 105 ++++- packages/plugin-e2e/src/matchers/index.ts | 9 - packages/plugin-e2e/src/matchers/toBeOK.ts | 4 +- .../src/matchers/toDisplayPreviews.ts | 6 +- .../plugin-e2e/src/matchers/toHaveAlert.ts | 6 +- packages/plugin-e2e/src/models/index.ts | 15 - .../plugin-e2e/src/models/pages/AppPage.ts | 2 +- .../src/{options/index.ts => options.ts} | 6 +- packages/plugin-e2e/src/types.ts | 403 +++++++++++++++--- 35 files changed, 524 insertions(+), 638 deletions(-) delete mode 100644 packages/plugin-e2e/src/api.ts delete mode 100644 packages/plugin-e2e/src/fixtures/index.ts delete mode 100644 packages/plugin-e2e/src/fixtures/types.ts delete mode 100644 packages/plugin-e2e/src/matchers/index.ts delete mode 100644 packages/plugin-e2e/src/models/index.ts rename packages/plugin-e2e/src/{options/index.ts => options.ts} (72%) diff --git a/packages/plugin-e2e/src/api.ts b/packages/plugin-e2e/src/api.ts deleted file mode 100644 index 80103b4c9..000000000 --- a/packages/plugin-e2e/src/api.ts +++ /dev/null @@ -1,295 +0,0 @@ -import { test as base, expect as baseExpect, selectors } from '@playwright/test'; -import { E2ESelectors } from './e2e-selectors/types'; -import fixtures from './fixtures'; -import matchers from './matchers'; -import { - CreateDataSourceArgs, - CreateDataSourcePageArgs, - DataSourceSettings, - ReadProvisionedDashboardArgs, - ReadProvisionedDataSourceArgs, - CreateUserArgs, - Dashboard, - DashboardPageArgs, - DashboardEditViewArgs, - GotoAppConfigPageArgs, - GotoAppPageArgs, -} from './types'; -import { - PanelEditPage, - GrafanaPage, - DataSourceConfigPage, - DashboardPage, - VariableEditPage, - AnnotationEditPage, - AppConfigPage, - AppPage, -} from './models'; -import { grafanaE2ESelectorEngine } from './selectorEngine'; -import { ExplorePage } from './models/pages/ExplorePage'; -import options from './options'; - -export type PluginOptions = { - /** - * When using the readProvisioning fixture, files will be read from this directory. If no directory is provided, - * the 'provisioning' directory in the current working directory will be used. - * - * eg. - * export default defineConfig({ - use: { - provisioningRootDir: 'path/to/provisioning', - }, - }); - * - */ - provisioningRootDir: string; - /** - * Optionally, you can add or override feature toggles. - * The feature toggles you specify here will only work in the frontend. If you need a feature toggle to work across the entire stack, you - * need to need to enable the feature in the Grafana config. See https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#feature_toggles - * - * To override feature toggles globally in the playwright.config.ts file: - * export default defineConfig({ - use: { - featureToggles: { - exploreMixedDatasource: true, - redshiftAsyncQueryDataSupport: false - }, - }, - }); - * - * To override feature toggles for tests on a certain file: - test.use({ - featureToggles: { - exploreMixedDatasource: true, - }, - * }); - */ - featureToggles: Record; - - /** - * The Grafana user to use for the tests. If no user is provided, the default admin/admin user will be used. - * - * You can use different users for different projects. See the fixture createUser for more information on how to create a user, - * and the fixture login for more information on how to authenticate. - */ - user?: CreateUserArgs; -}; - -export type PluginFixture = { - /** - * The current Grafana version. - * - * If a GRAFANA_VERSION environment variable is set, this will be used. Otherwise, - * the version will be picked from window.grafanaBootData.settings.buildInfo.version. - */ - grafanaVersion: string; - - /** - * The E2E selectors to use for the current version of Grafana - */ - selectors: E2ESelectors; - - /** - * Isolated {@link DashboardPage} instance for each test. - * - * Navigates to a new to a new dashboard page. - */ - dashboardPage: DashboardPage; - - /** - * Isolated {@link PanelEditPage} instance for each test. - * - * Navigates to a new dashboard page and adds a new panel. - * - * Use {@link PanelEditPage.setVisualization} to change the visualization - * Use {@link PanelEditPage.datasource.set} to change the datasource - * Use {@link ExplorePage.getQueryEditorEditorRow} to retrieve the query - * editor row locator for a given query refId - */ - panelEditPage: PanelEditPage; - - /** - * Isolated {@link VariableEditPage} instance for each test. - * - * Navigates to a new dashboard page and adds a new variable. - * - * Use {@link VariableEditPage.setVariableType} to change the variable type - */ - variableEditPage: VariableEditPage; - - /** - * Isolated {@link AnnotationEditPage} instance for each test. - * - * Navigates to a new dashboard page and adds a new annotation. - * - * Use {@link AnnotationEditPage.datasource.set} to change the datasource - */ - annotationEditPage: AnnotationEditPage; - - /** - * Isolated {@link ExplorePage} instance for each test. - * - * Navigates to a the explore page. - * - * Use {@link ExplorePage.datasource.set} to change the datasource - * Use {@link ExplorePage.getQueryEditorEditorRow} to retrieve the query editor - * row locator for a given query refId - */ - explorePage: ExplorePage; - - /** - * Fixture command that will create an isolated DataSourceConfigPage instance for a given data source type. - * - * The data source config page cannot be navigated to without a data source uid, so this fixture will create a new - * data source using the Grafana API, create a new DataSourceConfigPage instance and navigate to the page. - */ - createDataSourceConfigPage: (args: CreateDataSourcePageArgs) => Promise; - - /** - * Fixture command that creates a data source via the Grafana API. - * - * If you have tests that depend on the the existance of a data source, - * you may use this command in a setup project. Read more about setup projects - * here: https://playwright.dev/docs/auth#basic-shared-account-in-all-tests - */ - createDataSource: (args: CreateDataSourceArgs) => Promise; - - /** - * Fixture command that creates a user via the Grafana API and assigns a role to it if a role is provided - * This may be useful if your plugin supports RBAC and you need to create a user with a specific role. See login fixture for more information. - */ - createUser: () => Promise; - - /** - * Fixture command that login to Grafana using the Grafana API and stores the cookie state on disk. - * The file name for the storage state will be `playwright/.auth/.json`, so it's important that the username is unique. - * - * If you have not specified a user, the default admin/admin credentials will be used. - * - * e.g - * projects: [ - { - name: 'authenticate', - testDir: './src/auth', - testMatch: [/.*auth\.setup\.ts/], - }, - { - name: 'run tests as admin user', - testDir: './tests', - use: { - ...devices['Desktop Chrome'], - storageState: 'playwright/.auth/admin.json', - }, - dependencies: ['authenticate'], - } - } - * - * If your plugin supports RBAC, you may want to use different projects for different roles. - * In the following example, a new user with the role `Viewer` gets created and authenticated in a `createUserAndAuthenticate` project. - * In the `viewer` project, authentication state from the previous project is used in all tests in the ./tests/viewer folder. - * projects: [ - { - name: 'createUserAndAuthenticate', - testDir: 'node_modules/@grafana/plugin-e2e/dist/auth', - testMatch: [/.*auth\.setup\.ts/], - use: { - user: { - user: 'viewer', - password: 'password', - role: 'Viewer', - }, - }, - }, - { - name: 'viewer', - testDir: './tests/viewer', - use: { - ...devices['Desktop Chrome'], - storageState: 'playwright/.auth/viewer.json', - }, - dependencies: ['createUserAndAuthenticate'], - } - } - * - * To override credentials in a single test: - * test.use({ storageState: 'playwright/.auth/admin.json', user: { user: 'admin', password: 'admin' } }); - * To avoid authentication in a single test: - * test.use({ storageState: { cookies: [], origins: [] } }); - */ - login: () => Promise; - - /** - * Fixture command that reads a yaml file in the provisioning/datasources directory. - * - * The file name should be the name of the file with the .yaml|.yml extension. - * If a data source name is provided, the first data source that matches the name will be returned. - * If no name is provided, the first data source in the list of data sources will be returned. - */ - readProvisionedDataSource(args: ReadProvisionedDataSourceArgs): Promise>; - - /** - * Fixture command that reads a dashboard json file in the provisioning/dashboards directory. - * - * Can be useful when navigating to a provisioned dashboard and you don't want to hard code the dashboard UID. - */ - readProvisionedDashboard(args: ReadProvisionedDashboardArgs): Promise; - - /** - * Function that checks if a feature toggle is enabled. Only works for frontend feature toggles. - */ - isFeatureToggleEnabled(featureToggle: keyof T): Promise; - - /** - * Fixture command that navigates to an already exist dashboard. Returns a DashboardPage instance. - */ - gotoDashboardPage: (args: DashboardPageArgs) => Promise; - - /** - * Fixture command that navigates a panel edit page for an already existing panel in a dashboard. - */ - gotoPanelEditPage: (args: DashboardEditViewArgs) => Promise; - - /** - * Fixture command that navigates a variable edit page for an already existing variable query in a dashboard. - */ - gotoVariableEditPage: (args: DashboardEditViewArgs) => Promise; - - /** - * Fixture command that navigates an annotation edit page for an already existing annotation query in a dashboard. - */ - gotoAnnotationEditPage: (args: DashboardEditViewArgs) => Promise; - - /** - * Fixture command that navigates a configuration page for an already existing data source instance. - */ - gotoDataSourceConfigPage: (uid: string) => Promise; - - /** - * Fixture command that navigates to the AppConfigPage for a given plugin. - */ - gotoAppConfigPage: (args: GotoAppConfigPageArgs) => Promise; - - /** - * Fixture command that navigates to an AppPage for a given plugin. - */ - gotoAppPage: (args: GotoAppPageArgs) => Promise; -}; - -// extend Playwright with Grafana plugin specific fixtures -export const test = base.extend({ ...fixtures, ...options }); - -export const expect = baseExpect.extend(matchers); - -/** Register a custom selector engine that resolves locators for Grafana E2E selectors - * - * The same functionality is available in the {@link GrafanaPage.getByTestIdOrAriaLabel} method. However, - * by registering the selector engine, one can resolve locators by Grafana E2E selectors also within a locator. - * - * Example: - * const queryEditorRow = await panelEditPage.getQueryEditorRow('A'); // returns a locator - * queryEditorRow.locator(`selector=${selectors.components.TimePicker.openButton}`).click(); - * */ -selectors.register('selector', grafanaE2ESelectorEngine); - -export { selectors } from '@playwright/test'; diff --git a/packages/plugin-e2e/src/auth/auth.setup.ts b/packages/plugin-e2e/src/auth/auth.setup.ts index ede5d32cd..f33eb21fa 100644 --- a/packages/plugin-e2e/src/auth/auth.setup.ts +++ b/packages/plugin-e2e/src/auth/auth.setup.ts @@ -1,4 +1,4 @@ -import { test as setup } from '../api'; +import { test as setup } from '../'; setup('authenticate', async ({ login, createUser, user }) => { if (user) { diff --git a/packages/plugin-e2e/src/fixtures/annotationEditPage.ts b/packages/plugin-e2e/src/fixtures/annotationEditPage.ts index c9226c5d3..33fb9ea38 100644 --- a/packages/plugin-e2e/src/fixtures/annotationEditPage.ts +++ b/packages/plugin-e2e/src/fixtures/annotationEditPage.ts @@ -1,14 +1,11 @@ import { TestFixture } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../api'; -import { AnnotationEditPage, AnnotationPage } from '../models'; -import { PlaywrightCombinedArgs } from './types'; +import { PlaywrightArgs } from '../types'; +import { AnnotationPage } from '../models/pages/AnnotationPage'; +import { AnnotationEditPage } from '../models/pages/AnnotationEditPage'; -type AnnotationEditPageFixture = TestFixture< - AnnotationEditPage, - PluginFixture & PluginOptions & PlaywrightCombinedArgs ->; +type AnnotationEditPageFixture = TestFixture; -const annotationEditPage: AnnotationEditPageFixture = async ( +export const annotationEditPage: AnnotationEditPageFixture = async ( { page, selectors, grafanaVersion, request }, use, testInfo @@ -18,5 +15,3 @@ const annotationEditPage: AnnotationEditPageFixture = async ( const annotationEditPage = await annotationPage.clickAddNew(); await use(annotationEditPage); }; - -export default annotationEditPage; diff --git a/packages/plugin-e2e/src/fixtures/commands/createDataSource.ts b/packages/plugin-e2e/src/fixtures/commands/createDataSource.ts index 716727ad0..aef2e742d 100644 --- a/packages/plugin-e2e/src/fixtures/commands/createDataSource.ts +++ b/packages/plugin-e2e/src/fixtures/commands/createDataSource.ts @@ -1,12 +1,10 @@ import { v4 as uuidv4 } from 'uuid'; import { APIRequestContext, expect, TestFixture } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../../api'; -import { CreateDataSourceArgs, DataSourceSettings } from '../../types'; -import { PlaywrightCombinedArgs } from '../types'; +import { CreateDataSourceArgs, DataSourceSettings, PlaywrightArgs } from '../../types'; type CreateDataSourceViaAPIFixture = TestFixture< (args: CreateDataSourceArgs) => Promise, - PluginFixture & PluginOptions & PlaywrightCombinedArgs + PlaywrightArgs >; export const createDataSourceViaAPI = async ( @@ -40,10 +38,8 @@ export const createDataSourceViaAPI = async ( return existingDataSource.json(); }; -const createDataSource: CreateDataSourceViaAPIFixture = async ({ request }, use) => { +export const createDataSource: CreateDataSourceViaAPIFixture = async ({ request }, use) => { await use(async (args) => { return createDataSourceViaAPI(request, args); }); }; - -export default createDataSource; diff --git a/packages/plugin-e2e/src/fixtures/commands/createDataSourceConfigPage.ts b/packages/plugin-e2e/src/fixtures/commands/createDataSourceConfigPage.ts index ac6b702c9..289d4e044 100644 --- a/packages/plugin-e2e/src/fixtures/commands/createDataSourceConfigPage.ts +++ b/packages/plugin-e2e/src/fixtures/commands/createDataSourceConfigPage.ts @@ -1,16 +1,14 @@ import { TestFixture } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../../api'; -import { CreateDataSourcePageArgs } from '../../types'; -import { PlaywrightCombinedArgs } from '../types'; -import { DataSourceConfigPage } from '../../models'; +import { CreateDataSourcePageArgs, PlaywrightArgs } from '../../types'; import { createDataSourceViaAPI } from './createDataSource'; +import { DataSourceConfigPage } from '../../models/pages/DataSourceConfigPage'; type CreateDataSourceConfigPageFixture = TestFixture< (args: CreateDataSourcePageArgs) => Promise, - PluginFixture & PluginOptions & PlaywrightCombinedArgs + PlaywrightArgs >; -const createDataSourceConfigPage: CreateDataSourceConfigPageFixture = async ( +export const createDataSourceConfigPage: CreateDataSourceConfigPageFixture = async ( { request, page, selectors, grafanaVersion }, use, testInfo @@ -26,5 +24,3 @@ const createDataSourceConfigPage: CreateDataSourceConfigPageFixture = async ( }); deleteDataSource && (await datasourceConfigPage?.deleteDataSource()); }; - -export default createDataSourceConfigPage; diff --git a/packages/plugin-e2e/src/fixtures/commands/createUser.ts b/packages/plugin-e2e/src/fixtures/commands/createUser.ts index 5b65aa811..a1e03fc66 100644 --- a/packages/plugin-e2e/src/fixtures/commands/createUser.ts +++ b/packages/plugin-e2e/src/fixtures/commands/createUser.ts @@ -1,8 +1,7 @@ import { APIRequestContext, expect, TestFixture } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../../api'; -import { PlaywrightCombinedArgs } from '../types'; +import { PlaywrightArgs } from '../../types'; -type CreateUserFixture = TestFixture<() => Promise, PluginFixture & PluginOptions & PlaywrightCombinedArgs>; +type CreateUserFixture = TestFixture<() => Promise, PlaywrightArgs>; const headers = { Authorization: `Basic ${Buffer.from(`admin:admin`).toString('base64')}`, @@ -17,7 +16,7 @@ const getUserIdByUsername = async (request: APIRequestContext, userName: string) return json.id; }; -const createUser: CreateUserFixture = async ({ request, user }, use) => { +export const createUser: CreateUserFixture = async ({ request, user }, use) => { await use(async () => { if (!user) { throw new Error('Playwright option `User` was not provided'); @@ -56,5 +55,3 @@ const createUser: CreateUserFixture = async ({ request, user }, use) => { } }); }; - -export default createUser; diff --git a/packages/plugin-e2e/src/fixtures/commands/gotoAnnotationEditPage.ts b/packages/plugin-e2e/src/fixtures/commands/gotoAnnotationEditPage.ts index 3d4fe7197..83f5eb5ec 100644 --- a/packages/plugin-e2e/src/fixtures/commands/gotoAnnotationEditPage.ts +++ b/packages/plugin-e2e/src/fixtures/commands/gotoAnnotationEditPage.ts @@ -1,15 +1,13 @@ import { TestFixture } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../../api'; -import { DashboardEditViewArgs } from '../../types'; -import { PlaywrightCombinedArgs } from '../types'; -import { AnnotationEditPage } from '../../models'; +import { DashboardEditViewArgs, PlaywrightArgs } from '../../types'; +import { AnnotationEditPage } from '../../models/pages/AnnotationEditPage'; type GotoAnnotationEditPageFixture = TestFixture< (args: DashboardEditViewArgs) => Promise, - PluginFixture & PluginOptions & PlaywrightCombinedArgs + PlaywrightArgs >; -const gotoAnnotationEditPage: GotoAnnotationEditPageFixture = async ( +export const gotoAnnotationEditPage: GotoAnnotationEditPageFixture = async ( { request, page, selectors, grafanaVersion }, use, testInfo @@ -20,5 +18,3 @@ const gotoAnnotationEditPage: GotoAnnotationEditPageFixture = async ( return annotationEditPage; }); }; - -export default gotoAnnotationEditPage; diff --git a/packages/plugin-e2e/src/fixtures/commands/gotoAppConfigPage.ts b/packages/plugin-e2e/src/fixtures/commands/gotoAppConfigPage.ts index 28c1b4a07..40f52f4a5 100644 --- a/packages/plugin-e2e/src/fixtures/commands/gotoAppConfigPage.ts +++ b/packages/plugin-e2e/src/fixtures/commands/gotoAppConfigPage.ts @@ -1,13 +1,8 @@ import { TestFixture } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../../api'; -import { GotoAppConfigPageArgs } from '../../types'; -import { PlaywrightCombinedArgs } from '../types'; +import { GotoAppConfigPageArgs, PlaywrightArgs } from '../../types'; import { AppConfigPage } from '../../models/pages/AppConfigPage'; -type GotoAppConfigPageFixture = TestFixture< - (args: GotoAppConfigPageArgs) => Promise, - PluginFixture & PluginOptions & PlaywrightCombinedArgs ->; +type GotoAppConfigPageFixture = TestFixture<(args: GotoAppConfigPageArgs) => Promise, PlaywrightArgs>; export const gotoAppConfigPage: GotoAppConfigPageFixture = async ( { page, selectors, grafanaVersion, request }, @@ -20,5 +15,3 @@ export const gotoAppConfigPage: GotoAppConfigPageFixture = async ( return appConfigPage; }); }; - -export default gotoAppConfigPage; diff --git a/packages/plugin-e2e/src/fixtures/commands/gotoAppPage.ts b/packages/plugin-e2e/src/fixtures/commands/gotoAppPage.ts index ec0f9575b..81b0de2b1 100644 --- a/packages/plugin-e2e/src/fixtures/commands/gotoAppPage.ts +++ b/packages/plugin-e2e/src/fixtures/commands/gotoAppPage.ts @@ -1,12 +1,8 @@ import { TestFixture } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../../api'; -import { PlaywrightCombinedArgs } from '../types'; +import { PlaywrightArgs } from '../../types'; import { AppPage, GotoAppPageArgs } from '../..'; -type GotoAppPageFixture = TestFixture< - (args: GotoAppPageArgs) => Promise, - PluginFixture & PluginOptions & PlaywrightCombinedArgs ->; +type GotoAppPageFixture = TestFixture<(args: GotoAppPageArgs) => Promise, PlaywrightArgs>; export const gotoAppPage: GotoAppPageFixture = async ({ page, selectors, grafanaVersion, request }, use, testInfo) => { await use(async ({ pluginId, path }) => { @@ -15,5 +11,3 @@ export const gotoAppPage: GotoAppPageFixture = async ({ page, selectors, grafana return appPage; }); }; - -export default gotoAppPage; diff --git a/packages/plugin-e2e/src/fixtures/commands/gotoDashboardPage.ts b/packages/plugin-e2e/src/fixtures/commands/gotoDashboardPage.ts index 501366d24..7f261b467 100644 --- a/packages/plugin-e2e/src/fixtures/commands/gotoDashboardPage.ts +++ b/packages/plugin-e2e/src/fixtures/commands/gotoDashboardPage.ts @@ -1,20 +1,17 @@ import { TestFixture } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../../api'; -import { DashboardPageArgs } from '../../types'; -import { PlaywrightCombinedArgs } from '../types'; -import { DashboardPage } from '../../models'; +import { DashboardPageArgs, PlaywrightArgs } from '../../types'; +import { DashboardPage } from '../../models/pages/DashboardPage'; -type GotoDashboardFixture = TestFixture< - (args: DashboardPageArgs) => Promise, - PluginFixture & PluginOptions & PlaywrightCombinedArgs ->; +type GotoDashboardFixture = TestFixture<(args: DashboardPageArgs) => Promise, PlaywrightArgs>; -const gotoDashboardPage: GotoDashboardFixture = async ({ request, page, selectors, grafanaVersion }, use, testInfo) => { +export const gotoDashboardPage: GotoDashboardFixture = async ( + { request, page, selectors, grafanaVersion }, + use, + testInfo +) => { await use(async (args) => { const dashboardPage = new DashboardPage({ page, selectors, grafanaVersion, request, testInfo }, args); await dashboardPage.goto(); return dashboardPage; }); }; - -export default gotoDashboardPage; diff --git a/packages/plugin-e2e/src/fixtures/commands/gotoDataSourceConfigPage.ts b/packages/plugin-e2e/src/fixtures/commands/gotoDataSourceConfigPage.ts index b85354a9b..ffbdd8329 100644 --- a/packages/plugin-e2e/src/fixtures/commands/gotoDataSourceConfigPage.ts +++ b/packages/plugin-e2e/src/fixtures/commands/gotoDataSourceConfigPage.ts @@ -1,15 +1,10 @@ import { TestFixture } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../../api'; -import { DataSourceSettings } from '../../types'; -import { PlaywrightCombinedArgs } from '../types'; -import { DataSourceConfigPage } from '../../models'; +import { DataSourceSettings, PlaywrightArgs } from '../../types'; +import { DataSourceConfigPage } from '../../models/pages/DataSourceConfigPage'; -type GotoDataSourceConfigPageFixture = TestFixture< - (uid: string) => Promise, - PluginFixture & PluginOptions & PlaywrightCombinedArgs ->; +type GotoDataSourceConfigPageFixture = TestFixture<(uid: string) => Promise, PlaywrightArgs>; -const gotoDataSourceConfigPage: GotoDataSourceConfigPageFixture = async ( +export const gotoDataSourceConfigPage: GotoDataSourceConfigPageFixture = async ( { request, page, selectors, grafanaVersion }, use, testInfo @@ -35,5 +30,3 @@ const gotoDataSourceConfigPage: GotoDataSourceConfigPageFixture = async ( return dataSourceConfigPage; }); }; - -export default gotoDataSourceConfigPage; diff --git a/packages/plugin-e2e/src/fixtures/commands/gotoPanelEditPage.ts b/packages/plugin-e2e/src/fixtures/commands/gotoPanelEditPage.ts index 4d48cd0ff..ebe1e4204 100644 --- a/packages/plugin-e2e/src/fixtures/commands/gotoPanelEditPage.ts +++ b/packages/plugin-e2e/src/fixtures/commands/gotoPanelEditPage.ts @@ -1,15 +1,13 @@ import { TestFixture } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../../api'; -import { DashboardEditViewArgs } from '../../types'; -import { PlaywrightCombinedArgs } from '../types'; -import { PanelEditPage } from '../../models'; +import { DashboardEditViewArgs, PlaywrightArgs } from '../../types'; +import { PanelEditPage } from '../../models/pages/PanelEditPage'; type GotoPanelEditPageFixture = TestFixture< (args: DashboardEditViewArgs) => Promise, - PluginFixture & PluginOptions & PlaywrightCombinedArgs + PlaywrightArgs >; -const gotoPanelEditPage: GotoPanelEditPageFixture = async ( +export const gotoPanelEditPage: GotoPanelEditPageFixture = async ( { request, page, selectors, grafanaVersion }, use, testInfo @@ -20,5 +18,3 @@ const gotoPanelEditPage: GotoPanelEditPageFixture = async ( return panelEditPage; }); }; - -export default gotoPanelEditPage; diff --git a/packages/plugin-e2e/src/fixtures/commands/gotoVariableEditPage.ts b/packages/plugin-e2e/src/fixtures/commands/gotoVariableEditPage.ts index 527b23226..d66ef53f0 100644 --- a/packages/plugin-e2e/src/fixtures/commands/gotoVariableEditPage.ts +++ b/packages/plugin-e2e/src/fixtures/commands/gotoVariableEditPage.ts @@ -1,15 +1,13 @@ import { TestFixture } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../../api'; -import { DashboardEditViewArgs } from '../../types'; -import { PlaywrightCombinedArgs } from '../types'; -import { VariableEditPage } from '../../models'; +import { DashboardEditViewArgs, PlaywrightArgs } from '../../types'; +import { VariableEditPage } from '../../models/pages/VariableEditPage'; type GotoVariableEditPageFixture = TestFixture< (args: DashboardEditViewArgs) => Promise, - PluginFixture & PluginOptions & PlaywrightCombinedArgs + PlaywrightArgs >; -const gotoVariableEditPage: GotoVariableEditPageFixture = async ( +export const gotoVariableEditPage: GotoVariableEditPageFixture = async ( { request, page, selectors, grafanaVersion }, use, testInfo @@ -20,5 +18,3 @@ const gotoVariableEditPage: GotoVariableEditPageFixture = async ( return variableEditPage; }); }; - -export default gotoVariableEditPage; diff --git a/packages/plugin-e2e/src/fixtures/commands/login.ts b/packages/plugin-e2e/src/fixtures/commands/login.ts index 5669b7d79..bb7efb18c 100644 --- a/packages/plugin-e2e/src/fixtures/commands/login.ts +++ b/packages/plugin-e2e/src/fixtures/commands/login.ts @@ -1,15 +1,12 @@ import path from 'path'; import { expect, TestFixture } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../../api'; -import { PlaywrightCombinedArgs } from '../types'; +import { PlaywrightArgs } from '../../types'; -const authFile = 'playwright/.auth/user.json'; - -type LoginFixture = TestFixture<() => Promise, PluginFixture & PluginOptions & PlaywrightCombinedArgs>; +type LoginFixture = TestFixture<() => Promise, PlaywrightArgs>; const ADMIN_USER = { user: 'admin', password: 'admin' }; -const login: LoginFixture = async ({ request, user }, use) => { +export const login: LoginFixture = async ({ request, user }, use) => { await use(async () => { const data = user ?? ADMIN_USER; const loginReq = await request.post('/login', { data }); @@ -18,5 +15,3 @@ const login: LoginFixture = async ({ request, user }, use) => { await request.storageState({ path: path.join(process.cwd(), `playwright/.auth/${data.user}.json`) }); }); }; - -export default login; diff --git a/packages/plugin-e2e/src/fixtures/commands/readProvisionedDashboard.ts b/packages/plugin-e2e/src/fixtures/commands/readProvisionedDashboard.ts index e3ff7cec4..3ddc369c8 100644 --- a/packages/plugin-e2e/src/fixtures/commands/readProvisionedDashboard.ts +++ b/packages/plugin-e2e/src/fixtures/commands/readProvisionedDashboard.ts @@ -1,23 +1,19 @@ import path from 'path'; import { TestFixture } from '@playwright/test'; import { promises } from 'fs'; -import { PluginFixture, PluginOptions } from '../../api'; -import { ReadProvisionedDashboardArgs } from '../../types'; -import { PlaywrightCombinedArgs } from '../types'; +import { PlaywrightArgs, ReadProvisionedDashboardArgs } from '../../types'; type ReadProvisionedDashboardFixture = TestFixture< (args: ReadProvisionedDashboardArgs) => Promise, - PluginFixture & PluginOptions & PlaywrightCombinedArgs + PlaywrightArgs >; const DASHBOARDS_DIR = 'dashboards'; -const readProvisionedDashboard: ReadProvisionedDashboardFixture = async ({ provisioningRootDir }, use) => { +export const readProvisionedDashboard: ReadProvisionedDashboardFixture = async ({ provisioningRootDir }, use) => { await use(async ({ fileName }) => { const resolvedPath = path.resolve(path.join(provisioningRootDir, DASHBOARDS_DIR, fileName)); const contents = await promises.readFile(resolvedPath, 'utf8'); return JSON.parse(contents); }); }; - -export default readProvisionedDashboard; diff --git a/packages/plugin-e2e/src/fixtures/commands/readProvisionedDataSource.ts b/packages/plugin-e2e/src/fixtures/commands/readProvisionedDataSource.ts index d1f1e97bf..dc6839986 100644 --- a/packages/plugin-e2e/src/fixtures/commands/readProvisionedDataSource.ts +++ b/packages/plugin-e2e/src/fixtures/commands/readProvisionedDataSource.ts @@ -2,18 +2,16 @@ import { TestFixture } from '@playwright/test'; import { promises } from 'fs'; import path from 'path'; import { parse as parseYml } from 'yaml'; -import { PluginFixture, PluginOptions } from '../../api'; -import { DataSourceSettings, ReadProvisionedDataSourceArgs } from '../../types'; -import { PlaywrightCombinedArgs } from '../types'; +import { DataSourceSettings, ReadProvisionedDataSourceArgs, PlaywrightArgs } from '../../types'; type ReadProvisionedDataSourceFixture = TestFixture< (args: ReadProvisionedDataSourceArgs) => Promise, - PluginFixture & PluginOptions & PlaywrightCombinedArgs + PlaywrightArgs >; const DATASOURCES_DIR = 'datasources'; -const readProvisionedDataSource: ReadProvisionedDataSourceFixture = async ({ provisioningRootDir }, use) => { +export const readProvisionedDataSource: ReadProvisionedDataSourceFixture = async ({ provisioningRootDir }, use) => { await use(async ({ fileName: filePath, name }) => { const resolvedPath = path.resolve(path.join(provisioningRootDir, DATASOURCES_DIR, filePath)); const contents = await promises.readFile(resolvedPath, 'utf8'); @@ -24,5 +22,3 @@ const readProvisionedDataSource: ReadProvisionedDataSourceFixture = async ({ pro return yml.datasources.find((ds: DataSourceSettings) => ds.name === name); }); }; - -export default readProvisionedDataSource; diff --git a/packages/plugin-e2e/src/fixtures/dashboardPage.ts b/packages/plugin-e2e/src/fixtures/dashboardPage.ts index ce3a2d32a..70b9adb59 100644 --- a/packages/plugin-e2e/src/fixtures/dashboardPage.ts +++ b/packages/plugin-e2e/src/fixtures/dashboardPage.ts @@ -1,14 +1,15 @@ import { TestFixture } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../api'; -import { DashboardPage } from '../models'; -import { PlaywrightCombinedArgs } from './types'; +import { PlaywrightArgs } from '../types'; +import { DashboardPage } from '../models/pages/DashboardPage'; -type DashboardPageFixture = TestFixture; +type DashboardPageFixture = TestFixture; -const dashboardPage: DashboardPageFixture = async ({ page, request, selectors, grafanaVersion }, use, testInfo) => { +export const dashboardPage: DashboardPageFixture = async ( + { page, request, selectors, grafanaVersion }, + use, + testInfo +) => { const dashboardPage = new DashboardPage({ page, selectors, grafanaVersion, request, testInfo }); await dashboardPage.goto(); await use(dashboardPage); }; - -export default dashboardPage; diff --git a/packages/plugin-e2e/src/fixtures/explorePage.ts b/packages/plugin-e2e/src/fixtures/explorePage.ts index 8fe337500..ae1c4c550 100644 --- a/packages/plugin-e2e/src/fixtures/explorePage.ts +++ b/packages/plugin-e2e/src/fixtures/explorePage.ts @@ -1,14 +1,11 @@ import { TestFixture } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../api'; +import { PlaywrightArgs } from '../types'; import { ExplorePage } from '../models/pages/ExplorePage'; -import { PlaywrightCombinedArgs } from './types'; -type ExplorePageFixture = TestFixture; +type ExplorePageFixture = TestFixture; -const explorePage: ExplorePageFixture = async ({ page, selectors, grafanaVersion, request }, use, testInfo) => { +export const explorePage: ExplorePageFixture = async ({ page, selectors, grafanaVersion, request }, use, testInfo) => { const explorePage = new ExplorePage({ page, selectors, grafanaVersion, request, testInfo }); await explorePage.goto(); await use(explorePage); }; - -export default explorePage; diff --git a/packages/plugin-e2e/src/fixtures/grafanaVersion.ts b/packages/plugin-e2e/src/fixtures/grafanaVersion.ts index 402ef91da..5554110c6 100644 --- a/packages/plugin-e2e/src/fixtures/grafanaVersion.ts +++ b/packages/plugin-e2e/src/fixtures/grafanaVersion.ts @@ -2,7 +2,7 @@ import { PlaywrightTestArgs, TestFixture } from '@playwright/test'; type GrafanaVersion = TestFixture; -const grafanaVersion: GrafanaVersion = async ({ page }, use) => { +export const grafanaVersion: GrafanaVersion = async ({ page }, use) => { let grafanaVersion = process.env.GRAFANA_VERSION ?? ''; if (!grafanaVersion) { await page.goto('/'); @@ -11,5 +11,3 @@ const grafanaVersion: GrafanaVersion = async ({ page }, use) => { await use(grafanaVersion.replace(/\-.*/, '')); }; - -export default grafanaVersion; diff --git a/packages/plugin-e2e/src/fixtures/index.ts b/packages/plugin-e2e/src/fixtures/index.ts deleted file mode 100644 index e005e7149..000000000 --- a/packages/plugin-e2e/src/fixtures/index.ts +++ /dev/null @@ -1,49 +0,0 @@ -import annotationEditPage from './annotationEditPage'; -import grafanaVersion from './grafanaVersion'; -import selectors from './selectors'; -import login from './commands/login'; -import createDataSourceConfigPage from './commands/createDataSourceConfigPage'; -import panelEditPage from './panelEditPage'; -import createDataSource from './commands/createDataSource'; -import readProvisionedDataSource from './commands/readProvisionedDataSource'; -import readProvisionedDashboard from './commands/readProvisionedDashboard'; -import dashboardPage from './dashboardPage'; -import variableEditPage from './variableEditPage'; -import explorePage from './explorePage'; -import isFeatureToggleEnabled from './isFeatureToggleEnabled'; -import page from './page'; -import createUser from './commands/createUser'; -import gotoDashboardPage from './commands/gotoDashboardPage'; -import gotoPanelEditPage from './commands/gotoPanelEditPage'; -import gotoVariableEditPage from './commands/gotoVariableEditPage'; -import gotoAnnotationEditPage from './commands/gotoAnnotationEditPage'; -import gotoDataSourceConfigPage from './commands/gotoDataSourceConfigPage'; -import gotoAppConfigPage from './commands/gotoAppConfigPage'; -import gotoAppPage from './commands/gotoAppPage'; - -const fixtures = { - selectors, - grafanaVersion, - login, - createDataSourceConfigPage, - page, - dashboardPage, - panelEditPage, - variableEditPage, - annotationEditPage, - explorePage, - createDataSource, - readProvisionedDataSource, - readProvisionedDashboard, - isFeatureToggleEnabled, - createUser, - gotoDashboardPage, - gotoPanelEditPage, - gotoVariableEditPage, - gotoAnnotationEditPage, - gotoDataSourceConfigPage, - gotoAppConfigPage, - gotoAppPage, -}; - -export default fixtures; diff --git a/packages/plugin-e2e/src/fixtures/isFeatureToggleEnabled.ts b/packages/plugin-e2e/src/fixtures/isFeatureToggleEnabled.ts index 6ba9f2c46..c6f53fd9b 100644 --- a/packages/plugin-e2e/src/fixtures/isFeatureToggleEnabled.ts +++ b/packages/plugin-e2e/src/fixtures/isFeatureToggleEnabled.ts @@ -1,17 +1,11 @@ import { TestFixture } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../api'; -import { PlaywrightCombinedArgs } from './types'; +import { PlaywrightArgs } from '../types'; -type FeatureToggleFixture = TestFixture< - (featureToggle: keyof T) => Promise, - PluginFixture & PluginOptions & PlaywrightCombinedArgs ->; +type FeatureToggleFixture = TestFixture<(featureToggle: keyof T) => Promise, PlaywrightArgs>; -const isFeatureToggleEnabled: FeatureToggleFixture = async ({ page, grafanaVersion }, use) => { +export const isFeatureToggleEnabled: FeatureToggleFixture = async ({ page, grafanaVersion }, use) => { await use(async (featureToggle: keyof T) => { const featureToggles: T = await page.evaluate('window.grafanaBootData.settings.featureToggles'); return Boolean(featureToggles[featureToggle]); }); }; - -export default isFeatureToggleEnabled; diff --git a/packages/plugin-e2e/src/fixtures/page.ts b/packages/plugin-e2e/src/fixtures/page.ts index 23b8b4828..b595952b9 100644 --- a/packages/plugin-e2e/src/fixtures/page.ts +++ b/packages/plugin-e2e/src/fixtures/page.ts @@ -1,9 +1,8 @@ import { TestFixture, Page } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../api'; -import { PlaywrightCombinedArgs } from './types'; +import { PlaywrightArgs } from '../types'; import { overrideFeatureToggles } from './scripts/overrideFeatureToggles'; -type PageFixture = TestFixture; +type PageFixture = TestFixture; /** * This fixture ensures the feature toggles defined in the Playwright config are being used in Grafana frontend. @@ -16,7 +15,7 @@ type PageFixture = TestFixture { +export const page: PageFixture = async ({ page, featureToggles }, use) => { if (Object.keys(featureToggles).length > 0) { try { await page.addInitScript(overrideFeatureToggles, featureToggles); @@ -27,5 +26,3 @@ const page: PageFixture = async ({ page, featureToggles }, use) => { await page.goto('/'); await use(page); }; - -export default page; diff --git a/packages/plugin-e2e/src/fixtures/panelEditPage.ts b/packages/plugin-e2e/src/fixtures/panelEditPage.ts index a900213c0..6aec8fda2 100644 --- a/packages/plugin-e2e/src/fixtures/panelEditPage.ts +++ b/packages/plugin-e2e/src/fixtures/panelEditPage.ts @@ -1,13 +1,10 @@ import { TestFixture } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../api'; -import { PanelEditPage } from '../models'; -import { PlaywrightCombinedArgs } from './types'; +import { PlaywrightArgs } from '../types'; +import { PanelEditPage } from '../models/pages/PanelEditPage'; -type PanelEditPageFixture = TestFixture; +type PanelEditPageFixture = TestFixture; -const panelEditPage: PanelEditPageFixture = async ({ dashboardPage }, use) => { +export const panelEditPage: PanelEditPageFixture = async ({ dashboardPage }, use) => { const panelEditPage = await dashboardPage.addPanel(); await use(panelEditPage); }; - -export default panelEditPage; diff --git a/packages/plugin-e2e/src/fixtures/selectors.ts b/packages/plugin-e2e/src/fixtures/selectors.ts index d8f1b3839..fa94bdf56 100644 --- a/packages/plugin-e2e/src/fixtures/selectors.ts +++ b/packages/plugin-e2e/src/fixtures/selectors.ts @@ -1,13 +1,12 @@ import { TestFixture } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../api'; +import { PlaywrightArgs } from '../types'; import { E2ESelectors, resolveSelectors } from '../e2e-selectors'; import { versionedComponents, versionedPages } from '../e2e-selectors/versioned'; -import { PlaywrightCombinedArgs } from './types'; import { versionedAPIs } from '../e2e-selectors/versioned/apis'; -type SelectorFixture = TestFixture; +type SelectorFixture = TestFixture; -const selectors: SelectorFixture = async ({ grafanaVersion }, use) => { +export const selectors: SelectorFixture = async ({ grafanaVersion }, use) => { const selectors = resolveSelectors( { components: versionedComponents, @@ -18,5 +17,3 @@ const selectors: SelectorFixture = async ({ grafanaVersion }, use) => { ); await use(selectors); }; - -export default selectors; diff --git a/packages/plugin-e2e/src/fixtures/types.ts b/packages/plugin-e2e/src/fixtures/types.ts deleted file mode 100644 index 4f4302445..000000000 --- a/packages/plugin-e2e/src/fixtures/types.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { - PlaywrightTestArgs, - PlaywrightTestOptions, - PlaywrightWorkerArgs, - PlaywrightWorkerOptions, -} from '@playwright/test'; - -export type PlaywrightCombinedArgs = PlaywrightTestArgs & - PlaywrightTestOptions & - PlaywrightWorkerArgs & - PlaywrightWorkerOptions; diff --git a/packages/plugin-e2e/src/fixtures/variableEditPage.ts b/packages/plugin-e2e/src/fixtures/variableEditPage.ts index 647674714..1ee0b2a64 100644 --- a/packages/plugin-e2e/src/fixtures/variableEditPage.ts +++ b/packages/plugin-e2e/src/fixtures/variableEditPage.ts @@ -1,11 +1,11 @@ import { TestFixture } from '@playwright/test'; -import { PluginFixture, PluginOptions } from '../api'; -import { VariableEditPage, VariablePage } from '../models'; -import { PlaywrightCombinedArgs } from './types'; +import { PlaywrightArgs } from '../types'; +import { VariableEditPage } from '../models/pages/VariableEditPage'; +import { VariablePage } from '../models/pages/VariablePage'; -type VariableEditPageFixture = TestFixture; +type VariableEditPageFixture = TestFixture; -const variableEditPage: VariableEditPageFixture = async ( +export const variableEditPage: VariableEditPageFixture = async ( { page, selectors, grafanaVersion, request }, use, testInfo @@ -15,5 +15,3 @@ const variableEditPage: VariableEditPageFixture = async ( const variableEditPage = await variablePage.clickAddNew(); await use(variableEditPage); }; - -export default variableEditPage; diff --git a/packages/plugin-e2e/src/index.ts b/packages/plugin-e2e/src/index.ts index 6d5039d21..d5868987b 100644 --- a/packages/plugin-e2e/src/index.ts +++ b/packages/plugin-e2e/src/index.ts @@ -1,12 +1,105 @@ -import { GrafanaPage, VariableEditPage } from './models'; -import { AlertPageOptions, AlertVariant, ContainTextOptions } from './types'; +import { test as base, expect as baseExpect, selectors } from '@playwright/test'; -export { expect, test, type PluginFixture, type PluginOptions } from './api'; -export * from './e2e-selectors'; -export * from './fixtures'; -export * from './models'; +import { AlertPageOptions, AlertVariant, ContainTextOptions, PluginFixture, PluginOptions } from './types'; +import { annotationEditPage } from './fixtures/annotationEditPage'; +import { createDataSource } from './fixtures/commands/createDataSource'; +import { createDataSourceConfigPage } from './fixtures/commands/createDataSourceConfigPage'; +import { createUser } from './fixtures/commands/createUser'; +import { gotoAnnotationEditPage } from './fixtures/commands/gotoAnnotationEditPage'; +import { gotoAppConfigPage } from './fixtures/commands/gotoAppConfigPage'; +import { gotoAppPage } from './fixtures/commands/gotoAppPage'; +import { gotoDashboardPage } from './fixtures/commands/gotoDashboardPage'; +import { gotoDataSourceConfigPage } from './fixtures/commands/gotoDataSourceConfigPage'; +import { gotoPanelEditPage } from './fixtures/commands/gotoPanelEditPage'; +import { gotoVariableEditPage } from './fixtures/commands/gotoVariableEditPage'; +import { login } from './fixtures/commands/login'; +import { readProvisionedDashboard } from './fixtures/commands/readProvisionedDashboard'; +import { readProvisionedDataSource } from './fixtures/commands/readProvisionedDataSource'; +import { dashboardPage } from './fixtures/dashboardPage'; +import { explorePage } from './fixtures/explorePage'; +import { grafanaVersion } from './fixtures/grafanaVersion'; +import { isFeatureToggleEnabled } from './fixtures/isFeatureToggleEnabled'; +import { page } from './fixtures/page'; +import { panelEditPage } from './fixtures/panelEditPage'; +import { selectors as e2eSelectors } from './fixtures/selectors'; +import { variableEditPage } from './fixtures/variableEditPage'; +import { options } from './options'; +import { grafanaE2ESelectorEngine } from './selectorEngine'; +import { toHaveAlert } from './matchers/toHaveAlert'; +import { toDisplayPreviews } from './matchers/toDisplayPreviews'; +import { toBeOK } from './matchers/toBeOK'; +import { GrafanaPage } from './models/pages/GrafanaPage'; +import { VariableEditPage } from './models/pages/VariableEditPage'; + +// models +export { DataSourcePicker } from './models/components/DataSourcePicker'; +export { Panel } from './models/components/Panel'; +export { TimeRange } from './models/components/TimeRange'; +export { AnnotationEditPage } from './models/pages/AnnotationEditPage'; +export { AnnotationPage } from './models/pages/AnnotationPage'; +export { DashboardPage } from './models/pages/DashboardPage'; +export { DataSourceConfigPage } from './models/pages/DataSourceConfigPage'; +export { ExplorePage } from './models/pages/ExplorePage'; +export { GrafanaPage } from './models/pages/GrafanaPage'; +export { PanelEditPage } from './models/pages/PanelEditPage'; +export { VariableEditPage } from './models/pages/VariableEditPage'; +export { VariablePage } from './models/pages/VariablePage'; +export { AppConfigPage } from './models/pages/AppConfigPage'; +export { PluginConfigPage } from './models/pages/PluginConfigPage'; +export { AppPage } from './models/pages/AppPage'; + +// e2e-selectors +export { Components, Pages, APIs, E2ESelectors } from './e2e-selectors/types'; +export { resolveSelectors } from './e2e-selectors/resolver'; + +// types export * from './types'; +export const test = base.extend({ + selectors: e2eSelectors, + grafanaVersion, + login, + createDataSourceConfigPage, + page, + dashboardPage, + panelEditPage, + variableEditPage, + annotationEditPage, + explorePage, + createDataSource, + readProvisionedDataSource, + readProvisionedDashboard, + isFeatureToggleEnabled, + createUser, + gotoDashboardPage, + gotoPanelEditPage, + gotoVariableEditPage, + gotoAnnotationEditPage, + gotoDataSourceConfigPage, + gotoAppConfigPage, + gotoAppPage, + ...options, +}); + +export const expect = baseExpect.extend({ + toHaveAlert, + toDisplayPreviews, + toBeOK, +}); + +/** Register a custom selector engine that resolves locators for Grafana E2E selectors + * + * The same functionality is available in the {@link GrafanaPage.getByTestIdOrAriaLabel} method. However, + * by registering the selector engine, one can resolve locators by Grafana E2E selectors also within a locator. + * + * Example: + * const queryEditorRow = await panelEditPage.getQueryEditorRow('A'); // returns a locator + * queryEditorRow.locator(`selector=${selectors.components.TimePicker.openButton}`).click(); + * */ +selectors.register('selector', grafanaE2ESelectorEngine); + +export { selectors } from '@playwright/test'; + declare global { interface Window { monaco: any; diff --git a/packages/plugin-e2e/src/matchers/index.ts b/packages/plugin-e2e/src/matchers/index.ts deleted file mode 100644 index 5a1506306..000000000 --- a/packages/plugin-e2e/src/matchers/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import toBeOK from './toBeOK'; -import toDisplayPreviews from './toDisplayPreviews'; -import toHaveAlert from './toHaveAlert'; - -export default { - toBeOK, - toDisplayPreviews, - toHaveAlert, -}; diff --git a/packages/plugin-e2e/src/matchers/toBeOK.ts b/packages/plugin-e2e/src/matchers/toBeOK.ts index 733f3cb9e..0ac09e225 100644 --- a/packages/plugin-e2e/src/matchers/toBeOK.ts +++ b/packages/plugin-e2e/src/matchers/toBeOK.ts @@ -1,7 +1,7 @@ import { Response } from '@playwright/test'; import { getMessage } from './utils'; -const toBeOK = async (request: Promise) => { +export const toBeOK = async (request: Promise) => { let pass = false; let actual; let message: any = 'Response status code is within 200..299 range.'; @@ -21,5 +21,3 @@ const toBeOK = async (request: Promise) => { }; } }; - -export default toBeOK; diff --git a/packages/plugin-e2e/src/matchers/toDisplayPreviews.ts b/packages/plugin-e2e/src/matchers/toDisplayPreviews.ts index 8f20d8707..5bb794358 100644 --- a/packages/plugin-e2e/src/matchers/toDisplayPreviews.ts +++ b/packages/plugin-e2e/src/matchers/toDisplayPreviews.ts @@ -1,9 +1,9 @@ import { expect } from '@playwright/test'; import { getMessage } from './utils'; -import { VariableEditPage } from '../models'; import { ContainTextOptions } from '../types'; +import { VariableEditPage } from '../models/pages/VariableEditPage'; -const toDisplayPreviews = async ( +export const toDisplayPreviews = async ( variableEditPage: VariableEditPage, previewTexts: Array, options?: ContainTextOptions @@ -31,5 +31,3 @@ const toDisplayPreviews = async ( }; } }; - -export default toDisplayPreviews; diff --git a/packages/plugin-e2e/src/matchers/toHaveAlert.ts b/packages/plugin-e2e/src/matchers/toHaveAlert.ts index 56bf5c4c1..622ca6ab9 100644 --- a/packages/plugin-e2e/src/matchers/toHaveAlert.ts +++ b/packages/plugin-e2e/src/matchers/toHaveAlert.ts @@ -1,10 +1,10 @@ import { expect } from '@playwright/test'; import { getMessage } from './utils'; -import { GrafanaPage } from '../models'; import { AlertPageOptions } from '../types'; +import { GrafanaPage } from '../models/pages/GrafanaPage'; export type AlertVariant = 'success' | 'warning' | 'error' | 'info'; -const toHaveAlert = async (grafanaPage: GrafanaPage, severity: AlertVariant, options?: AlertPageOptions) => { +export const toHaveAlert = async (grafanaPage: GrafanaPage, severity: AlertVariant, options?: AlertPageOptions) => { let pass = true; let message: any = `An alert of variant ${severity} to be displayed on the page`; @@ -28,5 +28,3 @@ const toHaveAlert = async (grafanaPage: GrafanaPage, severity: AlertVariant, opt pass, }; }; - -export default toHaveAlert; diff --git a/packages/plugin-e2e/src/models/index.ts b/packages/plugin-e2e/src/models/index.ts deleted file mode 100644 index e4a42d570..000000000 --- a/packages/plugin-e2e/src/models/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -export { AnnotationEditPage } from './pages/AnnotationEditPage'; -export { AnnotationPage } from './pages/AnnotationPage'; -export { DashboardPage } from './pages/DashboardPage'; -export { DataSourceConfigPage } from './pages/DataSourceConfigPage'; -export { ExplorePage } from './pages/ExplorePage'; -export { GrafanaPage } from './pages/GrafanaPage'; -export { PanelEditPage } from './pages/PanelEditPage'; -export { VariableEditPage } from './pages/VariableEditPage'; -export { VariablePage } from './pages/VariablePage'; -export { DataSourcePicker } from './components/DataSourcePicker'; -export { Panel } from './components/Panel'; -export { TimeRange } from './components/TimeRange'; -export { AppConfigPage } from './pages/AppConfigPage'; -export { PluginConfigPage } from './pages/PluginConfigPage'; -export { AppPage } from './pages/AppPage'; diff --git a/packages/plugin-e2e/src/models/pages/AppPage.ts b/packages/plugin-e2e/src/models/pages/AppPage.ts index f57822b79..b1c17a9f8 100644 --- a/packages/plugin-e2e/src/models/pages/AppPage.ts +++ b/packages/plugin-e2e/src/models/pages/AppPage.ts @@ -1,6 +1,6 @@ import * as nodePath from 'path'; import { AppPageNavigateOptions, PluginPageArgs, PluginTestCtx } from '../../types'; -import { GrafanaPage } from '..'; +import { GrafanaPage } from './GrafanaPage'; export class AppPage extends GrafanaPage { constructor(readonly ctx: PluginTestCtx, readonly args: PluginPageArgs) { diff --git a/packages/plugin-e2e/src/options/index.ts b/packages/plugin-e2e/src/options.ts similarity index 72% rename from packages/plugin-e2e/src/options/index.ts rename to packages/plugin-e2e/src/options.ts index 323cb70eb..701666f8e 100644 --- a/packages/plugin-e2e/src/options/index.ts +++ b/packages/plugin-e2e/src/options.ts @@ -1,11 +1,9 @@ import path = require('path'); import { Fixtures } from '@playwright/test'; -import { PluginOptions } from '../api'; +import { PluginOptions } from './types'; -const options: Fixtures<{}, PluginOptions> = { +export const options: Fixtures<{}, PluginOptions> = { user: [undefined, { option: true, scope: 'worker' }], featureToggles: [{}, { option: true, scope: 'worker' }], provisioningRootDir: [path.join(process.cwd(), 'provisioning'), { option: true, scope: 'worker' }], }; - -export default options; diff --git a/packages/plugin-e2e/src/types.ts b/packages/plugin-e2e/src/types.ts index 197b64866..d72267ca2 100644 --- a/packages/plugin-e2e/src/types.ts +++ b/packages/plugin-e2e/src/types.ts @@ -1,6 +1,269 @@ -import { Locator, PlaywrightTestArgs, Response, TestInfo } from '@playwright/test'; +import { + Locator, + PlaywrightTestArgs, + PlaywrightTestOptions, + PlaywrightWorkerArgs, + PlaywrightWorkerOptions, + Response, + TestInfo, +} from '@playwright/test'; import { E2ESelectors } from './e2e-selectors/types'; +import { AnnotationEditPage } from './models/pages/AnnotationEditPage'; +import { AppConfigPage } from './models/pages/AppConfigPage'; +import { AppPage } from './models/pages/AppPage'; +import { DashboardPage } from './models/pages/DashboardPage'; +import { DataSourceConfigPage } from './models/pages/DataSourceConfigPage'; +import { ExplorePage } from './models/pages/ExplorePage'; +import { PanelEditPage } from './models/pages/PanelEditPage'; +import { VariableEditPage } from './models/pages/VariableEditPage'; + +export type PluginOptions = { + /** + * When using the readProvisioning fixture, files will be read from this directory. If no directory is provided, + * the 'provisioning' directory in the current working directory will be used. + * + * eg. + * export default defineConfig({ + use: { + provisioningRootDir: 'path/to/provisioning', + }, + }); + * + */ + provisioningRootDir: string; + /** + * Optionally, you can add or override feature toggles. + * The feature toggles you specify here will only work in the frontend. If you need a feature toggle to work across the entire stack, you + * need to need to enable the feature in the Grafana config. See https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#feature_toggles + * + * To override feature toggles globally in the playwright.config.ts file: + * export default defineConfig({ + use: { + featureToggles: { + exploreMixedDatasource: true, + redshiftAsyncQueryDataSupport: false + }, + }, + }); + * + * To override feature toggles for tests on a certain file: + test.use({ + featureToggles: { + exploreMixedDatasource: true, + }, + * }); + */ + featureToggles: Record; + + /** + * The Grafana user to use for the tests. If no user is provided, the default admin/admin user will be used. + * + * You can use different users for different projects. See the fixture createUser for more information on how to create a user, + * and the fixture login for more information on how to authenticate. + */ + user?: CreateUserArgs; +}; + +export type PluginFixture = { + /** + * The current Grafana version. + * + * If a GRAFANA_VERSION environment variable is set, this will be used. Otherwise, + * the version will be picked from window.grafanaBootData.settings.buildInfo.version. + */ + grafanaVersion: string; + + /** + * The E2E selectors to use for the current version of Grafana + */ + selectors: E2ESelectors; + + /** + * Isolated {@link DashboardPage} instance for each test. + * + * Navigates to a new to a new dashboard page. + */ + dashboardPage: DashboardPage; + + /** + * Isolated {@link PanelEditPage} instance for each test. + * + * Navigates to a new dashboard page and adds a new panel. + * + * Use {@link PanelEditPage.setVisualization} to change the visualization + * Use {@link PanelEditPage.datasource.set} to change the datasource + * Use {@link ExplorePage.getQueryEditorEditorRow} to retrieve the query + * editor row locator for a given query refId + */ + panelEditPage: PanelEditPage; + + /** + * Isolated {@link VariableEditPage} instance for each test. + * + * Navigates to a new dashboard page and adds a new variable. + * + * Use {@link VariableEditPage.setVariableType} to change the variable type + */ + variableEditPage: VariableEditPage; + + /** + * Isolated {@link AnnotationEditPage} instance for each test. + * + * Navigates to a new dashboard page and adds a new annotation. + * + * Use {@link AnnotationEditPage.datasource.set} to change the datasource + */ + annotationEditPage: AnnotationEditPage; + + /** + * Isolated {@link ExplorePage} instance for each test. + * + * Navigates to a the explore page. + * + * Use {@link ExplorePage.datasource.set} to change the datasource + * Use {@link ExplorePage.getQueryEditorEditorRow} to retrieve the query editor + * row locator for a given query refId + */ + explorePage: ExplorePage; + + /** + * Fixture command that will create an isolated DataSourceConfigPage instance for a given data source type. + * + * The data source config page cannot be navigated to without a data source uid, so this fixture will create a new + * data source using the Grafana API, create a new DataSourceConfigPage instance and navigate to the page. + */ + createDataSourceConfigPage: (args: CreateDataSourcePageArgs) => Promise; + + /** + * Fixture command that creates a data source via the Grafana API. + * + * If you have tests that depend on the the existance of a data source, + * you may use this command in a setup project. Read more about setup projects + * here: https://playwright.dev/docs/auth#basic-shared-account-in-all-tests + */ + createDataSource: (args: CreateDataSourceArgs) => Promise; + + /** + * Fixture command that creates a user via the Grafana API and assigns a role to it if a role is provided + * This may be useful if your plugin supports RBAC and you need to create a user with a specific role. See login fixture for more information. + */ + createUser: () => Promise; + + /** + * Fixture command that login to Grafana using the Grafana API and stores the cookie state on disk. + * The file name for the storage state will be `playwright/.auth/.json`, so it's important that the username is unique. + * + * If you have not specified a user, the default admin/admin credentials will be used. + * + * e.g + * projects: [ + { + name: 'authenticate', + testDir: './src/auth', + testMatch: [/.*auth\.setup\.ts/], + }, + { + name: 'run tests as admin user', + testDir: './tests', + use: { + ...devices['Desktop Chrome'], + storageState: 'playwright/.auth/admin.json', + }, + dependencies: ['authenticate'], + } + } + * + * If your plugin supports RBAC, you may want to use different projects for different roles. + * In the following example, a new user with the role `Viewer` gets created and authenticated in a `createUserAndAuthenticate` project. + * In the `viewer` project, authentication state from the previous project is used in all tests in the ./tests/viewer folder. + * projects: [ + { + name: 'createUserAndAuthenticate', + testDir: 'node_modules/@grafana/plugin-e2e/dist/auth', + testMatch: [/.*auth\.setup\.ts/], + use: { + user: { + user: 'viewer', + password: 'password', + role: 'Viewer', + }, + }, + }, + { + name: 'viewer', + testDir: './tests/viewer', + use: { + ...devices['Desktop Chrome'], + storageState: 'playwright/.auth/viewer.json', + }, + dependencies: ['createUserAndAuthenticate'], + } + } + * + * To override credentials in a single test: + * test.use({ storageState: 'playwright/.auth/admin.json', user: { user: 'admin', password: 'admin' } }); + * To avoid authentication in a single test: + * test.use({ storageState: { cookies: [], origins: [] } }); + */ + login: () => Promise; + + /** + * Fixture command that reads a yaml file in the provisioning/datasources directory. + * + * The file name should be the name of the file with the .yaml|.yml extension. + * If a data source name is provided, the first data source that matches the name will be returned. + * If no name is provided, the first data source in the list of data sources will be returned. + */ + readProvisionedDataSource(args: ReadProvisionedDataSourceArgs): Promise>; + + /** + * Fixture command that reads a dashboard json file in the provisioning/dashboards directory. + * + * Can be useful when navigating to a provisioned dashboard and you don't want to hard code the dashboard UID. + */ + readProvisionedDashboard(args: ReadProvisionedDashboardArgs): Promise; + + /** + * Function that checks if a feature toggle is enabled. Only works for frontend feature toggles. + */ + isFeatureToggleEnabled(featureToggle: keyof T): Promise; + + /** + * Fixture command that navigates to an already exist dashboard. Returns a DashboardPage instance. + */ + gotoDashboardPage: (args: DashboardPageArgs) => Promise; + + /** + * Fixture command that navigates a panel edit page for an already existing panel in a dashboard. + */ + gotoPanelEditPage: (args: DashboardEditViewArgs) => Promise; + + /** + * Fixture command that navigates a variable edit page for an already existing variable query in a dashboard. + */ + gotoVariableEditPage: (args: DashboardEditViewArgs) => Promise; + + /** + * Fixture command that navigates an annotation edit page for an already existing annotation query in a dashboard. + */ + gotoAnnotationEditPage: (args: DashboardEditViewArgs) => Promise; + + /** + * Fixture command that navigates a configuration page for an already existing data source instance. + */ + gotoDataSourceConfigPage: (uid: string) => Promise; + + /** + * Fixture command that navigates to the AppConfigPage for a given plugin. + */ + gotoAppConfigPage: (args: GotoAppConfigPageArgs) => Promise; + + /** + * Fixture command that navigates to an AppPage for a given plugin. + */ + gotoAppPage: (args: GotoAppPageArgs) => Promise; +}; /** * The context object passed to page object models @@ -10,6 +273,16 @@ export type PluginTestCtx = { grafanaVersion: string; selectors: E2ESelectors; t 'page' | 'request' >; +/** + * Playwright args used when defining fixtures + */ +export type PlaywrightArgs = PluginFixture & + PluginOptions & + PlaywrightTestArgs & + PlaywrightTestOptions & + PlaywrightWorkerArgs & + PlaywrightWorkerOptions; + /** * The data source settings */ @@ -36,8 +309,6 @@ export interface Dashboard { title?: string; } -export type OrgRole = 'None' | 'Viewer' | 'Editor' | 'Admin'; - export type CreateUserArgs = { /** * The username of the user to create. Needs to be unique @@ -87,18 +358,6 @@ export type CreateDataSourcePageArgs = { deleteDataSourceAfterTest?: boolean; }; -export type RequestOptions = { - /** - * Maximum wait time in milliseconds, defaults to 30 seconds, pass `0` to disable the timeout. The default value can - * be changed by using the - * [browserContext.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-default-timeout) - * or [page.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-page#page-set-default-timeout) methods. - */ - timeout?: number; - - waitForResponsePredicateCallback?: string | RegExp | ((response: Response) => boolean | Promise); -}; - export interface TimeRangeArgs { /** * The from time @@ -166,6 +425,28 @@ export type ReadProvisionedDataSourceArgs = { name?: string; }; +export type PluginPageArgs = { + pluginId: string; +}; + +export type GotoAppConfigPageArgs = PluginPageArgs; + +export type GotoAppPageArgs = PluginPageArgs & { + path?: string; +}; + +export type RequestOptions = { + /** + * Maximum wait time in milliseconds, defaults to 30 seconds, pass `0` to disable the timeout. The default value can + * be changed by using the + * [browserContext.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-default-timeout) + * or [page.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-page#page-set-default-timeout) methods. + */ + timeout?: number; + + waitForResponsePredicateCallback?: string | RegExp | ((response: Response) => boolean | Promise); +}; + export type NavigateOptions = { /** * Referer header value. @@ -218,29 +499,23 @@ export type TriggerRequestOptions = { path?: string; }; -/** - * Panel visualization types - */ -export type Visualization = - | 'Alert list' - | 'Bar gauge' - | 'Clock' - | 'Dashboard list' - | 'Gauge' - | 'Graph' - | 'Heatmap' - | 'Logs' - | 'News' - | 'Pie Chart' - | 'Plugin list' - | 'Polystat' - | 'Stat' - | 'Table' - | 'Text' - | 'Time series' - | 'Worldmap Panel'; +export interface ContainTextOptions { + /** + * Whether to perform case-insensitive match. `ignoreCase` option takes precedence over the corresponding regular + * expression flag if specified. + */ + ignoreCase?: boolean; -export type AlertVariant = 'success' | 'warning' | 'error' | 'info'; + /** + * Time to retry the assertion for in milliseconds. Defaults to `timeout` in `TestConfig.expect`. + */ + timeout?: number; + + /** + * Whether to use `element.innerText` instead of `element.textContent` when retrieving DOM node text. + */ + useInnerText?: boolean; +} export interface AlertPageOptions { /** @@ -282,38 +557,28 @@ export interface AlertPageOptions { hasText?: string | RegExp; } +export type OrgRole = 'None' | 'Viewer' | 'Editor' | 'Admin'; + /** - * @internal + * Panel visualization types */ -export interface AlertPage { - ctx: PluginTestCtx; - hasAlert: (severity: AlertVariant, options?: AlertPageOptions) => Promise; -} - -export interface ContainTextOptions { - /** - * Whether to perform case-insensitive match. `ignoreCase` option takes precedence over the corresponding regular - * expression flag if specified. - */ - ignoreCase?: boolean; - - /** - * Time to retry the assertion for in milliseconds. Defaults to `timeout` in `TestConfig.expect`. - */ - timeout?: number; - - /** - * Whether to use `element.innerText` instead of `element.textContent` when retrieving DOM node text. - */ - useInnerText?: boolean; -} - -export type PluginPageArgs = { - pluginId: string; -}; - -export type GotoAppConfigPageArgs = PluginPageArgs; +export type Visualization = + | 'Alert list' + | 'Bar gauge' + | 'Clock' + | 'Dashboard list' + | 'Gauge' + | 'Graph' + | 'Heatmap' + | 'Logs' + | 'News' + | 'Pie Chart' + | 'Plugin list' + | 'Polystat' + | 'Stat' + | 'Table' + | 'Text' + | 'Time series' + | 'Worldmap Panel'; -export type GotoAppPageArgs = PluginPageArgs & { - path?: string; -}; +export type AlertVariant = 'success' | 'warning' | 'error' | 'info';