From ecf242b088794b3cdf82bf30d31517b23f219deb Mon Sep 17 00:00:00 2001 From: Dushyant Acharya Date: Mon, 18 May 2026 03:24:50 +0530 Subject: [PATCH 1/2] docs: add section on testing Workspace Trust behavior in extensions Adds a new section to the Testing Extensions guide explaining how extension authors can write integration tests that cover both trusted and untrusted workspace scenarios. Covers: - How Workspace Trust state works in the Extension Development Host - Configuring separate test runs per trust state via @vscode/test-cli - Using an isolated --user-data-dir to prevent trust from persisting - Writing assertions using vscode.workspace.isTrusted - Using onDidGrantWorkspaceTrust event in tests - Configuring launch.json for trusted and untrusted test runs Closes #9583 --- .../testing-extension.md | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/api/working-with-extensions/testing-extension.md b/api/working-with-extensions/testing-extension.md index a833b6f52a..5f99d884a1 100644 --- a/api/working-with-extensions/testing-extension.md +++ b/api/working-with-extensions/testing-extension.md @@ -363,6 +363,131 @@ async function main() { main(); ``` +## Testing Workspace Trust behavior + +If your extension declares support for [Workspace Trust](/api/extension-guides/workspace-trust) (via the `capabilities.untrustedWorkspaces` field in `package.json`), you should write integration tests that verify your extension behaves correctly in both trusted and untrusted workspaces. + +### How Workspace Trust works in tests + +By default, the Extension Development Host opens workspaces as **trusted**. To test your extension's behavior in an **untrusted** (Restricted Mode) workspace, you need to open a workspace folder that VS Code treats as untrusted by passing the `--disable-workspace-trust` flag **and** pointing to a folder that has not been explicitly trusted by the user. + +The most reliable approach is to use a temporary, fresh workspace folder that has never been opened before — VS Code will prompt for trust on a new workspace, but in a headless test environment, the workspace defaults to untrusted when `security.workspace.trust.enabled` is `true` and no trust has been granted. + +### Configuring separate test runs for trusted and untrusted workspaces + +When using `@vscode/test-cli`, you can define separate test configurations for each trust state: + +```js +// .vscode-test.js +const { defineConfig } = require('@vscode/test-cli'); +const path = require('path'); + +module.exports = defineConfig([ + { + label: 'trustedWorkspaceTests', + files: 'out/test/**/*.test.js', + workspaceFolder: './test/fixtures/trusted-workspace', + }, + { + label: 'untrustedWorkspaceTests', + files: 'out/test/**/*.test.js', + workspaceFolder: './test/fixtures/untrusted-workspace', + // Pass user data dir to isolate trust settings per test run + launchArgs: [ + '--user-data-dir', + path.join(__dirname, '.vscode-test', 'user-data-untrusted'), + ], + }, +]); +``` + +Because VS Code persists trust decisions in the user data directory, using a dedicated `--user-data-dir` for the untrusted test run ensures the workspace is never automatically trusted between runs. + +### Writing tests that assert trust state + +Inside your test suite, you can read the current trust state using `vscode.workspace.isTrusted` and assert that your extension responds correctly: + +```ts +import * as assert from 'assert'; +import * as vscode from 'vscode'; + +suite('Workspace Trust Tests', () => { + + test('workspace is trusted by default in standard test run', () => { + assert.strictEqual(vscode.workspace.isTrusted, true); + }); + + test('extension disables restricted features in untrusted workspace', async () => { + // Replace with your extension's actual command or exported API + const isFeatureAvailable = await vscode.commands.executeCommand( + 'myExtension.isRestrictedFeatureEnabled' + ); + + if (vscode.workspace.isTrusted) { + assert.strictEqual(isFeatureAvailable, true, 'Feature should be enabled in a trusted workspace'); + } else { + assert.strictEqual(isFeatureAvailable, false, 'Feature should be disabled in an untrusted workspace'); + } + }); + + test('extension respects onDidChangeTrust event', async () => { + let trustChanged = false; + const disposable = vscode.workspace.onDidGrantWorkspaceTrust(() => { + trustChanged = true; + }); + + // In a real scenario, trust would be granted programmatically or by user action. + // This test demonstrates how to listen for the event. + disposable.dispose(); + + // Verify the listener was registered without error + assert.ok(true); + }); +}); +``` + +> **Note**: You cannot programmatically grant or revoke workspace trust from within a test. To verify behavior across both trust states, run separate test configurations as shown above — one for each trust state. + +### Using `launch.json` to test an untrusted workspace + +If you prefer using the debug launch configuration, add a second configuration that points to an isolated user data directory: + +```json +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Extension Tests (Trusted)", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}", + "--extensionTestsPath=${workspaceFolder}/out/test/suite/index", + "${workspaceFolder}/test/fixtures/trusted-workspace" + ], + "outFiles": ["${workspaceFolder}/out/test/**/*.js"] + }, + { + "name": "Extension Tests (Untrusted)", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}", + "--extensionTestsPath=${workspaceFolder}/out/test/suite/index", + "--user-data-dir=${workspaceFolder}/.vscode-test/user-data-untrusted", + "${workspaceFolder}/test/fixtures/untrusted-workspace" + ], + "outFiles": ["${workspaceFolder}/out/test/**/*.js"] + } + ] +} +``` + +For more information on how to declare trust requirements in your extension manifest and how to use the `vscode.workspace.isTrusted` API, see the [Workspace Trust Extension Guide](/api/extension-guides/workspace-trust). + ## Next steps - [Continuous Integration](/api/working-with-extensions/continuous-integration) - Run your extension tests in a Continuous Integration service such as Azure DevOps. +- [Workspace Trust Extension Guide](/api/extension-guides/workspace-trust) - Learn how to declare and handle workspace trust in your extension. From aaa28b13b737a37604cebdfd15115e9e7381c706 Mon Sep 17 00:00:00 2001 From: Nick Trogh Date: Thu, 28 May 2026 13:44:28 +0200 Subject: [PATCH 2/2] Edit pass to make the section more concise --- .../testing-extension.md | 88 +++---------------- 1 file changed, 12 insertions(+), 76 deletions(-) diff --git a/api/working-with-extensions/testing-extension.md b/api/working-with-extensions/testing-extension.md index 5f99d884a1..081b26eb9f 100644 --- a/api/working-with-extensions/testing-extension.md +++ b/api/working-with-extensions/testing-extension.md @@ -365,17 +365,14 @@ main(); ## Testing Workspace Trust behavior -If your extension declares support for [Workspace Trust](/api/extension-guides/workspace-trust) (via the `capabilities.untrustedWorkspaces` field in `package.json`), you should write integration tests that verify your extension behaves correctly in both trusted and untrusted workspaces. +If your extension declares `capabilities.untrustedWorkspaces` in `package.json`, add integration tests for both trusted and untrusted workspaces. You can't programmatically grant or revoke Workspace Trust from an extension test. Use separate test runs for trusted and untrusted states. -### How Workspace Trust works in tests +When using `@vscode/test-cli`, define separate test configurations so you can run each trust state independently: -By default, the Extension Development Host opens workspaces as **trusted**. To test your extension's behavior in an **untrusted** (Restricted Mode) workspace, you need to open a workspace folder that VS Code treats as untrusted by passing the `--disable-workspace-trust` flag **and** pointing to a folder that has not been explicitly trusted by the user. +- **trustedWorkspaceTests**: Gives you a baseline run where trust restrictions are not applied. This helps verify your extension's full-feature behavior and catch regressions in the trusted path. +- **untrustedWorkspaceTests**: Verifies Restricted Mode behavior with Workspace Trust still enabled. Using a dedicated `--user-data-dir` prevents previously persisted trust decisions from making this run accidentally trusted. -The most reliable approach is to use a temporary, fresh workspace folder that has never been opened before — VS Code will prompt for trust on a new workspace, but in a headless test environment, the workspace defaults to untrusted when `security.workspace.trust.enabled` is `true` and no trust has been granted. - -### Configuring separate test runs for trusted and untrusted workspaces - -When using `@vscode/test-cli`, you can define separate test configurations for each trust state: +Because each configuration has its own `label`, you can run them independently (for example, `vscode-test --label trustedWorkspaceTests` and `vscode-test --label untrustedWorkspaceTests`) or run both in sequence. ```js // .vscode-test.js @@ -387,12 +384,14 @@ module.exports = defineConfig([ label: 'trustedWorkspaceTests', files: 'out/test/**/*.test.js', workspaceFolder: './test/fixtures/trusted-workspace', + // Optional: disables Workspace Trust for this run + launchArgs: ['--disable-workspace-trust'], }, { label: 'untrustedWorkspaceTests', files: 'out/test/**/*.test.js', workspaceFolder: './test/fixtures/untrusted-workspace', - // Pass user data dir to isolate trust settings per test run + // Keep Workspace Trust enabled and isolate user data for deterministic runs launchArgs: [ '--user-data-dir', path.join(__dirname, '.vscode-test', 'user-data-untrusted'), @@ -401,90 +400,27 @@ module.exports = defineConfig([ ]); ``` -Because VS Code persists trust decisions in the user data directory, using a dedicated `--user-data-dir` for the untrusted test run ensures the workspace is never automatically trusted between runs. - -### Writing tests that assert trust state - -Inside your test suite, you can read the current trust state using `vscode.workspace.isTrusted` and assert that your extension responds correctly: +In your tests, assert trust-aware behavior by checking `vscode.workspace.isTrusted`: ```ts import * as assert from 'assert'; import * as vscode from 'vscode'; suite('Workspace Trust Tests', () => { - - test('workspace is trusted by default in standard test run', () => { - assert.strictEqual(vscode.workspace.isTrusted, true); - }); - - test('extension disables restricted features in untrusted workspace', async () => { - // Replace with your extension's actual command or exported API + test('extension behavior changes by trust state', async () => { const isFeatureAvailable = await vscode.commands.executeCommand( 'myExtension.isRestrictedFeatureEnabled' ); if (vscode.workspace.isTrusted) { - assert.strictEqual(isFeatureAvailable, true, 'Feature should be enabled in a trusted workspace'); + assert.strictEqual(isFeatureAvailable, true); } else { - assert.strictEqual(isFeatureAvailable, false, 'Feature should be disabled in an untrusted workspace'); + assert.strictEqual(isFeatureAvailable, false); } }); - - test('extension respects onDidChangeTrust event', async () => { - let trustChanged = false; - const disposable = vscode.workspace.onDidGrantWorkspaceTrust(() => { - trustChanged = true; - }); - - // In a real scenario, trust would be granted programmatically or by user action. - // This test demonstrates how to listen for the event. - disposable.dispose(); - - // Verify the listener was registered without error - assert.ok(true); - }); }); ``` -> **Note**: You cannot programmatically grant or revoke workspace trust from within a test. To verify behavior across both trust states, run separate test configurations as shown above — one for each trust state. - -### Using `launch.json` to test an untrusted workspace - -If you prefer using the debug launch configuration, add a second configuration that points to an isolated user data directory: - -```json -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Extension Tests (Trusted)", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}", - "--extensionTestsPath=${workspaceFolder}/out/test/suite/index", - "${workspaceFolder}/test/fixtures/trusted-workspace" - ], - "outFiles": ["${workspaceFolder}/out/test/**/*.js"] - }, - { - "name": "Extension Tests (Untrusted)", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}", - "--extensionTestsPath=${workspaceFolder}/out/test/suite/index", - "--user-data-dir=${workspaceFolder}/.vscode-test/user-data-untrusted", - "${workspaceFolder}/test/fixtures/untrusted-workspace" - ], - "outFiles": ["${workspaceFolder}/out/test/**/*.js"] - } - ] -} -``` - For more information on how to declare trust requirements in your extension manifest and how to use the `vscode.workspace.isTrusted` API, see the [Workspace Trust Extension Guide](/api/extension-guides/workspace-trust). ## Next steps