configurationEditingService.test.ts 15.7 KB
Newer Older
1 2 3 4 5 6 7
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

S
Sandeep Somavarapu 已提交
8
import * as sinon from 'sinon';
9 10 11 12 13
import assert = require('assert');
import os = require('os');
import path = require('path');
import fs = require('fs');
import * as json from 'vs/base/common/json';
S
Sandeep Somavarapu 已提交
14
import URI from 'vs/base/common/uri';
J
Johannes Rieken 已提交
15
import { TPromise } from 'vs/base/common/winjs.base';
16
import { Registry } from 'vs/platform/registry/common/platform';
S
Sandeep Somavarapu 已提交
17
import { ParsedArgs, IEnvironmentService } from 'vs/platform/environment/common/environment';
J
Joao Moreno 已提交
18
import { parseArgs } from 'vs/platform/environment/node/argv';
19
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
J
Johannes Rieken 已提交
20
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
21
import extfs = require('vs/base/node/extfs');
T
t-amqi 已提交
22
import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService } from 'vs/workbench/test/workbenchTestServices';
23
import uuid = require('vs/base/common/uuid');
J
Johannes Rieken 已提交
24
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
25
import { WorkspaceService, EmptyWorkspaceServiceImpl, WorkspaceServiceImpl } from 'vs/workbench/services/configuration/node/configuration';
J
Johannes Rieken 已提交
26
import { FileService } from 'vs/workbench/services/files/node/fileService';
27
import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService';
28
import { ConfigurationTarget, ConfigurationEditingError, ConfigurationEditingErrorCode } from 'vs/workbench/services/configuration/common/configurationEditing';
J
Johannes Rieken 已提交
29
import { IFileService } from 'vs/platform/files/common/files';
30
import { WORKSPACE_STANDALONE_CONFIGURATIONS } from 'vs/workbench/services/configuration/common/configuration';
J
Johannes Rieken 已提交
31
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
S
Sandeep Somavarapu 已提交
32
import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
J
Johannes Rieken 已提交
33 34
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
S
Sandeep Somavarapu 已提交
35
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
36
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
B
Benjamin Pasero 已提交
37
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
S
Sandeep Somavarapu 已提交
38 39
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
40
import { ITextModelService } from 'vs/editor/common/services/resolverService';
S
Sandeep Somavarapu 已提交
41 42 43 44 45
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
S
Sandeep Somavarapu 已提交
46
import { IChoiceService, IMessageService } from 'vs/platform/message/common/message';
B
Benjamin Pasero 已提交
47
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
48
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
49 50 51 52 53 54 55 56 57 58

class SettingsTestEnvironmentService extends EnvironmentService {

	constructor(args: ParsedArgs, _execPath: string, private customAppSettingsHome) {
		super(args, _execPath);
	}

	get appSettingsPath(): string { return this.customAppSettingsHome; }
}

S
Sandeep Somavarapu 已提交
59 60
suite('ConfigurationEditingService', () => {

S
Sandeep Somavarapu 已提交
61
	let instantiationService: TestInstantiationService;
S
Sandeep Somavarapu 已提交
62 63 64 65 66
	let testObject: ConfigurationEditingService;
	let parentDir;
	let workspaceDir;
	let globalSettingsFile;
	let workspaceSettingsDir;
S
Sandeep Somavarapu 已提交
67
	let choiceService;
S
Sandeep Somavarapu 已提交
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

	suiteSetup(() => {
		const configurationRegistry = <IConfigurationRegistry>Registry.as(ConfigurationExtensions.Configuration);
		configurationRegistry.registerConfiguration({
			'id': '_test',
			'type': 'object',
			'properties': {
				'configurationEditing.service.testSetting': {
					'type': 'string',
					'default': 'isSet'
				},
				'configurationEditing.service.testSettingTwo': {
					'type': 'string',
					'default': 'isSet'
				},
				'configurationEditing.service.testSettingThree': {
					'type': 'string',
					'default': 'isSet'
				}
			}
		});
	});
90

S
Sandeep Somavarapu 已提交
91 92 93 94
	setup(() => {
		return setUpWorkspace()
			.then(() => setUpServices());
	});
95

S
Sandeep Somavarapu 已提交
96 97 98 99 100 101 102 103 104 105 106 107 108 109
	function setUpWorkspace(): TPromise<void> {
		return new TPromise<void>((c, e) => {
			const id = uuid.generateUuid();
			parentDir = path.join(os.tmpdir(), 'vsctests', id);
			workspaceDir = path.join(parentDir, 'workspaceconfig', id);
			globalSettingsFile = path.join(workspaceDir, 'config.json');
			workspaceSettingsDir = path.join(workspaceDir, '.vscode');
			extfs.mkdirp(workspaceSettingsDir, 493, (error) => {
				if (error) {
					e(error);
				} else {
					c(null);
				}
			});
110 111 112
		});
	}

S
Sandeep Somavarapu 已提交
113
	function setUpServices(noWorkspace: boolean = false): TPromise<void> {
114 115 116
		// Clear services if they are already created
		clearServices();

S
Sandeep Somavarapu 已提交
117
		instantiationService = new TestInstantiationService();
118 119
		const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile);
		instantiationService.stub(IEnvironmentService, environmentService);
120
		const workspacesService = instantiationService.stub(IWorkspacesService, {});
S
Sandeep Somavarapu 已提交
121
		const workspaceService = noWorkspace ? new EmptyWorkspaceServiceImpl(environmentService) : new WorkspaceServiceImpl(null, URI.file(workspaceDir), environmentService, workspacesService);
122 123
		instantiationService.stub(IWorkspaceContextService, workspaceService);
		instantiationService.stub(IConfigurationService, workspaceService);
S
Sandeep Somavarapu 已提交
124 125 126 127 128
		instantiationService.stub(ILifecycleService, new TestLifecycleService());
		instantiationService.stub(IEditorGroupService, new TestEditorGroupService());
		instantiationService.stub(ITelemetryService, NullTelemetryService);
		instantiationService.stub(IModeService, ModeServiceImpl);
		instantiationService.stub(IModelService, instantiationService.createInstance(ModelServiceImpl));
129
		instantiationService.stub(IFileService, new FileService(workspaceService, new TestConfigurationService(), { disableWatcher: true }));
S
Sandeep Somavarapu 已提交
130 131
		instantiationService.stub(IUntitledEditorService, instantiationService.createInstance(UntitledEditorService));
		instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService));
