|
1 | | -// |
| 1 | +// |
2 | 2 | // Copyright (c) Microsoft Corporation. All rights reserved. |
3 | 3 | // |
4 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -427,7 +427,7 @@ namespace FourSlash { |
427 | 427 |
|
428 | 428 | if (exists !== negative) { |
429 | 429 | this.printErrorLog(negative, this.getAllDiagnostics()); |
430 | | - throw new Error("Failure between markers: " + startMarkerName + ", " + endMarkerName); |
| 430 | + throw new Error(`Failure between markers: '${startMarkerName}', '${endMarkerName}'`); |
431 | 431 | } |
432 | 432 | } |
433 | 433 |
|
@@ -740,7 +740,6 @@ namespace FourSlash { |
740 | 740 | } |
741 | 741 | } |
742 | 742 |
|
743 | | - |
744 | 743 | public verifyCompletionListAllowsNewIdentifier(negative: boolean) { |
745 | 744 | const completions = this.getCompletionListAtCaret(); |
746 | 745 |
|
@@ -1610,7 +1609,7 @@ namespace FourSlash { |
1610 | 1609 | if (isFormattingEdit) { |
1611 | 1610 | const newContent = this.getFileContent(fileName); |
1612 | 1611 |
|
1613 | | - if (newContent.replace(/\s/g, "") !== oldContent.replace(/\s/g, "")) { |
| 1612 | + if (this.removeWhitespace(newContent) !== this.removeWhitespace(oldContent)) { |
1614 | 1613 | this.raiseError("Formatting operation destroyed non-whitespace content"); |
1615 | 1614 | } |
1616 | 1615 | } |
@@ -1676,6 +1675,10 @@ namespace FourSlash { |
1676 | 1675 | } |
1677 | 1676 | } |
1678 | 1677 |
|
| 1678 | + private removeWhitespace(text: string): string { |
| 1679 | + return text.replace(/\s/g, ""); |
| 1680 | + } |
| 1681 | + |
1679 | 1682 | public goToBOF() { |
1680 | 1683 | this.goToPosition(0); |
1681 | 1684 | } |
@@ -2041,6 +2044,47 @@ namespace FourSlash { |
2041 | 2044 | } |
2042 | 2045 | } |
2043 | 2046 |
|
| 2047 | + private getCodeFixes(errorCode?: number) { |
| 2048 | + const fileName = this.activeFile.fileName; |
| 2049 | + const diagnostics = this.getDiagnostics(fileName); |
| 2050 | + |
| 2051 | + if (diagnostics.length === 0) { |
| 2052 | + this.raiseError("Errors expected."); |
| 2053 | + } |
| 2054 | + |
| 2055 | + if (diagnostics.length > 1 && errorCode !== undefined) { |
| 2056 | + this.raiseError("When there's more than one error, you must specify the errror to fix."); |
| 2057 | + } |
| 2058 | + |
| 2059 | + const diagnostic = !errorCode ? diagnostics[0] : ts.find(diagnostics, d => d.code == errorCode); |
| 2060 | + |
| 2061 | + return this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.length, [diagnostic.code]); |
| 2062 | + } |
| 2063 | + |
| 2064 | + public verifyCodeFixAtPosition(expectedText: string, errorCode?: number) { |
| 2065 | + const ranges = this.getRanges(); |
| 2066 | + if (ranges.length == 0) { |
| 2067 | + this.raiseError("At least one range should be specified in the testfile."); |
| 2068 | + } |
| 2069 | + |
| 2070 | + const actual = this.getCodeFixes(errorCode); |
| 2071 | + |
| 2072 | + if (!actual || actual.length == 0) { |
| 2073 | + this.raiseError("No codefixes returned."); |
| 2074 | + } |
| 2075 | + |
| 2076 | + if (actual.length > 1) { |
| 2077 | + this.raiseError("More than 1 codefix returned."); |
| 2078 | + } |
| 2079 | + |
| 2080 | + this.applyEdits(actual[0].changes[0].fileName, actual[0].changes[0].textChanges, /*isFormattingEdit*/ false); |
| 2081 | + const actualText = this.rangeText(ranges[0]); |
| 2082 | + |
| 2083 | + if (this.removeWhitespace(actualText) !== this.removeWhitespace(expectedText)) { |
| 2084 | + this.raiseError(`Actual text doesn't match expected text. Actual: '${actualText}' Expected: '${expectedText}'`); |
| 2085 | + } |
| 2086 | + } |
| 2087 | + |
2044 | 2088 | public verifyDocCommentTemplate(expected?: ts.TextInsertion) { |
2045 | 2089 | const name = "verifyDocCommentTemplate"; |
2046 | 2090 | const actual = this.languageService.getDocCommentTemplateAtPosition(this.activeFile.fileName, this.currentCaretPosition); |
@@ -2312,6 +2356,18 @@ namespace FourSlash { |
2312 | 2356 | } |
2313 | 2357 | } |
2314 | 2358 |
|
| 2359 | + public verifyCodeFixAvailable(negative: boolean, errorCode?: number) { |
| 2360 | + const fixes = this.getCodeFixes(errorCode); |
| 2361 | + |
| 2362 | + if (negative && fixes && fixes.length > 0) { |
| 2363 | + this.raiseError(`verifyCodeFixAvailable failed - expected no fixes, actual: ${fixes.length}`); |
| 2364 | + } |
| 2365 | + |
| 2366 | + if (!negative && (fixes === undefined || fixes.length === 0)) { |
| 2367 | + this.raiseError(`verifyCodeFixAvailable failed - expected code fixes, actual: 0`); |
| 2368 | + } |
| 2369 | + } |
| 2370 | + |
2315 | 2371 | // Get the text of the entire line the caret is currently at |
2316 | 2372 | private getCurrentLineContent() { |
2317 | 2373 | const text = this.getFileContent(this.activeFile.fileName); |
@@ -3099,6 +3155,10 @@ namespace FourSlashInterface { |
3099 | 3155 | public isValidBraceCompletionAtPosition(openingBrace: string) { |
3100 | 3156 | this.state.verifyBraceCompletionAtPosition(this.negative, openingBrace); |
3101 | 3157 | } |
| 3158 | + |
| 3159 | + public codeFixAvailable(errorCode?: number) { |
| 3160 | + this.state.verifyCodeFixAvailable(this.negative, errorCode); |
| 3161 | + } |
3102 | 3162 | } |
3103 | 3163 |
|
3104 | 3164 | export class Verify extends VerifyNegatable { |
@@ -3278,6 +3338,10 @@ namespace FourSlashInterface { |
3278 | 3338 | this.DocCommentTemplate(/*expectedText*/ undefined, /*expectedOffset*/ undefined, /*empty*/ true); |
3279 | 3339 | } |
3280 | 3340 |
|
| 3341 | + public codeFixAtPosition(expectedText: string, errorCode?: number): void { |
| 3342 | + this.state.verifyCodeFixAtPosition(expectedText, errorCode); |
| 3343 | + } |
| 3344 | + |
3281 | 3345 | public navigationBar(json: any) { |
3282 | 3346 | this.state.verifyNavigationBar(json); |
3283 | 3347 | } |
|
0 commit comments