|
18 | 18 | * |
19 | 19 | */ |
20 | 20 |
|
21 | | -/*global describe, it, expect, beforeAll, afterAll, afterEach, awaitsFor, awaitsForDone, path, jsPromise */ |
| 21 | +/*global describe, it, expect, beforeAll, afterAll, beforeEach, afterEach, awaitsFor, awaitsForDone, path, jsPromise */ |
22 | 22 |
|
23 | 23 | define(function (require, exports, module) { |
24 | 24 |
|
@@ -864,5 +864,87 @@ define(function (require, exports, module) { |
864 | 864 | }, "parameter hint popup to show again", 30000); |
865 | 865 | }, 90000); |
866 | 866 | }); |
| 867 | + |
| 868 | + // ----- hint-severity diagnostics: untagged suggestions dropped, tagged ones styled ----- |
| 869 | + describe("hint diagnostics and tags", function () { |
| 870 | + let publishedByFile; |
| 871 | + let origSetInspectionResults; |
| 872 | + |
| 873 | + beforeAll(function () { |
| 874 | + // Capture what actually reaches the linting layer (post the LSPClient hint filter) |
| 875 | + // so the specs can await/assert on publishes deterministically instead of relying |
| 876 | + // only on problems-panel text. |
| 877 | + const DefaultProviders = testWindow.require("languageTools/DefaultProviders"); |
| 878 | + const proto = DefaultProviders.LintingProvider.prototype; |
| 879 | + publishedByFile = {}; |
| 880 | + origSetInspectionResults = proto.setInspectionResults; |
| 881 | + proto.setInspectionResults = function (msgObj) { |
| 882 | + const name = msgObj.uri.substring(msgObj.uri.lastIndexOf("/") + 1); |
| 883 | + publishedByFile[name] = publishedByFile[name] || []; |
| 884 | + publishedByFile[name].push(msgObj.diagnostics || []); |
| 885 | + return origSetInspectionResults.call(this, msgObj); |
| 886 | + }; |
| 887 | + }); |
| 888 | + |
| 889 | + afterAll(function () { |
| 890 | + const DefaultProviders = testWindow.require("languageTools/DefaultProviders"); |
| 891 | + DefaultProviders.LintingProvider.prototype.setInspectionResults = origSetInspectionResults; |
| 892 | + }); |
| 893 | + |
| 894 | + beforeEach(async function () { |
| 895 | + // Isolate from whatever earlier specs left behind (dirty documents, an open |
| 896 | + // parameter-hint popup, stale panel state). |
| 897 | + await awaitsForDone(CommandManager.execute(Commands.FILE_CLOSE_ALL, { _forceClose: true }), |
| 898 | + "close all files"); |
| 899 | + }); |
| 900 | + |
| 901 | + it("should keep tagged hints (unused/deprecated) in the panel and style the text", async function () { |
| 902 | + await _openInProject("ts/", "type-error.ts"); |
| 903 | + const editor = EditorManager.getActiveEditor(); |
| 904 | + editor.document.setText( |
| 905 | + "const unusedVar: number = 1;\n" + |
| 906 | + "/** @deprecated use newFn */\n" + |
| 907 | + "function oldFn(): number { return 1; }\n" + |
| 908 | + "oldFn();\n" + |
| 909 | + "export {};\n" |
| 910 | + ); |
| 911 | + // tagged hints (unused tag 1, deprecated tag 2) must survive the hint filter |
| 912 | + await awaitsFor(function () { |
| 913 | + const all = (publishedByFile["type-error.ts"] || []).flat(); |
| 914 | + return all.some(function (d) { return d.tags && d.tags.indexOf(1) !== -1; }) && |
| 915 | + all.some(function (d) { return d.tags && d.tags.indexOf(2) !== -1; }); |
| 916 | + }, "tagged unused + deprecated diagnostics to be published", 30000); |
| 917 | + await awaitsFor(function () { |
| 918 | + return panelText().includes("never read") && panelText().includes("deprecated"); |
| 919 | + }, "unused + deprecated hint rows in the problems panel", 30000); |
| 920 | + // the marked text carries the tag styles on top of the info squiggle |
| 921 | + await awaitsFor(function () { |
| 922 | + return $(".editor-text-fragment-unnecessary").length > 0 && |
| 923 | + $(".editor-text-fragment-deprecated").length > 0; |
| 924 | + }, "faded + strikethrough text marks in the editor", 30000); |
| 925 | + }, 90000); |
| 926 | + |
| 927 | + it("should drop untagged hint suggestions like the CommonJS to ESM nag", async function () { |
| 928 | + await _openInProject("js-plain/", "implicit.js"); |
| 929 | + const editor = EditorManager.getActiveEditor(); |
| 930 | + const publishesBeforeEdit = (publishedByFile["implicit.js"] || []).length; |
| 931 | + // "require(" is concatenated so RequireJS's static dependency scan of this module's |
| 932 | + // source doesn't read the string literal as an AMD dependency named "http" - that |
| 933 | + // fails the whole file's load and silently unregisters every suite in it. |
| 934 | + const requireCall = "require"; |
| 935 | + editor.document.setText("const http = " + requireCall + "('http');\nconsole.log(http);\n"); |
| 936 | + // the server re-publishes (possibly empty) diagnostics after the edit - wait for |
| 937 | + // one, then assert the untagged 80001 CommonJS suggestion never came through |
| 938 | + await awaitsFor(function () { |
| 939 | + return (publishedByFile["implicit.js"] || []).length > publishesBeforeEdit; |
| 940 | + }, "a diagnostics publish for implicit.js after the edit", 30000); |
| 941 | + const all = (publishedByFile["implicit.js"] || []).flat(); |
| 942 | + expect(all.some(function (d) { return d.message.indexOf("CommonJS") !== -1; })).toBe(false); |
| 943 | + expect(all.some(function (d) { |
| 944 | + return d.severity === 4 && !(d.tags && d.tags.length); |
| 945 | + })).toBe(false); |
| 946 | + expect(panelText().includes("CommonJS")).toBe(false); |
| 947 | + }, 90000); |
| 948 | + }); |
867 | 949 | }); |
868 | 950 | }); |
0 commit comments