diff --git a/packages/plugin-e2e/docker-compose.yaml b/packages/plugin-e2e/docker-compose.yaml index eb4766ab4..06657fda1 100644 --- a/packages/plugin-e2e/docker-compose.yaml +++ b/packages/plugin-e2e/docker-compose.yaml @@ -7,6 +7,7 @@ services: - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin - GF_AUTH_ANONYMOUS_ORG_NAME=Main Org. - GF_AUTH_ANONYMOUS_ORG_ID=1 + - GF_PANELS_ENABLE_ALPHA=true - GOOGLE_JWT_FILE=${GOOGLE_JWT_FILE} - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} diff --git a/packages/plugin-e2e/src/models/components/PanelEditOptionsGroup.ts b/packages/plugin-e2e/src/models/components/PanelEditOptionsGroup.ts index 98d628275..1af65b05f 100644 --- a/packages/plugin-e2e/src/models/components/PanelEditOptionsGroup.ts +++ b/packages/plugin-e2e/src/models/components/PanelEditOptionsGroup.ts @@ -1,6 +1,6 @@ import { Locator } from '@playwright/test'; import { PluginTestCtx } from '../../types'; -import { Select } from './Select'; +import { createSelectProxy } from './SelectProxy'; import { ColorPicker } from './ColorPicker'; import { UnitPicker } from './UnitPicker'; @@ -29,8 +29,8 @@ export class PanelEditOptionsGroup { return this.getNumberInput(label); } - getSelect(label: string): Select { - return new Select(this.ctx, this.getByLabel(label)); + getSelect(label: string): Locator { + return createSelectProxy(this.getByLabel(label)); } getColorPicker(label: string): ColorPicker { diff --git a/packages/plugin-e2e/src/models/components/Select.ts b/packages/plugin-e2e/src/models/components/Select.ts deleted file mode 100644 index 3270f6d46..000000000 --- a/packages/plugin-e2e/src/models/components/Select.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Locator } from '@playwright/test'; -import { PluginTestCtx } from '../../types'; - -export class Select { - constructor(private ctx: PluginTestCtx, public readonly element: Locator) {} - - getOption(label: string): Locator { - // This one is opened in a portal so it is outside of the element - return this.ctx.page.getByLabel('Select options menu').getByText(label); - } - - open(): Promise { - return this.element.getByRole('combobox').click(); - } - - value(): Locator { - return this.element.locator('div[class*="-grafana-select-value-container"]'); - } - - values(): Locator { - return this.element.locator('div[class*="-grafana-select-multi-value-container"]'); - } -} diff --git a/packages/plugin-e2e/src/models/components/SelectProxy.ts b/packages/plugin-e2e/src/models/components/SelectProxy.ts new file mode 100644 index 000000000..f87cd803c --- /dev/null +++ b/packages/plugin-e2e/src/models/components/SelectProxy.ts @@ -0,0 +1,52 @@ +import { Locator } from '@playwright/test'; + +export function createSelectProxy(locator: Locator): Locator { + return new Proxy(locator, { + get(target, prop, receiver) { + if (prop === 'selectOption') { + return selectOption.bind(target); + } + if (prop === '_selector') { + const selector = Reflect.get(target, prop, receiver); + return `${selector}\ >>\ div[class*=\"-grafana-select-value-container\"]`; + } + return Reflect.get(target, prop, receiver); + }, + }); +} + +const selectOption: Locator['selectOption'] = async function (this: Locator, values, options) { + // Open the menu of the select component + this.getByRole('combobox').click(); + + if (typeof values === 'string') { + const option = this.page().getByLabel('Select options menu').getByText(values); + await option.click(options); + return [values]; + } + + return Promise.resolve([]); +}; + +// const textContent: Locator['textContent'] = async function (this: Locator, options) { +// const singleContainer = this.locator('div[class*="-grafana-select-value-container"]'); +// const isSingle = await singleContainer.isVisible(); + +// if (isSingle) { +// return singleContainer.locator('div[class*="-singleValue"]').innerText(options); +// } + +// const multiContainer = this.locator('div[class*="-grafana-select-multi-value-container"]'); +// const isMulti = await multiContainer.isVisible(); + +// if (isMulti) { +// const valueContainers = await multiContainer +// .locator('div[class*="-grafana-select-multi-value-container"] > div') +// .all(); + +// const values = await Promise.all(valueContainers.map((v) => v.innerText(options))); +// return Promise.resolve(values.join(', ')); +// } + +// return Promise.resolve(null); +// }; diff --git a/packages/plugin-e2e/tests/as-admin-user/panel/panelEdit.spec.ts b/packages/plugin-e2e/tests/as-admin-user/panel/panelEdit.spec.ts index 50f9d6040..13ce01cf2 100644 --- a/packages/plugin-e2e/tests/as-admin-user/panel/panelEdit.spec.ts +++ b/packages/plugin-e2e/tests/as-admin-user/panel/panelEdit.spec.ts @@ -81,10 +81,8 @@ test('select value in single value select', async ({ gotoPanelEditPage }) => { // This one is a bit weird since the select don't have a field label const timeZoneSelect = timeFormatOptions.getSelect('Timezone'); - await timeZoneSelect.open(); - await timeZoneSelect.getOption('Europe/Stockholm').click(); - - await expect(timeZoneSelect.value()).toHaveText('Europe/Stockholm'); + await timeZoneSelect.selectOption('Europe/Stockholm'); + await expect(timeZoneSelect).toHaveText('Europe/Stockholm'); }); test('enter value in slider', async ({ gotoPanelEditPage }) => { @@ -141,11 +139,6 @@ test('select timezone in timezone picker', async ({ gotoPanelEditPage }) => { const standardOptions = panelEdit.getOptionsGroup('Axis'); const timeZonePicker = standardOptions.getSelect('Time zone'); - await expect(timeZonePicker.value()).toHaveText('Default'); - - await timeZonePicker.open(); - const option = await timeZonePicker.getOption('Europe/Stockholm'); - await option.click(); - - await expect(timeZonePicker.value()).toHaveText('Europe/Stockholm'); + const option = await timeZonePicker.selectOption('Europe/Stockholm'); + await expect(timeZonePicker).toHaveText('Europe/Stockholm'); });