132
		instantiationService.stub(ITextModelService, <ITextModelService>instantiationService.createInstance(TextModelResolverService));
S
Sandeep Somavarapu 已提交
133
		instantiationService.stub(IBackupFileService, new TestBackupFileService());
S
Sandeep Somavarapu 已提交
134
		choiceService = instantiationService.stub(IChoiceService, {
S
Sandeep Somavarapu 已提交
135 136 137 138 139 140 141
			choose: (severity, message, options, cancelId): TPromise<number> => {
				return TPromise.as(cancelId);
			}
		});
		instantiationService.stub(IMessageService, {
			show: (severity, message, options, cancelId): void => { }
		});
S
Sandeep Somavarapu 已提交
142 143

		testObject = instantiationService.createInstance(ConfigurationEditingService);
144
		return workspaceService.initialize();
145 146
	}

S
Sandeep Somavarapu 已提交
147
	teardown(() => {
148
		clearServices();
S
Sandeep Somavarapu 已提交
149
		return clearWorkspace();
150 151
	});

152 153
	function clearServices(): void {
		if (instantiationService) {
154
			const configuraitonService = <WorkspaceService>instantiationService.get(IConfigurationService);
155 156 157 158 159 160 161
			if (configuraitonService) {
				configuraitonService.dispose();
			}
			instantiationService = null;
		}
	}

S
Sandeep Somavarapu 已提交
162 163 164
	function clearWorkspace(): TPromise<void> {
		return new TPromise<void>((c, e) => {
			if (parentDir) {
165
				extfs.del(parentDir, os.tmpdir(), () => c(null), () => c(null));
S
Sandeep Somavarapu 已提交
166 167
			} else {
				c(null);
168
			}
169
		}).then(() => parentDir = null);
S
Sandeep Somavarapu 已提交
170
	}
171

S
Sandeep Somavarapu 已提交
172 173 174
	test('errors cases - invalid key', () => {
		return testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'unknown.key', value: 'value' })
			.then(() => assert.fail('Should fail with ERROR_UNKNOWN_KEY'),
175
			(error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_UNKNOWN_KEY));
176 177
	});

S
Sandeep Somavarapu 已提交
178 179 180
	test('errors cases - invalid target', () => {
		return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'tasks.something', value: 'value' })
			.then(() => assert.fail('Should fail with ERROR_INVALID_TARGET'),
181
			(error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_INVALID_TARGET));
182 183
	});

S
Sandeep Somavarapu 已提交
184 185 186 187
	test('errors cases - no workspace', () => {
		return setUpServices(true)
			.then(() => testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'configurationEditing.service.testSetting', value: 'value' }))
			.then(() => assert.fail('Should fail with ERROR_NO_WORKSPACE_OPENED'),
188
			(error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_NO_WORKSPACE_OPENED));
189 190
	});

S
Sandeep Somavarapu 已提交
191 192 193 194
	test('errors cases - invalid configuration', () => {
		fs.writeFileSync(globalSettingsFile, ',,,,,,,,,,,,,,');
		return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' })
			.then(() => assert.fail('Should fail with ERROR_INVALID_CONFIGURATION'),
195
			(error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_INVALID_CONFIGURATION));
196 197
	});

S
Sandeep Somavarapu 已提交
198 199 200 201
	test('errors cases - dirty', () => {
		instantiationService.stub(ITextFileService, 'isDirty', true);
		return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' })
			.then(() => assert.fail('Should fail with ERROR_CONFIGURATION_FILE_DIRTY error.'),
202
			(error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY));
203 204
	});

