abbreviationAction.test.ts 26.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.
 *--------------------------------------------------------------------------------------------*/

6
import 'mocha';
7
import * as assert from 'assert';
M
Matt Bierner 已提交
8
import { Selection, workspace, CancellationTokenSource, CompletionTriggerKind, ConfigurationTarget } from 'vscode';
9
import { withRandomFileEditor, closeAllEditors } from './testUtils';
R
Ramya Achutha Rao 已提交
10
import { expandEmmetAbbreviation } from '../abbreviationActions';
11
import { DefaultCompletionItemProvider } from '../defaultCompletionProvider';
12

13
const completionProvider = new DefaultCompletionItemProvider();
14

15 16 17 18 19 20 21 22 23
const htmlContents = `
<body class="header">
	<ul class="nav main">
		<li class="item1">img</li>
		<li class="item2">hithere</li>
		ul>li
		ul>li*2
		ul>li.item$*2
		ul>li.item$@44*2
24
		<div i
25 26 27
	</ul>
	<style>
		.boo {
28
			display: dn; m10
29 30
		}
	</style>
31
	<span></span>
32 33
	(ul>li.item$)*2
	(ul>li.item$)*2+span
34
	(div>dl>(dt+dd)*2)
35 36 37 38
	<script type="text/html">
		span.hello
	</script>
	<script type="text/javascript">
39
		span.bye
40
	</script>
41 42 43 44
</body>
`;

