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';
J
Johannes Rieken 已提交
14
import { TPromise } from 'vs/base/common/winjs.base';
15
import { Registry } from 'vs/platform/registry/common/platform';
S
Sandeep Somavarapu 已提交
16
import { ParsedArgs, IEnvironmentService } from 'vs/platform/environment/common/environment';
J
Joao Moreno 已提交
17
import { parseArgs } from 'vs/platform/environment/node/argv';
18
import { IWorkspaceContextService, Workspace } from 'vs/platform/workspace/common/workspace';
J
Johannes Rieken 已提交
19
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
20
import extfs = require('vs/base/node/extfs');
T
t-amqi 已提交
21
import { TestTextFileService, TestEditorGroupService, TestLifecycleService, TestBackupFileService, TestStorageService } from 'vs/workbench/test/workbenchTestServices';
22
import uuid = require('vs/base/common/uuid');
J
Johannes Rieken 已提交
23
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
24
import { WorkspaceConfigurationService } from 'vs/workbench/services/configuration/node/configuration';
25
import URI from 'vs/base/common/uri';
J
Johannes Rieken 已提交
26
import { FileService } from 'vs/workbench/services/files/node/fileService';
27
import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService';
J
Johannes Rieken 已提交
28 29
import { ConfigurationTarget, IConfigurationEditingError, ConfigurationEditingErrorCode } from 'vs/workbench/services/configuration/common/configurationEditing';
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';
T
t-amqi 已提交
47
import { IStorageService } from 'vs/platform/storage/common/storage';
48 49 50 51 52 53 54 55 56 57

class SettingsTestEnvironmentService extends EnvironmentService {

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

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

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

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

	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'
				}
			}
		});
	});
89

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

S
Sandeep Somavarapu 已提交
95 96 97 98 99 100 101 102 103 104 105 106 107 108
	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);
				}
			});
109 110 111
		});
	}

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

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

		testObject = instantiationService.createInstance(ConfigurationEditingService);
149
		return workspaceService.initialize();
150 151
	}

S
Sandeep Somavarapu 已提交
152
	teardown(() => {
153
		clearServices();
S
Sandeep Somavarapu 已提交
154
		return clearWorkspace();
155 156
	});

157 158
	function clearServices(): void {
		if (instantiationService) {
159
			const configuraitonService = <WorkspaceConfigurationService>instantiationService.get(IConfigurationService);
160 161 162 163 164 165 166
			if (configuraitonService) {
				configuraitonService.dispose();
			}
			instantiationService = null;
		}
	}

S
Sandeep Somavarapu 已提交
167 168 169
	function clearWorkspace(): TPromise<void> {
		return new TPromise<void>((c, e) => {
			if (parentDir) {
170
				extfs.del(parentDir, os.tmpdir(), () => c(null), () => c(null));
S
Sandeep Somavarapu 已提交
171 172
			} else {
				c(null);
173
			}
174
		}).then(() => parentDir = null);
S
Sandeep Somavarapu 已提交
175
	}
176

S
Sandeep Somavarapu 已提交
177 178 179 180
	test('errors cases - invalid key', () => {
		return testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'unknown.key', value: 'value' })
			.then(() => assert.fail('Should fail with ERROR_UNKNOWN_KEY'),
			(error: IConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_UNKNOWN_KEY));
181 182
	});

S
Sandeep Somavarapu 已提交
183 184 185 186
	test('errors cases - invalid target', () => {
		return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'tasks.something', value: 'value' })
			.then(() => assert.fail('Should fail with ERROR_INVALID_TARGET'),
			(error: IConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_INVALID_TARGET));
187 188
	});

S
Sandeep Somavarapu 已提交
189 190 191 192 193
	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'),
			(error: IConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_NO_WORKSPACE_OPENED));
194 195
	});

S
Sandeep Somavarapu 已提交
196 197 198 199 200
	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'),
			(error: IConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_INVALID_CONFIGURATION));
201 202
	});

S
Sandeep Somavarapu 已提交
203 204 205 206 207
	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.'),
			(error: IConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY));
208 209
	});

S
Sandeep Somavarapu 已提交
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
	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.'),
			(error: IConfigurationEditingError) => {
				assert.equal(false, target.calledOnce);
				assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY);
			});
	});

S
Sandeep Somavarapu 已提交
228 229 230 231 232 233 234 235
	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');
			});
236 237
	});

S
Sandeep Somavarapu 已提交
238 239 240 241 242 243 244 245 246 247 248 249 250
	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');
			});
251
	});
252

S
Sandeep Somavarapu 已提交
253 254 255 256 257 258 259 260 261 262
	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');
			});
263 264
	});

S
Sandeep Somavarapu 已提交
265 266 267 268 269 270 271 272 273 274 275 276 277 278
	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');
			});
279
	});
280

S
Sandeep Somavarapu 已提交
281 282 283 284 285 286 287 288 289 290 291
	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');
			});
	});
292

S
Sandeep Somavarapu 已提交
293 294 295 296 297 298 299 300 301 302 303 304 305
	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');
			});
	});
306

S
Sandeep Somavarapu 已提交
307 308 309 310 311 312 313 314 315 316 317 318
	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');
			});
319
	});
320
});