From 7a7092de0d68940bc8260627a811d362e9361eaf Mon Sep 17 00:00:00 2001 From: Koen Vlaswinkel Date: Thu, 21 Dec 2023 17:02:31 +0100 Subject: [PATCH] Add eslint-plugin-import It seems like we had some rules that disabled rules of this plugin, but we didn't actually have it installed. I've now installed it, used the recommended configuration, and removed our own disable rules. I've fixed any errors that this introduced. --- extensions/ql-vscode/.eslintrc.js | 24 ++++--- .../vscode-theme-addon/withTheme.ts | 12 ++-- .../ql-vscode/gulpfile.ts/appInsights.ts | 2 +- .../ql-vscode/gulpfile.ts/typescript.ts | 6 +- extensions/ql-vscode/gulpfile.ts/webpack.ts | 6 +- extensions/ql-vscode/jest.config.js | 1 + extensions/ql-vscode/package-lock.json | 62 ++++++++++++++++--- extensions/ql-vscode/package.json | 2 + .../ql-vscode/src/common/vscode/telemetry.ts | 1 + extensions/ql-vscode/src/query-results.ts | 6 +- extensions/ql-vscode/src/view/webview.tsx | 2 +- .../variant-analysis-manager.test.ts | 53 +++++++++------- .../variant-analysis-results-manager.test.ts | 32 +++++----- .../test/vscode-tests/global.helper.ts | 1 + .../local-queries/local-databases.test.ts | 42 ++++++------- .../test/vscode-tests/test-config.ts | 1 + 16 files changed, 160 insertions(+), 93 deletions(-) diff --git a/extensions/ql-vscode/.eslintrc.js b/extensions/ql-vscode/.eslintrc.js index 976186c39..afa504d4d 100644 --- a/extensions/ql-vscode/.eslintrc.js +++ b/extensions/ql-vscode/.eslintrc.js @@ -27,6 +27,8 @@ const baseConfig = { "plugin:jest-dom/recommended", "plugin:prettier/recommended", "plugin:@typescript-eslint/recommended", + "plugin:import/recommended", + "plugin:import/typescript", ], rules: { "@typescript-eslint/await-thenable": "error", @@ -57,15 +59,6 @@ const baseConfig = { "filenames/match-regexp": "off", "func-style": "off", "i18n-text/no-en": "off", - "import/named": "off", - "import/no-dynamic-require": "off", - "import/no-dynamic-required": "off", - "import/no-anonymous-default-export": "off", - "import/no-commonjs": "off", - "import/no-mutable-exports": "off", - "import/no-namespace": "off", - "import/no-unresolved": "off", - "import/no-webpack-loader-syntax": "off", "no-invalid-this": "off", "no-fallthrough": "off", "no-console": "off", @@ -73,6 +66,19 @@ const baseConfig = { "github/array-foreach": "off", "github/no-then": "off", "react/jsx-key": ["error", { checkFragmentShorthand: true }], + "import/no-cycle": "off", + "import/no-namespace": "off", + // Never allow extensions in import paths, except for JSON files where they are required. + "import/extensions": ["error", "never", { json: "always" }], + }, + settings: { + "import/resolver": { + typescript: true, + node: true, + }, + "import/extensions": [".js", ".jsx", ".ts", ".tsx", ".json"], + // vscode and sarif don't exist on-disk, but only provide types. + "import/core-modules": ["vscode", "sarif"], }, }; diff --git a/extensions/ql-vscode/.storybook/vscode-theme-addon/withTheme.ts b/extensions/ql-vscode/.storybook/vscode-theme-addon/withTheme.ts index 73f960ae4..0e388cedd 100644 --- a/extensions/ql-vscode/.storybook/vscode-theme-addon/withTheme.ts +++ b/extensions/ql-vscode/.storybook/vscode-theme-addon/withTheme.ts @@ -8,27 +8,27 @@ import { VSCodeTheme } from "./theme"; const themeFiles: { [key in VSCodeTheme]: string } = { [VSCodeTheme.Dark]: - // eslint-disable-next-line @typescript-eslint/no-var-requires + // eslint-disable-next-line @typescript-eslint/no-var-requires,import/no-commonjs,import/no-webpack-loader-syntax require("!file-loader?modules!../../src/stories/vscode-theme-dark.css") .default, [VSCodeTheme.Light]: - // eslint-disable-next-line @typescript-eslint/no-var-requires + // eslint-disable-next-line @typescript-eslint/no-var-requires,import/no-commonjs,import/no-webpack-loader-syntax require("!file-loader?modules!../../src/stories/vscode-theme-light.css") .default, [VSCodeTheme.LightHighContrast]: - // eslint-disable-next-line @typescript-eslint/no-var-requires + // eslint-disable-next-line @typescript-eslint/no-var-requires,import/no-commonjs,import/no-webpack-loader-syntax require("!file-loader?modules!../../src/stories/vscode-theme-light-high-contrast.css") .default, [VSCodeTheme.DarkHighContrast]: - // eslint-disable-next-line @typescript-eslint/no-var-requires + // eslint-disable-next-line @typescript-eslint/no-var-requires,import/no-commonjs,import/no-webpack-loader-syntax require("!file-loader?modules!../../src/stories/vscode-theme-dark-high-contrast.css") .default, [VSCodeTheme.GitHubLightDefault]: - // eslint-disable-next-line @typescript-eslint/no-var-requires + // eslint-disable-next-line @typescript-eslint/no-var-requires,import/no-commonjs,import/no-webpack-loader-syntax require("!file-loader?modules!../../src/stories/vscode-theme-github-light-default.css") .default, [VSCodeTheme.GitHubDarkDefault]: - // eslint-disable-next-line @typescript-eslint/no-var-requires + // eslint-disable-next-line @typescript-eslint/no-var-requires,import/no-commonjs,import/no-webpack-loader-syntax require("!file-loader?modules!../../src/stories/vscode-theme-github-dark-default.css") .default, }; diff --git a/extensions/ql-vscode/gulpfile.ts/appInsights.ts b/extensions/ql-vscode/gulpfile.ts/appInsights.ts index 9faf27193..8e96f2866 100644 --- a/extensions/ql-vscode/gulpfile.ts/appInsights.ts +++ b/extensions/ql-vscode/gulpfile.ts/appInsights.ts @@ -1,5 +1,5 @@ import { src, dest } from "gulp"; -// eslint-disable-next-line @typescript-eslint/no-var-requires +// eslint-disable-next-line @typescript-eslint/no-var-requires,import/no-commonjs const replace = require("gulp-replace"); /** Inject the application insights key into the telemetry file */ diff --git a/extensions/ql-vscode/gulpfile.ts/typescript.ts b/extensions/ql-vscode/gulpfile.ts/typescript.ts index 0f02de6a7..3fce050de 100644 --- a/extensions/ql-vscode/gulpfile.ts/typescript.ts +++ b/extensions/ql-vscode/gulpfile.ts/typescript.ts @@ -1,10 +1,10 @@ import { gray, red } from "ansi-colors"; import { dest, src, watch } from "gulp"; import esbuild from "gulp-esbuild"; -import ts from "gulp-typescript"; +import { createProject, reporter } from "gulp-typescript"; import del from "del"; -function goodReporter(): ts.reporter.Reporter { +function goodReporter(): reporter.Reporter { return { error: (error, typescript) => { if (error.tsFile) { @@ -27,7 +27,7 @@ function goodReporter(): ts.reporter.Reporter { }; } -const tsProject = ts.createProject("tsconfig.json"); +const tsProject = createProject("tsconfig.json"); export function cleanOutput() { return tsProject.projectDirectory diff --git a/extensions/ql-vscode/gulpfile.ts/webpack.ts b/extensions/ql-vscode/gulpfile.ts/webpack.ts index 62045334f..f99995241 100644 --- a/extensions/ql-vscode/gulpfile.ts/webpack.ts +++ b/extensions/ql-vscode/gulpfile.ts/webpack.ts @@ -1,4 +1,4 @@ -import webpack from "webpack"; +import { Configuration, Stats, webpack } from "webpack"; import { config } from "./webpack.config"; export function compileView(cb: (err?: Error) => void) { @@ -18,11 +18,11 @@ export function watchView(cb: (err?: Error) => void) { } function doWebpack( - internalConfig: webpack.Configuration, + internalConfig: Configuration, failOnError: boolean, cb: (err?: Error) => void, ) { - const resultCb = (error: Error | undefined, stats?: webpack.Stats) => { + const resultCb = (error: Error | undefined, stats?: Stats) => { if (error) { cb(error); } diff --git a/extensions/ql-vscode/jest.config.js b/extensions/ql-vscode/jest.config.js index f06906060..ac57b8e7a 100644 --- a/extensions/ql-vscode/jest.config.js +++ b/extensions/ql-vscode/jest.config.js @@ -4,6 +4,7 @@ */ /** @type {import('@jest/types').Config.InitialOptions} */ +// eslint-disable-next-line import/no-commonjs module.exports = { projects: [ "/src/view", diff --git a/extensions/ql-vscode/package-lock.json b/extensions/ql-vscode/package-lock.json index dc8efeeea..32c20be99 100644 --- a/extensions/ql-vscode/package-lock.json +++ b/extensions/ql-vscode/package-lock.json @@ -108,8 +108,10 @@ "del": "^6.0.0", "eslint": "^8.56.0", "eslint-config-prettier": "^9.0.0", + "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-etc": "^2.0.2", "eslint-plugin-github": "^4.4.1", + "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest-dom": "^5.0.1", "eslint-plugin-prettier": "^5.0.0", "eslint-plugin-react": "^7.31.8", @@ -14981,6 +14983,31 @@ "ms": "^2.1.1" } }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" + } + }, "node_modules/eslint-module-utils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", @@ -15121,9 +15148,9 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz", - "integrity": "sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==", + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dev": true, "dependencies": { "array-includes": "^3.1.7", @@ -15142,7 +15169,7 @@ "object.groupby": "^1.0.1", "object.values": "^1.1.7", "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" + "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" @@ -17319,6 +17346,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-tsconfig": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", + "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -27594,6 +27633,15 @@ "node": ">= 0.10" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -30148,9 +30196,9 @@ } }, "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "dependencies": { "@types/json5": "^0.0.29", diff --git a/extensions/ql-vscode/package.json b/extensions/ql-vscode/package.json index 73634edac..7de87ee9b 100644 --- a/extensions/ql-vscode/package.json +++ b/extensions/ql-vscode/package.json @@ -2005,8 +2005,10 @@ "del": "^6.0.0", "eslint": "^8.56.0", "eslint-config-prettier": "^9.0.0", + "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-etc": "^2.0.2", "eslint-plugin-github": "^4.4.1", + "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest-dom": "^5.0.1", "eslint-plugin-prettier": "^5.0.0", "eslint-plugin-react": "^7.31.8", diff --git a/extensions/ql-vscode/src/common/vscode/telemetry.ts b/extensions/ql-vscode/src/common/vscode/telemetry.ts index 868d3dc3e..6f8c918db 100644 --- a/extensions/ql-vscode/src/common/vscode/telemetry.ts +++ b/extensions/ql-vscode/src/common/vscode/telemetry.ts @@ -275,6 +275,7 @@ export class ExtensionTelemetryListener /** * The global Telemetry instance */ +// eslint-disable-next-line import/no-mutable-exports export let telemetryListener: ExtensionTelemetryListener | undefined; export async function initializeTelemetry( diff --git a/extensions/ql-vscode/src/query-results.ts b/extensions/ql-vscode/src/query-results.ts index 2939052cf..983a84653 100644 --- a/extensions/ql-vscode/src/query-results.ts +++ b/extensions/ql-vscode/src/query-results.ts @@ -164,18 +164,18 @@ export async function interpretResultsSarif( * Call cli command to interpret graph results. */ export async function interpretGraphResults( - cli: cli.CodeQLCliServer, + cliServer: cli.CodeQLCliServer, metadata: QueryMetadata | undefined, resultsPaths: ResultsPaths, sourceInfo?: cli.SourceInfo, ): Promise { const { resultsPath, interpretedResultsPath } = resultsPaths; if (await pathExists(interpretedResultsPath)) { - const dot = await cli.readDotFiles(interpretedResultsPath); + const dot = await cliServer.readDotFiles(interpretedResultsPath); return { dot, t: "GraphInterpretationData" }; } - const dot = await cli.interpretBqrsGraph( + const dot = await cliServer.interpretBqrsGraph( ensureMetadataIsComplete(metadata), resultsPath, interpretedResultsPath, diff --git a/extensions/ql-vscode/src/view/webview.tsx b/extensions/ql-vscode/src/view/webview.tsx index 9207975d9..acac0fb37 100644 --- a/extensions/ql-vscode/src/view/webview.tsx +++ b/extensions/ql-vscode/src/view/webview.tsx @@ -27,7 +27,7 @@ const render = () => { // It's a lot harder to use dynamic imports since those don't import the CSS // and require a less strict CSP policy - // eslint-disable-next-line @typescript-eslint/no-var-requires + // eslint-disable-next-line @typescript-eslint/no-var-requires,import/no-dynamic-require const view: WebviewDefinition = require(`./${viewName}/index.tsx`).default; const root = createRoot(element); diff --git a/extensions/ql-vscode/test/vscode-tests/activated-extension/variant-analysis/variant-analysis-manager.test.ts b/extensions/ql-vscode/test/vscode-tests/activated-extension/variant-analysis/variant-analysis-manager.test.ts index 7f5e461f8..d1ae98ad1 100644 --- a/extensions/ql-vscode/test/vscode-tests/activated-extension/variant-analysis/variant-analysis-manager.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/activated-extension/variant-analysis/variant-analysis-manager.test.ts @@ -10,7 +10,14 @@ import { import { extLogger } from "../../../../src/common/logging/vscode"; import * as ghApiClient from "../../../../src/variant-analysis/gh-api/gh-api-client"; import * as ghActionsApiClient from "../../../../src/variant-analysis/gh-api/gh-actions-api-client"; -import * as fs from "fs-extra"; +import { + ensureDir, + outputJson, + pathExists, + readFile, + readJson, + remove, +} from "fs-extra"; import { join } from "path"; import { Readable } from "stream"; import * as fetchModule from "node-fetch"; @@ -100,7 +107,7 @@ describe("Variant Analysis Manager", () => { describe("when the directory exists", () => { beforeEach(async () => { - await fs.ensureDir(join(storagePath, variantAnalysis.id.toString())); + await ensureDir(join(storagePath, variantAnalysis.id.toString())); }); it("should store the variant analysis", async () => { @@ -216,7 +223,7 @@ describe("Variant Analysis Manager", () => { __dirname, "data/variant-analysis-results.zip", ); - const fileContents = fs.readFileSync(sourceFilePath); + const fileContents = await readFile(sourceFilePath); const response = new Response(Readable.from(fileContents)); response.size = fileContents.length; getVariantAnalysisRepoResultStub.mockResolvedValue(response); @@ -263,7 +270,7 @@ describe("Variant Analysis Manager", () => { variantAnalysis, ); - await expect(fs.readJson(repoStatesPath)).resolves.toEqual({ + await expect(readJson(repoStatesPath)).resolves.toEqual({ [scannedRepos[0].repository.id]: { repositoryId: scannedRepos[0].repository.id, downloadStatus: @@ -284,7 +291,7 @@ describe("Variant Analysis Manager", () => { ), ).rejects.toThrow(); - await expect(fs.pathExists(repoStatesPath)).resolves.toBe(false); + await expect(pathExists(repoStatesPath)).resolves.toBe(false); }); it("should have a failed repo state when the repo task API fails", async () => { @@ -299,14 +306,14 @@ describe("Variant Analysis Manager", () => { ), ).rejects.toThrow(); - await expect(fs.pathExists(repoStatesPath)).resolves.toBe(false); + await expect(pathExists(repoStatesPath)).resolves.toBe(false); await variantAnalysisManager.autoDownloadVariantAnalysisResult( scannedRepos[1], variantAnalysis, ); - await expect(fs.readJson(repoStatesPath)).resolves.toEqual({ + await expect(readJson(repoStatesPath)).resolves.toEqual({ [scannedRepos[0].repository.id]: { repositoryId: scannedRepos[0].repository.id, downloadStatus: @@ -332,14 +339,14 @@ describe("Variant Analysis Manager", () => { ), ).rejects.toThrow(); - await expect(fs.pathExists(repoStatesPath)).resolves.toBe(false); + await expect(pathExists(repoStatesPath)).resolves.toBe(false); await variantAnalysisManager.autoDownloadVariantAnalysisResult( scannedRepos[1], variantAnalysis, ); - await expect(fs.readJson(repoStatesPath)).resolves.toEqual({ + await expect(readJson(repoStatesPath)).resolves.toEqual({ [scannedRepos[0].repository.id]: { repositoryId: scannedRepos[0].repository.id, downloadStatus: @@ -374,7 +381,7 @@ describe("Variant Analysis Manager", () => { variantAnalysis, ); - await expect(fs.readJson(repoStatesPath)).resolves.toEqual({ + await expect(readJson(repoStatesPath)).resolves.toEqual({ [scannedRepos[1].repository.id]: { repositoryId: scannedRepos[1].repository.id, downloadStatus: @@ -396,7 +403,7 @@ describe("Variant Analysis Manager", () => { async function mockRepoStates( repoStates: Record, ) { - await fs.outputJson(repoStatesPath, repoStates); + await outputJson(repoStatesPath, repoStates); } }); }); @@ -440,7 +447,7 @@ describe("Variant Analysis Manager", () => { }); it("should remove variant analysis", async () => { - await fs.ensureDir(join(storagePath, dummyVariantAnalysis.id.toString())); + await ensureDir(join(storagePath, dummyVariantAnalysis.id.toString())); await variantAnalysisManager.rehydrateVariantAnalysis( dummyVariantAnalysis, @@ -453,7 +460,7 @@ describe("Variant Analysis Manager", () => { expect(variantAnalysisManager.variantAnalysesSize).toBe(0); await expect( - fs.pathExists(join(storagePath, dummyVariantAnalysis.id.toString())), + pathExists(join(storagePath, dummyVariantAnalysis.id.toString())), ).resolves.toBe(false); }); }); @@ -498,8 +505,8 @@ describe("Variant Analysis Manager", () => { await createTimestampFile(variantAnalysisStorageLocation); }); - afterEach(() => { - fs.rmSync(variantAnalysisStorageLocation, { recursive: true }); + afterEach(async () => { + await remove(variantAnalysisStorageLocation); }); describe("when the variant analysis is not complete", () => { @@ -574,8 +581,8 @@ describe("Variant Analysis Manager", () => { await variantAnalysisManager.rehydrateVariantAnalysis(variantAnalysis); }); - afterEach(() => { - fs.rmSync(variantAnalysisStorageLocation, { recursive: true }); + afterEach(async () => { + await remove(variantAnalysisStorageLocation); }); it("should return early if the variant analysis is not found", async () => { @@ -637,8 +644,8 @@ describe("Variant Analysis Manager", () => { }); }); - afterEach(() => { - fs.rmSync(variantAnalysisStorageLocation, { recursive: true }); + afterEach(async () => { + await remove(variantAnalysisStorageLocation); }); describe("when the variant analysis does not have any repositories", () => { @@ -813,8 +820,8 @@ describe("Variant Analysis Manager", () => { .mockResolvedValue(mockedObject({})); }); - afterEach(() => { - fs.rmSync(variantAnalysisStorageLocation, { recursive: true }); + afterEach(async () => { + await remove(variantAnalysisStorageLocation); }); it("opens the query text", async () => { @@ -861,8 +868,8 @@ describe("Variant Analysis Manager", () => { .mockResolvedValue(mockedObject({})); }); - afterEach(() => { - fs.rmSync(variantAnalysisStorageLocation, { recursive: true }); + afterEach(async () => { + await remove(variantAnalysisStorageLocation); }); it("opens the query file", async () => { diff --git a/extensions/ql-vscode/test/vscode-tests/activated-extension/variant-analysis/variant-analysis-results-manager.test.ts b/extensions/ql-vscode/test/vscode-tests/activated-extension/variant-analysis/variant-analysis-results-manager.test.ts index 223753577..ab148b48e 100644 --- a/extensions/ql-vscode/test/vscode-tests/activated-extension/variant-analysis/variant-analysis-results-manager.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/activated-extension/variant-analysis/variant-analysis-results-manager.test.ts @@ -1,5 +1,5 @@ import { extLogger } from "../../../../src/common/logging/vscode"; -import * as fs from "fs-extra"; +import { readFile, pathExists, remove, outputJson, readJson } from "fs-extra"; import { join, resolve } from "path"; import { Readable } from "stream"; import * as fetchModule from "node-fetch"; @@ -54,8 +54,8 @@ describe(VariantAnalysisResultsManager.name, () => { }); afterEach(async () => { - if (await fs.pathExists(variantAnalysisStoragePath)) { - await fs.remove(variantAnalysisStoragePath); + if (await pathExists(variantAnalysisStoragePath)) { + await remove(variantAnalysisStoragePath); } }); @@ -97,7 +97,7 @@ describe(VariantAnalysisResultsManager.name, () => { __dirname, "data/variant-analysis-results.zip", ); - fileContents = fs.readFileSync(sourceFilePath); + fileContents = await readFile(sourceFilePath); getVariantAnalysisRepoResultStub = jest .spyOn(fetchModule, "default") @@ -128,9 +128,9 @@ describe(VariantAnalysisResultsManager.name, () => { () => Promise.resolve(), ); - expect(fs.existsSync(`${repoTaskStorageDirectory}/results.zip`)).toBe( - true, - ); + expect( + await pathExists(`${repoTaskStorageDirectory}/results.zip`), + ).toBe(true); }); it("should unzip the results in a `results/` folder", async () => { @@ -142,7 +142,7 @@ describe(VariantAnalysisResultsManager.name, () => { ); expect( - fs.existsSync(`${repoTaskStorageDirectory}/results/results.sarif`), + await pathExists(`${repoTaskStorageDirectory}/results/results.sarif`), ).toBe(true); }); @@ -237,8 +237,8 @@ describe(VariantAnalysisResultsManager.name, () => { }); afterEach(async () => { - if (await fs.pathExists(variantAnalysisStoragePath)) { - await fs.remove(variantAnalysisStoragePath); + if (await pathExists(variantAnalysisStoragePath)) { + await remove(variantAnalysisStoragePath); } }); @@ -256,7 +256,7 @@ describe(VariantAnalysisResultsManager.name, () => { describe("when the repo task has been written to disk", () => { beforeEach(async () => { - await fs.outputJson( + await outputJson( join(repoTaskStorageDirectory, "repo_task.json"), dummyRepoTask, ); @@ -276,9 +276,9 @@ describe(VariantAnalysisResultsManager.name, () => { describe("when the SARIF results are downloaded", () => { beforeEach(async () => { - await fs.outputJson( + await outputJson( join(repoTaskStorageDirectory, "results/results.sarif"), - await fs.readJson( + await readJson( resolve(__dirname, "../../../data/sarif/validSarif.sarif"), ), ); @@ -313,7 +313,7 @@ describe(VariantAnalysisResultsManager.name, () => { onResultLoadedSpy.mockClear(); // Delete the directory so it can't read from disk - await fs.remove(variantAnalysisStoragePath); + await remove(variantAnalysisStoragePath); await expect( variantAnalysisResultsManager.loadResults( @@ -343,7 +343,7 @@ describe(VariantAnalysisResultsManager.name, () => { ); // Delete the directory so it can't read from disk - await fs.remove(variantAnalysisStoragePath); + await remove(variantAnalysisStoragePath); await expect( variantAnalysisResultsManager.loadResults( @@ -365,7 +365,7 @@ describe(VariantAnalysisResultsManager.name, () => { ); // Delete the directory so it can't read from disk - await fs.remove(variantAnalysisStoragePath); + await remove(variantAnalysisStoragePath); await expect( variantAnalysisResultsManager.loadResults( diff --git a/extensions/ql-vscode/test/vscode-tests/global.helper.ts b/extensions/ql-vscode/test/vscode-tests/global.helper.ts index de2cc81e5..a84d8b368 100644 --- a/extensions/ql-vscode/test/vscode-tests/global.helper.ts +++ b/extensions/ql-vscode/test/vscode-tests/global.helper.ts @@ -21,6 +21,7 @@ export const dbLoc = join( realpathSync(join(__dirname, "../../../")), "build/tests/db.zip", ); +// eslint-disable-next-line import/no-mutable-exports export let storagePath: string; /** diff --git a/extensions/ql-vscode/test/vscode-tests/minimal-workspace/local-queries/local-databases.test.ts b/extensions/ql-vscode/test/vscode-tests/minimal-workspace/local-queries/local-databases.test.ts index 954d9f3fa..a889e95e4 100644 --- a/extensions/ql-vscode/test/vscode-tests/minimal-workspace/local-queries/local-databases.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/minimal-workspace/local-queries/local-databases.test.ts @@ -1,5 +1,5 @@ import * as tmp from "tmp"; -import * as fs from "fs-extra"; +import { ensureDir, ensureFile, pathExists, writeFile } from "fs-extra"; import { join } from "path"; import { ExtensionContext, Uri, workspace } from "vscode"; @@ -216,7 +216,7 @@ describe("local databases", () => { it("should remove a database item", async () => { const mockDbItem = createMockDB(dir); - await fs.ensureDir(mockDbItem.databaseUri.fsPath); + await ensureDir(mockDbItem.databaseUri.fsPath); // pretend that this item is the first workspace folder in the list jest @@ -235,14 +235,14 @@ describe("local databases", () => { expect(workspace.updateWorkspaceFolders).toBeCalledWith(0, 1); // should also delete the db contents - await expect(fs.pathExists(mockDbItem.databaseUri.fsPath)).resolves.toBe( + await expect(pathExists(mockDbItem.databaseUri.fsPath)).resolves.toBe( false, ); }); it("should remove a database item outside of the extension controlled area", async () => { const mockDbItem = createMockDB(dir); - await fs.ensureDir(mockDbItem.databaseUri.fsPath); + await ensureDir(mockDbItem.databaseUri.fsPath); // pretend that this item is the first workspace folder in the list jest @@ -263,7 +263,7 @@ describe("local databases", () => { expect(workspace.updateWorkspaceFolders).toBeCalledWith(0, 1); // should NOT delete the db contents - await expect(fs.pathExists(mockDbItem.databaseUri.fsPath)).resolves.toBe( + await expect(pathExists(mockDbItem.databaseUri.fsPath)).resolves.toBe( true, ); }); @@ -432,11 +432,11 @@ describe("local databases", () => { beforeEach(async () => { directoryPath = join(dir.name, "dir"); - await fs.ensureDir(directoryPath); + await ensureDir(directoryPath); projectPath = join(directoryPath, "dir.testproj"); - await fs.writeFile(projectPath, ""); + await writeFile(projectPath, ""); qlFilePath = join(directoryPath, "test.ql"); - await fs.writeFile(qlFilePath, ""); + await writeFile(qlFilePath, ""); }); it("should return true for testproj database in test directory", async () => { @@ -463,7 +463,7 @@ describe("local databases", () => { it("should return false for non-testproj database in test directory", async () => { const anotherProjectPath = join(directoryPath, "dir.proj"); - await fs.writeFile(anotherProjectPath, ""); + await writeFile(anotherProjectPath, ""); const db = createMockDB( dir, @@ -476,9 +476,9 @@ describe("local databases", () => { it("should return false for testproj database outside test directory", async () => { const anotherProjectDir = join(dir.name, "other"); - await fs.ensureDir(anotherProjectDir); + await ensureDir(anotherProjectDir); const anotherProjectPath = join(anotherProjectDir, "other.testproj"); - await fs.writeFile(anotherProjectPath, ""); + await writeFile(anotherProjectPath, ""); const db = createMockDB( dir, @@ -524,7 +524,7 @@ describe("local databases", () => { it("should return false for non-testproj database for test file", async () => { const anotherProjectPath = join(directoryPath, "dir.proj"); - await fs.writeFile(anotherProjectPath, ""); + await writeFile(anotherProjectPath, ""); const db = createMockDB( dir, @@ -537,7 +537,7 @@ describe("local databases", () => { it("should return false for testproj database not matching test file", async () => { const otherTestFile = join(dir.name, "test.ql"); - await fs.writeFile(otherTestFile, ""); + await writeFile(otherTestFile, ""); const db = createMockDB( dir, @@ -553,24 +553,24 @@ describe("local databases", () => { ["src", "output/src_archive"].forEach((name) => { it(`should find source folder in ${name}`, async () => { const uri = Uri.file(join(dir.name, name)); - fs.createFileSync(join(uri.fsPath, "hucairz.txt")); + await ensureFile(join(uri.fsPath, "hucairz.txt")); const srcUri = await findSourceArchive(dir.name); expect(srcUri!.fsPath).toBe(uri.fsPath); }); it(`should find source archive in ${name}.zip`, async () => { const uri = Uri.file(join(dir.name, `${name}.zip`)); - fs.createFileSync(uri.fsPath); + await ensureFile(uri.fsPath); const srcUri = await findSourceArchive(dir.name); expect(srcUri!.fsPath).toBe(uri.fsPath); }); it(`should prioritize ${name}.zip over ${name}`, async () => { const uri = Uri.file(join(dir.name, `${name}.zip`)); - fs.createFileSync(uri.fsPath); + await ensureFile(uri.fsPath); const uriFolder = Uri.file(join(dir.name, name)); - fs.createFileSync(join(uriFolder.fsPath, "hucairz.txt")); + await ensureFile(join(uriFolder.fsPath, "hucairz.txt")); const srcUri = await findSourceArchive(dir.name); expect(srcUri!.fsPath).toBe(uri.fsPath); @@ -579,9 +579,9 @@ describe("local databases", () => { it("should prioritize src over output/src_archive", async () => { const uriSrc = Uri.file(join(dir.name, "src.zip")); - fs.createFileSync(uriSrc.fsPath); + await ensureFile(uriSrc.fsPath); const uriSrcArchive = Uri.file(join(dir.name, "src.zip")); - fs.createFileSync(uriSrcArchive.fsPath); + await ensureFile(uriSrcArchive.fsPath); const resultUri = await findSourceArchive(dir.name); expect(resultUri!.fsPath).toBe(uriSrc.fsPath); @@ -679,8 +679,8 @@ describe("local databases", () => { }); describe("when the QL pack already exists", () => { - beforeEach(() => { - fs.mkdirSync(join(dir.name, `codeql-custom-queries-${language}`)); + beforeEach(async () => { + await ensureDir(join(dir.name, `codeql-custom-queries-${language}`)); }); it("should exit early", async () => { diff --git a/extensions/ql-vscode/test/vscode-tests/test-config.ts b/extensions/ql-vscode/test/vscode-tests/test-config.ts index 9441b77e1..b702ce2c1 100644 --- a/extensions/ql-vscode/test/vscode-tests/test-config.ts +++ b/extensions/ql-vscode/test/vscode-tests/test-config.ts @@ -177,6 +177,7 @@ const packageConfiguration: PackageConfiguration = return properties; })(); +// eslint-disable-next-line import/no-mutable-exports export let vscodeGetConfigurationMock: jest.SpiedFunction< typeof workspace.getConfiguration >;