suite('Tests for Expand Abbreviations (HTML)', () => {
45
	const oldValueForExcludeLanguages = workspace.getConfiguration('emmet').inspect('excludeLanguages');
46
	const oldValueForInlcudeLanguages = workspace.getConfiguration('emmet').inspect('includeLanguages');
47
	teardown(() => {
48 49
		// close all editors
		return closeAllEditors;
50
	});
51 52

	test('Expand snippets (HTML)', () => {
53
		return testExpandAbbreviation('html', new Selection(3, 23, 3, 23), 'img', '<img src=\"\" alt=\"\">');
54 55
	});

56 57 58 59
	test('Expand snippets in completion list (HTML)', () => {
		return testHtmlCompletionProvider(new Selection(3, 23, 3, 23), 'img', '<img src=\"\" alt=\"\">');
	});

60
	test('Expand snippets when no parent node (HTML)', () => {
M
Matt Bierner 已提交
61
		return withRandomFileEditor('img', 'html', async (editor, _doc) => {
62
			editor.selection = new Selection(0, 3, 0, 3);
M
Matt Bierner 已提交
63 64 65
			await expandEmmetAbbreviation(null);
			assert.equal(editor.document.getText(), '<img src=\"\" alt=\"\">');
			return Promise.resolve();
66 67 68 69
		});
	});

	test('Expand snippets when no parent node in completion list (HTML)', () => {
M
Matt Bierner 已提交
70
		return withRandomFileEditor('img', 'html', async (editor, _doc) => {
71 72
			editor.selection = new Selection(0, 3, 0, 3);
			const cancelSrc = new CancellationTokenSource();
73
			const completionPromise = completionProvider.provideCompletionItems(editor.document, editor.selection.active, cancelSrc.token, { triggerKind: CompletionTriggerKind.Invoke });
74 75 76 77
			if (!completionPromise) {
				assert.equal(!completionPromise, false, `Got unexpected undefined instead of a completion promise`);
				return Promise.resolve();
			}
M
Matt Bierner 已提交
78 79 80 81 82 83 84
			const completionList = await completionPromise;
			assert.equal(completionList && completionList.items && completionList.items.length > 0, true);
			if (completionList) {
				assert.equal(completionList.items[0].label, 'img');
				assert.equal(((<string>completionList.items[0].documentation) || '').replace(/\|/g, ''), '<img src=\"\" alt=\"\">');
			}
			return Promise.resolve();
85 86 87
		});
	});

88
	test('Expand abbreviation (HTML)', () => {
89
		return testExpandAbbreviation('html', new Selection(5, 25, 5, 25), 'ul>li', '<ul>\n\t\t\t<li></li>\n\t\t</ul>');
90 91
	});

92 93 94 95
	test('Expand abbreviation in completion list (HTML)', () => {
		return testHtmlCompletionProvider(new Selection(5, 25, 5, 25), 'ul>li', '<ul>\n\t<li></li>\n</ul>');
	});

96
	test('Expand text that is neither an abbreviation nor a snippet to tags (HTML)', () => {
97
		return testExpandAbbreviation('html', new Selection(4, 20, 4, 27), 'hithere', '<hithere></hithere>');
98 99
	});

100 101 102 103
	test('Do not Expand text that is neither an abbreviation nor a snippet to tags in completion list (HTML)', () => {
		return testHtmlCompletionProvider(new Selection(4, 20, 4, 27), 'hithere', '<hithere></hithere>', true);
	});

104
	test('Expand abbreviation with repeaters (HTML)', () => {
105
		return testExpandAbbreviation('html', new Selection(6, 27, 6, 27), 'ul>li*2', '<ul>\n\t\t\t<li></li>\n\t\t\t<li></li>\n\t\t</ul>');
106 107
	});

108 109 110 111
	test('Expand abbreviation with repeaters in completion list (HTML)', () => {
		return testHtmlCompletionProvider(new Selection(6, 27, 6, 27), 'ul>li*2', '<ul>\n\t<li></li>\n\t<li></li>\n</ul>');
	});

112
	test('Expand abbreviation with numbered repeaters (HTML)', () => {
113
		return testExpandAbbreviation('html', new Selection(7, 33, 7, 33), 'ul>li.item$*2', '<ul>\n\t\t\t<li class="item1"></li>\n\t\t\t<li class="item2"></li>\n\t\t</ul>');
114 115
	});

116
	test('Expand abbreviation with numbered repeaters in completion list (HTML)', () => {
117
		return testHtmlCompletionProvider(new Selection(7, 33, 7, 33), 'ul>li.item$*2', '<ul>\n\t<li class="item1"></li>\n\t<li class="item2"></li>\n</ul>');
118 119
	});

120
	test('Expand abbreviation with numbered repeaters with offset (HTML)', () => {
121
		return testExpandAbbreviation('html', new Selection(8, 36, 8, 36), 'ul>li.item$@44*2', '<ul>\n\t\t\t<li class="item44"></li>\n\t\t\t<li class="item45"></li>\n\t\t</ul>');
122 123
	});

124
	test('Expand abbreviation with numbered repeaters with offset in completion list (HTML)', () => {
125
		return testHtmlCompletionProvider(new Selection(8, 36, 8, 36), 'ul>li.item$@44*2', '<ul>\n\t<li class="item44"></li>\n\t<li class="item45"></li>\n</ul>');
126 127
	});

128
	test('Expand abbreviation with numbered repeaters in groups (HTML)', () => {
129
		return testExpandAbbreviation('html', new Selection(17, 16, 17, 16), '(ul>li.item$)*2', '<ul>\n\t\t<li class="item1"></li>\n\t</ul>\n\t<ul>\n\t\t<li class="item2"></li>\n\t</ul>');
130 131
	});

132 133 134 135
	test('Expand abbreviation with numbered repeaters in groups in completion list (HTML)', () => {
		return testHtmlCompletionProvider(new Selection(17, 16, 17, 16), '(ul>li.item$)*2', '<ul>\n\t<li class="item1"></li>\n</ul>\n<ul>\n\t<li class="item2"></li>\n</ul>');
	});

136
	test('Expand abbreviation with numbered repeaters in groups with sibling in the end (HTML)', () => {
137
		return testExpandAbbreviation('html', new Selection(18, 21, 18, 21), '(ul>li.item$)*2+span', '<ul>\n\t\t<li class="item1"></li>\n\t</ul>\n\t<ul>\n\t\t<li class="item2"></li>\n\t</ul>\n\t<span></span>');
138 139
	});

140 141 142 143
	test('Expand abbreviation with numbered repeaters in groups with sibling in the end in completion list (HTML)', () => {
		return testHtmlCompletionProvider(new Selection(18, 21, 18, 21), '(ul>li.item$)*2+span', '<ul>\n\t<li class="item1"></li>\n</ul>\n<ul>\n\t<li class="item2"></li>\n</ul>\n<span></span>');
	});

144
	test('Expand abbreviation with nested groups (HTML)', () => {
145
		return testExpandAbbreviation('html', new Selection(19, 19, 19, 19), '(div>dl>(dt+dd)*2)', '<div>\n\t\t<dl>\n\t\t\t<dt></dt>\n\t\t\t<dd></dd>\n\t\t\t<dt></dt>\n\t\t\t<dd></dd>\n\t\t</dl>\n\t</div>');
146 147
	});

148 149 150 151
	test('Expand abbreviation with nested groups in completion list (HTML)', () => {
		return testHtmlCompletionProvider(new Selection(19, 19, 19, 19), '(div>dl>(dt+dd)*2)', '<div>\n\t<dl>\n\t\t<dt></dt>\n\t\t<dd></dd>\n\t\t<dt></dt>\n\t\t<dd></dd>\n\t</dl>\n</div>');
	});

152
	test('Expand tag that is opened, but not closed (HTML)', () => {
153
		return testExpandAbbreviation('html', new Selection(9, 6, 9, 6), '<div', '<div></div>');
154 155
	});

156 157 158 159
	test('Do not Expand tag that is opened, but not closed in completion list (HTML)', () => {
		return testHtmlCompletionProvider(new Selection(9, 6, 9, 6), '<div', '<div></div>', true);
	});

160
	test('No expanding text inside open tag (HTML)', () => {
M
Matt Bierner 已提交
161
		return withRandomFileEditor(htmlContents, 'html', async (editor, _doc) => {
162
			editor.selection = new Selection(2, 4, 2, 4);
M
Matt Bierner 已提交
163 164 165
			await expandEmmetAbbreviation(null);
			assert.equal(editor.document.getText(), htmlContents);
			return Promise.resolve();
166
		});
167 168
	});

169
	test('No expanding text inside open tag in completion list (HTML)', () => {
M
Matt Bierner 已提交
170
		return withRandomFileEditor(htmlContents, 'html', (editor, _doc) => {
171 172
			editor.selection = new Selection(2, 4, 2, 4);
			const cancelSrc = new CancellationTokenSource();
173
			const completionPromise = completionProvider.provideCompletionItems(editor.document, editor.selection.active, cancelSrc.token, { triggerKind: CompletionTriggerKind.Invoke });
174 175 176
			assert.equal(!completionPromise, true, `Got unexpected comapletion promise instead of undefined`);
			return Promise.resolve();
		});
177 178
	});

179
	test('No expanding text inside open tag when there is no closing tag (HTML)', () => {
M
Matt Bierner 已提交
180
		return withRandomFileEditor(htmlContents, 'html', async (editor, _doc) => {
181
			editor.selection = new Selection(9, 8, 9, 8);
M
Matt Bierner 已提交
182 183 184
			await expandEmmetAbbreviation(null);
			assert.equal(editor.document.getText(), htmlContents);
			return Promise.resolve();
185
		});
186 187
	});

188
	test('No expanding text inside open tag when there is no closing tag in completion list (HTML)', () => {
M
Matt Bierner 已提交
189
		return withRandomFileEditor(htmlContents, 'html', (editor, _doc) => {
190 191
			editor.selection = new Selection(9, 8, 9, 8);
			const cancelSrc = new CancellationTokenSource();
192
			const completionPromise = completionProvider.provideCompletionItems(editor.document, editor.selection.active, cancelSrc.token, { triggerKind: CompletionTriggerKind.Invoke });
193 194 195 196 197 198 199
			assert.equal(!completionPromise, true, `Got unexpected comapletion promise instead of undefined`);
			return Promise.resolve();
		});
	});

	test('No expanding text inside open tag when there is no closing tag when there is no parent node (HTML)', () => {
		const fileContents = '<img s';
M
Matt Bierner 已提交
200
		return withRandomFileEditor(fileContents, 'html', async (editor, _doc) => {
201
			editor.selection = new Selection(0, 6, 0, 6);
M
Matt Bierner 已提交
202 203 204
			await expandEmmetAbbreviation(null);
			assert.equal(editor.document.getText(), fileContents);
			return Promise.resolve();
205 206 207 208 209
		});
	});

	test('No expanding text in completion list inside open tag when there is no closing tag when there is no parent node (HTML)', () => {
		const fileContents = '<img s';
M
Matt Bierner 已提交
210
		return withRandomFileEditor(fileContents, 'html', (editor, _doc) => {
211 212
			editor.selection = new Selection(0, 6, 0, 6);
			const cancelSrc = new CancellationTokenSource();
213
			const completionPromise = completionProvider.provideCompletionItems(editor.document, editor.selection.active, cancelSrc.token, { triggerKind: CompletionTriggerKind.Invoke });
214 215 216
			assert.equal(!completionPromise, true, `Got unexpected comapletion promise instead of undefined`);
			return Promise.resolve();
		});
217 218
	});

219
	test('Expand css when inside style tag (HTML)', () => {
M
Matt Bierner 已提交
220
		return withRandomFileEditor(htmlContents, 'html', async (editor, _doc) => {
221
			editor.selection = new Selection(13, 16, 13, 19);
222
			let expandPromise = expandEmmetAbbreviation({ language: 'css' });
223 224 225
			if (!expandPromise) {
				return Promise.resolve();
			}
M
Matt Bierner 已提交
226 227 228
			await expandPromise;
			assert.equal(editor.document.getText(), htmlContents.replace('m10', 'margin: 10px;'));
			return Promise.resolve();
229 230
		});
	});
231

232 233 234 235
	test('Expand css when inside style tag in completion list (HTML)', () => {
		const abbreviation = 'm10';
		const expandedText = 'margin: 10px;';

M
Matt Bierner 已提交
236
		return withRandomFileEditor(htmlContents, 'html', async (editor, _doc) => {
237 238 239 240 241 242 243 244
			editor.selection = new Selection(13, 16, 13, 19);
			const cancelSrc = new CancellationTokenSource();
			const completionPromise = completionProvider.provideCompletionItems(editor.document, editor.selection.active, cancelSrc.token, { triggerKind: CompletionTriggerKind.Invoke });
			if (!completionPromise) {
				assert.equal(1, 2, `Problem with expanding m10`);
				return Promise.resolve();
			}

M
Matt Bierner 已提交
245 246 247
			const completionList = await completionPromise;
			if (!completionList || !completionList.items || !completionList.items.length) {
				assert.equal(1, 2, `Problem with expanding m10`);
248
				return Promise.resolve();
M
Matt Bierner 已提交
249 250 251 252 253 254
			}
			const emmetCompletionItem = completionList.items[0];
			assert.equal(emmetCompletionItem.label, expandedText, `Label of completion item doesnt match.`);
			assert.equal(((<string>emmetCompletionItem.documentation) || '').replace(/\|/g, ''), expandedText, `Docs of completion item doesnt match.`);
			assert.equal(emmetCompletionItem.filterText, abbreviation, `FilterText of completion item doesnt match.`);
			return Promise.resolve();
255 256 257 258
		});
	});

	test('No expanding text inside style tag if position is not for property name (HTML)', () => {
M
Matt Bierner 已提交
259
		return withRandomFileEditor(htmlContents, 'html', async (editor, _doc) => {
260
			editor.selection = new Selection(13, 14, 13, 14);
M
Matt Bierner 已提交
261 262 263
			await expandEmmetAbbreviation(null);
			assert.equal(editor.document.getText(), htmlContents);
			return Promise.resolve();
264 265 266 267 268
		});
	});

	test('Expand css when inside style attribute (HTML)', () => {
		const styleAttributeContent = '<div style="m10" class="hello"></div>';
M
Matt Bierner 已提交
269
		return withRandomFileEditor(styleAttributeContent, 'html', async (editor, _doc) => {
270 271 272 273 274
			editor.selection = new Selection(0, 15, 0, 15);
			let expandPromise = expandEmmetAbbreviation(null);
			if (!expandPromise) {
				return Promise.resolve();
			}
M
Matt Bierner 已提交
275 276 277
			await expandPromise;
			assert.equal(editor.document.getText(), styleAttributeContent.replace('m10', 'margin: 10px;'));
			return Promise.resolve();
278 279 280 281 282 283 284
		});
	});

	test('Expand css when inside style attribute in completion list (HTML)', () => {
		const abbreviation = 'm10';
		const expandedText = 'margin: 10px;';

M
Matt Bierner 已提交
285
		return withRandomFileEditor('<div style="m10" class="hello"></div>', 'html', async (editor, _doc) => {
286 287 288 289 290 291 292 293
			editor.selection = new Selection(0, 15, 0, 15);
			const cancelSrc = new CancellationTokenSource();
			const completionPromise = completionProvider.provideCompletionItems(editor.document, editor.selection.active, cancelSrc.token, { triggerKind: CompletionTriggerKind.Invoke });
			if (!completionPromise) {
				assert.equal(1, 2, `Problem with expanding m10`);
				return Promise.resolve();
			}

M
Matt Bierner 已提交
294 295 296
			const completionList = await completionPromise;
			if (!completionList || !completionList.items || !completionList.items.length) {
				assert.equal(1, 2, `Problem with expanding m10`);
297
				return Promise.resolve();
M
Matt Bierner 已提交
298 299 300 301 302 303
			}
			const emmetCompletionItem = completionList.items[0];
			assert.equal(emmetCompletionItem.label, expandedText, `Label of completion item doesnt match.`);
			assert.equal(((<string>emmetCompletionItem.documentation) || '').replace(/\|/g, ''), expandedText, `Docs of completion item doesnt match.`);
			assert.equal(emmetCompletionItem.filterText, abbreviation, `FilterText of completion item doesnt match.`);
			return Promise.resolve();
304 305 306 307
		});
	});

	test('Expand html when inside script tag with html type (HTML)', () => {
M
Matt Bierner 已提交
308
		return withRandomFileEditor(htmlContents, 'html', async (editor, _doc) => {
309 310 311 312 313
			editor.selection = new Selection(21, 12, 21, 12);
			let expandPromise = expandEmmetAbbreviation(null);
			if (!expandPromise) {
				return Promise.resolve();
			}
M
Matt Bierner 已提交
314 315 316
			await expandPromise;
			assert.equal(editor.document.getText(), htmlContents.replace('span.hello', '<span class="hello"></span>'));
			return Promise.resolve();
317 318 319
		});
	});

320
	test('Expand html in completion list when inside script tag with html type (HTML)', () => {
321 322 323
		const abbreviation = 'span.hello';
		const expandedText = '<span class="hello"></span>';

M
Matt Bierner 已提交
324
		return withRandomFileEditor(htmlContents, 'html', async (editor, _doc) => {
325 326 327 328 329 330 331 332
			editor.selection = new Selection(21, 12, 21, 12);
			const cancelSrc = new CancellationTokenSource();
			const completionPromise = completionProvider.provideCompletionItems(editor.document, editor.selection.active, cancelSrc.token, { triggerKind: CompletionTriggerKind.Invoke });
			if (!completionPromise) {
				assert.equal(1, 2, `Problem with expanding span.hello`);
				return Promise.resolve();
			}

M
Matt Bierner 已提交
333 334 335
			const completionList = await completionPromise;
			if (!completionList || !completionList.items || !completionList.items.length) {
				assert.equal(1, 2, `Problem with expanding span.hello`);
336
				return Promise.resolve();
M
Matt Bierner 已提交
337 338 339 340 341
			}
			const emmetCompletionItem = completionList.items[0];
			assert.equal(emmetCompletionItem.label, abbreviation, `Label of completion item doesnt match.`);
			assert.equal(((<string>emmetCompletionItem.documentation) || '').replace(/\|/g, ''), expandedText, `Docs of completion item doesnt match.`);
			return Promise.resolve();
342 343 344 345
		});
	});

	test('No expanding text inside script tag with javascript type (HTML)', () => {
M
Matt Bierner 已提交
346
		return withRandomFileEditor(htmlContents, 'html', async (editor, _doc) => {
347
			editor.selection = new Selection(24, 12, 24, 12);
M
Matt Bierner 已提交
348 349 350
			await expandEmmetAbbreviation(null);
			assert.equal(editor.document.getText(), htmlContents);
			return Promise.resolve();
351 352 353 354
		});
	});

	test('No expanding text in completion list inside script tag with javascript type (HTML)', () => {
M
Matt Bierner 已提交
355
		return withRandomFileEditor(htmlContents, 'html', (editor, _doc) => {
356 357 358 359 360 361 362
			editor.selection = new Selection(24, 12, 24, 12);
			const cancelSrc = new CancellationTokenSource();
			const completionPromise = completionProvider.provideCompletionItems(editor.document, editor.selection.active, cancelSrc.token, { triggerKind: CompletionTriggerKind.Invoke });
			assert.equal(!completionPromise, true, `Got unexpected comapletion promise instead of undefined`);
			return Promise.resolve();
		});
	});
363

M
Matt Bierner 已提交
364 365
	test('Expand html when inside script tag with javascript type if js is mapped to html (HTML)', async () => {
		await workspace.getConfiguration('emmet').update('includeLanguages', { "javascript": "html" }, ConfigurationTarget.Global);
M
Matt Bierner 已提交
366
		await withRandomFileEditor(htmlContents, 'html', async (editor, _doc) => {
M
Matt Bierner 已提交
367 368 369 370 371 372 373
			editor.selection = new Selection(24, 10, 24, 10);
			let expandPromise = expandEmmetAbbreviation(null);
			if (!expandPromise) {
				return Promise.resolve();
			}
			await expandPromise;
			assert.equal(editor.document.getText(), htmlContents.replace('span.bye', '<span class="bye"></span>'));
374
		});
M
Matt Bierner 已提交
375
		return workspace.getConfiguration('emmet').update('includeLanguages', oldValueForInlcudeLanguages || {}, ConfigurationTarget.Global);
376 377
	});

M
Matt Bierner 已提交
378
	test('Expand html in completion list when inside script tag with javascript type if js is mapped to html (HTML)', async () => {
379 380
		const abbreviation = 'span.bye';
		const expandedText = '<span class="bye"></span>';
M
Matt Bierner 已提交
381
		await workspace.getConfiguration('emmet').update('includeLanguages', { "javascript": "html" }, ConfigurationTarget.Global);
M
Matt Bierner 已提交
382
		await withRandomFileEditor(htmlContents, 'html', async (editor, _doc) => {
M
Matt Bierner 已提交
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398
			editor.selection = new Selection(24, 10, 24, 10);
			const cancelSrc = new CancellationTokenSource();
			const completionPromise = completionProvider.provideCompletionItems(editor.document, editor.selection.active, cancelSrc.token, { triggerKind: CompletionTriggerKind.Invoke });
			if (!completionPromise) {
				assert.equal(1, 2, `Problem with expanding span.bye`);
				return Promise.resolve();
			}
			const completionList = await completionPromise;
			if (!completionList || !completionList.items || !completionList.items.length) {
				assert.equal(1, 2, `Problem with expanding span.bye`);
				return Promise.resolve();
			}
			const emmetCompletionItem = completionList.items[0];
			assert.equal(emmetCompletionItem.label, abbreviation, `Label of completion item (${emmetCompletionItem.label}) doesnt match.`);
			assert.equal(((<string>emmetCompletionItem.documentation) || '').replace(/\|/g, ''), expandedText, `Docs of completion item doesnt match.`);
			return Promise.resolve();
399
		});
M
Matt Bierner 已提交
400
		return workspace.getConfiguration('emmet').update('includeLanguages', oldValueForInlcudeLanguages || {}, ConfigurationTarget.Global);
401 402
	});

403 404 405 406 407 408 409
	// test('No expanding when html is excluded in the settings', () => {
	// 	return workspace.getConfiguration('emmet').update('excludeLanguages', ['html'], ConfigurationTarget.Global).then(() => {
	// 		return testExpandAbbreviation('html', new Selection(9, 6, 9, 6), '', '', true).then(() => {
	// 			return workspace.getConfiguration('emmet').update('excludeLanguages', oldValueForExcludeLanguages ? oldValueForExcludeLanguages.globalValue : undefined, ConfigurationTarget.Global);
	// 		});
	// 	});
	// });
410

M
Matt Bierner 已提交
411 412 413 414
	test('No expanding when html is excluded in the settings in completion list', async () => {
		await workspace.getConfiguration('emmet').update('excludeLanguages', ['html'], ConfigurationTarget.Global);
		await testHtmlCompletionProvider(new Selection(9, 6, 9, 6), '', '', true);
		return workspace.getConfiguration('emmet').update('excludeLanguages', oldValueForExcludeLanguages ? oldValueForExcludeLanguages.globalValue : undefined, ConfigurationTarget.Global);
415 416
	});

417 418 419 420 421 422 423
	// test('No expanding when php (mapped syntax) is excluded in the settings', () => {
	// 	return workspace.getConfiguration('emmet').update('excludeLanguages', ['php'], ConfigurationTarget.Global).then(() => {
	// 		return testExpandAbbreviation('php', new Selection(9, 6, 9, 6), '', '', true).then(() => {
	// 			return workspace.getConfiguration('emmet').update('excludeLanguages', oldValueForExcludeLanguages ? oldValueForExcludeLanguages.globalValue : undefined, ConfigurationTarget.Global);
	// 		});
	// 	});
	// });
424 425


426 427
});

