Skip to content

fix(plugin-e2e): wait for feature toggles instead of reading them once - #2832

Merged
adamyeats merged 2 commits into
mainfrom
adamyeats/plugin-e2e-await-feature-toggles
Aug 21, 2026
Merged

fix(plugin-e2e): wait for feature toggles instead of reading them once#2832
adamyeats merged 2 commits into
mainfrom
adamyeats/plugin-e2e-await-feature-toggles

Conversation

@adamyeats

Copy link
Copy Markdown
Contributor

What this PR does / why we need it:

isLegacyFeatureEnabled read window.grafanaBootData.settings.featureToggles with no guard:

const featureToggles = await page.evaluate('window.grafanaBootData.settings.featureToggles');
return Boolean(featureToggles[featureToggle]);

Grafana can render the app shell before it has merged its boot data. When that happens the map is briefly absent and the second line throws TypeError: Cannot read properties of undefined (reading '<toggle>'). DashboardPage.addPanel calls this on any Grafana 13 or later to decide useNewSidebarLayout, so the panelEditPage fixture fails outright and takes the whole test with it.

We hit this on a Grafana Cloud instance, whose shell fetches its settings asynchronously. It does not reproduce against a local Grafana, which inlines the settings into the document, so the failure only appears against a deployed instance.

Optional chaining alone would be the wrong fix. A missing map is indistinguishable from every toggle being disabled, so addPanel would silently choose its legacy branch on an instance where dashboardNewLayouts is actually enabled. That trades a loud crash for a quiet wrong path. This waits for the map instead, and only falls back to an empty one if it never arrives, which is the same degrade-and-log approach the bootData fixture already uses.

Worth noting the Window declaration in src/index.ts types featureToggles as always present, which is why there was nothing to prompt a guard here. I have left that type alone rather than making it optional, since it describes what Grafana settles on, and widening it would ripple through unrelated call sites.

Which issue(s) this PR fixes:

No upstream issue. Found downstream while getting a Cloud E2E suite green, catalogued in grafana/grafana-cloudwatch-datasource#619.

Special notes for your reviewer:

  • Adds isFeatureToggleEnabled.test.ts covering an enabled toggle, a toggle absent from the map, that the map is waited for rather than read once, and that a map which never arrives returns false and logs rather than throwing.
  • The 5s ceiling is a polling ceiling, so a local Grafana with inline settings resolves immediately and pays nothing.
  • npm run lint, npm run typecheck and npx vitest run are all clean in packages/plugin-e2e, 48 tests passing.

One adjacent thing I did not change, in case you want it in a separate PR: DataSourcePicker.set() fills the combobox and presses Enter without asserting that anything was selected. A name that matches nothing leaves the panel on its previous datasource and the test fails much later on a missing control. That silent no-op cost us several days of misdiagnosis. Happy to send a patch if you would like the assertion added.

@adamyeats
adamyeats requested a review from a team as a code owner August 19, 2026 12:03
@adamyeats
adamyeats requested review from leventebalogh, toddtreece and xnyo and removed request for a team August 19, 2026 12:03
@cla-assistant

cla-assistant Bot commented Aug 19, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@cla-assistant

cla-assistant Bot commented Aug 19, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@adamyeats

adamyeats commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

The two red legs are pre-existing, not from this change.

Both fail on components.timeRangePicker.within … scoped to a root locator (#2583). DashboardPage.toolbar gates on the version each selector first existed, but at 9.4.17 and 11.1.13 the element is still behind a default-off toggle (topnav, dashboardScene), so the scoped locator waits out the test timeout — the browser has been closed error is the teardown cascade, not the cause. Both versions only entered the matrix this week.

This change can't reach that test: isLegacyFeatureEnabled is called only from addPanel, which that test never calls.

Fixed in #2836, verified 8.5.27 → 13.2.0.

Unrelated and repo-wide: Test create-plugin update command fails because @grafana/data@12.4.9 pins the unpublished @grafana/schema@12.4.9.

@sunker sunker left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for raising this! Added a minor comment.

The create-plugin update step should be fixed here, although you'll need to sync with main to pick up the fix. I suspect the other two failures may be intermittent and are something for me and the team to investigate. Let me know if you're still seeing them.

Comment thread packages/plugin-e2e/src/fixtures/isFeatureToggleEnabled.ts Outdated
@adamyeats
adamyeats requested a review from sunker August 20, 2026 20:19
@adamyeats

adamyeats commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

The rethrow is in, and the branch now includes main for #2837. Thanks for sorting that.

The two version legs are not intermittent. DashboardPage.toolbar picks its root by the version where each selector first existed. At 9.4.x, and from 11.1.x to 11.2.x, that element sits behind a default-off toggle, so Grafana never renders it. #2836 corrects it and is green on all six legs.

@sunker sunker left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice! 🚀

isLegacyFeatureEnabled read window.grafanaBootData.settings.featureToggles with no
guard, so it threw "Cannot read properties of undefined" whenever the app shell had
rendered before its boot data was merged. DashboardPage.addPanel calls it on any
Grafana 13 or later, so the panelEditPage fixture failed outright.

Optional chaining alone is not enough. A missing map is indistinguishable from every
toggle being disabled, so callers would take their legacy branch on an instance where
the toggle is enabled. This waits for the map and only falls back to an empty one if
it never arrives, which matches the existing bootData fixture's handling.

Adds unit tests for the enabled, absent-toggle and never-arrives cases.
@adamyeats
adamyeats force-pushed the adamyeats/plugin-e2e-await-feature-toggles branch from 24c6ce4 to 6ea2936 Compare August 21, 2026 22:42
@adamyeats
adamyeats enabled auto-merge (squash) August 21, 2026 22:43
@adamyeats
adamyeats merged commit 7b1f4fd into main Aug 21, 2026
40 checks passed
@adamyeats
adamyeats deleted the adamyeats/plugin-e2e-await-feature-toggles branch August 21, 2026 22:46
@github-project-automation github-project-automation Bot moved this from 🔬 In review to 🚀 Shipped in Grafana Catalog Team Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 🚀 Shipped

Development

Successfully merging this pull request may close these issues.

3 participants