diff --git a/extensions/ql-vscode/src/databases.ts b/extensions/ql-vscode/src/databases.ts index 7e47e9d44..b114084c3 100644 --- a/extensions/ql-vscode/src/databases.ts +++ b/extensions/ql-vscode/src/databases.ts @@ -924,7 +924,7 @@ export class DatabaseManager extends DisposableObject { // Delete folder from file system only if it is controlled by the extension if (this.isExtensionControlledLocation(item.databaseUri)) { void extLogger.log("Deleting database from filesystem."); - remove(item.databaseUri.fsPath).then( + await remove(item.databaseUri.fsPath).then( () => void extLogger.log(`Deleted '${item.databaseUri.fsPath}'`), (e) => void extLogger.log( diff --git a/extensions/ql-vscode/test/vscode-tests/minimal-workspace/databases.test.ts b/extensions/ql-vscode/test/vscode-tests/minimal-workspace/databases.test.ts index a76f14e1d..d2a5e9e9b 100644 --- a/extensions/ql-vscode/test/vscode-tests/minimal-workspace/databases.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/minimal-workspace/databases.test.ts @@ -200,9 +200,7 @@ describe("databases", () => { it("should remove a database item", async () => { const mockDbItem = createMockDB(); - const removeMock = jest - .spyOn(fs, "remove") - .mockImplementation(() => Promise.resolve()); + await fs.ensureDir(mockDbItem.databaseUri.fsPath); // pretend that this item is the first workspace folder in the list jest @@ -229,13 +227,14 @@ describe("databases", () => { expect(workspace.updateWorkspaceFolders).toBeCalledWith(0, 1); // should also delete the db contents - expect(removeMock).toBeCalledWith(mockDbItem.databaseUri.fsPath); + await expect(fs.pathExists(mockDbItem.databaseUri.fsPath)).resolves.toBe( + false, + ); }); it("should remove a database item outside of the extension controlled area", async () => { const mockDbItem = createMockDB(); - const removeMock = jest.spyOn(fs, "remove"); - removeMock.mockReset().mockImplementation(() => Promise.resolve()); + await fs.ensureDir(mockDbItem.databaseUri.fsPath); // pretend that this item is the first workspace folder in the list jest @@ -263,7 +262,9 @@ describe("databases", () => { expect(workspace.updateWorkspaceFolders).toBeCalledWith(0, 1); // should NOT delete the db contents - expect(removeMock).not.toBeCalled(); + await expect(fs.pathExists(mockDbItem.databaseUri.fsPath)).resolves.toBe( + true, + ); }); it("should register and deregister a database when adding and removing it", async () => { @@ -271,8 +272,6 @@ describe("databases", () => { // registration messages. const mockDbItem = createMockDB(); - jest.spyOn(fs, "remove").mockImplementation(() => Promise.resolve()); - await (databaseManager as any).addDatabaseItem( {} as ProgressCallback, {} as CancellationToken, @@ -411,98 +410,93 @@ describe("databases", () => { }); describe("isAffectedByTest", () => { - const directoryStats = new fs.Stats(); - const fileStats = new fs.Stats(); - beforeEach(() => { - jest.spyOn(directoryStats, "isDirectory").mockReturnValue(true); - jest.spyOn(fileStats, "isDirectory").mockReturnValue(false); + let directoryPath: string; + let projectPath: string; + let qlFilePath: string; + + beforeEach(async () => { + directoryPath = join(dir.name, "dir"); + await fs.ensureDir(directoryPath); + projectPath = join(directoryPath, "dir.testproj"); + await fs.writeFile(projectPath, ""); + qlFilePath = join(directoryPath, "test.ql"); + await fs.writeFile(qlFilePath, ""); }); it("should return true for testproj database in test directory", async () => { - jest.spyOn(fs, "stat").mockResolvedValue(directoryStats); - const db = createMockDB( - sourceLocationUri(), - Uri.file("/path/to/dir/dir.testproj"), - ); - expect(await db.isAffectedByTest("/path/to/dir")).toBe(true); + const db = createMockDB(sourceLocationUri(), Uri.file(projectPath)); + expect(await db.isAffectedByTest(directoryPath)).toBe(true); }); it("should return false for non-existent test directory", async () => { - jest.spyOn(fs, "stat").mockImplementation(() => { - throw new Error("Simulated Error: ENOENT"); - }); const db = createMockDB( sourceLocationUri(), - Uri.file("/path/to/dir/dir.testproj"), + Uri.file(join(dir.name, "non-existent/non-existent.testproj")), + ); + expect(await db.isAffectedByTest(join(dir.name, "non-existent"))).toBe( + false, ); - expect(await db.isAffectedByTest("/path/to/dir")).toBe(false); }); it("should return false for non-testproj database in test directory", async () => { - jest.spyOn(fs, "stat").mockResolvedValue(directoryStats); + const anotherProjectPath = join(directoryPath, "dir.proj"); + await fs.writeFile(anotherProjectPath, ""); + const db = createMockDB( sourceLocationUri(), - Uri.file("/path/to/dir/dir.proj"), + Uri.file(anotherProjectPath), ); - expect(await db.isAffectedByTest("/path/to/dir")).toBe(false); + expect(await db.isAffectedByTest(directoryPath)).toBe(false); }); it("should return false for testproj database outside test directory", async () => { - jest.spyOn(fs, "stat").mockResolvedValue(directoryStats); + const anotherProjectDir = join(dir.name, "other"); + await fs.ensureDir(anotherProjectDir); + const anotherProjectPath = join(anotherProjectDir, "other.testproj"); + await fs.writeFile(anotherProjectPath, ""); + const db = createMockDB( sourceLocationUri(), - Uri.file("/path/to/other/dir.testproj"), + Uri.file(anotherProjectPath), ); - expect(await db.isAffectedByTest("/path/to/dir")).toBe(false); + expect(await db.isAffectedByTest(directoryPath)).toBe(false); }); it("should return false for testproj database for prefix directory", async () => { - jest.spyOn(fs, "stat").mockResolvedValue(directoryStats); - const db = createMockDB( - sourceLocationUri(), - Uri.file("/path/to/dir/dir.testproj"), - ); - // /path/to/d is a prefix of /path/to/dir/dir.testproj, but - // /path/to/dir/dir.testproj is not under /path/to/d - expect(await db.isAffectedByTest("/path/to/d")).toBe(false); + const db = createMockDB(sourceLocationUri(), Uri.file(projectPath)); + // /d is a prefix of /dir/dir.testproj, but + // /dir/dir.testproj is not under /d + expect(await db.isAffectedByTest(join(directoryPath, "d"))).toBe(false); }); it("should return true for testproj database for test file", async () => { - jest.spyOn(fs, "stat").mockResolvedValue(fileStats); - const db = createMockDB( - sourceLocationUri(), - Uri.file("/path/to/dir/dir.testproj"), - ); - expect(await db.isAffectedByTest("/path/to/dir/test.ql")).toBe(true); + const db = createMockDB(sourceLocationUri(), Uri.file(projectPath)); + expect(await db.isAffectedByTest(qlFilePath)).toBe(true); }); it("should return false for non-existent test file", async () => { - jest.spyOn(fs, "stat").mockImplementation(() => { - throw new Error("Simulated Error: ENOENT"); - }); - const db = createMockDB( - sourceLocationUri(), - Uri.file("/path/to/dir/dir.testproj"), - ); - expect(await db.isAffectedByTest("/path/to/dir/test.ql")).toBe(false); + const otherTestFile = join(directoryPath, "other-test.ql"); + const db = createMockDB(sourceLocationUri(), Uri.file(projectPath)); + expect(await db.isAffectedByTest(otherTestFile)).toBe(false); }); it("should return false for non-testproj database for test file", async () => { - jest.spyOn(fs, "stat").mockResolvedValue(fileStats); + const anotherProjectPath = join(directoryPath, "dir.proj"); + await fs.writeFile(anotherProjectPath, ""); + const db = createMockDB( sourceLocationUri(), - Uri.file("/path/to/dir/dir.proj"), + Uri.file(anotherProjectPath), ); - expect(await db.isAffectedByTest("/path/to/dir/test.ql")).toBe(false); + expect(await db.isAffectedByTest(qlFilePath)).toBe(false); }); it("should return false for testproj database not matching test file", async () => { - jest.spyOn(fs, "stat").mockResolvedValue(fileStats); - const db = createMockDB( - sourceLocationUri(), - Uri.file("/path/to/dir/dir.testproj"), - ); - expect(await db.isAffectedByTest("/path/to/test.ql")).toBe(false); + const otherTestFile = join(dir.name, "test.ql"); + await fs.writeFile(otherTestFile, ""); + + const db = createMockDB(sourceLocationUri(), Uri.file(projectPath)); + expect(await db.isAffectedByTest(otherTestFile)).toBe(false); }); }); diff --git a/extensions/ql-vscode/test/vscode-tests/minimal-workspace/qltest-discovery.test.ts b/extensions/ql-vscode/test/vscode-tests/minimal-workspace/qltest-discovery.test.ts index d1ef02bb3..f0c3e522c 100644 --- a/extensions/ql-vscode/test/vscode-tests/minimal-workspace/qltest-discovery.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/minimal-workspace/qltest-discovery.test.ts @@ -1,20 +1,36 @@ import { Uri, WorkspaceFolder } from "vscode"; import * as fs from "fs-extra"; +import { join } from "path"; import { QLTestDiscovery } from "../../../src/qltest-discovery"; +import { DirectoryResult } from "tmp-promise"; +import * as tmp from "tmp-promise"; describe("qltest-discovery", () => { describe("discoverTests", () => { - const baseUri = Uri.parse("file:/a/b"); - const baseDir = baseUri.fsPath; - const cDir = Uri.parse("file:/a/b/c").fsPath; - const dFile = Uri.parse("file:/a/b/c/d.ql").fsPath; - const eFile = Uri.parse("file:/a/b/c/e.ql").fsPath; - const hDir = Uri.parse("file:/a/b/c/f/g/h").fsPath; - const iFile = Uri.parse("file:/a/b/c/f/g/h/i.ql").fsPath; + let directory: DirectoryResult; + + let baseDir: string; + let cDir: string; + let dFile: string; + let eFile: string; + let hDir: string; + let iFile: string; let qlTestDiscover: QLTestDiscovery; - beforeEach(() => { + beforeEach(async () => { + directory = await tmp.dir({ + unsafeCleanup: true, + }); + + const baseUri = Uri.file(directory.path); + baseDir = directory.path; + cDir = join(baseDir, "c"); + dFile = join(cDir, "d.ql"); + eFile = join(cDir, "e.ql"); + hDir = join(cDir, "f/g/h"); + iFile = join(hDir, "i.ql"); + qlTestDiscover = new QLTestDiscovery( { uri: baseUri, @@ -22,32 +38,31 @@ describe("qltest-discovery", () => { } as unknown as WorkspaceFolder, { resolveTests() { - return [ - Uri.parse("file:/a/b/c/d.ql").fsPath, - Uri.parse("file:/a/b/c/e.ql").fsPath, - Uri.parse("file:/a/b/c/f/g/h/i.ql").fsPath, - ]; + return [dFile, eFile, iFile]; }, } as any, ); }); - it("should run discovery", async () => { - jest - .spyOn(fs, "pathExists") - .mockImplementation(() => Promise.resolve(true)); + afterEach(async () => { + await directory.cleanup(); + }); + it("should run discovery", async () => { const result = await (qlTestDiscover as any).discover(); expect(result.watchPath).toBe(baseDir); expect(result.testDirectory.path).toBe(baseDir); expect(result.testDirectory.name).toBe("My tests"); let children = result.testDirectory.children; - expect(children[0].path).toBe(cDir); - expect(children[0].name).toBe("c"); expect(children.length).toBe(1); + expect(children[0].path).toBe(cDir); + expect(children[0].name).toBe("c"); + children = children[0].children; + expect(children.length).toBe(3); + expect(children[0].path).toBe(dFile); expect(children[0].name).toBe("d.ql"); expect(children[1].path).toBe(eFile); @@ -56,7 +71,6 @@ describe("qltest-discovery", () => { // A merged foler expect(children[2].path).toBe(hDir); expect(children[2].name).toBe("f / g / h"); - expect(children.length).toBe(3); children = children[2].children; expect(children[0].path).toBe(iFile); @@ -64,9 +78,7 @@ describe("qltest-discovery", () => { }); it("should avoid discovery if a folder does not exist", async () => { - jest - .spyOn(fs, "pathExists") - .mockImplementation(() => Promise.resolve(false)); + await fs.remove(baseDir); const result = await (qlTestDiscover as any).discover(); expect(result.watchPath).toBe(baseDir);