grafana / grafana/plugin-tools
Bug: Scaffolded jest config's canvas stub crashes @grafana/ui components (Combobox); IntersectionObserver isn't polyfilled
- Dominant language
- TypeScript
- Stars
- 89
- Forks
- 57
- Avg merge
- 3d 17h
- Merged PRs (30d)
- 37
Description
### Which package(s) does this bug affect?
- [x] Create Plugin
- [ ] ESLint Config
- [ ] Plugin Docs CLI
- [ ] Plugin Docs Parser
- [ ] Plugin E2E
- [ ] Plugin ESLint Rules
- [ ] Plugin Meta Extractor
- [ ] Plugin Types Bundler
- [ ] React detect
- [ ] Sign Plugin
- [ ] TS Config
### Package versions
```shell
7.10.0
```
### What happened?
The scaffolded `.config/jest-setup.js` sets:
`HTMLCanvasElement.prototype.getContext = () => {};`
This returns `undefined` instead of a usable canvas context. `@grafana/ui`'s `measureText` utility (used internally by `Combobox` to size its dropdown) calls `document.createElement('canvas').getContext('2d')` and then does `context.font = ...` / `context.measureText(text)`. With the scaffolded stub, `context` is `undefined`, so this throws:
`TypeError: Cannot read properties of undefined (reading 'measureText')`
Separately, jsdom doesn't implement `IntersectionObserver`, and the scaffolded setup doesn't polyfill it either. Opening a `Combobox`'s dropdown mounts its `ScrollIndicators`, which uses `IntersectionObserver`, throwing:
`ReferenceError: IntersectionObserver is not defined`
### What you expected to happen
Rendering and interacting with a `@grafana/ui` `Combobox` (and any component that uses it) inside a test using the scaffolded jest config should work out of the box, without needing to hand-roll these stubs in every plugin.
### How to reproduce it (as minimally and precisely as possible)
1. Scaffold a new plugin with `@grafana/create-plugin` (default jest config).
2. Add a test that renders any component containing a `@grafana/ui` ``, using `@testing-library/react`'s `render`.
3. Run pnpm test:ci (or jest).
4. See `TypeError: Cannot read properties of undefined (reading 'measureText')` on render, and `ReferenceError: IntersectionObserver is not defined` if the dropdown is opened.
### Environment
```shell
System:
OS: macOS 15.7.7
CPU: (14) arm64 Apple M4 Pro
Memory: 570.22 MB / 24.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 24.16.0 - ~/.nvm/versions/node/v24.16.0/bin/node
npm: 11.13.0 - ~/.nvm/versions/node/v24.16.0/bin/npm
pnpm: 11.22.0 - ~/.nvm/versions/node/v24.16.0/bin/pnpm
Browsers:
Chrome: 151.0.7922.170
Firefox: 148.0.2
Safari: 26.5.2
npmPackages:
@grafana/assistant: ^0.1.33 => 0.1.33
@grafana/data: ^13.1.1 => 13.1.1
@grafana/eslint-config: ^10.0.0 => 10.0.0
@grafana/google-sdk: ^0.6.1 => 0.6.1
@grafana/plugin-e2e: ^3.10.0 => 3.10.0
@grafana/runtime: ^13.1.1 => 13.1.1
@grafana/schema: ^13.1.1 => 13.1.1
@grafana/sign-plugin: ^3.3.3 => 3.3.3
@grafana/tsconfig: ^2.2.0 => 2.2.0
@grafana/ui: ^13.1.1 => 13.1.1
```
### Additional context
_No response_
Contributor guide
Research direction
Start with the scaffolded .config/jest-setup.js and reproduce the issue using a minimal test that renders and opens a @grafana/ui Combobox, then run pnpm test:ci. Done means the scaffolded Jest setup supports the canvas-dependent rendering and dropdown interaction without the reported TypeError or ReferenceError.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- frontend, testing, tooling
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100