From cb2802e2e7c685eb90dadefa88cae4accef8dfe1 Mon Sep 17 00:00:00 2001 From: Nora Date: Tue, 22 Aug 2023 08:55:25 +0000 Subject: [PATCH 1/6] Add mode details panel test --- .../model-details/model-details-panel.test.ts | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-panel.test.ts diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-panel.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-panel.test.ts new file mode 100644 index 00000000000..4bf214d29b4 --- /dev/null +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-panel.test.ts @@ -0,0 +1,42 @@ +import { window, TreeView } from "vscode"; +import { CodeQLCliServer } from "../../../../../src/codeql-cli/cli"; +import { ExternalApiUsage } from "../../../../../src/data-extensions-editor/external-api-usage"; +import { ModelDetailsPanel } from "../../../../../src/data-extensions-editor/model-details/model-details-panel"; +import { DatabaseItem } from "../../../../../src/databases/local-databases"; +import { mockedObject } from "../../../utils/mocking.helpers"; + +describe("ModelDetailsPanel", () => { + const mockCliServer = mockedObject({}); + + describe("setState", () => { + const hideModeledApis: boolean = false; + const externalApiUsages: ExternalApiUsage[] = [ + { + library: "test", + supported: false, + supportedType: "none", + usages: [], + signature: "test", + packageName: "test", + typeName: "test", + methodName: "test", + methodParameters: "test", + }, + ]; + const dbItem = mockedObject({ + getSourceLocationPrefix: () => "test", + }); + + it("should update the tree view with the correct batch number", async () => { + const mockTreeView = { + badge: undefined, + } as TreeView; + jest.spyOn(window, "createTreeView").mockReturnValue(mockTreeView); + + const panel = new ModelDetailsPanel(mockCliServer); + await panel.setState(externalApiUsages, dbItem, hideModeledApis); + + expect(mockTreeView.badge?.value).toBe(1); + }); + }); +}); From 6e4e89a006d13bdeffc67c97eb2b1583f534791c Mon Sep 17 00:00:00 2001 From: Nora Date: Tue, 22 Aug 2023 08:56:07 +0000 Subject: [PATCH 2/6] Move dataProvider creation to beforeEach --- .../model-details/model-details-data-provider.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-data-provider.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-data-provider.test.ts index 0bc4405b561..07f5822f9b9 100644 --- a/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-data-provider.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-data-provider.test.ts @@ -6,6 +6,11 @@ import { mockedObject } from "../../../utils/mocking.helpers"; describe("ModelDetailsDataProvider", () => { const mockCliServer = mockedObject({}); + let dataProvider: ModelDetailsDataProvider; + + beforeEach(() => { + dataProvider = new ModelDetailsDataProvider(mockCliServer); + }); describe("setState", () => { const hideModeledApis: boolean = false; @@ -15,7 +20,6 @@ describe("ModelDetailsDataProvider", () => { }); it("should not emit onDidChangeTreeData event when state has not changed", async () => { - const dataProvider = new ModelDetailsDataProvider(mockCliServer); await dataProvider.setState(externalApiUsages, dbItem, hideModeledApis); const onDidChangeTreeDataListener = jest.fn(); @@ -29,7 +33,6 @@ describe("ModelDetailsDataProvider", () => { it("should emit onDidChangeTreeData event when externalApiUsages has changed", async () => { const externalApiUsages2: ExternalApiUsage[] = []; - const dataProvider = new ModelDetailsDataProvider(mockCliServer); await dataProvider.setState(externalApiUsages, dbItem, hideModeledApis); const onDidChangeTreeDataListener = jest.fn(); @@ -45,7 +48,6 @@ describe("ModelDetailsDataProvider", () => { getSourceLocationPrefix: () => "test", }); - const dataProvider = new ModelDetailsDataProvider(mockCliServer); await dataProvider.setState(externalApiUsages, dbItem, hideModeledApis); const onDidChangeTreeDataListener = jest.fn(); @@ -57,7 +59,6 @@ describe("ModelDetailsDataProvider", () => { }); it("should emit onDidChangeTreeData event when hideModeledApis has changed", async () => { - const dataProvider = new ModelDetailsDataProvider(mockCliServer); await dataProvider.setState(externalApiUsages, dbItem, hideModeledApis); const onDidChangeTreeDataListener = jest.fn(); @@ -74,7 +75,6 @@ describe("ModelDetailsDataProvider", () => { }); const externalApiUsages2: ExternalApiUsage[] = []; - const dataProvider = new ModelDetailsDataProvider(mockCliServer); await dataProvider.setState(externalApiUsages, dbItem, hideModeledApis); const onDidChangeTreeDataListener = jest.fn(); From 392e76d8f2cba204e5a29a5cb40f063d5b2cbee0 Mon Sep 17 00:00:00 2001 From: Nora Date: Tue, 22 Aug 2023 08:56:42 +0000 Subject: [PATCH 3/6] Add getChildren tests --- .../model-details-data-provider.test.ts | 46 ++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-data-provider.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-data-provider.test.ts index 07f5822f9b9..3a9dc306db9 100644 --- a/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-data-provider.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-data-provider.test.ts @@ -1,6 +1,12 @@ import { CodeQLCliServer } from "../../../../../src/codeql-cli/cli"; -import { ExternalApiUsage } from "../../../../../src/data-extensions-editor/external-api-usage"; -import { ModelDetailsDataProvider } from "../../../../../src/data-extensions-editor/model-details/model-details-data-provider"; +import { + ExternalApiUsage, + Usage, +} from "../../../../../src/data-extensions-editor/external-api-usage"; +import { + ModelDetailsDataProvider, + ModelDetailsTreeViewItem, +} from "../../../../../src/data-extensions-editor/model-details/model-details-data-provider"; import { DatabaseItem } from "../../../../../src/databases/local-databases"; import { mockedObject } from "../../../utils/mocking.helpers"; @@ -89,4 +95,40 @@ describe("ModelDetailsDataProvider", () => { expect(onDidChangeTreeDataListener).toHaveBeenCalledTimes(1); }); }); + + describe("getChildren", () => { + const externalApiUsages: ExternalApiUsage[] = [ + mockedObject({ supported: true }), + mockedObject({ supported: false }), + ]; + const dbItem = mockedObject({ + getSourceLocationPrefix: () => "test", + }); + + it("should return [] if item is a usage", async () => { + const item = { usages: undefined } as unknown as ModelDetailsTreeViewItem; + expect(dataProvider.getChildren(item)).toEqual([]); + }); + + it("should return usages if item is external api usage", async () => { + const usage = mockedObject({}); + const item = mockedObject({ + usages: [usage], + }); + + expect(dataProvider.getChildren(item)).toEqual([usage]); + }); + + it("should show all externalApiUsages if hideModeledApis is false and item is undefined", async () => { + const hideModeledApis: boolean = false; + await dataProvider.setState(externalApiUsages, dbItem, hideModeledApis); + expect(dataProvider.getChildren().length).toEqual(2); + }); + + it("should filter externalApiUsages if hideModeledApis is true and item is undefined", async () => { + const hideModeledApis: boolean = true; + await dataProvider.setState(externalApiUsages, dbItem, hideModeledApis); + expect(dataProvider.getChildren().length).toEqual(1); + }); + }); }); From 45f7d22d2a3625cc1d2f238e7c3f362762771f9a Mon Sep 17 00:00:00 2001 From: Nora Date: Tue, 22 Aug 2023 13:11:46 +0000 Subject: [PATCH 4/6] Add reveal test --- .../model-details/model-details-panel.test.ts | 58 ++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-panel.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-panel.test.ts index 4bf214d29b4..898a7e08bfa 100644 --- a/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-panel.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-panel.test.ts @@ -1,6 +1,9 @@ import { window, TreeView } from "vscode"; import { CodeQLCliServer } from "../../../../../src/codeql-cli/cli"; -import { ExternalApiUsage } from "../../../../../src/data-extensions-editor/external-api-usage"; +import { + CallClassification, + ExternalApiUsage, +} from "../../../../../src/data-extensions-editor/external-api-usage"; import { ModelDetailsPanel } from "../../../../../src/data-extensions-editor/model-details/model-details-panel"; import { DatabaseItem } from "../../../../../src/databases/local-databases"; import { mockedObject } from "../../../utils/mocking.helpers"; @@ -39,4 +42,57 @@ describe("ModelDetailsPanel", () => { expect(mockTreeView.badge?.value).toBe(1); }); }); + + describe("revealItem", () => { + let mockTreeView: TreeView; + + const hideModeledApis: boolean = false; + const dbItem = mockedObject({ + getSourceLocationPrefix: () => "test", + }); + const usage = { + classification: "unknown" as CallClassification, + label: "test", + url: { + uri: "test", + startLine: 1, + startColumn: 1, + endLine: 1, + endColumn: 1, + }, + }; + + beforeEach(() => { + mockTreeView = { + reveal: jest.fn(), + } as unknown as TreeView; + jest.spyOn(window, "createTreeView").mockReturnValue(mockTreeView); + }); + + it("should reveal the correct item in the tree view", async () => { + const externalApiUsages = mockedObject([ + { + usages: [usage], + }, + ]); + + const panel = new ModelDetailsPanel(mockCliServer); + await panel.setState(externalApiUsages, dbItem, hideModeledApis); + + await panel.revealItem(usage); + + expect(mockTreeView.reveal).toHaveBeenCalledWith(usage); + }); + + it("should do nothing if usage cannot be found", async () => { + const externalApiUsages = mockedObject([]); + + const panel = new ModelDetailsPanel(mockCliServer); + await panel.setState(externalApiUsages, dbItem, hideModeledApis); + + await panel.revealItem(usage); + + expect(mockTreeView.reveal).not.toHaveBeenCalled(); + }); + }); }); From c56936e2f698b983932bc5deb96fb695937b3546 Mon Sep 17 00:00:00 2001 From: Nora Date: Wed, 23 Aug 2023 16:06:30 +0000 Subject: [PATCH 5/6] create and use factories --- .../data-extension/external-api-factories.ts | 57 +++++++++++++++++++ .../model-details-data-provider.test.ts | 39 +++++++------ .../model-details/model-details-panel.test.ts | 55 +++++------------- 3 files changed, 93 insertions(+), 58 deletions(-) create mode 100644 extensions/ql-vscode/test/factories/data-extension/external-api-factories.ts diff --git a/extensions/ql-vscode/test/factories/data-extension/external-api-factories.ts b/extensions/ql-vscode/test/factories/data-extension/external-api-factories.ts new file mode 100644 index 00000000000..fb245e8c514 --- /dev/null +++ b/extensions/ql-vscode/test/factories/data-extension/external-api-factories.ts @@ -0,0 +1,57 @@ +import { + Usage, + ExternalApiUsage, + CallClassification, +} from "../../../src/data-extensions-editor/external-api-usage"; +import { ModeledMethodType } from "../../../src/data-extensions-editor/modeled-method"; +import { ResolvableLocationValue } from "../../../src/common/bqrs-cli-types"; + +export function createExternalApiUsage({ + library = "test", + supported = true, + supportedType = "none" as ModeledMethodType, + usages = [], + signature = "test", + packageName = "test", + typeName = "test", + methodName = "test", + methodParameters = "test", +}: { + library?: string; + supported?: boolean; + supportedType?: ModeledMethodType; + usages?: Usage[]; + signature?: string; + packageName?: string; + typeName?: string; + methodName?: string; + methodParameters?: string; +} = {}): ExternalApiUsage { + return { + library, + supported, + supportedType, + usages, + signature, + packageName, + typeName, + methodName, + methodParameters, + }; +} + +export function createUsage({ + classification = CallClassification.Unknown, + label = "test", + url = {} as ResolvableLocationValue, +}: { + classification?: CallClassification; + label?: string; + url?: ResolvableLocationValue; +} = {}): Usage { + return { + classification, + label, + url, + }; +} diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-data-provider.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-data-provider.test.ts index 3a9dc306db9..8b4d760abbc 100644 --- a/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-data-provider.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-data-provider.test.ts @@ -1,13 +1,11 @@ import { CodeQLCliServer } from "../../../../../src/codeql-cli/cli"; -import { - ExternalApiUsage, - Usage, -} from "../../../../../src/data-extensions-editor/external-api-usage"; -import { - ModelDetailsDataProvider, - ModelDetailsTreeViewItem, -} from "../../../../../src/data-extensions-editor/model-details/model-details-data-provider"; +import { ExternalApiUsage } from "../../../../../src/data-extensions-editor/external-api-usage"; +import { ModelDetailsDataProvider } from "../../../../../src/data-extensions-editor/model-details/model-details-data-provider"; import { DatabaseItem } from "../../../../../src/databases/local-databases"; +import { + createExternalApiUsage, + createUsage, +} from "../../../../factories/data-extension/external-api-factories"; import { mockedObject } from "../../../utils/mocking.helpers"; describe("ModelDetailsDataProvider", () => { @@ -97,26 +95,31 @@ describe("ModelDetailsDataProvider", () => { }); describe("getChildren", () => { + const supportedExternalApiUsage = createExternalApiUsage({ + supported: true, + }); + + const unsupportedExternalApiUsage = createExternalApiUsage({ + supported: false, + }); + const externalApiUsages: ExternalApiUsage[] = [ - mockedObject({ supported: true }), - mockedObject({ supported: false }), + supportedExternalApiUsage, + unsupportedExternalApiUsage, ]; const dbItem = mockedObject({ getSourceLocationPrefix: () => "test", }); + const usage = createUsage({}); + it("should return [] if item is a usage", async () => { - const item = { usages: undefined } as unknown as ModelDetailsTreeViewItem; - expect(dataProvider.getChildren(item)).toEqual([]); + expect(dataProvider.getChildren(usage)).toEqual([]); }); it("should return usages if item is external api usage", async () => { - const usage = mockedObject({}); - const item = mockedObject({ - usages: [usage], - }); - - expect(dataProvider.getChildren(item)).toEqual([usage]); + const externalApiUsage = createExternalApiUsage({ usages: [usage] }); + expect(dataProvider.getChildren(externalApiUsage)).toEqual([usage]); }); it("should show all externalApiUsages if hideModeledApis is false and item is undefined", async () => { diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-panel.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-panel.test.ts index 898a7e08bfa..caa9e3e177a 100644 --- a/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-panel.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-panel.test.ts @@ -1,34 +1,23 @@ import { window, TreeView } from "vscode"; import { CodeQLCliServer } from "../../../../../src/codeql-cli/cli"; -import { - CallClassification, - ExternalApiUsage, -} from "../../../../../src/data-extensions-editor/external-api-usage"; +import { ExternalApiUsage } from "../../../../../src/data-extensions-editor/external-api-usage"; import { ModelDetailsPanel } from "../../../../../src/data-extensions-editor/model-details/model-details-panel"; import { DatabaseItem } from "../../../../../src/databases/local-databases"; import { mockedObject } from "../../../utils/mocking.helpers"; +import { + createExternalApiUsage, + createUsage, +} from "../../../../factories/data-extension/external-api-factories"; describe("ModelDetailsPanel", () => { const mockCliServer = mockedObject({}); + const dbItem = mockedObject({ + getSourceLocationPrefix: () => "test", + }); describe("setState", () => { const hideModeledApis: boolean = false; - const externalApiUsages: ExternalApiUsage[] = [ - { - library: "test", - supported: false, - supportedType: "none", - usages: [], - signature: "test", - packageName: "test", - typeName: "test", - methodName: "test", - methodParameters: "test", - }, - ]; - const dbItem = mockedObject({ - getSourceLocationPrefix: () => "test", - }); + const externalApiUsages: ExternalApiUsage[] = [createExternalApiUsage()]; it("should update the tree view with the correct batch number", async () => { const mockTreeView = { @@ -47,20 +36,7 @@ describe("ModelDetailsPanel", () => { let mockTreeView: TreeView; const hideModeledApis: boolean = false; - const dbItem = mockedObject({ - getSourceLocationPrefix: () => "test", - }); - const usage = { - classification: "unknown" as CallClassification, - label: "test", - url: { - uri: "test", - startLine: 1, - startColumn: 1, - endLine: 1, - endColumn: 1, - }, - }; + const usage = createUsage(); beforeEach(() => { mockTreeView = { @@ -70,11 +46,11 @@ describe("ModelDetailsPanel", () => { }); it("should reveal the correct item in the tree view", async () => { - const externalApiUsages = mockedObject([ - { + const externalApiUsages = [ + createExternalApiUsage({ usages: [usage], - }, - ]); + }), + ]; const panel = new ModelDetailsPanel(mockCliServer); await panel.setState(externalApiUsages, dbItem, hideModeledApis); @@ -85,8 +61,7 @@ describe("ModelDetailsPanel", () => { }); it("should do nothing if usage cannot be found", async () => { - const externalApiUsages = mockedObject([]); - + const externalApiUsages = [createExternalApiUsage({})]; const panel = new ModelDetailsPanel(mockCliServer); await panel.setState(externalApiUsages, dbItem, hideModeledApis); From 0daa06bc0de8589df887a29d87385314431c54a5 Mon Sep 17 00:00:00 2001 From: Nora Date: Thu, 24 Aug 2023 08:58:37 +0000 Subject: [PATCH 6/6] rename test and remove boolean type --- .../model-details/model-details-data-provider.test.ts | 10 +++++----- .../model-details/model-details-panel.test.ts | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-data-provider.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-data-provider.test.ts index 8b4d760abbc..4564b68b3e9 100644 --- a/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-data-provider.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-data-provider.test.ts @@ -17,7 +17,7 @@ describe("ModelDetailsDataProvider", () => { }); describe("setState", () => { - const hideModeledApis: boolean = false; + const hideModeledApis = false; const externalApiUsages: ExternalApiUsage[] = []; const dbItem = mockedObject({ getSourceLocationPrefix: () => "test", @@ -122,14 +122,14 @@ describe("ModelDetailsDataProvider", () => { expect(dataProvider.getChildren(externalApiUsage)).toEqual([usage]); }); - it("should show all externalApiUsages if hideModeledApis is false and item is undefined", async () => { - const hideModeledApis: boolean = false; + it("should show all externalApiUsages if hideModeledApis is false and looking at the root", async () => { + const hideModeledApis = false; await dataProvider.setState(externalApiUsages, dbItem, hideModeledApis); expect(dataProvider.getChildren().length).toEqual(2); }); - it("should filter externalApiUsages if hideModeledApis is true and item is undefined", async () => { - const hideModeledApis: boolean = true; + it("should filter externalApiUsages if hideModeledApis is true and looking at the root", async () => { + const hideModeledApis = true; await dataProvider.setState(externalApiUsages, dbItem, hideModeledApis); expect(dataProvider.getChildren().length).toEqual(1); }); diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-panel.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-panel.test.ts index caa9e3e177a..2b3ac10dde7 100644 --- a/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-panel.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/model-details/model-details-panel.test.ts @@ -16,7 +16,7 @@ describe("ModelDetailsPanel", () => { }); describe("setState", () => { - const hideModeledApis: boolean = false; + const hideModeledApis = false; const externalApiUsages: ExternalApiUsage[] = [createExternalApiUsage()]; it("should update the tree view with the correct batch number", async () => {