428
suite('Tests for jsx, xml and xsl', () => {
429
	const oldValueForSyntaxProfiles = workspace.getConfiguration('emmet').inspect('syntaxProfiles');
430
	teardown(closeAllEditors);
431

432
	test('Expand abbreviation with className instead of class in jsx', () => {
M
Matt Bierner 已提交
433
		return withRandomFileEditor('ul.nav', 'javascriptreact', async (editor, _doc) => {
434
			editor.selection = new Selection(0, 6, 0, 6);
M
Matt Bierner 已提交
435 436 437
			await expandEmmetAbbreviation({ language: 'javascriptreact' });
			assert.equal(editor.document.getText(), '<ul className="nav"></ul>');
			return Promise.resolve();
438
		});
439
	});
R
Ramya Achutha Rao 已提交
440

441
	test('Expand abbreviation with self closing tags for jsx', () => {
M
Matt Bierner 已提交
442
		return withRandomFileEditor('img', 'javascriptreact', async (editor, _doc) => {
443
			editor.selection = new Selection(0, 6, 0, 6);
M
Matt Bierner 已提交
444 445 446
			await expandEmmetAbbreviation({ language: 'javascriptreact' });
			assert.equal(editor.document.getText(), '<img src="" alt=""/>');
			return Promise.resolve();
447
		});
448
	});
449

M
Matt Bierner 已提交
450 451
	test('Expand abbreviation with single quotes for jsx', async () => {
		await workspace.getConfiguration('emmet').update('syntaxProfiles', { jsx: { "attr_quotes": "single" } }, ConfigurationTarget.Global);
M
Matt Bierner 已提交
452
		return withRandomFileEditor('img', 'javascriptreact', async (editor, _doc) => {
M
Matt Bierner 已提交
453 454 455 456
			editor.selection = new Selection(0, 6, 0, 6);
			await expandEmmetAbbreviation({ language: 'javascriptreact' });
			assert.equal(editor.document.getText(), '<img src=\'\' alt=\'\'/>');
			return workspace.getConfiguration('emmet').update('syntaxProfiles', oldValueForSyntaxProfiles ? oldValueForSyntaxProfiles.globalValue : undefined, ConfigurationTarget.Global);
457 458 459
		});
	});

460
	test('Expand abbreviation with self closing tags for xml', () => {
M
Matt Bierner 已提交
461
		return withRandomFileEditor('img', 'xml', async (editor, _doc) => {
462
			editor.selection = new Selection(0, 6, 0, 6);
M
Matt Bierner 已提交
463 464 465
			await expandEmmetAbbreviation({ language: 'xml' });
			assert.equal(editor.document.getText(), '<img src="" alt=""/>');
			return Promise.resolve();
466
		});
467
	});
468

469
	test('Expand abbreviation with no self closing tags for html', () => {
M
Matt Bierner 已提交
470
		return withRandomFileEditor('img', 'html', async (editor, _doc) => {
471
			editor.selection = new Selection(0, 6, 0, 6);
M
Matt Bierner 已提交
472 473 474
			await expandEmmetAbbreviation({ language: 'html' });
			assert.equal(editor.document.getText(), '<img src="" alt="">');
			return Promise.resolve();
475
		});
476
	});
477

478
	test('Expand abbreviation with condition containing less than sign for jsx', () => {
M
Matt Bierner 已提交
479
		return withRandomFileEditor('if (foo < 10) { span.bar', 'javascriptreact', async (editor, _doc) => {
480
			editor.selection = new Selection(0, 27, 0, 27);
M
Matt Bierner 已提交
481 482 483
			await expandEmmetAbbreviation({ language: 'javascriptreact' });
			assert.equal(editor.document.getText(), 'if (foo < 10) { <span className="bar"></span>');
			return Promise.resolve();
484 485 486
		});
	});

487
	test('No expanding text inside open tag in completion list (jsx)', () => {
488
		return testNoCompletion('jsx', htmlContents, new Selection(2, 4, 2, 4));
489 490 491
	});

	test('No expanding tag that is opened, but not closed in completion list (jsx)', () => {
492
		return testNoCompletion('jsx', htmlContents, new Selection(9, 6, 9, 6));
493 494 495
	});

	test('No expanding text inside open tag when there is no closing tag in completion list (jsx)', () => {
496
		return testNoCompletion('jsx', htmlContents, new Selection(9, 8, 9, 8));
497 498 499
	});

	test('No expanding text in completion list inside open tag when there is no closing tag when there is no parent node (jsx)', () => {
500
		return testNoCompletion('jsx', '<img s', new Selection(0, 6, 0, 6));
501
	});
502

503
});
504

