From b309e231e8117ebc46d56526af5f05f35c60243d Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Wed, 12 Jul 2023 17:27:40 -0400 Subject: [PATCH] add unit tests for ProfilesUtils Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../__unit__/dataset/DatasetTree.unit.test.ts | 26 ++-- .../__tests__/__unit__/utils.unit.test.ts | 5 +- .../__unit__/utils/ProfilesUtils.unit.test.ts | 115 +++++++++++++++++- .../zowe-explorer/src/utils/ProfilesUtils.ts | 58 +++------ 4 files changed, 150 insertions(+), 54 deletions(-) diff --git a/packages/zowe-explorer/__tests__/__unit__/dataset/DatasetTree.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/dataset/DatasetTree.unit.test.ts index 628e751594..4012f96292 100644 --- a/packages/zowe-explorer/__tests__/__unit__/dataset/DatasetTree.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/dataset/DatasetTree.unit.test.ts @@ -1438,7 +1438,7 @@ describe("Dataset Tree Unit Tests - Function datasetFilterPrompt", () => { } it("Checking adding of new filter - Theia", async () => { - const globalMocks = await createGlobalMocks(); + const globalMocks = createGlobalMocks(); const blockMocks = await createBlockMocks(globalMocks); globalMocks.isTheia.mockReturnValue(true); @@ -1454,7 +1454,7 @@ describe("Dataset Tree Unit Tests - Function datasetFilterPrompt", () => { expect(testTree.mSessionNodes[1].pattern).toEqual("HLQ.PROD1.STUFF"); }); it("Checking cancelled attempt to add a filter - Theia", async () => { - const globalMocks = await createGlobalMocks(); + const globalMocks = createGlobalMocks(); const blockMocks = await createBlockMocks(globalMocks); globalMocks.isTheia.mockReturnValue(true); @@ -1469,7 +1469,7 @@ describe("Dataset Tree Unit Tests - Function datasetFilterPrompt", () => { expect(mocked(Gui.showMessage)).toBeCalledWith("You must enter a pattern."); }); it("Checking usage of existing filter - Theia", async () => { - const globalMocks = await createGlobalMocks(); + const globalMocks = createGlobalMocks(); const blockMocks = await createBlockMocks(globalMocks); globalMocks.isTheia.mockReturnValue(true); @@ -1485,7 +1485,7 @@ describe("Dataset Tree Unit Tests - Function datasetFilterPrompt", () => { expect(testTree.mSessionNodes[1].pattern).toEqual("HLQ.PROD1.STUFF"); }); it("Checking cancelling of filter prompt with available filters - Theia", async () => { - const globalMocks = await createGlobalMocks(); + const globalMocks = createGlobalMocks(); const blockMocks = await createBlockMocks(globalMocks); globalMocks.isTheia.mockReturnValue(true); @@ -1500,7 +1500,7 @@ describe("Dataset Tree Unit Tests - Function datasetFilterPrompt", () => { expect(mocked(Gui.showMessage)).toBeCalledWith("No selection made. Operation cancelled."); }); it("Checking function on favorites", async () => { - const globalMocks = await createGlobalMocks(); + const globalMocks = createGlobalMocks(); const blockMocks = await createBlockMocks(globalMocks); mocked(vscode.window.createTreeView).mockReturnValueOnce(blockMocks.treeView); @@ -1523,7 +1523,7 @@ describe("Dataset Tree Unit Tests - Function datasetFilterPrompt", () => { expect(addSessionSpy).toHaveBeenLastCalledWith(blockMocks.datasetSessionNode.label.trim()); }); it("Checking adding of new filter", async () => { - const globalMocks = await createGlobalMocks(); + const globalMocks = createGlobalMocks(); const blockMocks = await createBlockMocks(globalMocks); mocked(vscode.window.showQuickPick).mockResolvedValueOnce(new utils.FilterDescriptor("\uFF0B " + "Create a new filter")); @@ -1538,7 +1538,7 @@ describe("Dataset Tree Unit Tests - Function datasetFilterPrompt", () => { expect(testTree.mSessionNodes[1].pattern).toEqual("HLQ.PROD1.STUFF"); }); it("Checking adding of new filter with data set member", async () => { - const globalMocks = await createGlobalMocks(); + const globalMocks = createGlobalMocks(); const blockMocks = await createBlockMocks(globalMocks); mocked(vscode.window.showQuickPick).mockResolvedValueOnce(new utils.FilterDescriptor("\uFF0B " + "Create a new filter")); @@ -1551,7 +1551,7 @@ describe("Dataset Tree Unit Tests - Function datasetFilterPrompt", () => { expect(testTree.mSessionNodes[1].pattern).toEqual("HLQ.PROD1"); }); it("Checking adding of new filter with Unverified profile", async () => { - const globalMocks = await createGlobalMocks(); + const globalMocks = createGlobalMocks(); const blockMocks = await createBlockMocks(globalMocks); Object.defineProperty(Profiles, "getInstance", { value: jest.fn(() => { @@ -1579,7 +1579,7 @@ describe("Dataset Tree Unit Tests - Function datasetFilterPrompt", () => { expect(testTree.mSessionNodes[1].pattern).toEqual("HLQ.PROD1.STUFF"); }); it("Checking cancelled attempt to add a filter", async () => { - const globalMocks = await createGlobalMocks(); + const globalMocks = createGlobalMocks(); const blockMocks = await createBlockMocks(globalMocks); mocked(vscode.window.showQuickPick).mockResolvedValueOnce(new utils.FilterDescriptor("\uFF0B " + "Create a new filter")); @@ -1593,7 +1593,7 @@ describe("Dataset Tree Unit Tests - Function datasetFilterPrompt", () => { expect(mocked(Gui.showMessage)).toBeCalledWith("You must enter a pattern."); }); it("Checking usage of existing filter", async () => { - const globalMocks = await createGlobalMocks(); + const globalMocks = createGlobalMocks(); const blockMocks = await createBlockMocks(globalMocks); const quickPickItem = new utils.FilterDescriptor("HLQ.PROD1.STUFF"); @@ -1614,7 +1614,7 @@ describe("Dataset Tree Unit Tests - Function datasetFilterPrompt", () => { expect(testTree.mSessionNodes[1].pattern).toEqual("HLQ.PROD1.STUFF"); }); it("Checking cancelling of filter prompt with available filters", async () => { - const globalMocks = await createGlobalMocks(); + const globalMocks = createGlobalMocks(); const blockMocks = await createBlockMocks(globalMocks); const quickPickItem = undefined; @@ -1632,7 +1632,7 @@ describe("Dataset Tree Unit Tests - Function datasetFilterPrompt", () => { expect(mocked(Gui.showMessage)).toBeCalledWith("No selection made. Operation cancelled."); }); it("Checking adding of new filter error is caught on getChildren", async () => { - const globalMocks = await createGlobalMocks(); + const globalMocks = createGlobalMocks(); const blockMocks = await createBlockMocks(globalMocks); mocked(vscode.window.showQuickPick).mockResolvedValueOnce(new utils.FilterDescriptor("\uFF0B " + "Create a new filter")); @@ -1718,7 +1718,7 @@ describe("Dataset Tree Unit Tests - Function editSession", () => { } it("Checking common run of function", async () => { - const globalMocks = await createGlobalMocks(); + createGlobalMocks(); const blockMocks = await createBlockMocks(); mocked(vscode.window.createTreeView).mockReturnValueOnce(blockMocks.treeView); diff --git a/packages/zowe-explorer/__tests__/__unit__/utils.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/utils.unit.test.ts index 57699a395a..3731556459 100644 --- a/packages/zowe-explorer/__tests__/__unit__/utils.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/utils.unit.test.ts @@ -115,7 +115,10 @@ describe("Utils Unit Tests - Function errorHandling", () => { mocked(Profiles.getInstance).mockReturnValue(blockMocks.profile); mocked(vscode.window.showErrorMessage).mockResolvedValueOnce({ title: "Update Credentials" }); - mocked(utils.isTheia).mockReturnValue(true); + Object.defineProperty(globals, "ISTHEIA", { + value: true, + configurable: true, + }); const errorDetails = new imperative.ImperativeError({ msg: "Invalid credentials", errorCode: 401 as unknown as string, diff --git a/packages/zowe-explorer/__tests__/__unit__/utils/ProfilesUtils.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/utils/ProfilesUtils.unit.test.ts index b6c52a3d46..dfe8c575e8 100644 --- a/packages/zowe-explorer/__tests__/__unit__/utils/ProfilesUtils.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/utils/ProfilesUtils.unit.test.ts @@ -118,7 +118,7 @@ describe("ProfilesUtils unit tests", () => { expect(spyOpenConfigFile).toBeCalledTimes(1); }); - it("should handle error and prompt for authentication", async () => { + it("should handle token error and prompt for authentication", async () => { const errorDetails = new zowe.imperative.ImperativeError({ msg: "Invalid credentials", errorCode: 401 as unknown as string, @@ -126,7 +126,10 @@ describe("ProfilesUtils unit tests", () => { }); const label = "test"; const moreInfo = "Task failed successfully"; - jest.spyOn(profUtils, "isTheia").mockReturnValue(false); + Object.defineProperty(globals, "ISTHEIA", { + value: false, + configurable: true, + }); const showMessageSpy = jest.spyOn(Gui, "showMessage").mockResolvedValue("selection"); const ssoLoginSpy = jest.fn(); Object.defineProperty(Profiles, "getInstance", { @@ -137,6 +140,114 @@ describe("ProfilesUtils unit tests", () => { await profUtils.errorHandling(errorDetails, label, moreInfo); expect(showMessageSpy).toBeCalledTimes(1); expect(ssoLoginSpy).toBeCalledTimes(1); + showMessageSpy.mockClear(); + ssoLoginSpy.mockClear(); + }); + it("should handle token error and procede to login - Theia", async () => { + const errorDetails = new zowe.imperative.ImperativeError({ + msg: "Invalid credentials", + errorCode: 401 as unknown as string, + additionalDetails: "Token is not valid or expired.", + }); + const label = "test"; + const moreInfo = "Task failed successfully"; + Object.defineProperty(globals, "ISTHEIA", { + value: true, + configurable: true, + }); + const showErrorSpy = jest.spyOn(Gui, "errorMessage").mockResolvedValue(undefined); + const showMessageSpy = jest.spyOn(Gui, "showMessage"); + const ssoLoginSpy = jest.fn(); + Object.defineProperty(Profiles, "getInstance", { + value: () => ({ + ssoLogin: ssoLoginSpy, + }), + }); + await profUtils.errorHandling(errorDetails, label, moreInfo); + expect(showErrorSpy).toBeCalledTimes(1); + expect(ssoLoginSpy).toBeCalledTimes(1); + expect(showMessageSpy).not.toBeCalled(); + showErrorSpy.mockClear(); + showMessageSpy.mockClear(); + ssoLoginSpy.mockClear(); + }); + it("should handle credential error and prompt for authentication", async () => { + const errorDetails = new zowe.imperative.ImperativeError({ + msg: "Invalid credentials", + errorCode: 401 as unknown as string, + additionalDetails: "Authentication failed.", + }); + const label = "test"; + const moreInfo = "Task failed successfully"; + Object.defineProperty(globals, "ISTHEIA", { + value: false, + configurable: true, + }); + const showErrorSpy = jest.spyOn(Gui, "errorMessage").mockResolvedValue("selection"); + const promptCredentialsSpy = jest.fn(); + Object.defineProperty(Profiles, "getInstance", { + value: () => ({ + promptCredentials: promptCredentialsSpy, + }), + }); + await profUtils.errorHandling(errorDetails, label, moreInfo); + expect(showErrorSpy).toBeCalledTimes(1); + expect(promptCredentialsSpy).toBeCalledTimes(1); + showErrorSpy.mockClear(); + promptCredentialsSpy.mockClear(); + }); + it("should handle credential error and no selection made for update", async () => { + const errorDetails = new zowe.imperative.ImperativeError({ + msg: "Invalid credentials", + errorCode: 401 as unknown as string, + additionalDetails: "Authentication failed.", + }); + const label = "test"; + const moreInfo = "Task failed successfully"; + Object.defineProperty(globals, "ISTHEIA", { + value: false, + configurable: true, + }); + const showErrorSpy = jest.spyOn(Gui, "errorMessage").mockResolvedValue(undefined); + const showMsgSpy = jest.spyOn(Gui, "showMessage"); + const promptCredentialsSpy = jest.fn(); + Object.defineProperty(Profiles, "getInstance", { + value: () => ({ + promptCredentials: promptCredentialsSpy, + }), + }); + await profUtils.errorHandling(errorDetails, label, moreInfo); + expect(showErrorSpy).toBeCalledTimes(1); + expect(promptCredentialsSpy).not.toBeCalled(); + expect(showMsgSpy).toBeCalledWith("Operation Cancelled"); + showErrorSpy.mockClear(); + showMsgSpy.mockClear(); + promptCredentialsSpy.mockClear(); + }); + it("should handle credential error with error message - Theia", async () => { + const errorDetails = new zowe.imperative.ImperativeError({ + msg: "Invalid credentials", + errorCode: 401 as unknown as string, + additionalDetails: "Authentication failed.", + }); + const label = "test"; + const moreInfo = "Task failed successfully"; + Object.defineProperty(globals, "ISTHEIA", { + value: true, + configurable: true, + }); + const showErrorSpy = jest.spyOn(Gui, "errorMessage"); + const promptCredentialsSpy = jest.fn(); + Object.defineProperty(Profiles, "getInstance", { + value: () => ({ + promptCredentials: promptCredentialsSpy, + }), + }); + await profUtils.errorHandling(errorDetails, label, moreInfo); + expect(showErrorSpy).toBeCalledTimes(1); + expect(promptCredentialsSpy).not.toBeCalled(); + showErrorSpy.mockClear(); + promptCredentialsSpy.mockClear(); }); }); diff --git a/packages/zowe-explorer/src/utils/ProfilesUtils.ts b/packages/zowe-explorer/src/utils/ProfilesUtils.ts index 7a18ded6be..187caec4ec 100644 --- a/packages/zowe-explorer/src/utils/ProfilesUtils.ts +++ b/packages/zowe-explorer/src/utils/ProfilesUtils.ts @@ -75,18 +75,18 @@ export async function handleInvalidToken(label: string): Promise { "errorHandling.invalid.token", "Your connection is no longer active. Please log in to an authentication service to restore the connection." ); - if (isTheia()) { + if (globals.ISTHEIA) { Gui.errorMessage(tokenErrMsg).then(async () => { await Profiles.getInstance().ssoLogin(null, label); }); - } else { - const message = localize("errorHandling.authentication.login", "Log in to Authentication Service"); - await Gui.showMessage(tokenErrMsg, { items: [message] }).then(async (selection) => { - if (selection) { - await Profiles.getInstance().ssoLogin(null, label); - } - }); + return; } + const message = localize("errorHandling.authentication.login", "Log in to Authentication Service"); + await Gui.showMessage(tokenErrMsg, { items: [message] }).then(async (selection) => { + if (selection) { + await Profiles.getInstance().ssoLogin(null, label); + } + }); } export async function handleInvalidCredentials(label: string): Promise { @@ -95,27 +95,20 @@ export async function handleInvalidCredentials(label: string): Promise { "Invalid Credentials. Please ensure the username and password for {0} are valid or this may lead to a lock-out.", label ); - if (isTheia()) { + if (globals.ISTHEIA) { Gui.errorMessage(genErrMsg); - } else { - const updateCredsButton = localize("errorHandling.updateCredentials.button", "Update Credentials"); - const choice = await Gui.errorMessage(genErrMsg, { - items: [updateCredsButton], - vsCodeOpts: { modal: true }, - }); - if (!choice) { - Gui.showMessage(localize("errorHandling.checkCredentials.cancelled", "Operation Cancelled")); - return; - } - await Profiles.getInstance().promptCredentials(label.trim(), true); - // .then(async (selection) => { - // if (selection === updateCredsButton) { - - // } else { - - // } - // }); + return; + } + const updateCredsButton = localize("errorHandling.updateCredentials.button", "Update Credentials"); + const choice = await Gui.errorMessage(genErrMsg, { + items: [updateCredsButton], + vsCodeOpts: { modal: true }, + }); + if (!choice) { + Gui.showMessage(localize("errorHandling.checkCredentials.cancelled", "Operation Cancelled")); + return; } + await Profiles.getInstance().promptCredentials(label.trim(), true); } export async function handleNoHostname(label: string): Promise { @@ -132,17 +125,6 @@ export async function handleNoHostname(label: string): Promise { } } -// TODO: remove this second occurence -export function isTheia(): boolean { - ZoweLogger.trace("ProfileUtils.isTheia called."); - const VSCODE_APPNAME: string[] = ["Visual Studio Code", "VSCodium"]; - const appName = vscode.env.appName; - if (appName && !VSCODE_APPNAME.includes(appName)) { - return true; - } - return false; -} - /** * Function to update session and profile information in provided node * @param profiles is data source to find profiles