Skip to content

fix(vscode): blank preview panel on VSCode 1.116 (#2361)#2372

Merged
markscott-ms merged 7 commits intofinos:mainfrom
rocketstack-matt:fix/2361-blank-preview-panel-vscode-1.116
Apr 28, 2026
Merged

fix(vscode): blank preview panel on VSCode 1.116 (#2361)#2372
markscott-ms merged 7 commits intofinos:mainfrom
rocketstack-matt:fix/2361-blank-preview-panel-vscode-1.116

Conversation

@rocketstack-matt
Copy link
Copy Markdown
Member

Description

Fixes #2361.

On VSCode 1.116+, opening the CALM Preview shows a blank pane until the user covers/uncovers it or otherwise forces a relayout. Root cause: CalmPreviewPanel.createOrShow calls panel.reveal() on a webview panel that vscode.window.createWebviewPanel just created. createWebviewPanel already shows the panel; the extra reveal() races with the compositor and stalls the first paint.

CalmPreviewPanel.reveal() gains an optional revealPanel flag; brand-new panels are initialized with revealPanel: false, the reuse path is unchanged.

Regression guards (triple-layered):

  1. Unit test — asserts panel.reveal() is NOT called on brand-new panels and IS called on reuse. Fails on the pre-fix code, passes on the fix. This is the structural guard.
  2. Integration test (@vscode/test-electron) — new test/integration/ harness launches a real VSCode instance (Xvfb on Linux CI), opens the preview against a fixture, and probes the webview with a requestAnimationFrame-gated rendered message. A stalled compositor means rAF never fires → probe returns false → test fails. Matrix runs across 1.115.0, 1.116.0, and stable.
  3. Paint-probe self-validationtest/integration/suite/paint-probe-validation.test.ts creates a standalone webview inside the test (not the CALM extension) that deliberately reproduces the pre-fix buggy pattern. Asserts rendered=false on 1.116 (proves probe catches the stall) and rendered=true on 1.115 (proves probe doesn't silently false-positive under Xvfb). This verifies the probe itself is trustworthy on the remote runner — without this, a passing main test could hide a broken probe.

Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📚 Documentation update
  • 🎨 Code style/formatting changes
  • ♻️ Refactoring (no functional changes)
  • ⚡ Performance improvements
  • ✅ Test additions or updates
  • 🔧 Chore (maintenance, dependencies, CI, etc.)

Affected Components

  • CLI (`cli/`)
  • Schema (`calm/`)
  • CALM AI (`calm-ai/`)
  • CALM Hub (`calm-hub/`)
  • CALM Hub UI (`calm-hub-ui/`)
  • CALM Server (`calm-server/`)
  • CALM Widgets (`calm-widgets/`)
  • Documentation (`docs/`)
  • Shared (`shared/`)
  • VS Code Extension (`calm-plugins/vscode/`)
  • Dependencies
  • CI/CD

Commit Message Format ✅

Testing

  • I have tested my changes locally
  • I have added/updated unit tests
  • All existing tests pass

Local 2×2 matrix (rerun with and without the fix, against both VSCode versions):

VSCode With fix (this PR) Without fix (pre-PR)
1.115.0 main ✓, self-validation ✓
1.116.0 main ✓, self-validation ✓ (probe returns rendered=false as expected) main test fails as expected

Unit test suite: 375 passing (including 2 new regression tests in `preview-panel.spec.ts`).

Checklist

  • My commits follow the conventional commit format
  • I have updated documentation if necessary (added `calm-plugins/vscode/test/integration/README.md`)
  • I have added tests for my changes (if applicable)
  • My changes follow the project's coding standards

Notes for reviewers

  • Production code in `preview-panel.ts` contains only the fix — there is no test-only code mixed in. The buggy pattern is reproduced entirely inside the self-validation test via a standalone vscode.window.createWebviewPanel call.
  • The extension's activate() now returns a small test-only API (src/test-api.ts) exposing waitForPreviewReady / waitForPreviewRendered for integration tests. Not intended for runtime use by other extensions.
  • CI workflow has been split into `build-and-test` → `integration-test` (matrix) → `package-and-publish` so the integration matrix can fan out independently.

Calling panel.reveal() on a webview panel that createWebviewPanel just
created causes a blank first paint on VSCode 1.116+. createWebviewPanel
already shows the panel, so the extra reveal() is redundant and races
with the compositor.

Adds a revealPanel option to CalmPreviewPanel.reveal() so the brand-new
panel path skips the extra call; the reuse path is unchanged.

Regression guards:
- Unit test asserts panel.reveal() is not called on brand-new panels
  and is called on reuse.
- Integration test harness (@vscode/test-electron + Xvfb on CI) runs a
  matrix across 1.115.0, 1.116.0, and stable, using a rAF-based paint
  probe that catches compositor stalls.
- Self-validation test creates a standalone webview with the original
  buggy pattern and asserts the probe returns rendered=false on 1.116
  and rendered=true on 1.115 — proves the probe works remotely and
  isn't silently passing or false-positiving.
@rocketstack-matt rocketstack-matt requested a review from a team as a code owner April 23, 2026 13:49
Copilot AI review requested due to automatic review settings April 23, 2026 13:49
tsup fails to resolve @finos/calm-shared / @finos/calm-models in CI
because the integration-test job skipped `build:shared`. Mirrors the
pattern used by test:vscode and package:vscode.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes a VS Code 1.116+ regression where the CALM Preview webview can appear blank on first open due to an extra panel.reveal() call racing the compositor, and adds layered regression tests (unit + real VS Code integration) to prevent recurrence.

Changes:

  • Avoid calling WebviewPanel.reveal() when creating a brand-new CALM preview panel; keep reveal behavior for panel reuse.
  • Add a webview “paint probe” (ready + rAF-gated rendered) and expose a small test-only API from activate() for integration tests.
  • Introduce @vscode/test-electron integration test harness + CI matrix across multiple VS Code versions.

Reviewed changes

Copilot reviewed 17 out of 18 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
calm-plugins/vscode/src/features/preview/preview-panel.ts Skips panel.reveal() on newly created panels; wires new rendered message handling.
calm-plugins/vscode/src/features/preview/commands.ts Adds rendered webview message type + command.
calm-plugins/vscode/src/features/preview/webview/panel.view-model.ts Posts ready and rAF-based rendered signals from the webview.
calm-plugins/vscode/src/features/preview/preview.view-model.ts Tracks rendered state and emits onRenderedStateChanged for tests.
calm-plugins/vscode/src/test-api.ts Adds test-only API used by integration tests to await ready/rendered.
calm-plugins/vscode/src/extension.ts Makes activate() async and returns the test API for integration tests.
calm-plugins/vscode/src/calm-extension-controller.ts Stores PreviewPanelFactory and provides getTestApi() for integration tests.
calm-plugins/vscode/src/features/preview/preview-panel.spec.ts Adds unit regression tests ensuring reveal() is not called on first create, but is on reuse.
calm-plugins/vscode/test/integration/* Adds Mocha-based @vscode/test-electron harness + regression/self-validation suites.
calm-plugins/vscode/vitest.config.mts Excludes test/integration/** from vitest runs.
calm-plugins/vscode/package.json Adds integration test scripts + dev dependencies (@vscode/test-electron, mocha, glob, types).
.github/workflows/build-vscode-extension.yml Splits workflow into build/test, integration matrix, then package/publish.
package-lock.json Lockfile updates for new dev dependencies.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/build-vscode-extension.yml
Comment thread calm-plugins/vscode/test/integration/suite/paint-probe-validation.test.ts Outdated
Comment thread calm-plugins/vscode/src/features/preview/preview.view-model.ts
- Use vscode.version (runtime) instead of VSCODE_VERSION env var for
  paint-probe self-validation assertions. The env var holds the matrix
  label (e.g. "stable") and doesn't reflect the actual version under test.
- Reset isRendered to false when the preview panel is disposed. The
  PreviewViewModel outlives individual CalmPreviewPanel instances; without
  this reset a stale rendered=true from a prior panel would mask a new
  blank-paint regression on reopen.
- Retry runTests() once in runTest.ts to survive transient CDN timeouts
  when @vscode/test-electron resolves the 'stable' version tag.
- Mark the 'stable' matrix entry as continue-on-error: it's an early
  warning for upcoming VSCode releases, not a hard gate. Pinned versions
  (1.115.0, 1.116.0) remain required.
Copy link
Copy Markdown
Contributor

@markscott-ms markscott-ms left a comment

Choose a reason for hiding this comment

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

Tested on VSCode 1.117.0 / Windows.

Comment thread calm-plugins/vscode/package.json Outdated
@markscott-ms
Copy link
Copy Markdown
Contributor

Also, @LeighFinegold notes in #2361 that VSCode 1.117 does not need this fix, i.e. it was a compatibility issue with 1.116 only.

@markscott-ms markscott-ms merged commit 9142b16 into finos:main Apr 28, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CALM Preview shows blank pane after upgrading to VSCode 1.116

3 participants