505
function testExpandAbbreviation(syntax: string, selection: Selection, abbreviation: string, expandedText: string, shouldFail?: boolean): Thenable<any> {
M
Matt Bierner 已提交
506
	return withRandomFileEditor(htmlContents, syntax, async (editor, _doc) => {
507
		editor.selection = selection;
508
		let expandPromise = expandEmmetAbbreviation(null);
509 510 511 512 513 514
		if (!expandPromise) {
			if (!shouldFail) {
				assert.equal(1, 2, `Problem with expanding ${abbreviation} to ${expandedText}`);
			}
			return Promise.resolve();
		}
M
Matt Bierner 已提交
515 516 517
		await expandPromise;
		assert.equal(editor.document.getText(), htmlContents.replace(abbreviation, expandedText));
		return Promise.resolve();
518 519 520
	});
}

521
function testHtmlCompletionProvider(selection: Selection, abbreviation: string, expandedText: string, shouldFail?: boolean): Thenable<any> {
M
Matt Bierner 已提交
522
	return withRandomFileEditor(htmlContents, 'html', async (editor, _doc) => {
523 524
		editor.selection = selection;
		const cancelSrc = new CancellationTokenSource();
525
		const completionPromise = completionProvider.provideCompletionItems(editor.document, editor.selection.active, cancelSrc.token, { triggerKind: CompletionTriggerKind.Invoke });
526 527 528 529 530 531
		if (!completionPromise) {
			if (!shouldFail) {
				assert.equal(1, 2, `Problem with expanding ${abbreviation} to ${expandedText}`);
			}
			return Promise.resolve();
		}
R
Ramya Achutha Rao 已提交
532

M
Matt Bierner 已提交
533 534 535 536
		const completionList = await completionPromise;
		if (!completionList || !completionList.items || !completionList.items.length) {
			if (!shouldFail) {
				assert.equal(1, 2, `Problem with expanding ${abbreviation} to ${expandedText}`);
537 538
			}
			return Promise.resolve();
M
Matt Bierner 已提交
539 540 541 542 543
		}
		const emmetCompletionItem = completionList.items[0];
		assert.equal(emmetCompletionItem.label, abbreviation, `Label of completion item doesnt match.`);
		assert.equal(((<string>emmetCompletionItem.documentation) || '').replace(/\|/g, ''), expandedText, `Docs of completion item doesnt match.`);
		return Promise.resolve();
544 545 546
	});
}

547
function testNoCompletion(syntax: string, fileContents: string, selection: Selection): Thenable<any> {
M
Matt Bierner 已提交
548
	return withRandomFileEditor(fileContents, syntax, (editor, _doc) => {
549 550 551 552 553 554 555
		editor.selection = selection;
		const cancelSrc = new CancellationTokenSource();
		const completionPromise = completionProvider.provideCompletionItems(editor.document, editor.selection.active, cancelSrc.token, { triggerKind: CompletionTriggerKind.Invoke });
		assert.equal(!completionPromise, true, `Got unexpected comapletion promise instead of undefined`);
		return Promise.resolve();
	});
}