Path: blob/main/extensions/emmet/src/test/wrapWithAbbreviation.test.ts
4774 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import 'mocha';6import * as assert from 'assert';7import { Selection, workspace, ConfigurationTarget } from 'vscode';8import { withRandomFileEditor, closeAllEditors } from './testUtils';9import { wrapWithAbbreviation } from '../abbreviationActions';1011const htmlContentsForBlockWrapTests = `12<ul class="nav main">13<li class="item1">img</li>14<li class="item2">$hithere</li>15<li class="item3">\${hithere}</li>16</ul>17`;1819const htmlContentsForInlineWrapTests = `20<ul class="nav main">21<em class="item1">img</em>22<em class="item2">$hithere</em>23<em class="item3">\${hithere}</em>24</ul>25`;2627const wrapBlockElementExpected = `28<ul class="nav main">29<div>30<li class="item1">img</li>31</div>32<div>33<li class="item2">$hithere</li>34</div>35<div>36<li class="item3">\${hithere}</li>37</div>38</ul>39`;4041const wrapInlineElementExpected = `42<ul class="nav main">43<span><em class="item1">img</em></span>44<span><em class="item2">$hithere</em></span>45<span><em class="item3">\${hithere}</em></span>46</ul>47`;4849const wrapSnippetExpected = `50<ul class="nav main">51<a href="">52<li class="item1">img</li>53</a>54<a href="">55<li class="item2">$hithere</li>56</a>57<a href="">58<li class="item3">\${hithere}</li>59</a>60</ul>61`;6263const wrapMultiLineAbbrExpected = `64<ul class="nav main">65<ul>66<li>67<li class="item1">img</li>68</li>69</ul>70<ul>71<li>72<li class="item2">$hithere</li>73</li>74</ul>75<ul>76<li>77<li class="item3">\${hithere}</li>78</li>79</ul>80</ul>81`;8283// technically a bug, but also a feature (requested behaviour)84// https://github.com/microsoft/vscode/issues/7801585const wrapInlineElementExpectedFormatFalse = `86<ul class="nav main">87<h1>88<li class="item1">img</li>89</h1>90<h1>91<li class="item2">$hithere</li>92</h1>93<h1>94<li class="item3">\${hithere}</li>95</h1>96</ul>97`;9899suite('Tests for Wrap with Abbreviations', () => {100teardown(closeAllEditors);101102const multiCursors = [new Selection(2, 6, 2, 6), new Selection(3, 6, 3, 6), new Selection(4, 6, 4, 6)];103const multiCursorsWithSelection = [new Selection(2, 2, 2, 28), new Selection(3, 2, 3, 33), new Selection(4, 6, 4, 36)];104const multiCursorsWithFullLineSelection = [new Selection(2, 0, 2, 28), new Selection(3, 0, 3, 33), new Selection(4, 0, 4, 36)];105106const oldValueForSyntaxProfiles = workspace.getConfiguration('emmet').inspect('syntaxProfiles');107108test('Wrap with block element using multi cursor', () => {109return testWrapWithAbbreviation(multiCursors, 'div', wrapBlockElementExpected, htmlContentsForBlockWrapTests);110});111112test('Wrap with inline element using multi cursor', () => {113return testWrapWithAbbreviation(multiCursors, 'span', wrapInlineElementExpected, htmlContentsForInlineWrapTests);114});115116test('Wrap with snippet using multi cursor', () => {117return testWrapWithAbbreviation(multiCursors, 'a', wrapSnippetExpected, htmlContentsForBlockWrapTests);118});119120test('Wrap with multi line abbreviation using multi cursor', () => {121return testWrapWithAbbreviation(multiCursors, 'ul>li', wrapMultiLineAbbrExpected, htmlContentsForBlockWrapTests);122});123124test('Wrap with block element using multi cursor selection', () => {125return testWrapWithAbbreviation(multiCursorsWithSelection, 'div', wrapBlockElementExpected, htmlContentsForBlockWrapTests);126});127128test('Wrap with inline element using multi cursor selection', () => {129return testWrapWithAbbreviation(multiCursorsWithSelection, 'span', wrapInlineElementExpected, htmlContentsForInlineWrapTests);130});131132test('Wrap with snippet using multi cursor selection', () => {133return testWrapWithAbbreviation(multiCursorsWithSelection, 'a', wrapSnippetExpected, htmlContentsForBlockWrapTests);134});135136test('Wrap with multi line abbreviation using multi cursor selection', () => {137return testWrapWithAbbreviation(multiCursorsWithSelection, 'ul>li', wrapMultiLineAbbrExpected, htmlContentsForBlockWrapTests);138});139140test('Wrap with block element using multi cursor full line selection', () => {141return testWrapWithAbbreviation(multiCursorsWithFullLineSelection, 'div', wrapBlockElementExpected, htmlContentsForBlockWrapTests);142});143144test('Wrap with inline element using multi cursor full line selection', () => {145return testWrapWithAbbreviation(multiCursorsWithFullLineSelection, 'span', wrapInlineElementExpected, htmlContentsForInlineWrapTests);146});147148test('Wrap with snippet using multi cursor full line selection', () => {149return testWrapWithAbbreviation(multiCursorsWithFullLineSelection, 'a', wrapSnippetExpected, htmlContentsForBlockWrapTests);150});151152test('Wrap with multi line abbreviation using multi cursor full line selection', () => {153return testWrapWithAbbreviation(multiCursorsWithFullLineSelection, 'ul>li', wrapMultiLineAbbrExpected, htmlContentsForBlockWrapTests);154});155156test('Wrap with abbreviation and comment filter', () => {157const contents = `158<ul class="nav main">159line160</ul>161`;162const expectedContents = `163<ul class="nav main">164<li class="hello">line</li>165<!-- /.hello -->166</ul>167`;168return testWrapWithAbbreviation([new Selection(2, 0, 2, 0)], 'li.hello|c', expectedContents, contents);169});170171test('Wrap with abbreviation link', () => {172const contents = `173<ul class="nav main">174line175</ul>176`;177const expectedContents = `178<a href="https://example.com">179<div>180<ul class="nav main">181line182</ul>183</div>184</a>185`;186return testWrapWithAbbreviation([new Selection(1, 2, 1, 2)], 'a[href="https://example.com"]>div', expectedContents, contents);187});188189test('Wrap with abbreviation entire node when cursor is on opening tag', () => {190const contents = `191<div class="nav main">192hello193</div>194`;195const expectedContents = `196<div>197<div class="nav main">198hello199</div>200</div>201`;202return testWrapWithAbbreviation([new Selection(1, 2, 1, 2)], 'div', expectedContents, contents);203});204205test('Wrap with abbreviation entire node when cursor is on closing tag', () => {206const contents = `207<div class="nav main">208hello209</div>210`;211const expectedContents = `212<div>213<div class="nav main">214hello215</div>216</div>217`;218return testWrapWithAbbreviation([new Selection(3, 2, 3, 2)], 'div', expectedContents, contents);219});220221test('Wrap with abbreviation inner node in cdata', () => {222const contents = `223<div class="nav main">224<![CDATA[225<div>226<p>Test 1</p>227</div>228<p>Test 2</p>229]]>230hello231</div>232`;233const expectedContents = `234<div class="nav main">235<![CDATA[236<div>237<p>Test 1</p>238</div>239<div>240<p>Test 2</p>241</div>242]]>243hello244</div>245`;246return testWrapWithAbbreviation([new Selection(6, 5, 6, 5)], 'div', expectedContents, contents);247});248249test('Wrap with abbreviation inner node in script in cdata', () => {250const contents = `251<div class="nav main">252<![CDATA[253<script type="text/plain">254<p>Test 1</p>255</script>256<p>Test 2</p>257]]>258hello259</div>260`;261const expectedContents = `262<div class="nav main">263<![CDATA[264<script type="text/plain">265<div>266<p>Test 1</p>267</div>268</script>269<p>Test 2</p>270]]>271hello272</div>273`;274return testWrapWithAbbreviation([new Selection(4, 10, 4, 10)], 'div', expectedContents, contents);275});276277test('Wrap with abbreviation inner node in cdata one-liner', () => {278const contents = `279<div class="nav main">280<![CDATA[<p>Test here</p>]]>281hello282</div>283`;284// this result occurs because no selection on the open/close p tag was given285const expectedContents = `286<div class="nav main">287<div><![CDATA[<p>Test here</p>]]></div>288hello289</div>290`;291return testWrapWithAbbreviation([new Selection(2, 15, 2, 15)], 'div', expectedContents, contents);292});293294test('Wrap with multiline abbreviation doesnt add extra spaces', () => {295// Issue #29898296const contents = `297hello298`;299const expectedContents = `300<ul>301<li><a href="">hello</a></li>302</ul>303`;304return testWrapWithAbbreviation([new Selection(1, 2, 1, 2)], 'ul>li>a', expectedContents, contents);305});306307test('Wrap individual lines with abbreviation', () => {308const contents = `309<ul class="nav main">310<li class="item1">This $10 is not a tabstop</li>311<li class="item2">hi.there</li>312</ul>313`;314const wrapIndividualLinesExpected = `315<ul class="nav main">316<ul>317<li class="hello1">318<li class="item1">This $10 is not a tabstop</li>319</li>320<li class="hello2">321<li class="item2">hi.there</li>322</li>323</ul>324</ul>325`;326return testWrapIndividualLinesWithAbbreviation([new Selection(2, 2, 3, 33)], 'ul>li.hello$*', wrapIndividualLinesExpected, contents);327});328329test('Wrap individual lines with abbreviation with extra space selected', () => {330const contents = `331<ul class="nav main">332<li class="item1">img</li>333<li class="item2">hi.there</li>334</ul>335`;336const wrapIndividualLinesExpected = `337<ul class="nav main">338<ul>339<li class="hello1">340<li class="item1">img</li>341</li>342<li class="hello2">343<li class="item2">hi.there</li>344</li>345</ul>346</ul>347`;348return testWrapIndividualLinesWithAbbreviation([new Selection(2, 1, 4, 0)], 'ul>li.hello$*', wrapIndividualLinesExpected, contents);349});350351test('Wrap individual lines with abbreviation with comment filter', () => {352const contents = `353<ul class="nav main">354<li class="item1">img</li>355<li class="item2">hi.there</li>356</ul>357`;358const wrapIndividualLinesExpected = `359<ul class="nav main">360<ul>361<li class="hello">362<li class="item1">img</li>363</li>364<!-- /.hello -->365<li class="hello">366<li class="item2">hi.there</li>367</li>368<!-- /.hello -->369</ul>370</ul>371`;372return testWrapIndividualLinesWithAbbreviation([new Selection(2, 2, 3, 33)], 'ul>li.hello*|c', wrapIndividualLinesExpected, contents);373});374375test('Wrap individual lines with abbreviation and trim', () => {376const contents = `377<ul class="nav main">378• lorem ipsum379• lorem ipsum380</ul>381`;382const wrapIndividualLinesExpected = `383<ul class="nav main">384<ul>385<li class="hello1">lorem ipsum</li>386<li class="hello2">lorem ipsum</li>387</ul>388</ul>389`;390return testWrapIndividualLinesWithAbbreviation([new Selection(2, 3, 3, 16)], 'ul>li.hello$*|t', wrapIndividualLinesExpected, contents);391});392393test('Wrap with abbreviation and format set to false', () => {394return workspace.getConfiguration('emmet').update('syntaxProfiles', { 'html': { 'format': false } }, ConfigurationTarget.Global).then(() => {395return testWrapWithAbbreviation(multiCursors, 'h1', wrapInlineElementExpectedFormatFalse, htmlContentsForBlockWrapTests).then(() => {396return workspace.getConfiguration('emmet').update('syntaxProfiles', oldValueForSyntaxProfiles ? oldValueForSyntaxProfiles.globalValue : undefined, ConfigurationTarget.Global);397});398});399});400401test('Wrap multi line selections with abbreviation', () => {402const htmlContentsForWrapMultiLineTests = `403<ul class="nav main">404line1405line2406407line3408line4409</ul>410`;411412const wrapMultiLineExpected = `413<ul class="nav main">414<div>415line1416line2417</div>418419<div>420line3421line4422</div>423</ul>424`;425426return testWrapWithAbbreviation([new Selection(2, 4, 3, 9), new Selection(5, 4, 6, 9)], 'div', wrapMultiLineExpected, htmlContentsForWrapMultiLineTests);427});428429test('Wrap multiline with abbreviation uses className for jsx files', () => {430const wrapMultiLineJsxExpected = `431<ul class="nav main">432<div className="hello">433<li class="item1">img</li>434<li class="item2">$hithere</li>435<li class="item3">\${hithere}</li>436</div>437</ul>438`;439440return testWrapWithAbbreviation([new Selection(2, 2, 4, 36)], '.hello', wrapMultiLineJsxExpected, htmlContentsForBlockWrapTests, 'jsx');441});442443test('Wrap individual line with abbreviation uses className for jsx files', () => {444const wrapIndividualLinesJsxExpected = `445<ul class="nav main">446<div className="hello1">447<li class="item1">img</li>448</div>449<div className="hello2">450<li class="item2">$hithere</li>451</div>452<div className="hello3">453<li class="item3">\${hithere}</li>454</div>455</ul>456`;457458return testWrapIndividualLinesWithAbbreviation([new Selection(2, 2, 4, 36)], '.hello$*', wrapIndividualLinesJsxExpected, htmlContentsForBlockWrapTests, 'jsx');459});460461test('Wrap with abbreviation merge overlapping computed ranges', () => {462const contents = `463<div class="nav main">464hello465</div>466`;467const expectedContents = `468<div>469<div class="nav main">470hello471</div>472</div>473`;474return testWrapWithAbbreviation([new Selection(1, 2, 1, 2), new Selection(1, 10, 1, 10)], 'div', expectedContents, contents);475});476477test('Wrap with abbreviation ignore invalid abbreviation', () => {478const contents = `479<div class="nav main">480hello481</div>482`;483return testWrapWithAbbreviation([new Selection(1, 2, 1, 2)], 'div]', contents, contents);484});485486});487488489function testWrapWithAbbreviation(selections: Selection[], abbreviation: string, expectedContents: string, input: string, fileExtension: string = 'html'): Thenable<any> {490return withRandomFileEditor(input, fileExtension, (editor, _) => {491editor.selections = selections;492const promise = wrapWithAbbreviation({ abbreviation });493if (!promise) {494assert.strictEqual(1, 2, 'Wrap with Abbreviation returned undefined.');495return Promise.resolve();496}497498return promise.then(() => {499assert.strictEqual(editor.document.getText(), expectedContents);500return Promise.resolve();501});502});503}504505function testWrapIndividualLinesWithAbbreviation(selections: Selection[], abbreviation: string, expectedContents: string, input: string, fileExtension: string = 'html'): Thenable<any> {506return withRandomFileEditor(input, fileExtension, (editor, _) => {507editor.selections = selections;508const promise = wrapWithAbbreviation({ abbreviation });509if (!promise) {510assert.strictEqual(1, 2, 'Wrap individual lines with Abbreviation returned undefined.');511return Promise.resolve();512}513514return promise.then(() => {515assert.strictEqual(editor.document.getText(), expectedContents);516return Promise.resolve();517});518});519}520521522