S
Sandeep Somavarapu 已提交
205 206 207 208 209 210 211 212 213 214 215 216
	test('dirty error is not thrown if not asked to save', () => {
		instantiationService.stub(ITextFileService, 'isDirty', true);
		return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }, { donotSave: true })
			.then(() => null, error => assert.fail('Should not fail.'));
	});

	test('do not notify error', () => {
		instantiationService.stub(ITextFileService, 'isDirty', true);
		const target = sinon.stub();
		instantiationService.stubPromise(IChoiceService, 'choose', target);
		return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }, { donotNotifyError: true })
			.then(() => assert.fail('Should fail with ERROR_CONFIGURATION_FILE_DIRTY error.'),
217
			(error: ConfigurationEditingError) => {
S
Sandeep Somavarapu 已提交
218 219 220 221 222
				assert.equal(false, target.calledOnce);
				assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY);
			});
	});

S
Sandeep Somavarapu 已提交
223 224 225 226 227 228 229 230
	test('write one setting - empty file', () => {
		return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' })
			.then(() => {
				const contents = fs.readFileSync(globalSettingsFile).toString('utf8');
				const parsed = json.parse(contents);
				assert.equal(parsed['configurationEditing.service.testSetting'], 'value');
				assert.equal(instantiationService.get(IConfigurationService).lookup('configurationEditing.service.testSetting').value, 'value');
			});
231 232
	});

S
Sandeep Somavarapu 已提交
233 234 235 236 237 238 239 240 241 242 243 244 245
	test('write one setting - existing file', () => {
		fs.writeFileSync(globalSettingsFile, '{ "my.super.setting": "my.super.value" }');
		return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' })
			.then(() => {
				const contents = fs.readFileSync(globalSettingsFile).toString('utf8');
				const parsed = json.parse(contents);
				assert.equal(parsed['configurationEditing.service.testSetting'], 'value');
				assert.equal(parsed['my.super.setting'], 'my.super.value');

				const configurationService = instantiationService.get(IConfigurationService);
				assert.equal(configurationService.lookup('configurationEditing.service.testSetting').value, 'value');
				assert.equal(configurationService.lookup('my.super.setting').value, 'my.super.value');
			});
246
	});
247

S
Sandeep Somavarapu 已提交
248 249 250 251 252 253 254 255 256 257
	test('write workspace standalone setting - empty file', () => {
		return testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'tasks.service.testSetting', value: 'value' })
			.then(() => {
				const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']);
				const contents = fs.readFileSync(target).toString('utf8');
				const parsed = json.parse(contents);
				assert.equal(parsed['service.testSetting'], 'value');
				const configurationService = instantiationService.get(IConfigurationService);
				assert.equal(configurationService.lookup('tasks.service.testSetting').value, 'value');
			});
258 259
	});

S
Sandeep Somavarapu 已提交
260 261 262 263 264 265 266 267 268 269 270 271 272 273
	test('write workspace standalone setting - existing file', () => {
		const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['launch']);
		fs.writeFileSync(target, '{ "my.super.setting": "my.super.value" }');
		return testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'launch.service.testSetting', value: 'value' })
			.then(() => {
				const contents = fs.readFileSync(target).toString('utf8');
				const parsed = json.parse(contents);
				assert.equal(parsed['service.testSetting'], 'value');
				assert.equal(parsed['my.super.setting'], 'my.super.value');

				const configurationService = instantiationService.get(IConfigurationService);
				assert.equal(configurationService.lookup('launch.service.testSetting').value, 'value');
				assert.equal(configurationService.lookup('launch.my.super.setting').value, 'my.super.value');
			});
274
	});
275

S
Sandeep Somavarapu 已提交
276 277 278 279 280 281 282 283 284 285 286
	test('write workspace standalone setting - empty file - full JSON', () => {
		return testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] } })
			.then(() => {
				const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']);
				const contents = fs.readFileSync(target).toString('utf8');
				const parsed = json.parse(contents);

				assert.equal(parsed['version'], '1.0.0');
				assert.equal(parsed['tasks'][0]['taskName'], 'myTask');
			});
	});
287

S
Sandeep Somavarapu 已提交
288 289 290 291 292 293 294 295 296 297 298 299 300
	test('write workspace standalone setting - existing file - full JSON', () => {
		const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['launch']);
		fs.writeFileSync(target, '{ "my.super.setting": "my.super.value" }');
		return testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] } })
			.then(() => {
				const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']);
				const contents = fs.readFileSync(target).toString('utf8');
				const parsed = json.parse(contents);

				assert.equal(parsed['version'], '1.0.0');
				assert.equal(parsed['tasks'][0]['taskName'], 'myTask');
			});
	});
301

S
Sandeep Somavarapu 已提交
302 303 304 305 306 307 308 309 310 311 312 313
	test('write workspace standalone setting - existing file with JSON errors - full JSON', () => {
		const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['launch']);
		fs.writeFileSync(target, '{ "my.super.setting": '); // invalid JSON
		return testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] } })
			.then(() => {
				const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']);
				const contents = fs.readFileSync(target).toString('utf8');
				const parsed = json.parse(contents);

				assert.equal(parsed['version'], '1.0.0');
				assert.equal(parsed['tasks'][0]['taskName'], 'myTask');
			});
314
	});
315
});