@theia/workspace
Version:
Theia - Workspace Extension
755 lines (599 loc) • 33.3 kB
text/typescript
// *****************************************************************************
// Copyright (C) 2026 EclipseSource GmbH.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
import { expect } from 'chai';
import * as sinon from 'sinon';
import { PreferenceChange, PreferenceScope } from '@theia/core/lib/common/preferences';
import { WorkspaceTrustService } from './workspace-trust-service';
import {
WORKSPACE_TRUST_EMPTY_WINDOW,
WORKSPACE_TRUST_ENABLED,
WORKSPACE_TRUST_STARTUP_PROMPT,
WORKSPACE_TRUST_TRUSTED_FOLDERS,
WorkspaceTrustPrompt
} from '../common/workspace-trust-preferences';
import URI from '@theia/core/lib/common/uri';
class TestableWorkspaceTrustService extends WorkspaceTrustService {
public async testHandlePreferenceChange(change: PreferenceChange): Promise<void> {
return this.handlePreferenceChange(change);
}
public async testHandleWorkspaceChanged(): Promise<void> {
return this.handleWorkspaceChanged();
}
public setCurrentTrust(trust: boolean | undefined): void {
this.currentTrust = trust;
}
public getCurrentTrust(): boolean | undefined {
return this.currentTrust;
}
public override isWorkspaceTrustResolved(): boolean {
return super.isWorkspaceTrustResolved();
}
public async testCalculateWorkspaceTrust(): Promise<boolean | undefined> {
return this.calculateWorkspaceTrust();
}
public testShouldReloadForTrustChange(newTrust: boolean): boolean {
return this.shouldReloadForTrustChange(newTrust);
}
}
describe('WorkspaceTrustService', () => {
let service: TestableWorkspaceTrustService;
beforeEach(() => {
service = new TestableWorkspaceTrustService();
});
afterEach(() => {
sinon.restore();
});
describe('calculateWorkspaceTrust', () => {
let workspaceTrustPrefStub: { [key: string]: unknown };
let workspaceServiceStub: {
tryGetRoots: () => Array<{ resource: URI }>;
workspace: { resource: URI } | undefined;
saved: boolean;
};
let untitledWorkspaceServiceStub: {
isUntitledWorkspace: (uri?: URI, configDirUri?: URI) => boolean;
};
let envVariablesServerStub: {
getConfigDirUri: () => Promise<string>;
};
beforeEach(() => {
workspaceTrustPrefStub = {
[WORKSPACE_TRUST_ENABLED]: true,
[WORKSPACE_TRUST_EMPTY_WINDOW]: false,
[WORKSPACE_TRUST_STARTUP_PROMPT]: WorkspaceTrustPrompt.NEVER,
[WORKSPACE_TRUST_TRUSTED_FOLDERS]: []
};
workspaceServiceStub = {
tryGetRoots: () => [],
workspace: undefined,
saved: false
};
untitledWorkspaceServiceStub = {
isUntitledWorkspace: () => false
};
envVariablesServerStub = {
getConfigDirUri: async () => 'file:///home/user/.theia'
};
(service as unknown as { workspaceTrustPref: typeof workspaceTrustPrefStub }).workspaceTrustPref = workspaceTrustPrefStub;
(service as unknown as { workspaceService: typeof workspaceServiceStub }).workspaceService = workspaceServiceStub;
(service as unknown as { untitledWorkspaceService: typeof untitledWorkspaceServiceStub }).untitledWorkspaceService = untitledWorkspaceServiceStub;
(service as unknown as { envVariablesServer: typeof envVariablesServerStub }).envVariablesServer = envVariablesServerStub;
});
it('should return true when trust is disabled', async () => {
workspaceTrustPrefStub[WORKSPACE_TRUST_ENABLED] = false;
expect(await service.testCalculateWorkspaceTrust()).to.be.true;
});
describe('empty workspace', () => {
it('should return emptyWindow setting when no workspace is open', async () => {
workspaceServiceStub.workspace = undefined;
workspaceTrustPrefStub[WORKSPACE_TRUST_EMPTY_WINDOW] = true;
expect(await service.testCalculateWorkspaceTrust()).to.be.true;
});
it('should return false when emptyWindow is false and no workspace', async () => {
workspaceServiceStub.workspace = undefined;
workspaceTrustPrefStub[WORKSPACE_TRUST_EMPTY_WINDOW] = false;
expect(await service.testCalculateWorkspaceTrust()).to.be.false;
});
it('should return emptyWindow setting for untitled workspace with no folders', async () => {
workspaceServiceStub.workspace = { resource: new URI('file:///home/user/.theia/workspaces/Untitled-123.theia-workspace') };
workspaceServiceStub.tryGetRoots = () => [];
untitledWorkspaceServiceStub.isUntitledWorkspace = () => true;
workspaceTrustPrefStub[WORKSPACE_TRUST_EMPTY_WINDOW] = true;
expect(await service.testCalculateWorkspaceTrust()).to.be.true;
});
it('should not treat saved workspace with no folders as empty', async () => {
workspaceServiceStub.workspace = { resource: new URI('file:///home/user/my.theia-workspace') };
workspaceServiceStub.tryGetRoots = () => [];
workspaceServiceStub.saved = true;
untitledWorkspaceServiceStub.isUntitledWorkspace = () => false;
workspaceTrustPrefStub[WORKSPACE_TRUST_EMPTY_WINDOW] = true;
// Should return false because saved workspace with 0 folders is not "empty"
// and the workspace file is not trusted
expect(await service.testCalculateWorkspaceTrust()).to.be.false;
});
});
describe('single-root workspace', () => {
it('should return true when folder is in trusted folders', async () => {
workspaceTrustPrefStub[WORKSPACE_TRUST_TRUSTED_FOLDERS] = ['file:///home/user/project'];
workspaceServiceStub.workspace = { resource: new URI('file:///home/user/project') };
workspaceServiceStub.tryGetRoots = () => [
{ resource: new URI('file:///home/user/project') }
];
expect(await service.testCalculateWorkspaceTrust()).to.be.true;
});
it('should return true when parent folder is trusted', async () => {
workspaceTrustPrefStub[WORKSPACE_TRUST_TRUSTED_FOLDERS] = ['file:///home/user'];
workspaceServiceStub.workspace = { resource: new URI('file:///home/user/project') };
workspaceServiceStub.tryGetRoots = () => [
{ resource: new URI('file:///home/user/project') }
];
expect(await service.testCalculateWorkspaceTrust()).to.be.true;
});
it('should return false when folder is not trusted', async () => {
workspaceTrustPrefStub[WORKSPACE_TRUST_TRUSTED_FOLDERS] = ['file:///home/other'];
workspaceServiceStub.workspace = { resource: new URI('file:///home/user/project') };
workspaceServiceStub.tryGetRoots = () => [
{ resource: new URI('file:///home/user/project') }
];
expect(await service.testCalculateWorkspaceTrust()).to.be.false;
});
});
describe('multi-root workspace', () => {
it('should return true when all folders are trusted', async () => {
workspaceTrustPrefStub[WORKSPACE_TRUST_TRUSTED_FOLDERS] = [
'file:///home/user/project1',
'file:///home/user/project2'
];
workspaceServiceStub.workspace = { resource: new URI('file:///home/user/my.theia-workspace') };
workspaceServiceStub.tryGetRoots = () => [
{ resource: new URI('file:///home/user/project1') },
{ resource: new URI('file:///home/user/project2') }
];
expect(await service.testCalculateWorkspaceTrust()).to.be.true;
});
it('should return false when one folder is not trusted', async () => {
workspaceTrustPrefStub[WORKSPACE_TRUST_TRUSTED_FOLDERS] = ['file:///home/user/project1'];
workspaceServiceStub.workspace = { resource: new URI('file:///home/user/my.theia-workspace') };
workspaceServiceStub.tryGetRoots = () => [
{ resource: new URI('file:///home/user/project1') },
{ resource: new URI('file:///home/user/project2') }
];
expect(await service.testCalculateWorkspaceTrust()).to.be.false;
});
it('should return true when parent folder covers all roots', async () => {
workspaceTrustPrefStub[WORKSPACE_TRUST_TRUSTED_FOLDERS] = ['file:///home/user'];
workspaceServiceStub.workspace = { resource: new URI('file:///home/user/my.theia-workspace') };
workspaceServiceStub.tryGetRoots = () => [
{ resource: new URI('file:///home/user/project1') },
{ resource: new URI('file:///home/user/project2') }
];
expect(await service.testCalculateWorkspaceTrust()).to.be.true;
});
});
describe('saved workspace file trust', () => {
it('should require workspace file to be trusted for saved workspaces', async () => {
// Folder is trusted but workspace file location is not
workspaceTrustPrefStub[WORKSPACE_TRUST_TRUSTED_FOLDERS] = ['file:///home/user/project'];
workspaceServiceStub.workspace = { resource: new URI('file:///other/location/my.theia-workspace') };
workspaceServiceStub.saved = true;
workspaceServiceStub.tryGetRoots = () => [
{ resource: new URI('file:///home/user/project') }
];
expect(await service.testCalculateWorkspaceTrust()).to.be.false;
});
it('should return true when both folder and workspace file are trusted', async () => {
workspaceTrustPrefStub[WORKSPACE_TRUST_TRUSTED_FOLDERS] = ['file:///home/user'];
workspaceServiceStub.workspace = { resource: new URI('file:///home/user/my.theia-workspace') };
workspaceServiceStub.saved = true;
workspaceServiceStub.tryGetRoots = () => [
{ resource: new URI('file:///home/user/project') }
];
expect(await service.testCalculateWorkspaceTrust()).to.be.true;
});
it('should not require workspace file trust for unsaved workspaces', async () => {
workspaceTrustPrefStub[WORKSPACE_TRUST_TRUSTED_FOLDERS] = ['file:///home/user/project'];
workspaceServiceStub.workspace = { resource: new URI('file:///tmp/untitled.theia-workspace') };
workspaceServiceStub.saved = false;
workspaceServiceStub.tryGetRoots = () => [
{ resource: new URI('file:///home/user/project') }
];
expect(await service.testCalculateWorkspaceTrust()).to.be.true;
});
});
});
describe('handleWorkspaceChanged', () => {
let resolveWorkspaceTrustStub: sinon.SinonStub;
let getWorkspaceTrustStub: sinon.SinonStub;
let updateRestrictedModeIndicatorStub: sinon.SinonStub;
beforeEach(() => {
resolveWorkspaceTrustStub = sinon.stub(service as unknown as { resolveWorkspaceTrust: () => Promise<void> }, 'resolveWorkspaceTrust').resolves();
getWorkspaceTrustStub = sinon.stub(service, 'getWorkspaceTrust').resolves(true);
updateRestrictedModeIndicatorStub = sinon.stub(
service as unknown as { updateRestrictedModeIndicator: (trust: boolean) => void },
'updateRestrictedModeIndicator'
);
});
it('should reset trust state when workspace changes', async () => {
service.setCurrentTrust(true);
await service.testHandleWorkspaceChanged();
expect(service.getCurrentTrust()).to.be.undefined;
});
it('should re-evaluate trust when workspace changes', async () => {
service.setCurrentTrust(true);
await service.testHandleWorkspaceChanged();
expect(resolveWorkspaceTrustStub.calledOnce).to.be.true;
});
it('should update restricted mode indicator after workspace change if not trusted', async () => {
getWorkspaceTrustStub.resolves(false);
await service.testHandleWorkspaceChanged();
expect(updateRestrictedModeIndicatorStub.calledOnceWith(false)).to.be.true;
});
it('should reset workspaceTrust deferred to unresolved state', async () => {
// First resolve the trust
service.setCurrentTrust(true);
await service.testHandleWorkspaceChanged();
// After workspace change, it should be reset and resolved again via resolveWorkspaceTrust
expect(resolveWorkspaceTrustStub.calledOnce).to.be.true;
});
});
describe('handlePreferenceChange', () => {
let areAllWorkspaceUrisTrustedStub: sinon.SinonStub;
let setWorkspaceTrustStub: sinon.SinonStub;
let isEmptyWorkspaceStub: sinon.SinonStub;
let workspaceTrustPrefStub: { [key: string]: unknown };
beforeEach(() => {
areAllWorkspaceUrisTrustedStub = sinon.stub(service as unknown as { areAllWorkspaceUrisTrusted: () => Promise<boolean> }, 'areAllWorkspaceUrisTrusted');
setWorkspaceTrustStub = sinon.stub(service, 'setWorkspaceTrust').resolves();
isEmptyWorkspaceStub = sinon.stub(service as unknown as { isEmptyWorkspace: () => Promise<boolean> }, 'isEmptyWorkspace');
// Mock workspaceTrustPref - default emptyWindow to false so trusted folders logic runs
workspaceTrustPrefStub = { [WORKSPACE_TRUST_EMPTY_WINDOW]: false };
(service as unknown as { workspaceTrustPref: { [key: string]: unknown } }).workspaceTrustPref = workspaceTrustPrefStub;
// Default to non-empty workspace
isEmptyWorkspaceStub.resolves(false);
});
it('should update trust to true when all workspace URIs become trusted', async () => {
service.setCurrentTrust(false);
areAllWorkspaceUrisTrustedStub.resolves(true);
const change: PreferenceChange = {
preferenceName: WORKSPACE_TRUST_TRUSTED_FOLDERS,
scope: PreferenceScope.User,
domain: [],
affects: () => true
};
await service.testHandlePreferenceChange(change);
expect(setWorkspaceTrustStub.calledOnceWith(true)).to.be.true;
});
it('should update trust to false when not all workspace URIs are trusted', async () => {
service.setCurrentTrust(true);
areAllWorkspaceUrisTrustedStub.resolves(false);
const change: PreferenceChange = {
preferenceName: WORKSPACE_TRUST_TRUSTED_FOLDERS,
scope: PreferenceScope.User,
domain: [],
affects: () => true
};
await service.testHandlePreferenceChange(change);
expect(setWorkspaceTrustStub.calledOnceWith(false)).to.be.true;
});
it('should not update trust when trustedFolders change does not affect trust status', async () => {
service.setCurrentTrust(false);
areAllWorkspaceUrisTrustedStub.resolves(false);
const change: PreferenceChange = {
preferenceName: WORKSPACE_TRUST_TRUSTED_FOLDERS,
scope: PreferenceScope.User,
domain: [],
affects: () => true
};
await service.testHandlePreferenceChange(change);
expect(setWorkspaceTrustStub.called).to.be.false;
});
describe('emptyWindow setting changes', () => {
beforeEach(() => {
// Reset to empty workspace for empty window tests
isEmptyWorkspaceStub.resolves(true);
});
it('should update trust to true when emptyWindow setting changes to true for empty window', async () => {
service.setCurrentTrust(false);
workspaceTrustPrefStub[WORKSPACE_TRUST_EMPTY_WINDOW] = true;
const change: PreferenceChange = {
preferenceName: WORKSPACE_TRUST_EMPTY_WINDOW,
scope: PreferenceScope.User,
domain: [],
affects: () => true
};
await service.testHandlePreferenceChange(change);
expect(setWorkspaceTrustStub.calledOnceWith(true, false)).to.be.true;
});
it('should update trust to false when emptyWindow setting changes to false for empty window', async () => {
service.setCurrentTrust(true);
const change: PreferenceChange = {
preferenceName: WORKSPACE_TRUST_EMPTY_WINDOW,
scope: PreferenceScope.User,
domain: [],
affects: () => true
};
await service.testHandlePreferenceChange(change);
expect(setWorkspaceTrustStub.calledOnceWith(false, false)).to.be.true;
});
it('should not update trust when emptyWindow setting changes but workspace has roots', async () => {
service.setCurrentTrust(false);
isEmptyWorkspaceStub.resolves(false);
const change: PreferenceChange = {
preferenceName: WORKSPACE_TRUST_EMPTY_WINDOW,
scope: PreferenceScope.User,
domain: [],
affects: () => true
};
await service.testHandlePreferenceChange(change);
expect(setWorkspaceTrustStub.called).to.be.false;
});
it('should not update trust when emptyWindow setting changes but trust already matches', async () => {
service.setCurrentTrust(true);
workspaceTrustPrefStub[WORKSPACE_TRUST_EMPTY_WINDOW] = true;
const change: PreferenceChange = {
preferenceName: WORKSPACE_TRUST_EMPTY_WINDOW,
scope: PreferenceScope.User,
domain: [],
affects: () => true
};
await service.testHandlePreferenceChange(change);
expect(setWorkspaceTrustStub.called).to.be.false;
});
});
describe('workspaceTrustEnabled setting changes', () => {
let windowServiceStub: { reload: sinon.SinonStub; setSafeToShutDown: sinon.SinonStub };
let confirmRestartStub: sinon.SinonStub;
beforeEach(() => {
windowServiceStub = { reload: sinon.stub(), setSafeToShutDown: sinon.stub() };
(service as unknown as { windowService: typeof windowServiceStub }).windowService = windowServiceStub;
confirmRestartStub = sinon.stub(
service as unknown as { confirmRestart: () => Promise<boolean> },
'confirmRestart'
);
sinon.stub(
service as unknown as { resolveWorkspaceTrust: () => Promise<void> },
'resolveWorkspaceTrust'
).resolves();
// Stub isWorkspaceTrustResolved to return true (simulates resolved state)
sinon.stub(service, 'isWorkspaceTrustResolved').returns(true);
service.setCurrentTrust(true);
});
it('should reload without setSafeToShutDown when user confirms restart', async () => {
confirmRestartStub.resolves(true);
const change: PreferenceChange = {
preferenceName: WORKSPACE_TRUST_ENABLED,
scope: PreferenceScope.User,
domain: [],
affects: () => true
};
await service.testHandlePreferenceChange(change);
expect(windowServiceStub.reload.calledOnce).to.be.true;
expect(windowServiceStub.setSafeToShutDown.called).to.be.false;
});
it('should not reload when user cancels restart', async () => {
confirmRestartStub.resolves(false);
const change: PreferenceChange = {
preferenceName: WORKSPACE_TRUST_ENABLED,
scope: PreferenceScope.User,
domain: [],
affects: () => true
};
await service.testHandlePreferenceChange(change);
expect(windowServiceStub.reload.called).to.be.false;
expect(windowServiceStub.setSafeToShutDown.called).to.be.false;
});
});
describe('trustedFolders change for empty window with emptyWindow enabled', () => {
beforeEach(() => {
isEmptyWorkspaceStub.resolves(true);
workspaceTrustPrefStub[WORKSPACE_TRUST_EMPTY_WINDOW] = true;
});
it('should not change trust when trustedFolders change for empty window with emptyWindow enabled', async () => {
service.setCurrentTrust(true);
const change: PreferenceChange = {
preferenceName: WORKSPACE_TRUST_TRUSTED_FOLDERS,
scope: PreferenceScope.User,
domain: [],
affects: () => true
};
await service.testHandlePreferenceChange(change);
expect(setWorkspaceTrustStub.called).to.be.false;
});
});
});
describe('setWorkspaceTrust and trust change handling', () => {
let storeWorkspaceTrustStub: sinon.SinonStub;
let addToTrustedFoldersStub: sinon.SinonStub;
let removeFromTrustedFoldersStub: sinon.SinonStub;
let shouldReloadStub: sinon.SinonStub;
let windowServiceStub: { reload: sinon.SinonStub; setSafeToShutDown: sinon.SinonStub };
let contextKeyServiceStub: { setContext: sinon.SinonStub };
let onDidChangeEmitterStub: { fire: sinon.SinonStub };
let confirmRestartStub: sinon.SinonStub;
beforeEach(() => {
storeWorkspaceTrustStub = sinon.stub(
service as unknown as { storeWorkspaceTrust: (trust: boolean) => Promise<void> },
'storeWorkspaceTrust'
).resolves();
addToTrustedFoldersStub = sinon.stub(service, 'addToTrustedFolders').resolves();
removeFromTrustedFoldersStub = sinon.stub(service, 'removeFromTrustedFolders').resolves();
shouldReloadStub = sinon.stub(
service as unknown as { shouldReloadForTrustChange: () => boolean },
'shouldReloadForTrustChange'
);
confirmRestartStub = sinon.stub(
service as unknown as { confirmRestart: () => Promise<boolean> },
'confirmRestart'
).resolves(true);
windowServiceStub = { reload: sinon.stub(), setSafeToShutDown: sinon.stub() };
(service as unknown as { windowService: typeof windowServiceStub }).windowService = windowServiceStub;
contextKeyServiceStub = { setContext: sinon.stub() };
(service as unknown as { contextKeyService: typeof contextKeyServiceStub }).contextKeyService = contextKeyServiceStub;
onDidChangeEmitterStub = { fire: sinon.stub() };
(service as unknown as { onDidChangeWorkspaceTrustEmitter: typeof onDidChangeEmitterStub }).onDidChangeWorkspaceTrustEmitter = onDidChangeEmitterStub;
});
it('should update currentTrust and fire event', async () => {
service.setCurrentTrust(false);
shouldReloadStub.returns(false);
await service.setWorkspaceTrust(true);
expect(service.getCurrentTrust()).to.equal(true);
expect(contextKeyServiceStub.setContext.calledWith('isWorkspaceTrusted', true)).to.be.true;
expect(onDidChangeEmitterStub.fire.calledWith(true)).to.be.true;
});
it('should be a no-op when trust value does not change', async () => {
service.setCurrentTrust(true);
await service.setWorkspaceTrust(true);
expect(contextKeyServiceStub.setContext.called).to.be.false;
expect(onDidChangeEmitterStub.fire.called).to.be.false;
expect(storeWorkspaceTrustStub.called).to.be.false;
});
it('should confirm restart before storing or firing events when reload is required', async () => {
const callOrder: string[] = [];
confirmRestartStub.callsFake(async () => {
callOrder.push('confirm');
return true;
});
storeWorkspaceTrustStub.callsFake(() => {
callOrder.push('store');
return Promise.resolve();
});
onDidChangeEmitterStub.fire.callsFake(() => {
callOrder.push('fire');
});
shouldReloadStub.returns(true);
service.setCurrentTrust(false);
await service.setWorkspaceTrust(true);
expect(callOrder[0]).to.equal('confirm');
expect(callOrder).to.include('store');
expect(callOrder).to.include('fire');
});
it('should call windowService.reload() when shouldReloadForTrustChange returns true', async () => {
shouldReloadStub.returns(true);
service.setCurrentTrust(false);
await service.setWorkspaceTrust(true);
expect(windowServiceStub.reload.calledOnce).to.be.true;
});
it('should NOT call windowService.reload() when shouldReloadForTrustChange returns false', async () => {
shouldReloadStub.returns(false);
service.setCurrentTrust(false);
await service.setWorkspaceTrust(true);
expect(windowServiceStub.reload.called).to.be.false;
});
it('should NOT call setSafeToShutDown (unsaved-changes protection preserved)', async () => {
shouldReloadStub.returns(true);
service.setCurrentTrust(false);
await service.setWorkspaceTrust(true);
expect(windowServiceStub.setSafeToShutDown.called).to.be.false;
});
it('should NOT call windowService.reload() when user cancels confirm dialog', async () => {
shouldReloadStub.returns(true);
confirmRestartStub.resolves(false);
service.setCurrentTrust(false);
await service.setWorkspaceTrust(true);
expect(windowServiceStub.reload.called).to.be.false;
});
it('should leave trust state unchanged and not fire events when user cancels the restart dialog', async () => {
shouldReloadStub.returns(true);
confirmRestartStub.resolves(false);
service.setCurrentTrust(false);
await service.setWorkspaceTrust(true);
expect(service.getCurrentTrust()).to.equal(false);
expect(contextKeyServiceStub.setContext.called).to.be.false;
expect(onDidChangeEmitterStub.fire.called).to.be.false;
expect(storeWorkspaceTrustStub.called).to.be.false;
expect(addToTrustedFoldersStub.called).to.be.false;
expect(removeFromTrustedFoldersStub.called).to.be.false;
});
it('should call addToTrustedFolders when setting trusted=true', async () => {
shouldReloadStub.returns(false);
service.setCurrentTrust(false);
await service.setWorkspaceTrust(true);
expect(addToTrustedFoldersStub.calledOnce).to.be.true;
expect(removeFromTrustedFoldersStub.called).to.be.false;
});
it('should call removeFromTrustedFolders when setting trusted=false', async () => {
shouldReloadStub.returns(false);
service.setCurrentTrust(true);
await service.setWorkspaceTrust(false);
expect(removeFromTrustedFoldersStub.calledOnce).to.be.true;
expect(addToTrustedFoldersStub.called).to.be.false;
});
it('should NOT reload when reload=false even if shouldReloadForTrustChange returns true', async () => {
shouldReloadStub.returns(true);
service.setCurrentTrust(false);
await service.setWorkspaceTrust(true, false);
expect(windowServiceStub.reload.called).to.be.false;
});
it('should still update state and fire event when reload=false', async () => {
service.setCurrentTrust(false);
shouldReloadStub.returns(true);
await service.setWorkspaceTrust(true, false);
expect(service.getCurrentTrust()).to.equal(true);
expect(contextKeyServiceStub.setContext.calledWith('isWorkspaceTrusted', true)).to.be.true;
expect(onDidChangeEmitterStub.fire.calledWith(true)).to.be.true;
});
});
describe('shouldReloadForTrustChange', () => {
let freshService: TestableWorkspaceTrustService;
beforeEach(() => {
freshService = new TestableWorkspaceTrustService();
});
it('should return false when no restriction contributions are registered', () => {
(freshService as unknown as { restrictionContributions: { getContributions: () => unknown[] } })
.restrictionContributions = { getContributions: () => [] };
expect(freshService.testShouldReloadForTrustChange(true)).to.be.false;
});
it('should return false when contribution does not implement requiresReloadOnTrustChange', () => {
(freshService as unknown as { restrictionContributions: { getContributions: () => unknown[] } })
.restrictionContributions = { getContributions: () => [{ getRestrictions: () => [] }] };
expect(freshService.testShouldReloadForTrustChange(true)).to.be.false;
});
it('should return true when a contribution requires reload for the given trust value', () => {
(freshService as unknown as { restrictionContributions: { getContributions: () => unknown[] } })
.restrictionContributions = {
getContributions: () => [{
getRestrictions: () => [],
requiresReloadOnTrustChange: (_newTrust: boolean) => true
}]
};
expect(freshService.testShouldReloadForTrustChange(true)).to.be.true;
});
it('should return false when contribution returns false for requiresReloadOnTrustChange', () => {
(freshService as unknown as { restrictionContributions: { getContributions: () => unknown[] } })
.restrictionContributions = {
getContributions: () => [{
getRestrictions: () => [],
requiresReloadOnTrustChange: (_newTrust: boolean) => false
}]
};
expect(freshService.testShouldReloadForTrustChange(true)).to.be.false;
});
it('should pass newTrust value to requiresReloadOnTrustChange', () => {
const calls: boolean[] = [];
(freshService as unknown as { restrictionContributions: { getContributions: () => unknown[] } })
.restrictionContributions = {
getContributions: () => [{
getRestrictions: () => [],
requiresReloadOnTrustChange: (newTrust: boolean) => { calls.push(newTrust); return false; }
}]
};
freshService.testShouldReloadForTrustChange(false);
expect(calls).to.deep.equal([false]);
freshService.testShouldReloadForTrustChange(true);
expect(calls).to.deep.equal([false, true]);
});
});
});