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

S
Sandeep Somavarapu 已提交
6
import * as sinon from 'sinon';
7 8
import * as assert from 'assert';
import * as os from 'os';
9
import * as path from 'vs/base/common/path';
10
import * as fs from 'fs';
11
import * as json from 'vs/base/common/json';
12
import { Registry } from 'vs/platform/registry/common/platform';
S
Sandeep Somavarapu 已提交
13
import { ParsedArgs, IEnvironmentService } from 'vs/platform/environment/common/environment';
J
Joao Moreno 已提交
14
import { parseArgs } from 'vs/platform/environment/node/argv';
15
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
J
Johannes Rieken 已提交
16
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
17
import * as extfs from 'vs/base/node/extfs';
18 19
import { TestTextFileService, TestTextResourceConfigurationService, workbenchInstantiationService, TestLifecycleService, TestEnvironmentService, TestStorageService } from 'vs/workbench/test/workbenchTestServices';
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
20
import * as uuid from 'vs/base/common/uuid';
J
Johannes Rieken 已提交
21
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
22
import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService';
B
Benjamin Pasero 已提交
23
import { FileService } from 'vs/workbench/services/files/node/fileService';
24
import { ConfigurationEditingService, ConfigurationEditingError, ConfigurationEditingErrorCode } from 'vs/workbench/services/configuration/common/configurationEditingService';
J
Johannes Rieken 已提交
25
import { IFileService } from 'vs/platform/files/common/files';
26
import { WORKSPACE_STANDALONE_CONFIGURATIONS } from 'vs/workbench/services/configuration/common/configuration';
S
Sandeep Somavarapu 已提交
27
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
S
Sandeep Somavarapu 已提交
28 29
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
30
import { ITextModelService } from 'vs/editor/common/services/resolverService';
S
Sandeep Somavarapu 已提交
31
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
B
Benjamin Pasero 已提交
32
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
33
import { mkdirp } from 'vs/base/node/pfs';
34
import { INotificationService } from 'vs/platform/notification/common/notification';
S
Sandeep Somavarapu 已提交
35 36
import { ICommandService } from 'vs/platform/commands/common/commands';
import { CommandService } from 'vs/workbench/services/commands/common/commandService';
37
import { URI } from 'vs/base/common/uri';
38
import { createHash } from 'crypto';
39 40 41

class SettingsTestEnvironmentService extends EnvironmentService {

42
	constructor(args: ParsedArgs, _execPath: string, private customAppSettingsHome: string) {
43 44 45 46 47 48
		super(args, _execPath);
	}

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

S
Sandeep Somavarapu 已提交
49 50
suite('ConfigurationEditingService', () => {

S
Sandeep Somavarapu 已提交
51
	let instantiationService: TestInstantiationService;
S
Sandeep Somavarapu 已提交
52
	let testObject: ConfigurationEditingService;
53 54 55
	let parentDir: string;
	let workspaceDir: string;
	let globalSettingsFile: string;
S
Sandeep Somavarapu 已提交
56 57 58
	let workspaceSettingsDir;

	suiteSetup(() => {
59
		const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
S
Sandeep Somavarapu 已提交
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
		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'
				}
			}
		});
	});
79

S
Sandeep Somavarapu 已提交
80 81 82 83
	setup(() => {
		return setUpWorkspace()
			.then(() => setUpServices());
	});
84

85
	async function setUpWorkspace(): Promise<boolean> {
86 87 88 89 90 91
		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');

92
		return await mkdirp(workspaceSettingsDir, 493);
93 94
	}

S
Sandeep Somavarapu 已提交
95
	function setUpServices(noWorkspace: boolean = false): Promise<void> {
96 97 98
		// Clear services if they are already created
		clearServices();

S
Sandeep Somavarapu 已提交
99
		instantiationService = <TestInstantiationService>workbenchInstantiationService();
100 101
		const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile);
		instantiationService.stub(IEnvironmentService, environmentService);
S
Sandeep Somavarapu 已提交
102
		const workspaceService = new WorkspaceService(environmentService);
103
		instantiationService.stub(IWorkspaceContextService, workspaceService);
104
		return workspaceService.initialize(noWorkspace ? { id: '' } : { folder: URI.file(workspaceDir), id: createHash('md5').update(URI.file(workspaceDir).toString()).digest('hex') }).then(() => {
105
			instantiationService.stub(IConfigurationService, workspaceService);
106
			instantiationService.stub(IFileService, new FileService(workspaceService, TestEnvironmentService, new TestTextResourceConfigurationService(), new TestConfigurationService(), new TestLifecycleService(), new TestStorageService(), new TestNotificationService(), { disableWatcher: true }));
107 108
			instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService));
			instantiationService.stub(ITextModelService, <ITextModelService>instantiationService.createInstance(TextModelResolverService));
S
Sandeep Somavarapu 已提交
109
			instantiationService.stub(ICommandService, CommandService);
110 111
			testObject = instantiationService.createInstance(ConfigurationEditingService);
		});
112 113
	}

S
Sandeep Somavarapu 已提交
114
	teardown(() => {
115
		clearServices();
S
Sandeep Somavarapu 已提交
116
		return clearWorkspace();
117 118
	});

119 120
	function clearServices(): void {
		if (instantiationService) {
121
			const configuraitonService = <WorkspaceService>instantiationService.get(IConfigurationService);
122 123 124
			if (configuraitonService) {
				configuraitonService.dispose();
			}
125
			instantiationService = null!;
126 127 128
		}
	}

