diff --git a/packages/create-plugin/templates/common/.config/AGENTS/e2e-testing.md b/packages/create-plugin/templates/common/.config/AGENTS/e2e-testing.md new file mode 100644 index 0000000000..40a27ed2ea --- /dev/null +++ b/packages/create-plugin/templates/common/.config/AGENTS/e2e-testing.md @@ -0,0 +1,185 @@ +# E2E testing a Grafana plugin + +This plugin uses `@grafana/plugin-e2e` and Playwright for end-to-end testing. + +- Always import `test` and `expect` from `@grafana/plugin-e2e`, not from `@playwright/test`. +- Always use `@grafana/plugin-e2e` fixtures and page models instead of raw Playwright navigation. They handle Grafana version differences automatically. +- Place test files in `tests/` as `*.spec.ts`. +- Each test must be independent and assume fresh state. +- If tests fail against newer Grafana versions, update `@grafana/plugin-e2e` first. It evolves alongside Grafana core to handle selector and API changes. + +## Selecting elements + +### Grafana selectors + +- Use Grafana e2e-selectors whenever possible. Always get them from the `selectors` fixture provided by `@grafana/plugin-e2e` - never import from `@grafana/e2e-selectors` directly. The fixture resolves the correct selectors for the Grafana version under test. +- Always use the `getByGrafanaSelector` method (exposed by all plugin-e2e page models) to resolve selectors to Playwright locators. It handles the `aria-label` vs `data-testid` difference across Grafana versions automatically. + ```typescript + panelEditPage.getByGrafanaSelector(selectors.components.CodeEditor.container).click(); + ``` + +### Scoping locators + +Scope locators to the narrowest context possible. +```typescript +// bad - matches any "URL" text on the page +page.getByText('URL').click(); +// good - scoped to the plugin's wrapper +page.getByTestId('plugin-url-wrapper').getByText('URL').click(); +``` + +### Form elements + +The `InlineField` and `Field` components can be used interchangeably in the examples below. + +**Input** - use `getByRole('textbox', { name: '