@theia/core
Version:
Theia is a cloud & desktop IDE framework implemented in TypeScript.
495 lines • 24.4 kB
JavaScript
"use strict";
// *****************************************************************************
// Copyright (C) 2018 Ericsson and others.
//
// 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 WITH Classpath-exception-2.0
// *****************************************************************************
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable @typescript-eslint/no-explicit-any */
const jsdom_1 = require("../test/jsdom");
let disableJSDOM = (0, jsdom_1.enableJSDOM)();
const assert = require("assert");
const inversify_1 = require("inversify");
const frontend_application_bindings_1 = require("../frontend-application-bindings");
const test_1 = require("./test");
const preference_service_1 = require("./preference-service");
const preference_contribution_1 = require("./preference-contribution");
const preference_scope_1 = require("./preference-scope");
const preference_provider_1 = require("./preference-provider");
const frontend_application_config_provider_1 = require("../frontend-application-config-provider");
const preference_proxy_1 = require("./preference-proxy");
disableJSDOM();
process.on('unhandledRejection', (reason, promise) => {
console.error(reason);
throw reason;
});
const { expect } = require('chai');
let testContainer;
function createTestContainer() {
const result = new inversify_1.Container();
(0, frontend_application_bindings_1.bindPreferenceService)(result.bind.bind(result));
(0, test_1.bindMockPreferenceProviders)(result.bind.bind(result), result.unbind.bind(result));
return result;
}
describe('Preference Service', () => {
let prefService;
let prefSchema;
before(() => {
disableJSDOM = (0, jsdom_1.enableJSDOM)();
frontend_application_config_provider_1.FrontendApplicationConfigProvider.set({});
});
after(() => {
disableJSDOM();
});
beforeEach(async () => {
testContainer = createTestContainer();
prefSchema = testContainer.get(preference_contribution_1.PreferenceSchemaProvider);
prefService = testContainer.get(preference_service_1.PreferenceService);
getProvider(preference_scope_1.PreferenceScope.User).markReady();
getProvider(preference_scope_1.PreferenceScope.Workspace).markReady();
getProvider(preference_scope_1.PreferenceScope.Folder).markReady();
console.log('before ready');
try {
await prefService.ready;
}
catch (e) {
console.error(e);
}
console.log('done');
});
afterEach(() => {
});
function getProvider(scope) {
return testContainer.getNamed(preference_provider_1.PreferenceProvider, scope);
}
it('should return the preference from the more specific scope (user > workspace)', () => {
prefSchema.setSchema({
properties: {
'test.number': {
type: 'number',
scope: 'resource'
}
}
});
const userProvider = getProvider(preference_scope_1.PreferenceScope.User);
const workspaceProvider = getProvider(preference_scope_1.PreferenceScope.Workspace);
const folderProvider = getProvider(preference_scope_1.PreferenceScope.Folder);
userProvider.setPreference('test.number', 1);
expect(prefService.get('test.number')).equals(1);
workspaceProvider.setPreference('test.number', 0);
expect(prefService.get('test.number')).equals(0);
folderProvider.setPreference('test.number', 2);
expect(prefService.get('test.number')).equals(2);
// remove property on lower scope
folderProvider.setPreference('test.number', undefined);
expect(prefService.get('test.number')).equals(0);
});
it('should throw a TypeError if the preference (reference object) is modified', () => {
prefSchema.setSchema({
properties: {
'test.immutable': {
type: 'array',
items: {
type: 'string'
},
scope: 'resource'
}
}
});
const userProvider = getProvider(preference_scope_1.PreferenceScope.User);
userProvider.setPreference('test.immutable', [
'test', 'test', 'test'
]);
const immutablePref = prefService.get('test.immutable');
expect(immutablePref).to.not.be.undefined;
if (immutablePref !== undefined) {
expect(() => immutablePref.push('fails')).to.throw(TypeError);
}
});
it('should still report the more specific preference even though the less specific one changed', () => {
prefSchema.setSchema({
properties: {
'test.number': {
type: 'number',
scope: 'resource'
}
}
});
const userProvider = getProvider(preference_scope_1.PreferenceScope.User);
const workspaceProvider = getProvider(preference_scope_1.PreferenceScope.Workspace);
userProvider.setPreference('test.number', 1);
workspaceProvider.setPreference('test.number', 0);
expect(prefService.get('test.number')).equals(0);
userProvider.setPreference('test.number', 4);
expect(prefService.get('test.number')).equals(0);
});
it('should not fire events if preference schema is unset in the same tick ', async () => {
const events = [];
prefService.onPreferenceChanged(event => events.push(event));
prefSchema.registerOverrideIdentifier('go');
const toUnset = prefSchema.setSchema({
properties: {
'editor.insertSpaces': {
type: 'boolean',
default: true,
overridable: true
},
'[go]': {
type: 'object',
default: {
'editor.insertSpaces': false
}
}
}
});
assert.deepStrictEqual([], events.map(e => ({
preferenceName: e.preferenceName,
newValue: e.newValue,
oldValue: e.oldValue
})), 'events after set in the same tick');
assert.strictEqual(prefService.get('editor.insertSpaces'), true, 'get before');
assert.strictEqual(prefService.get('[go].editor.insertSpaces'), false, 'get before overridden');
toUnset.dispose();
assert.deepStrictEqual([], events.map(e => ({
preferenceName: e.preferenceName,
newValue: e.newValue,
oldValue: e.oldValue
})), 'events after unset in the same tick');
assert.strictEqual(prefService.get('editor.insertSpaces'), undefined, 'get after');
assert.strictEqual(prefService.get('[go].editor.insertSpaces'), undefined, 'get after overridden');
assert.deepStrictEqual([], events.map(e => ({
preferenceName: e.preferenceName,
newValue: e.newValue,
oldValue: e.oldValue
})), 'events in next tick');
});
it('should fire events if preference schema is unset in another tick', async () => {
prefSchema.registerOverrideIdentifier('go');
let pending = new Promise(resolve => prefService.onPreferencesChanged(resolve));
const toUnset = prefSchema.setSchema({
properties: {
'editor.insertSpaces': {
type: 'boolean',
default: true,
overridable: true
},
'[go]': {
type: 'object',
default: {
'editor.insertSpaces': false
}
}
}
});
let changes = await pending;
assert.deepStrictEqual([{
preferenceName: 'editor.insertSpaces',
newValue: true,
oldValue: undefined
}, {
preferenceName: '[go].editor.insertSpaces',
newValue: false,
oldValue: undefined
}], Object.keys(changes).map(key => {
const { preferenceName, newValue, oldValue } = changes[key];
return { preferenceName, newValue, oldValue };
}), 'events before');
assert.strictEqual(prefService.get('editor.insertSpaces'), true, 'get before');
assert.strictEqual(prefService.get('[go].editor.insertSpaces'), false, 'get before overridden');
pending = new Promise(resolve => prefService.onPreferencesChanged(resolve));
toUnset.dispose();
changes = await pending;
assert.deepStrictEqual([{
preferenceName: 'editor.insertSpaces',
newValue: undefined,
oldValue: true
}, {
preferenceName: '[go].editor.insertSpaces',
newValue: undefined,
oldValue: false
}], Object.keys(changes).map(key => {
const { preferenceName, newValue, oldValue } = changes[key];
return { preferenceName, newValue, oldValue };
}), 'events after');
assert.strictEqual(prefService.get('editor.insertSpaces'), undefined, 'get after');
assert.strictEqual(prefService.get('[go].editor.insertSpaces'), undefined, 'get after overridden');
});
function prepareServices(options) {
prefSchema.setSchema(options && options.schema || {
properties: {
'editor.tabSize': {
type: 'number',
description: '',
overridable: true,
default: 4
}
}
});
return { preferences: prefService, schema: prefSchema };
}
describe('PreferenceService.updateValues()', () => {
const TAB_SIZE = 'editor.tabSize';
const DUMMY_URI = 'dummy_uri';
async function generateAndCheckValues(preferences, globalValue, workspaceValue, workspaceFolderValue) {
var _a, _b;
await preferences.set(TAB_SIZE, globalValue, preference_scope_1.PreferenceScope.User);
await preferences.set(TAB_SIZE, workspaceValue, preference_scope_1.PreferenceScope.Workspace);
await preferences.set(TAB_SIZE, workspaceFolderValue, preference_scope_1.PreferenceScope.Folder, DUMMY_URI);
const expectedValue = (_b = (_a = workspaceFolderValue !== null && workspaceFolderValue !== void 0 ? workspaceFolderValue : workspaceValue) !== null && _a !== void 0 ? _a : globalValue) !== null && _b !== void 0 ? _b : 4;
checkValues(preferences, globalValue, workspaceValue, workspaceFolderValue, expectedValue);
}
function checkValues(preferences, globalValue, workspaceValue, workspaceFolderValue, value = 4) {
const expected = {
preferenceName: 'editor.tabSize',
defaultValue: 4,
globalValue,
workspaceValue,
workspaceFolderValue,
value,
};
const inspection = preferences.inspect(TAB_SIZE, DUMMY_URI);
assert.deepStrictEqual(inspection, expected);
}
it('should modify the narrowest scope.', async () => {
const { preferences } = prepareServices();
await generateAndCheckValues(preferences, 1, 2, 3);
await preferences.updateValue(TAB_SIZE, 8, DUMMY_URI);
checkValues(preferences, 1, 2, 8, 8);
await generateAndCheckValues(preferences, 1, 2, undefined);
await preferences.updateValue(TAB_SIZE, 8, DUMMY_URI);
checkValues(preferences, 1, 8, undefined, 8);
await generateAndCheckValues(preferences, 1, undefined, undefined);
await preferences.updateValue(TAB_SIZE, 8, DUMMY_URI);
checkValues(preferences, 8, undefined, undefined, 8);
});
it('defaults to user scope.', async () => {
const { preferences } = prepareServices();
checkValues(preferences, undefined, undefined, undefined);
await preferences.updateValue(TAB_SIZE, 8, DUMMY_URI);
checkValues(preferences, 8, undefined, undefined, 8);
});
it('clears all settings when input is undefined.', async () => {
const { preferences } = prepareServices();
await generateAndCheckValues(preferences, 1, 2, 3);
await preferences.updateValue(TAB_SIZE, undefined, DUMMY_URI);
checkValues(preferences, undefined, undefined, undefined);
});
it('deletes user setting if user is only defined scope and target is default value', async () => {
const { preferences } = prepareServices();
await generateAndCheckValues(preferences, 8, undefined, undefined);
await preferences.updateValue(TAB_SIZE, 4, DUMMY_URI);
checkValues(preferences, undefined, undefined, undefined);
});
it('does not delete setting in lower scopes, even if target is default', async () => {
const { preferences } = prepareServices();
await generateAndCheckValues(preferences, undefined, 2, undefined);
await preferences.updateValue(TAB_SIZE, 4, DUMMY_URI);
checkValues(preferences, undefined, 4, undefined);
});
});
describe('overridden preferences', () => {
it('get #0', () => {
const { preferences, schema } = prepareServices();
preferences.set('[json].editor.tabSize', 2, preference_scope_1.PreferenceScope.User);
expect(preferences.get('editor.tabSize')).to.equal(4);
expect(preferences.get('[json].editor.tabSize')).to.equal(undefined);
schema.registerOverrideIdentifier('json');
expect(preferences.get('editor.tabSize')).to.equal(4);
expect(preferences.get('[json].editor.tabSize')).to.equal(2);
});
it('get #1', () => {
const { preferences, schema } = prepareServices();
schema.registerOverrideIdentifier('json');
expect(preferences.get('editor.tabSize')).to.equal(4);
expect(preferences.get('[json].editor.tabSize')).to.equal(4);
preferences.set('[json].editor.tabSize', 2, preference_scope_1.PreferenceScope.User);
expect(preferences.get('editor.tabSize')).to.equal(4);
expect(preferences.get('[json].editor.tabSize')).to.equal(2);
});
it('get #2', () => {
const { preferences, schema } = prepareServices();
schema.registerOverrideIdentifier('json');
expect(preferences.get('editor.tabSize')).to.equal(4);
expect(preferences.get('[json].editor.tabSize')).to.equal(4);
preferences.set('editor.tabSize', 2, preference_scope_1.PreferenceScope.User);
expect(preferences.get('editor.tabSize')).to.equal(2);
expect(preferences.get('[json].editor.tabSize')).to.equal(2);
});
it('has', () => {
const { preferences, schema } = prepareServices();
expect(preferences.has('editor.tabSize')).to.be.true;
expect(preferences.has('[json].editor.tabSize')).to.be.false;
schema.registerOverrideIdentifier('json');
expect(preferences.has('editor.tabSize')).to.be.true;
expect(preferences.has('[json].editor.tabSize')).to.be.true;
});
it('inspect #0', () => {
const { preferences, schema } = prepareServices();
const expected = {
preferenceName: 'editor.tabSize',
defaultValue: 4,
globalValue: undefined,
workspaceValue: undefined,
workspaceFolderValue: undefined,
value: 4,
};
assert.deepStrictEqual(expected, preferences.inspect('editor.tabSize'));
assert.ok(!preferences.has('[json].editor.tabSize'));
schema.registerOverrideIdentifier('json');
assert.deepStrictEqual(expected, preferences.inspect('editor.tabSize'));
assert.deepStrictEqual(Object.assign(Object.assign({}, expected), { preferenceName: '[json].editor.tabSize' }), preferences.inspect('[json].editor.tabSize'));
});
it('inspect #1', () => {
const { preferences, schema } = prepareServices();
const expected = {
preferenceName: 'editor.tabSize',
defaultValue: 4,
globalValue: 2,
workspaceValue: undefined,
workspaceFolderValue: undefined,
value: 2
};
preferences.set('editor.tabSize', 2, preference_scope_1.PreferenceScope.User);
assert.deepStrictEqual(expected, preferences.inspect('editor.tabSize'));
assert.ok(!preferences.has('[json].editor.tabSize'));
schema.registerOverrideIdentifier('json');
assert.deepStrictEqual(expected, preferences.inspect('editor.tabSize'));
assert.deepStrictEqual(Object.assign(Object.assign({}, expected), { preferenceName: '[json].editor.tabSize' }), preferences.inspect('[json].editor.tabSize'));
});
it('inspect #2', () => {
const { preferences, schema } = prepareServices();
const expected = {
preferenceName: 'editor.tabSize',
defaultValue: 4,
globalValue: undefined,
workspaceValue: undefined,
workspaceFolderValue: undefined,
value: 4
};
assert.deepStrictEqual(expected, preferences.inspect('editor.tabSize'));
assert.ok(!preferences.has('[json].editor.tabSize'));
schema.registerOverrideIdentifier('json');
preferences.set('[json].editor.tabSize', 2, preference_scope_1.PreferenceScope.User);
assert.deepStrictEqual(expected, preferences.inspect('editor.tabSize'));
assert.deepStrictEqual(Object.assign(Object.assign({}, expected), { preferenceName: '[json].editor.tabSize', globalValue: 2, value: 2 }), preferences.inspect('[json].editor.tabSize'));
});
it('onPreferenceChanged #0', async () => {
const { preferences, schema } = prepareServices();
const events = [];
preferences.onPreferenceChanged(event => events.push(event));
schema.registerOverrideIdentifier('json');
preferences.set('[json].editor.tabSize', 2, preference_scope_1.PreferenceScope.User);
await preferences.set('editor.tabSize', 3, preference_scope_1.PreferenceScope.User);
assert.deepStrictEqual([{
preferenceName: '[json].editor.tabSize',
newValue: 2
}, {
preferenceName: 'editor.tabSize',
newValue: 3
}], events.map(e => ({
preferenceName: e.preferenceName,
newValue: e.newValue
})));
});
it('onPreferenceChanged #1', async () => {
const { preferences, schema } = prepareServices();
const events = [];
preferences.onPreferenceChanged(event => events.push(event));
schema.registerOverrideIdentifier('json');
await preferences.set('editor.tabSize', 2, preference_scope_1.PreferenceScope.User);
assert.deepStrictEqual([{
preferenceName: 'editor.tabSize',
newValue: 2
}, {
preferenceName: '[json].editor.tabSize',
newValue: 2
}], events.map(e => ({
preferenceName: e.preferenceName,
newValue: e.newValue
})));
});
it('onPreferenceChanged #2', async function () {
const { preferences, schema } = prepareServices();
schema.registerOverrideIdentifier('json');
schema.registerOverrideIdentifier('javascript');
preferences.set('[json].editor.tabSize', 2, preference_scope_1.PreferenceScope.User);
await preferences.set('editor.tabSize', 3, preference_scope_1.PreferenceScope.User);
const events = [];
const proxy = (0, preference_proxy_1.createPreferenceProxy)(preferences, schema.getCombinedSchema(), { overrideIdentifier: 'json' });
proxy.onPreferenceChanged(event => events.push(event));
await preferences.set('[javascript].editor.tabSize', 4, preference_scope_1.PreferenceScope.User);
assert.deepStrictEqual([], events.map(e => ({
preferenceName: e.preferenceName,
newValue: e.newValue
})), 'changes not relevant to json override should be ignored');
});
it('onPreferenceChanged #3', async () => {
const { preferences, schema } = prepareServices();
schema.registerOverrideIdentifier('json');
preferences.set('[json].editor.tabSize', 2, preference_scope_1.PreferenceScope.User);
await preferences.set('editor.tabSize', 3, preference_scope_1.PreferenceScope.User);
const events = [];
preferences.onPreferenceChanged(event => events.push(event));
await preferences.set('[json].editor.tabSize', undefined, preference_scope_1.PreferenceScope.User);
assert.deepStrictEqual([{
preferenceName: '[json].editor.tabSize',
newValue: 3
}], events.map(e => ({
preferenceName: e.preferenceName,
newValue: e.newValue
})));
});
it('defaultOverrides [go].editor.formatOnSave', () => {
const { preferences, schema } = prepareServices({
schema: {
properties: {
'editor.insertSpaces': {
type: 'boolean',
default: true,
overridable: true
},
'editor.formatOnSave': {
type: 'boolean',
default: false,
overridable: true
}
}
}
});
assert.strictEqual(true, preferences.get('editor.insertSpaces'));
assert.strictEqual(undefined, preferences.get('[go].editor.insertSpaces'));
assert.strictEqual(false, preferences.get('editor.formatOnSave'));
assert.strictEqual(undefined, preferences.get('[go].editor.formatOnSave'));
schema.registerOverrideIdentifier('go');
schema.setSchema({
id: 'defaultOverrides',
title: 'Default Configuration Overrides',
properties: {
'[go]': {
type: 'object',
default: {
'editor.insertSpaces': false,
'editor.formatOnSave': true
},
description: 'Configure editor settings to be overridden for go language.'
}
}
});
assert.strictEqual(true, preferences.get('editor.insertSpaces'));
assert.strictEqual(false, preferences.get('[go].editor.insertSpaces'));
assert.strictEqual(false, preferences.get('editor.formatOnSave'));
assert.strictEqual(true, preferences.get('[go].editor.formatOnSave'));
});
});
});
//# sourceMappingURL=preference-service.spec.js.map