S
Sandeep Somavarapu 已提交
129 130
	function clearWorkspace(): Promise<void> {
		return new Promise<void>((c, e) => {
S
Sandeep Somavarapu 已提交
131
			if (parentDir) {
R
Rob Lourens 已提交
132
				extfs.del(parentDir, os.tmpdir(), () => c(undefined), () => c(undefined));
S
Sandeep Somavarapu 已提交
133
			} else {
R
Rob Lourens 已提交
134
				c(undefined);
135
			}
136
		}).then(() => parentDir = null!);
S
Sandeep Somavarapu 已提交
137
	}
138

S
Sandeep Somavarapu 已提交
139 140 141
	test('errors cases - invalid key', () => {
		return testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'unknown.key', value: 'value' })
			.then(() => assert.fail('Should fail with ERROR_UNKNOWN_KEY'),
M
Matt Bierner 已提交
142
				(error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_UNKNOWN_KEY));
143 144
	});

S
Sandeep Somavarapu 已提交
145 146 147
	test('errors cases - invalid target', () => {
		return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'tasks.something', value: 'value' })
			.then(() => assert.fail('Should fail with ERROR_INVALID_TARGET'),
M
Matt Bierner 已提交
148
				(error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_INVALID_USER_TARGET));
149 150
	});

S
Sandeep Somavarapu 已提交
151 152 153 154
	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'),
M
Matt Bierner 已提交
155
				(error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_NO_WORKSPACE_OPENED));
156 157
	});

S
Sandeep Somavarapu 已提交
158 159 160 161
	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'),
M
Matt Bierner 已提交
162
				(error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_INVALID_CONFIGURATION));
163 164
	});

S
Sandeep Somavarapu 已提交
165 166 167 168
	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.'),
M
Matt Bierner 已提交
169
				(error: ConfigurationEditingError) => assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY));
170 171
	});

S
Sandeep Somavarapu 已提交
172 173 174 175 176 177 178 179 180
	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();
181
		instantiationService.stub(INotificationService, <INotificationService>{ prompt: target, _serviceBrand: null, notify: null!, error: null!, info: null!, warn: null! });
S
Sandeep Somavarapu 已提交
182 183
		return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }, { donotNotifyError: true })
			.then(() => assert.fail('Should fail with ERROR_CONFIGURATION_FILE_DIRTY error.'),
M
Matt Bierner 已提交
184 185 186 187
				(error: ConfigurationEditingError) => {
					assert.equal(false, target.calledOnce);
					assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY);
				});
S
Sandeep Somavarapu 已提交
188 189
	});

S
Sandeep Somavarapu 已提交
190 191 192 193 194 195 196
	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');
			});
197 198
	});

S
Sandeep Somavarapu 已提交
199 200 201 202 203 204 205 206 207
	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');
			});
208
	});
209

S
Sandeep Somavarapu 已提交
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
	test('remove an existing setting - existing file', () => {
		fs.writeFileSync(globalSettingsFile, '{ "my.super.setting": "my.super.value", "configurationEditing.service.testSetting": "value" }');
		return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: undefined })
			.then(() => {
				const contents = fs.readFileSync(globalSettingsFile).toString('utf8');
				const parsed = json.parse(contents);
				assert.deepEqual(Object.keys(parsed), ['my.super.setting']);
				assert.equal(parsed['my.super.setting'], 'my.super.value');
			});
	});

	test('remove non existing setting - existing file', () => {
		fs.writeFileSync(globalSettingsFile, '{ "my.super.setting": "my.super.value" }');
		return testObject.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: undefined })
			.then(() => {
				const contents = fs.readFileSync(globalSettingsFile).toString('utf8');
				const parsed = json.parse(contents);
				assert.deepEqual(Object.keys(parsed), ['my.super.setting']);
				assert.equal(parsed['my.super.setting'], 'my.super.value');
			});
	});

S
Sandeep Somavarapu 已提交
232 233 234 235 236 237 238 239
	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');
			});
240 241
	});

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

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

S
Sandeep Somavarapu 已提交
266
	test('write workspace standalone setting - existing file - full JSON', () => {
S
Sandeep Somavarapu 已提交
267
		const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']);
S
Sandeep Somavarapu 已提交
268 269 270 271 272 273 274 275 276 277
		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 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');
			});
	});
278

S
Sandeep Somavarapu 已提交
279
	test('write workspace standalone setting - existing file with JSON errors - full JSON', () => {
S
Sandeep Somavarapu 已提交
280
		const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']);
S
Sandeep Somavarapu 已提交
281 282 283 284 285 286 287 288 289
		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 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');
			});
290
	});
S
Sandeep Somavarapu 已提交
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311

	test('write workspace standalone setting should replace complete file', () => {
		const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']);
		fs.writeFileSync(target, `{
			"version": "1.0.0",
			"tasks": [
				{
					"taskName": "myTask1"
				},
				{
					"taskName": "myTask2"
				}
			]
		}`);
		return testObject.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask1' }] } })
			.then(() => {
				const actual = fs.readFileSync(target).toString('utf8');
				const expected = JSON.stringify({ 'version': '1.0.0', tasks: [{ 'taskName': 'myTask1' }] }, null, '\t');
				assert.equal(actual, expected);
			});
	});
312
});