From ea8fd30745b28b65a827dc5005fd1a3b8ab101f2 Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Thu, 21 Sep 2023 09:29:58 -0400 Subject: [PATCH 01/35] initial work for profile management Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../__unit__/Profiles.extended.unit.test.ts | 2 +- .../__unit__/utils/ProfilesUtils.unit.test.ts | 2 +- .../i18n/sample/package.i18n.json | 7 +- .../sample/src/utils/ProfilesUtils.i18n.json | 11 ++ packages/zowe-explorer/package.nls.json | 2 +- packages/zowe-explorer/src/Profiles.ts | 4 +- packages/zowe-explorer/src/shared/init.ts | 2 +- .../zowe-explorer/src/utils/ProfilesUtils.ts | 148 ++++++++++++++++-- 8 files changed, 156 insertions(+), 22 deletions(-) diff --git a/packages/zowe-explorer/__tests__/__unit__/Profiles.extended.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/Profiles.extended.unit.test.ts index 2876032d7b..ebe3b57fe3 100644 --- a/packages/zowe-explorer/__tests__/__unit__/Profiles.extended.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/Profiles.extended.unit.test.ts @@ -1376,7 +1376,7 @@ describe("Profiles Unit Tests - function checkCurrentProfile", () => { it("should throw an error if using token auth and is logged out or has expired token", async () => { const globalMocks = await createGlobalMocks(); jest.spyOn(utils, "errorHandling").mockImplementation(); - jest.spyOn(utils, "isUsingTokenAuth").mockResolvedValue(true); + jest.spyOn(utils.ProfilesUtils, "isUsingTokenAuth").mockResolvedValue(true); setupProfilesCheck(globalMocks); await expect(Profiles.getInstance().checkCurrentProfile(globalMocks.testProfile)).resolves.toEqual({ name: "sestest", status: "unverified" }); }); 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 65a2121ff8..74cdb85a8a 100644 --- a/packages/zowe-explorer/__tests__/__unit__/utils/ProfilesUtils.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/utils/ProfilesUtils.unit.test.ts @@ -743,7 +743,7 @@ describe("ProfilesUtils unit tests", () => { jest.spyOn(Profiles.getInstance(), "getDefaultProfile").mockReturnValueOnce({} as any); jest.spyOn(Profiles.getInstance(), "getLoadedProfConfig").mockResolvedValue({ type: "test" } as any); jest.spyOn(Profiles.getInstance(), "getSecurePropsForProfile").mockResolvedValue([]); - await expect(profUtils.isUsingTokenAuth("test")).resolves.toEqual(false); + await expect(profUtils.ProfilesUtils.isUsingTokenAuth("test")).resolves.toEqual(false); }); }); }); diff --git a/packages/zowe-explorer/i18n/sample/package.i18n.json b/packages/zowe-explorer/i18n/sample/package.i18n.json index 5930969b05..5caa899119 100644 --- a/packages/zowe-explorer/i18n/sample/package.i18n.json +++ b/packages/zowe-explorer/i18n/sample/package.i18n.json @@ -2,7 +2,7 @@ "displayName": "Zowe Explorer", "description": "VS Code extension, powered by Zowe CLI, that streamlines interaction with mainframe data sets, USS files, and jobs", "viewsContainers.activitybar": "Zowe Explorer", - "zowe.promptCredentials": "Update Credentials", + "zowe.promptCredentials": "Manage Profile", "zowe.extRefresh": "Refresh Zowe Explorer", "zowe.ds.explorer": "Data Sets", "zowe.uss.explorer": "Unix System Services (USS)", @@ -146,5 +146,8 @@ "createZoweSchema.reload.button": "Reload Window", "createZoweSchema.reload.infoMessage": "Team Configuration file created. Location: {0}. \n Please reload your window.", "copyFile": "Copy", - "pasteFile": "Paste" + "pasteFile": "Paste", + "jobs.sortbyreturncode": "Sort by ReturnCode", + "jobs.sortbyname": "Sort by Name", + "jobs.sortbyid": "Sort by ID" } diff --git a/packages/zowe-explorer/i18n/sample/src/utils/ProfilesUtils.i18n.json b/packages/zowe-explorer/i18n/sample/src/utils/ProfilesUtils.i18n.json index 2ed2cbc4ff..80ab2e3c84 100644 --- a/packages/zowe-explorer/i18n/sample/src/utils/ProfilesUtils.i18n.json +++ b/packages/zowe-explorer/i18n/sample/src/utils/ProfilesUtils.i18n.json @@ -21,5 +21,16 @@ "initializeZoweFolder.error": "Failed to initialize Zowe folder: {0}", "initializeZoweProfiles.success": "Zowe Profiles initialized successfully.", "initializeZoweTempFolder.success": "Zowe Temp folder initialized successfully.", + "profiles.operation.cancelled": "Operation Cancelled", + "editProfileQpItem.editProfile.qpLabel": "Edit profile", + "editProfileQpItem.editProfile.qpDetail": "Update profile information including authentication method", + "updateBasicAuthQpItem.updateCredentials.qpLabel": "Update Credentials", + "updateBasicAuthQpItem.updateCredentials.qpDetail": "Update stored username and password", + "loginQpItem.login.qpLabel": "Login to authentication service", + "loginQpItem.login.qpDetail": "Login to obtain and update stored token value", + "logoutQpItem.logout.qpLabel": "Log out of authentication service", + "logoutQpItem.logout.qpDetail": "Log out to invalidate and remove stored token value", + "qpPlaceholders.qp.basic": "Profile is using basic authentication. Choose a profile action.", + "qpPlaceholders.qp.token": "Profile is using token authentication. Choose a profile action.", "getProfile.notTreeItem": "Tree Item is not a Zowe Explorer item." } diff --git a/packages/zowe-explorer/package.nls.json b/packages/zowe-explorer/package.nls.json index 8bc5d8bf6c..5caa899119 100644 --- a/packages/zowe-explorer/package.nls.json +++ b/packages/zowe-explorer/package.nls.json @@ -2,7 +2,7 @@ "displayName": "Zowe Explorer", "description": "VS Code extension, powered by Zowe CLI, that streamlines interaction with mainframe data sets, USS files, and jobs", "viewsContainers.activitybar": "Zowe Explorer", - "zowe.promptCredentials": "Update Credentials", + "zowe.promptCredentials": "Manage Profile", "zowe.extRefresh": "Refresh Zowe Explorer", "zowe.ds.explorer": "Data Sets", "zowe.uss.explorer": "Unix System Services (USS)", diff --git a/packages/zowe-explorer/src/Profiles.ts b/packages/zowe-explorer/src/Profiles.ts index 1cdf3bd059..47a70a00e4 100644 --- a/packages/zowe-explorer/src/Profiles.ts +++ b/packages/zowe-explorer/src/Profiles.ts @@ -30,7 +30,7 @@ import { getFullPath, getZoweDir, } from "@zowe/zowe-explorer-api"; -import { errorHandling, FilterDescriptor, FilterItem, ProfilesUtils, isUsingTokenAuth } from "./utils/ProfilesUtils"; +import { errorHandling, FilterDescriptor, FilterItem, ProfilesUtils } from "./utils/ProfilesUtils"; import { ZoweExplorerApiRegister } from "./ZoweExplorerApiRegister"; import { ZoweExplorerExtender } from "./ZoweExplorerExtender"; import * as globals from "./globals"; @@ -88,7 +88,7 @@ export class Profiles extends ProfilesCache { public async checkCurrentProfile(theProfile: zowe.imperative.IProfileLoaded): Promise { ZoweLogger.trace("Profiles.checkCurrentProfile called."); let profileStatus: IProfileValidation; - const usingTokenAuth = await isUsingTokenAuth(theProfile.name); + const usingTokenAuth = await ProfilesUtils.isUsingTokenAuth(theProfile.name); if (usingTokenAuth && !theProfile.profile.tokenType) { const error = new zowe.imperative.ImperativeError({ diff --git a/packages/zowe-explorer/src/shared/init.ts b/packages/zowe-explorer/src/shared/init.ts index d023a1a969..acee163494 100644 --- a/packages/zowe-explorer/src/shared/init.ts +++ b/packages/zowe-explorer/src/shared/init.ts @@ -88,7 +88,7 @@ export function registerCommonCommands(context: vscode.ExtensionContext, provide context.subscriptions.push( vscode.commands.registerCommand("zowe.promptCredentials", async (node: IZoweTreeNode) => { - await ProfilesUtils.promptCredentials(node); + await ProfilesUtils.manageProfile(node); }) ); diff --git a/packages/zowe-explorer/src/utils/ProfilesUtils.ts b/packages/zowe-explorer/src/utils/ProfilesUtils.ts index 612284de16..00b4e40b9c 100644 --- a/packages/zowe-explorer/src/utils/ProfilesUtils.ts +++ b/packages/zowe-explorer/src/utils/ProfilesUtils.ts @@ -75,7 +75,7 @@ export async function errorHandling(errorDetails: Error | string, label?: string if (imperativeError.mDetails.additionalDetails) { const tokenError: string = imperativeError.mDetails.additionalDetails; - const isTokenAuth = await isUsingTokenAuth(label); + const isTokenAuth = await ProfilesUtils.isUsingTokenAuth(label); if (tokenError.includes("Token is not valid or expired.") || isTokenAuth) { if (isTheia()) { @@ -132,19 +132,6 @@ export function isTheia(): boolean { return false; } -/** - * Function that checks whether a profile is using token based authentication - * @param profileName the name of the profile to check - * @returns {Promise} a boolean representing whether token based auth is being used or not - */ -export async function isUsingTokenAuth(profileName: string): Promise { - const baseProfile = Profiles.getInstance().getDefaultProfile("base"); - const secureProfileProps = await Profiles.getInstance().getSecurePropsForProfile(profileName); - const secureBaseProfileProps = await Profiles.getInstance().getSecurePropsForProfile(baseProfile?.name); - const profileUsesBasicAuth = secureProfileProps.includes("user") && secureProfileProps.includes("password"); - return (secureProfileProps.includes("tokenValue") || secureBaseProfileProps.includes("tokenValue")) && !profileUsesBasicAuth; -} - /** * Function to update session and profile information in provided node * @param profiles is data source to find profiles @@ -320,6 +307,50 @@ export class ProfilesUtils { } } + public static async manageProfile(node: IZoweTreeNode): Promise { + const profile = node.getProfile(); + switch (true) { + case this.isProfileUsingBasicAuth(profile): { + await this.basicAuthProfileManagement(node); + break; + } + case await this.isUsingTokenAuth(profile.name): { + Gui.infoMessage("profile using token auth."); + break; + } + // will need a case for isUsingCertAuth + default: { + Gui.infoMessage("profile not using stated authentication type."); + break; + } + } + } + + /** + * Function that checks whether a profile is using basic authentication + * @param profile + * @returns {Promise} a boolean representing whether basic auth is being used or not + */ + public static isProfileUsingBasicAuth(profile: imperative.IProfileLoaded): boolean { + if (profile.profile.user && profile.profile.password) { + return true; + } + return false; + } + + /** + * Function that checks whether a profile is using token based authentication + * @param profileName the name of the profile to check + * @returns {Promise} a boolean representing whether token based auth is being used or not + */ + public static async isUsingTokenAuth(profileName: string): Promise { + const baseProfile = Profiles.getInstance().getDefaultProfile("base"); + const secureProfileProps = await Profiles.getInstance().getSecurePropsForProfile(profileName); + const secureBaseProfileProps = await Profiles.getInstance().getSecurePropsForProfile(baseProfile?.name); + const profileUsesBasicAuth = secureProfileProps.includes("user") && secureProfileProps.includes("password"); + return (secureProfileProps.includes("tokenValue") || secureBaseProfileProps.includes("tokenValue")) && !profileUsesBasicAuth; + } + public static async promptCredentials(node: IZoweTreeNode): Promise { ZoweLogger.trace("ProfilesUtils.promptCredentials called."); const mProfileInfo = await Profiles.getInstance().getProfileInfo(); @@ -479,6 +510,95 @@ export class ProfilesUtils { Gui.errorMessage(err.message); } } + + private static AuthQpLabels = { + update: "update-credentials", + edit: "edit-profile", + login: "obtain-token", + logout: "invalidate-token", + }; + private static editProfileQpItem: Record = { + [this.AuthQpLabels.edit]: { + label: localize("editProfileQpItem.editProfile.qpLabel", "Edit profile"), + detail: localize("editProfileQpItem.editProfile.qpDetail", "Update profile information including authentication method"), + }, + }; + private static updateBasicAuthQpItem: Record = { + [this.AuthQpLabels.update]: { + label: localize("updateBasicAuthQpItem.updateCredentials.qpLabel", "Update Credentials"), + detail: localize("updateBasicAuthQpItem.updateCredentials.qpDetail", "Update stored username and password"), + }, + }; + private static loginQpItem: Record = { + [this.AuthQpLabels.login]: { + label: localize("loginQpItem.login.qpLabel", "Login to authentication service"), + detail: localize("loginQpItem.login.qpDetail", "Login to obtain and update stored token value"), + }, + }; + private static logoutQpItem: Record = { + [this.AuthQpLabels.logout]: { + label: localize("logoutQpItem.logout.qpLabel", "Log out of authentication service"), + detail: localize("logoutQpItem.logout.qpDetail", "Log out to invalidate and remove stored token value"), + }, + }; + + private static async basicAuthProfileManagement(node: IZoweTreeNode): Promise { + const profile = node.getProfile(); + const selected = await this.setupProfileManagementQp(imperative.SessConstants.AUTH_TYPE_BASIC, profile.name); + switch (selected) { + case this.updateBasicAuthQpItem[this.AuthQpLabels.update]: { + await this.promptCredentials(node); + break; + } + case this.editProfileQpItem[this.AuthQpLabels.edit]: { + await Profiles.getInstance().editSession(profile, profile.name); + break; + } + default: { + Gui.infoMessage(localize("profiles.operation.cancelled", "Operation Cancelled")); + break; + } + } + } + private static async setupProfileManagementQp(managementType: string, profileName: string): Promise { + const qp = Gui.createQuickPick(); + let quickPickOptions: vscode.QuickPickItem[]; + switch (managementType) { + case imperative.SessConstants.AUTH_TYPE_BASIC: { + quickPickOptions = this.basicAuthQp(); + qp.placeholder = this.qpPlaceholders.basicAuth; + break; + } + case "token": { + quickPickOptions = this.tokenAuthQp(); + qp.placeholder = this.qpPlaceholders.tokenAuth; + break; + } + } + let selectedItem = quickPickOptions[0]; + qp.items = quickPickOptions; + qp.activeItems = [selectedItem]; + qp.show(); + selectedItem = await Gui.resolveQuickPick(qp); + qp.hide(); + return selectedItem; + } + + private static qpPlaceholders = { + basicAuth: localize("qpPlaceholders.qp.basic", "Profile is using basic authentication. Choose a profile action."), + tokenAuth: localize("qpPlaceholders.qp.token", "Profile is using token authentication. Choose a profile action."), + }; + + private static basicAuthQp(): vscode.QuickPickItem[] { + const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.updateBasicAuthQpItem); + quickPickOptions.push(this.editProfileQpItem[this.AuthQpLabels.edit]); + return quickPickOptions; + } + private static tokenAuthQp(): vscode.QuickPickItem[] { + const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.loginQpItem); + quickPickOptions.push(this.editProfileQpItem[this.AuthQpLabels.edit]); + return quickPickOptions; + } } /** From 82c19742811a3600823364f87cdd56c55b8bbc46 Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Thu, 21 Sep 2023 09:42:48 -0400 Subject: [PATCH 02/35] add token auth part Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../zowe-explorer/src/utils/ProfilesUtils.ts | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/packages/zowe-explorer/src/utils/ProfilesUtils.ts b/packages/zowe-explorer/src/utils/ProfilesUtils.ts index 00b4e40b9c..d57d43e9a4 100644 --- a/packages/zowe-explorer/src/utils/ProfilesUtils.ts +++ b/packages/zowe-explorer/src/utils/ProfilesUtils.ts @@ -315,7 +315,7 @@ export class ProfilesUtils { break; } case await this.isUsingTokenAuth(profile.name): { - Gui.infoMessage("profile using token auth."); + await this.tokenAuthProfileManagement(node); break; } // will need a case for isUsingCertAuth @@ -544,7 +544,7 @@ export class ProfilesUtils { private static async basicAuthProfileManagement(node: IZoweTreeNode): Promise { const profile = node.getProfile(); - const selected = await this.setupProfileManagementQp(imperative.SessConstants.AUTH_TYPE_BASIC, profile.name); + const selected = await this.setupProfileManagementQp(imperative.SessConstants.AUTH_TYPE_BASIC, profile); switch (selected) { case this.updateBasicAuthQpItem[this.AuthQpLabels.update]: { await this.promptCredentials(node); @@ -560,7 +560,29 @@ export class ProfilesUtils { } } } - private static async setupProfileManagementQp(managementType: string, profileName: string): Promise { + private static async tokenAuthProfileManagement(node: IZoweTreeNode): Promise { + const profile = node.getProfile(); + const selected = await this.setupProfileManagementQp("token", profile); + switch (selected) { + case this.loginQpItem[this.AuthQpLabels.login]: { + await Profiles.getInstance().ssoLogin(node, profile.name); + break; + } + case this.editProfileQpItem[this.AuthQpLabels.edit]: { + await Profiles.getInstance().editSession(profile, profile.name); + break; + } + case this.logoutQpItem[this.AuthQpLabels.logout]: { + await Profiles.getInstance().ssoLogout(node); + break; + } + default: { + Gui.infoMessage(localize("profiles.operation.cancelled", "Operation Cancelled")); + break; + } + } + } + private static async setupProfileManagementQp(managementType: string, profile: imperative.IProfileLoaded): Promise { const qp = Gui.createQuickPick(); let quickPickOptions: vscode.QuickPickItem[]; switch (managementType) { @@ -570,7 +592,7 @@ export class ProfilesUtils { break; } case "token": { - quickPickOptions = this.tokenAuthQp(); + quickPickOptions = this.tokenAuthQp(profile); qp.placeholder = this.qpPlaceholders.tokenAuth; break; } @@ -594,9 +616,12 @@ export class ProfilesUtils { quickPickOptions.push(this.editProfileQpItem[this.AuthQpLabels.edit]); return quickPickOptions; } - private static tokenAuthQp(): vscode.QuickPickItem[] { + private static tokenAuthQp(profile: imperative.IProfileLoaded): vscode.QuickPickItem[] { const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.loginQpItem); quickPickOptions.push(this.editProfileQpItem[this.AuthQpLabels.edit]); + if (profile.profile.tokenType) { + quickPickOptions.push(this.logoutQpItem[this.AuthQpLabels.logout]); + } return quickPickOptions; } } From 723e3756906ff8a94cf5aac391ad150550f56621 Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Thu, 21 Sep 2023 10:45:10 -0400 Subject: [PATCH 03/35] remove other commands similar to new profile management options Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- packages/zowe-explorer/package.json | 108 --------------------- packages/zowe-explorer/package.nls.json | 7 -- packages/zowe-explorer/src/dataset/init.ts | 10 +- packages/zowe-explorer/src/job/init.ts | 10 +- packages/zowe-explorer/src/uss/init.ts | 10 +- 5 files changed, 15 insertions(+), 130 deletions(-) diff --git a/packages/zowe-explorer/package.json b/packages/zowe-explorer/package.json index 527726260b..6eaccb4e0e 100644 --- a/packages/zowe-explorer/package.json +++ b/packages/zowe-explorer/package.json @@ -262,15 +262,6 @@ "dark": "./resources/dark/plus.svg" } }, - { - "command": "zowe.ds.editSession", - "title": "%editSession%", - "category": "Zowe Explorer", - "icon": { - "light": "./resources/light/edit.svg", - "dark": "./resources/dark/edit.svg" - } - }, { "command": "zowe.ds.deleteProfile", "title": "%deleteProfile%", @@ -480,15 +471,6 @@ "dark": "./resources/dark/plus.svg" } }, - { - "command": "zowe.uss.editSession", - "title": "%editSession%", - "category": "Zowe Explorer", - "icon": { - "light": "./resources/light/edit.svg", - "dark": "./resources/dark/edit.svg" - } - }, { "command": "zowe.uss.deleteProfile", "title": "%deleteProfile%", @@ -658,15 +640,6 @@ "dark": "./resources/dark/refresh.svg" } }, - { - "command": "zowe.jobs.editSession", - "title": "%editSession%", - "category": "Zowe Explorer", - "icon": { - "light": "./resources/light/edit.svg", - "dark": "./resources/dark/edit.svg" - } - }, { "command": "zowe.jobs.deleteProfile", "title": "%deleteProfile%", @@ -968,21 +941,6 @@ "command": "zowe.promptCredentials", "group": "098_zowe_ussProfileAuthentication@3" }, - { - "when": "view == zowe.uss.explorer && viewItem =~ /^(?!.*_fav.*)ussSession.*/ && !listMultiSelection", - "command": "zowe.uss.ssoLogin", - "group": "098_zowe_ussProfileAuthentication@4" - }, - { - "when": "view == zowe.uss.explorer && viewItem =~ /^(?!.*_fav.*)ussSession.*/ && !listMultiSelection", - "command": "zowe.uss.ssoLogout", - "group": "098_zowe_ussProfileAuthentication@5" - }, - { - "when": "viewItem =~ /^(?!.*_fav.*)ussSession.*/ && !listMultiSelection", - "command": "zowe.uss.editSession", - "group": "099_zowe_ussProfileModification@1" - }, { "when": "viewItem =~ /^(?!.*_fav.*)ussSession.*/", "command": "zowe.uss.removeSession", @@ -1183,21 +1141,6 @@ "command": "zowe.promptCredentials", "group": "098_zowe_dsProfileAuthentication@8" }, - { - "when": "view == zowe.ds.explorer && viewItem =~ /^(?!.*_fav.*)session.*/ && !listMultiSelection", - "command": "zowe.ds.ssoLogin", - "group": "098_zowe_dsProfileAuthentication@9" - }, - { - "when": "view == zowe.ds.explorer && viewItem =~ /^(?!.*_fav.*)session.*/ && !listMultiSelection", - "command": "zowe.ds.ssoLogout", - "group": "098_zowe_dsProfileAuthentication@10" - }, - { - "when": "view == zowe.ds.explorer && viewItem =~ /^(?!.*_fav.*)session.*/ && !listMultiSelection", - "command": "zowe.ds.editSession", - "group": "099_zowe_dsProfileModification@0" - }, { "when": "view == zowe.ds.explorer && viewItem =~ /^(?!.*_fav.*)session.*/", "command": "zowe.ds.removeSession", @@ -1348,21 +1291,6 @@ "command": "zowe.promptCredentials", "group": "098_zowe_jobsProfileAuthentication@5" }, - { - "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/ && !listMultiSelection", - "command": "zowe.jobs.ssoLogin", - "group": "098_zowe_jobsProfileAuthentication@6" - }, - { - "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/ && !listMultiSelection", - "command": "zowe.jobs.ssoLogout", - "group": "098_zowe_jobsProfileAuthentication@7" - }, - { - "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/ && !listMultiSelection", - "command": "zowe.jobs.editSession", - "group": "099_zowe_jobsProfileModification@0" - }, { "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/", "command": "zowe.jobs.removeJobsSession", @@ -1414,10 +1342,6 @@ "command": "zowe.ds.showAttributes", "when": "never" }, - { - "command": "zowe.ds.editSession", - "when": "never" - }, { "command": "zowe.ds.createMember", "when": "never" @@ -1510,30 +1434,6 @@ "command": "zowe.jobs.enableValidation", "when": "never" }, - { - "command": "zowe.ds.ssoLogin", - "when": "never" - }, - { - "command": "zowe.ds.ssoLogout", - "when": "never" - }, - { - "command": "zowe.uss.ssoLogin", - "when": "never" - }, - { - "command": "zowe.uss.ssoLogout", - "when": "never" - }, - { - "command": "zowe.jobs.ssoLogin", - "when": "never" - }, - { - "command": "zowe.jobs.ssoLogout", - "when": "never" - }, { "command": "zowe.ds.saveSearch", "when": "never" @@ -1610,10 +1510,6 @@ "command": "zowe.uss.saveSearch", "when": "never" }, - { - "command": "zowe.uss.editSession", - "when": "never" - }, { "command": "zowe.uss.deleteProfile", "when": "never" @@ -1698,10 +1594,6 @@ "command": "zowe.jobs.downloadSpoolBinary", "when": "never" }, - { - "command": "zowe.jobs.editSession", - "when": "never" - }, { "command": "zowe.jobs.removeJobsSession", "when": "never" diff --git a/packages/zowe-explorer/package.nls.json b/packages/zowe-explorer/package.nls.json index 5caa899119..dd0efbc93d 100644 --- a/packages/zowe-explorer/package.nls.json +++ b/packages/zowe-explorer/package.nls.json @@ -15,7 +15,6 @@ "removeFavProfile": "Remove profile from Favorites", "uss.addFavorite": "Add to Favorites", "addSession": "Add Profile to Data Sets View", - "editSession": "Update Profile", "createDataset": "Create New Data Set", "createMember": "Create New Member", "showAttributes": "Show Attributes", @@ -130,12 +129,6 @@ "enableValidation": "Enable Validation for Profile", "uss.enableValidation": "Enable Validation for Profile", "jobs.enableValidation": "Enable Validation for Profile", - "ssoLogin": "Log in to Authentication Service", - "uss.ssoLogin": "Log in to Authentication Service", - "jobs.ssoLogin": "Log in to Authentication Service", - "ssoLogout": "Log out from Authentication Service", - "uss.ssoLogout": "Log out from Authentication Service", - "jobs.ssoLogout": "Log out from Authentication Service", "jobs.refreshJob": "Refresh Job", "jobs.refreshSpool": "Pull from Mainframe", "manualPoll": "Poll Content in Active Editor", diff --git a/packages/zowe-explorer/src/dataset/init.ts b/packages/zowe-explorer/src/dataset/init.ts index 12e81d74eb..f43b4e4a77 100644 --- a/packages/zowe-explorer/src/dataset/init.ts +++ b/packages/zowe-explorer/src/dataset/init.ts @@ -68,9 +68,9 @@ export async function initDatasetProvider(context: vscode.ExtensionContext): Pro }) ); context.subscriptions.push(vscode.commands.registerCommand("zowe.ds.pattern", (node): void => datasetProvider.filterPrompt(node))); - context.subscriptions.push( - vscode.commands.registerCommand("zowe.ds.editSession", async (node) => datasetProvider.editSession(node, datasetProvider)) - ); + // context.subscriptions.push( + // vscode.commands.registerCommand("zowe.ds.editSession", async (node) => datasetProvider.editSession(node, datasetProvider)) + // ); context.subscriptions.push( vscode.commands.registerCommand("zowe.ds.ZoweNode.openPS", async (node) => dsActions.openPS(node, true, datasetProvider)) ); @@ -196,8 +196,8 @@ export async function initDatasetProvider(context: vscode.ExtensionContext): Pro datasetProvider.refreshElement(node); }) ); - context.subscriptions.push(vscode.commands.registerCommand("zowe.ds.ssoLogin", (node: IZoweTreeNode): void => datasetProvider.ssoLogin(node))); - context.subscriptions.push(vscode.commands.registerCommand("zowe.ds.ssoLogout", (node: IZoweTreeNode): void => datasetProvider.ssoLogout(node))); + // context.subscriptions.push(vscode.commands.registerCommand("zowe.ds.ssoLogin", (node: IZoweTreeNode): void => datasetProvider.ssoLogin(node))); + // context.subscriptions.push(vscode.commands.registerCommand("zowe.ds.ssoLogout", (node: IZoweTreeNode): void => datasetProvider.ssoLogout(node))); context.subscriptions.push( vscode.workspace.onDidChangeConfiguration((e) => { datasetProvider.onDidChangeConfiguration(e); diff --git a/packages/zowe-explorer/src/job/init.ts b/packages/zowe-explorer/src/job/init.ts index 55cb416fa2..d0e430b36d 100644 --- a/packages/zowe-explorer/src/job/init.ts +++ b/packages/zowe-explorer/src/job/init.ts @@ -104,9 +104,9 @@ export async function initJobsProvider(context: vscode.ExtensionContext): Promis vscode.commands.registerCommand("zowe.jobs.setJobSpool", async (session, jobId) => jobActions.focusOnJob(jobsProvider, session, jobId)) ); context.subscriptions.push(vscode.commands.registerCommand("zowe.jobs.search", (node): void => jobsProvider.filterPrompt(node))); - context.subscriptions.push( - vscode.commands.registerCommand("zowe.jobs.editSession", async (node): Promise => jobsProvider.editSession(node, jobsProvider)) - ); + // context.subscriptions.push( + // vscode.commands.registerCommand("zowe.jobs.editSession", async (node): Promise => jobsProvider.editSession(node, jobsProvider)) + // ); context.subscriptions.push( vscode.commands.registerCommand("zowe.jobs.addFavorite", async (node, nodeList) => { const selectedNodes = getSelectedNodeList(node, nodeList) as IZoweJobTreeNode[]; @@ -140,8 +140,8 @@ export async function initJobsProvider(context: vscode.ExtensionContext): Promis jobsProvider.refreshElement(node); }) ); - context.subscriptions.push(vscode.commands.registerCommand("zowe.jobs.ssoLogin", (node: IZoweTreeNode): void => jobsProvider.ssoLogin(node))); - context.subscriptions.push(vscode.commands.registerCommand("zowe.jobs.ssoLogout", (node: IZoweTreeNode): void => jobsProvider.ssoLogout(node))); + // context.subscriptions.push(vscode.commands.registerCommand("zowe.jobs.ssoLogin", (node: IZoweTreeNode): void => jobsProvider.ssoLogin(node))); + // context.subscriptions.push(vscode.commands.registerCommand("zowe.jobs.ssoLogout", (node: IZoweTreeNode): void => jobsProvider.ssoLogout(node))); const spoolFileTogglePoll = (startPolling: boolean) => async (node: IZoweTreeNode, nodeList: IZoweTreeNode[]): Promise => { diff --git a/packages/zowe-explorer/src/uss/init.ts b/packages/zowe-explorer/src/uss/init.ts index a4ac9d5ec3..cd3528541c 100644 --- a/packages/zowe-explorer/src/uss/init.ts +++ b/packages/zowe-explorer/src/uss/init.ts @@ -77,9 +77,9 @@ export async function initUSSProvider(context: vscode.ExtensionContext): Promise context.subscriptions.push( vscode.commands.registerCommand("zowe.uss.fullPath", (node: IZoweUSSTreeNode): void => ussFileProvider.filterPrompt(node)) ); - context.subscriptions.push( - vscode.commands.registerCommand("zowe.uss.editSession", async (node) => ussFileProvider.editSession(node, ussFileProvider)) - ); + // context.subscriptions.push( + // vscode.commands.registerCommand("zowe.uss.editSession", async (node) => ussFileProvider.editSession(node, ussFileProvider)) + // ); context.subscriptions.push( vscode.commands.registerCommand("zowe.uss.ZoweUSSNode.open", (node: IZoweUSSTreeNode): void => node.openUSS(false, true, ussFileProvider)) ); @@ -167,8 +167,8 @@ export async function initUSSProvider(context: vscode.ExtensionContext): Promise ussFileProvider.refreshElement(node); }) ); - context.subscriptions.push(vscode.commands.registerCommand("zowe.uss.ssoLogin", (node: IZoweTreeNode): void => ussFileProvider.ssoLogin(node))); - context.subscriptions.push(vscode.commands.registerCommand("zowe.uss.ssoLogout", (node: IZoweTreeNode): void => ussFileProvider.ssoLogout(node))); + // context.subscriptions.push(vscode.commands.registerCommand("zowe.uss.ssoLogin", (node: IZoweTreeNode): void => ussFileProvider.ssoLogin(node))); + // context.subscriptions.push(vscode.commands.registerCommand("zowe.uss.ssoLogout", (node: IZoweTreeNode): void => ussFileProvider.ssoLogout(node))); context.subscriptions.push( vscode.commands.registerCommand("zowe.uss.pasteUssFile", async (node: IZoweUSSTreeNode) => { if (ussFileProvider.copying != null) { From 041bd1fe5184226d910d471389449d9243738737 Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Thu, 21 Sep 2023 12:51:55 -0400 Subject: [PATCH 04/35] add commands back without when clause as to not be breaking change Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../__tests__/__unit__/extension.unit.test.ts | 1 + packages/zowe-explorer/package.json | 84 +++++++++++++++++-- packages/zowe-explorer/package.nls.json | 3 +- packages/zowe-explorer/src/dataset/init.ts | 10 +-- packages/zowe-explorer/src/globals.ts | 2 +- packages/zowe-explorer/src/job/init.ts | 10 +-- packages/zowe-explorer/src/shared/init.ts | 6 ++ packages/zowe-explorer/src/uss/init.ts | 10 +-- 8 files changed, 103 insertions(+), 23 deletions(-) diff --git a/packages/zowe-explorer/__tests__/__unit__/extension.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/extension.unit.test.ts index 0f637993a6..5f111c1d64 100644 --- a/packages/zowe-explorer/__tests__/__unit__/extension.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/extension.unit.test.ts @@ -244,6 +244,7 @@ async function createGlobalMocks() { "zowe.manualPoll", "zowe.updateSecureCredentials", "zowe.promptCredentials", + "zowe.profileManagement", "zowe.openRecentMember", "zowe.searchInAllLoadedItems", "zowe.ds.deleteProfile", diff --git a/packages/zowe-explorer/package.json b/packages/zowe-explorer/package.json index 6eaccb4e0e..0feb932f4f 100644 --- a/packages/zowe-explorer/package.json +++ b/packages/zowe-explorer/package.json @@ -141,6 +141,11 @@ "title": "%zowe.promptCredentials%", "category": "Zowe Explorer" }, + { + "command": "zowe.profileManagement", + "title": "%zowe.profileManagement%", + "category": "Zowe Explorer" + }, { "command": "zowe.extRefresh", "title": "%zowe.extRefresh%", @@ -262,6 +267,15 @@ "dark": "./resources/dark/plus.svg" } }, + { + "command": "zowe.ds.editSession", + "title": "%editSession%", + "category": "Zowe Explorer", + "icon": { + "light": "./resources/light/edit.svg", + "dark": "./resources/dark/edit.svg" + } + }, { "command": "zowe.ds.deleteProfile", "title": "%deleteProfile%", @@ -471,6 +485,15 @@ "dark": "./resources/dark/plus.svg" } }, + { + "command": "zowe.uss.editSession", + "title": "%editSession%", + "category": "Zowe Explorer", + "icon": { + "light": "./resources/light/edit.svg", + "dark": "./resources/dark/edit.svg" + } + }, { "command": "zowe.uss.deleteProfile", "title": "%deleteProfile%", @@ -640,6 +663,15 @@ "dark": "./resources/dark/refresh.svg" } }, + { + "command": "zowe.jobs.editSession", + "title": "%editSession%", + "category": "Zowe Explorer", + "icon": { + "light": "./resources/light/edit.svg", + "dark": "./resources/dark/edit.svg" + } + }, { "command": "zowe.jobs.deleteProfile", "title": "%deleteProfile%", @@ -938,8 +970,8 @@ }, { "when": "view == zowe.uss.explorer && viewItem =~ /^(?!.*_fav.*)ussSession.*/ && !listMultiSelection", - "command": "zowe.promptCredentials", - "group": "098_zowe_ussProfileAuthentication@3" + "command": "zowe.profileManagement", + "group": "099_zowe_ussProfileAuthentication@97" }, { "when": "viewItem =~ /^(?!.*_fav.*)ussSession.*/", @@ -1138,8 +1170,8 @@ }, { "when": "view == zowe.ds.explorer && viewItem =~ /^(?!.*_fav.*)session.*/ && !listMultiSelection", - "command": "zowe.promptCredentials", - "group": "098_zowe_dsProfileAuthentication@8" + "command": "zowe.profileManagement", + "group": "099_zowe_dsProfileAuthentication@97" }, { "when": "view == zowe.ds.explorer && viewItem =~ /^(?!.*_fav.*)session.*/", @@ -1288,8 +1320,8 @@ }, { "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/ && !listMultiSelection", - "command": "zowe.promptCredentials", - "group": "098_zowe_jobsProfileAuthentication@5" + "command": "zowe.profileManagement", + "group": "098_zowe_jobsProfileAuthentication@97" }, { "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/", @@ -1382,6 +1414,10 @@ "command": "zowe.ds.hMigrateDataSet", "when": "never" }, + { + "command": "zowe.ds.editSession", + "when": "never" + }, { "command": "zowe.ds.hRecallDataSet", "when": "never" @@ -1478,6 +1514,30 @@ "command": "zowe.uss.copyUssFile", "when": "never" }, + { + "command": "zowe.ds.ssoLogin", + "when": "never" + }, + { + "command": "zowe.ds.ssoLogout", + "when": "never" + }, + { + "command": "zowe.uss.ssoLogin", + "when": "never" + }, + { + "command": "zowe.uss.ssoLogout", + "when": "never" + }, + { + "command": "zowe.jobs.ssoLogin", + "when": "never" + }, + { + "command": "zowe.jobs.ssoLogout", + "when": "never" + }, { "command": "zowe.uss.pasteUssFile", "when": "never" @@ -1550,6 +1610,10 @@ "command": "zowe.jobs.setJobSpool", "when": "never" }, + { + "command": "zowe.uss.editSession", + "when": "never" + }, { "command": "zowe.jobs.refreshJobsServer", "when": "never" @@ -1598,6 +1662,10 @@ "command": "zowe.jobs.removeJobsSession", "when": "never" }, + { + "command": "zowe.jobs.editSession", + "when": "never" + }, { "command": "zowe.jobs.deleteProfile", "when": "never" @@ -1621,6 +1689,10 @@ { "command": "zowe.jobs.deleteJob", "when": "never" + }, + { + "command": "zowe.profileManagement", + "when": "never" } ] }, diff --git a/packages/zowe-explorer/package.nls.json b/packages/zowe-explorer/package.nls.json index dd0efbc93d..6b9444af1a 100644 --- a/packages/zowe-explorer/package.nls.json +++ b/packages/zowe-explorer/package.nls.json @@ -2,7 +2,8 @@ "displayName": "Zowe Explorer", "description": "VS Code extension, powered by Zowe CLI, that streamlines interaction with mainframe data sets, USS files, and jobs", "viewsContainers.activitybar": "Zowe Explorer", - "zowe.promptCredentials": "Manage Profile", + "zowe.promptCredentials": "Update Credentials", + "zowe.profileManagement": "Manage Profile", "zowe.extRefresh": "Refresh Zowe Explorer", "zowe.ds.explorer": "Data Sets", "zowe.uss.explorer": "Unix System Services (USS)", diff --git a/packages/zowe-explorer/src/dataset/init.ts b/packages/zowe-explorer/src/dataset/init.ts index f43b4e4a77..12e81d74eb 100644 --- a/packages/zowe-explorer/src/dataset/init.ts +++ b/packages/zowe-explorer/src/dataset/init.ts @@ -68,9 +68,9 @@ export async function initDatasetProvider(context: vscode.ExtensionContext): Pro }) ); context.subscriptions.push(vscode.commands.registerCommand("zowe.ds.pattern", (node): void => datasetProvider.filterPrompt(node))); - // context.subscriptions.push( - // vscode.commands.registerCommand("zowe.ds.editSession", async (node) => datasetProvider.editSession(node, datasetProvider)) - // ); + context.subscriptions.push( + vscode.commands.registerCommand("zowe.ds.editSession", async (node) => datasetProvider.editSession(node, datasetProvider)) + ); context.subscriptions.push( vscode.commands.registerCommand("zowe.ds.ZoweNode.openPS", async (node) => dsActions.openPS(node, true, datasetProvider)) ); @@ -196,8 +196,8 @@ export async function initDatasetProvider(context: vscode.ExtensionContext): Pro datasetProvider.refreshElement(node); }) ); - // context.subscriptions.push(vscode.commands.registerCommand("zowe.ds.ssoLogin", (node: IZoweTreeNode): void => datasetProvider.ssoLogin(node))); - // context.subscriptions.push(vscode.commands.registerCommand("zowe.ds.ssoLogout", (node: IZoweTreeNode): void => datasetProvider.ssoLogout(node))); + context.subscriptions.push(vscode.commands.registerCommand("zowe.ds.ssoLogin", (node: IZoweTreeNode): void => datasetProvider.ssoLogin(node))); + context.subscriptions.push(vscode.commands.registerCommand("zowe.ds.ssoLogout", (node: IZoweTreeNode): void => datasetProvider.ssoLogout(node))); context.subscriptions.push( vscode.workspace.onDidChangeConfiguration((e) => { datasetProvider.onDidChangeConfiguration(e); diff --git a/packages/zowe-explorer/src/globals.ts b/packages/zowe-explorer/src/globals.ts index a503fe7332..3d3d338c62 100644 --- a/packages/zowe-explorer/src/globals.ts +++ b/packages/zowe-explorer/src/globals.ts @@ -35,7 +35,7 @@ export let DS_DIR: string; export let CONFIG_PATH; // set during activate export let ISTHEIA = false; // set during activate export let LOG: imperative.Logger; -export const COMMAND_COUNT = 113; +export const COMMAND_COUNT = 114; export const MAX_SEARCH_HISTORY = 5; export const MAX_FILE_HISTORY = 10; export const MS_PER_SEC = 1000; diff --git a/packages/zowe-explorer/src/job/init.ts b/packages/zowe-explorer/src/job/init.ts index d0e430b36d..55cb416fa2 100644 --- a/packages/zowe-explorer/src/job/init.ts +++ b/packages/zowe-explorer/src/job/init.ts @@ -104,9 +104,9 @@ export async function initJobsProvider(context: vscode.ExtensionContext): Promis vscode.commands.registerCommand("zowe.jobs.setJobSpool", async (session, jobId) => jobActions.focusOnJob(jobsProvider, session, jobId)) ); context.subscriptions.push(vscode.commands.registerCommand("zowe.jobs.search", (node): void => jobsProvider.filterPrompt(node))); - // context.subscriptions.push( - // vscode.commands.registerCommand("zowe.jobs.editSession", async (node): Promise => jobsProvider.editSession(node, jobsProvider)) - // ); + context.subscriptions.push( + vscode.commands.registerCommand("zowe.jobs.editSession", async (node): Promise => jobsProvider.editSession(node, jobsProvider)) + ); context.subscriptions.push( vscode.commands.registerCommand("zowe.jobs.addFavorite", async (node, nodeList) => { const selectedNodes = getSelectedNodeList(node, nodeList) as IZoweJobTreeNode[]; @@ -140,8 +140,8 @@ export async function initJobsProvider(context: vscode.ExtensionContext): Promis jobsProvider.refreshElement(node); }) ); - // context.subscriptions.push(vscode.commands.registerCommand("zowe.jobs.ssoLogin", (node: IZoweTreeNode): void => jobsProvider.ssoLogin(node))); - // context.subscriptions.push(vscode.commands.registerCommand("zowe.jobs.ssoLogout", (node: IZoweTreeNode): void => jobsProvider.ssoLogout(node))); + context.subscriptions.push(vscode.commands.registerCommand("zowe.jobs.ssoLogin", (node: IZoweTreeNode): void => jobsProvider.ssoLogin(node))); + context.subscriptions.push(vscode.commands.registerCommand("zowe.jobs.ssoLogout", (node: IZoweTreeNode): void => jobsProvider.ssoLogout(node))); const spoolFileTogglePoll = (startPolling: boolean) => async (node: IZoweTreeNode, nodeList: IZoweTreeNode[]): Promise => { diff --git a/packages/zowe-explorer/src/shared/init.ts b/packages/zowe-explorer/src/shared/init.ts index acee163494..6efb21cad4 100644 --- a/packages/zowe-explorer/src/shared/init.ts +++ b/packages/zowe-explorer/src/shared/init.ts @@ -88,6 +88,12 @@ export function registerCommonCommands(context: vscode.ExtensionContext, provide context.subscriptions.push( vscode.commands.registerCommand("zowe.promptCredentials", async (node: IZoweTreeNode) => { + await ProfilesUtils.promptCredentials(node); + }) + ); + + context.subscriptions.push( + vscode.commands.registerCommand("zowe.profileManagement", async (node: IZoweTreeNode) => { await ProfilesUtils.manageProfile(node); }) ); diff --git a/packages/zowe-explorer/src/uss/init.ts b/packages/zowe-explorer/src/uss/init.ts index cd3528541c..a4ac9d5ec3 100644 --- a/packages/zowe-explorer/src/uss/init.ts +++ b/packages/zowe-explorer/src/uss/init.ts @@ -77,9 +77,9 @@ export async function initUSSProvider(context: vscode.ExtensionContext): Promise context.subscriptions.push( vscode.commands.registerCommand("zowe.uss.fullPath", (node: IZoweUSSTreeNode): void => ussFileProvider.filterPrompt(node)) ); - // context.subscriptions.push( - // vscode.commands.registerCommand("zowe.uss.editSession", async (node) => ussFileProvider.editSession(node, ussFileProvider)) - // ); + context.subscriptions.push( + vscode.commands.registerCommand("zowe.uss.editSession", async (node) => ussFileProvider.editSession(node, ussFileProvider)) + ); context.subscriptions.push( vscode.commands.registerCommand("zowe.uss.ZoweUSSNode.open", (node: IZoweUSSTreeNode): void => node.openUSS(false, true, ussFileProvider)) ); @@ -167,8 +167,8 @@ export async function initUSSProvider(context: vscode.ExtensionContext): Promise ussFileProvider.refreshElement(node); }) ); - // context.subscriptions.push(vscode.commands.registerCommand("zowe.uss.ssoLogin", (node: IZoweTreeNode): void => ussFileProvider.ssoLogin(node))); - // context.subscriptions.push(vscode.commands.registerCommand("zowe.uss.ssoLogout", (node: IZoweTreeNode): void => ussFileProvider.ssoLogout(node))); + context.subscriptions.push(vscode.commands.registerCommand("zowe.uss.ssoLogin", (node: IZoweTreeNode): void => ussFileProvider.ssoLogin(node))); + context.subscriptions.push(vscode.commands.registerCommand("zowe.uss.ssoLogout", (node: IZoweTreeNode): void => ussFileProvider.ssoLogout(node))); context.subscriptions.push( vscode.commands.registerCommand("zowe.uss.pasteUssFile", async (node: IZoweUSSTreeNode) => { if (ussFileProvider.copying != null) { From 7c49e513504b3d4ffce29ab4d5081531bb6eec06 Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Thu, 21 Sep 2023 12:54:02 -0400 Subject: [PATCH 05/35] run localization scripts Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- packages/zowe-explorer/i18n/sample/package.i18n.json | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/zowe-explorer/i18n/sample/package.i18n.json b/packages/zowe-explorer/i18n/sample/package.i18n.json index 5caa899119..6b9444af1a 100644 --- a/packages/zowe-explorer/i18n/sample/package.i18n.json +++ b/packages/zowe-explorer/i18n/sample/package.i18n.json @@ -2,7 +2,8 @@ "displayName": "Zowe Explorer", "description": "VS Code extension, powered by Zowe CLI, that streamlines interaction with mainframe data sets, USS files, and jobs", "viewsContainers.activitybar": "Zowe Explorer", - "zowe.promptCredentials": "Manage Profile", + "zowe.promptCredentials": "Update Credentials", + "zowe.profileManagement": "Manage Profile", "zowe.extRefresh": "Refresh Zowe Explorer", "zowe.ds.explorer": "Data Sets", "zowe.uss.explorer": "Unix System Services (USS)", @@ -15,7 +16,6 @@ "removeFavProfile": "Remove profile from Favorites", "uss.addFavorite": "Add to Favorites", "addSession": "Add Profile to Data Sets View", - "editSession": "Update Profile", "createDataset": "Create New Data Set", "createMember": "Create New Member", "showAttributes": "Show Attributes", @@ -130,12 +130,6 @@ "enableValidation": "Enable Validation for Profile", "uss.enableValidation": "Enable Validation for Profile", "jobs.enableValidation": "Enable Validation for Profile", - "ssoLogin": "Log in to Authentication Service", - "uss.ssoLogin": "Log in to Authentication Service", - "jobs.ssoLogin": "Log in to Authentication Service", - "ssoLogout": "Log out from Authentication Service", - "uss.ssoLogout": "Log out from Authentication Service", - "jobs.ssoLogout": "Log out from Authentication Service", "jobs.refreshJob": "Refresh Job", "jobs.refreshSpool": "Pull from Mainframe", "manualPoll": "Poll Content in Active Editor", From 36e3120621bc0d37226eb540e9fb73b4bff68b52 Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Thu, 21 Sep 2023 12:57:10 -0400 Subject: [PATCH 06/35] add items back to package.nls.json Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- packages/zowe-explorer/i18n/sample/package.i18n.json | 7 +++++++ packages/zowe-explorer/package.nls.json | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/packages/zowe-explorer/i18n/sample/package.i18n.json b/packages/zowe-explorer/i18n/sample/package.i18n.json index 6b9444af1a..a73e7985e5 100644 --- a/packages/zowe-explorer/i18n/sample/package.i18n.json +++ b/packages/zowe-explorer/i18n/sample/package.i18n.json @@ -16,6 +16,7 @@ "removeFavProfile": "Remove profile from Favorites", "uss.addFavorite": "Add to Favorites", "addSession": "Add Profile to Data Sets View", + "editSession": "Update Profile", "createDataset": "Create New Data Set", "createMember": "Create New Member", "showAttributes": "Show Attributes", @@ -130,6 +131,12 @@ "enableValidation": "Enable Validation for Profile", "uss.enableValidation": "Enable Validation for Profile", "jobs.enableValidation": "Enable Validation for Profile", + "ssoLogin": "Log in to Authentication Service", + "uss.ssoLogin": "Log in to Authentication Service", + "jobs.ssoLogin": "Log in to Authentication Service", + "ssoLogout": "Log out from Authentication Service", + "uss.ssoLogout": "Log out from Authentication Service", + "jobs.ssoLogout": "Log out from Authentication Service", "jobs.refreshJob": "Refresh Job", "jobs.refreshSpool": "Pull from Mainframe", "manualPoll": "Poll Content in Active Editor", diff --git a/packages/zowe-explorer/package.nls.json b/packages/zowe-explorer/package.nls.json index 6b9444af1a..a73e7985e5 100644 --- a/packages/zowe-explorer/package.nls.json +++ b/packages/zowe-explorer/package.nls.json @@ -16,6 +16,7 @@ "removeFavProfile": "Remove profile from Favorites", "uss.addFavorite": "Add to Favorites", "addSession": "Add Profile to Data Sets View", + "editSession": "Update Profile", "createDataset": "Create New Data Set", "createMember": "Create New Member", "showAttributes": "Show Attributes", @@ -130,6 +131,12 @@ "enableValidation": "Enable Validation for Profile", "uss.enableValidation": "Enable Validation for Profile", "jobs.enableValidation": "Enable Validation for Profile", + "ssoLogin": "Log in to Authentication Service", + "uss.ssoLogin": "Log in to Authentication Service", + "jobs.ssoLogin": "Log in to Authentication Service", + "ssoLogout": "Log out from Authentication Service", + "uss.ssoLogout": "Log out from Authentication Service", + "jobs.ssoLogout": "Log out from Authentication Service", "jobs.refreshJob": "Refresh Job", "jobs.refreshSpool": "Pull from Mainframe", "manualPoll": "Poll Content in Active Editor", From f6010fc581398092b466984844dfeaf731981dbf Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Thu, 21 Sep 2023 13:19:08 -0400 Subject: [PATCH 07/35] realign for easier comparison Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- packages/zowe-explorer/package.json | 54 ++++++++++++++--------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/packages/zowe-explorer/package.json b/packages/zowe-explorer/package.json index 0feb932f4f..773b4556e8 100644 --- a/packages/zowe-explorer/package.json +++ b/packages/zowe-explorer/package.json @@ -1374,6 +1374,10 @@ "command": "zowe.ds.showAttributes", "when": "never" }, + { + "command": "zowe.ds.editSession", + "when": "never" + }, { "command": "zowe.ds.createMember", "when": "never" @@ -1414,10 +1418,6 @@ "command": "zowe.ds.hMigrateDataSet", "when": "never" }, - { - "command": "zowe.ds.editSession", - "when": "never" - }, { "command": "zowe.ds.hRecallDataSet", "when": "never" @@ -1471,71 +1471,71 @@ "when": "never" }, { - "command": "zowe.ds.saveSearch", + "command": "zowe.ds.ssoLogin", "when": "never" }, { - "command": "zowe.ds.removeSavedSearch", + "command": "zowe.ds.ssoLogout", "when": "never" }, { - "command": "zowe.uss.fullPath", + "command": "zowe.uss.ssoLogin", "when": "never" }, { - "command": "zowe.uss.copyPath", + "command": "zowe.uss.ssoLogout", "when": "never" }, { - "command": "zowe.jobs.search", + "command": "zowe.jobs.ssoLogin", "when": "never" }, { - "command": "zowe.uss.refreshUSS", + "command": "zowe.jobs.ssoLogout", "when": "never" }, { - "command": "zowe.uss.refreshDirectory", + "command": "zowe.ds.saveSearch", "when": "never" }, { - "command": "zowe.uss.createFolder", + "command": "zowe.ds.removeSavedSearch", "when": "never" }, { - "command": "zowe.uss.createFile", + "command": "zowe.uss.fullPath", "when": "never" }, { - "command": "zowe.uss.uploadDialog", + "command": "zowe.uss.copyPath", "when": "never" }, { - "command": "zowe.uss.copyUssFile", + "command": "zowe.jobs.search", "when": "never" }, { - "command": "zowe.ds.ssoLogin", + "command": "zowe.uss.refreshUSS", "when": "never" }, { - "command": "zowe.ds.ssoLogout", + "command": "zowe.uss.refreshDirectory", "when": "never" }, { - "command": "zowe.uss.ssoLogin", + "command": "zowe.uss.createFolder", "when": "never" }, { - "command": "zowe.uss.ssoLogout", + "command": "zowe.uss.createFile", "when": "never" }, { - "command": "zowe.jobs.ssoLogin", + "command": "zowe.uss.uploadDialog", "when": "never" }, { - "command": "zowe.jobs.ssoLogout", + "command": "zowe.uss.copyUssFile", "when": "never" }, { @@ -1570,6 +1570,10 @@ "command": "zowe.uss.saveSearch", "when": "never" }, + { + "command": "zowe.uss.editSession", + "when": "never" + }, { "command": "zowe.uss.deleteProfile", "when": "never" @@ -1610,10 +1614,6 @@ "command": "zowe.jobs.setJobSpool", "when": "never" }, - { - "command": "zowe.uss.editSession", - "when": "never" - }, { "command": "zowe.jobs.refreshJobsServer", "when": "never" @@ -1659,11 +1659,11 @@ "when": "never" }, { - "command": "zowe.jobs.removeJobsSession", + "command": "zowe.jobs.editSession", "when": "never" }, { - "command": "zowe.jobs.editSession", + "command": "zowe.jobs.removeJobsSession", "when": "never" }, { From d6346a7a7d8f61cd47bb37b5f3d63756e994f95a Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Thu, 21 Sep 2023 13:51:38 -0400 Subject: [PATCH 08/35] handle case of no authentication method shown for profile Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../sample/src/utils/ProfilesUtils.i18n.json | 1 + .../zowe-explorer/src/utils/ProfilesUtils.ts | 85 +++++++++++-------- 2 files changed, 49 insertions(+), 37 deletions(-) diff --git a/packages/zowe-explorer/i18n/sample/src/utils/ProfilesUtils.i18n.json b/packages/zowe-explorer/i18n/sample/src/utils/ProfilesUtils.i18n.json index 80ab2e3c84..0c0a0b8f76 100644 --- a/packages/zowe-explorer/i18n/sample/src/utils/ProfilesUtils.i18n.json +++ b/packages/zowe-explorer/i18n/sample/src/utils/ProfilesUtils.i18n.json @@ -32,5 +32,6 @@ "logoutQpItem.logout.qpDetail": "Log out to invalidate and remove stored token value", "qpPlaceholders.qp.basic": "Profile is using basic authentication. Choose a profile action.", "qpPlaceholders.qp.token": "Profile is using token authentication. Choose a profile action.", + "qpPlaceholders.qp.choose": "Profile doesn't specify an authentication method. Choose a profile action.", "getProfile.notTreeItem": "Tree Item is not a Zowe Explorer item." } diff --git a/packages/zowe-explorer/src/utils/ProfilesUtils.ts b/packages/zowe-explorer/src/utils/ProfilesUtils.ts index d57d43e9a4..3039737640 100644 --- a/packages/zowe-explorer/src/utils/ProfilesUtils.ts +++ b/packages/zowe-explorer/src/utils/ProfilesUtils.ts @@ -320,7 +320,7 @@ export class ProfilesUtils { } // will need a case for isUsingCertAuth default: { - Gui.infoMessage("profile not using stated authentication type."); + await this.chooseAuthProfileManagement(node); break; } } @@ -520,67 +520,42 @@ export class ProfilesUtils { private static editProfileQpItem: Record = { [this.AuthQpLabels.edit]: { label: localize("editProfileQpItem.editProfile.qpLabel", "Edit profile"), - detail: localize("editProfileQpItem.editProfile.qpDetail", "Update profile information including authentication method"), + description: localize("editProfileQpItem.editProfile.qpDetail", "Update profile information including authentication method"), }, }; private static updateBasicAuthQpItem: Record = { [this.AuthQpLabels.update]: { label: localize("updateBasicAuthQpItem.updateCredentials.qpLabel", "Update Credentials"), - detail: localize("updateBasicAuthQpItem.updateCredentials.qpDetail", "Update stored username and password"), + description: localize("updateBasicAuthQpItem.updateCredentials.qpDetail", "Update stored username and password"), }, }; private static loginQpItem: Record = { [this.AuthQpLabels.login]: { label: localize("loginQpItem.login.qpLabel", "Login to authentication service"), - detail: localize("loginQpItem.login.qpDetail", "Login to obtain and update stored token value"), + description: localize("loginQpItem.login.qpDetail", "Login to obtain and update stored token value"), }, }; private static logoutQpItem: Record = { [this.AuthQpLabels.logout]: { label: localize("logoutQpItem.logout.qpLabel", "Log out of authentication service"), - detail: localize("logoutQpItem.logout.qpDetail", "Log out to invalidate and remove stored token value"), + description: localize("logoutQpItem.logout.qpDetail", "Log out to invalidate and remove stored token value"), }, }; private static async basicAuthProfileManagement(node: IZoweTreeNode): Promise { const profile = node.getProfile(); const selected = await this.setupProfileManagementQp(imperative.SessConstants.AUTH_TYPE_BASIC, profile); - switch (selected) { - case this.updateBasicAuthQpItem[this.AuthQpLabels.update]: { - await this.promptCredentials(node); - break; - } - case this.editProfileQpItem[this.AuthQpLabels.edit]: { - await Profiles.getInstance().editSession(profile, profile.name); - break; - } - default: { - Gui.infoMessage(localize("profiles.operation.cancelled", "Operation Cancelled")); - break; - } - } + await this.handleAuthSelection(selected, node, profile); } private static async tokenAuthProfileManagement(node: IZoweTreeNode): Promise { const profile = node.getProfile(); const selected = await this.setupProfileManagementQp("token", profile); - switch (selected) { - case this.loginQpItem[this.AuthQpLabels.login]: { - await Profiles.getInstance().ssoLogin(node, profile.name); - break; - } - case this.editProfileQpItem[this.AuthQpLabels.edit]: { - await Profiles.getInstance().editSession(profile, profile.name); - break; - } - case this.logoutQpItem[this.AuthQpLabels.logout]: { - await Profiles.getInstance().ssoLogout(node); - break; - } - default: { - Gui.infoMessage(localize("profiles.operation.cancelled", "Operation Cancelled")); - break; - } - } + await this.handleAuthSelection(selected, node, profile); + } + private static async chooseAuthProfileManagement(node: IZoweTreeNode): Promise { + const profile = node.getProfile(); + const selected = await this.setupProfileManagementQp(null, profile); + await this.handleAuthSelection(selected, node, profile); } private static async setupProfileManagementQp(managementType: string, profile: imperative.IProfileLoaded): Promise { const qp = Gui.createQuickPick(); @@ -596,6 +571,11 @@ export class ProfilesUtils { qp.placeholder = this.qpPlaceholders.tokenAuth; break; } + default: { + quickPickOptions = this.chooseAuthQp(); + qp.placeholder = this.qpPlaceholders.chooseAuth; + break; + } } let selectedItem = quickPickOptions[0]; qp.items = quickPickOptions; @@ -605,10 +585,35 @@ export class ProfilesUtils { qp.hide(); return selectedItem; } + private static async handleAuthSelection(selected: vscode.QuickPickItem, node: IZoweTreeNode, profile: imperative.IProfileLoaded): Promise { + switch (selected) { + case this.loginQpItem[this.AuthQpLabels.login]: { + await Profiles.getInstance().ssoLogin(node, profile.name); + break; + } + case this.editProfileQpItem[this.AuthQpLabels.edit]: { + await Profiles.getInstance().editSession(profile, profile.name); + break; + } + case this.logoutQpItem[this.AuthQpLabels.logout]: { + await Profiles.getInstance().ssoLogout(node); + break; + } + case this.updateBasicAuthQpItem[this.AuthQpLabels.update]: { + await this.promptCredentials(node); + break; + } + default: { + Gui.infoMessage(localize("profiles.operation.cancelled", "Operation Cancelled")); + break; + } + } + } private static qpPlaceholders = { basicAuth: localize("qpPlaceholders.qp.basic", "Profile is using basic authentication. Choose a profile action."), tokenAuth: localize("qpPlaceholders.qp.token", "Profile is using token authentication. Choose a profile action."), + chooseAuth: localize("qpPlaceholders.qp.choose", "Profile doesn't specify an authentication method. Choose a profile action."), }; private static basicAuthQp(): vscode.QuickPickItem[] { @@ -624,6 +629,12 @@ export class ProfilesUtils { } return quickPickOptions; } + private static chooseAuthQp(): vscode.QuickPickItem[] { + const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.updateBasicAuthQpItem); + quickPickOptions.push(this.loginQpItem[this.AuthQpLabels.login]); + quickPickOptions.push(this.editProfileQpItem[this.AuthQpLabels.edit]); + return quickPickOptions; + } } /** From 84cf3b56505d319f4987a5ac4c5b05c6933c7032 Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Thu, 21 Sep 2023 14:01:35 -0400 Subject: [PATCH 09/35] add changelog Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- packages/zowe-explorer/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/zowe-explorer/CHANGELOG.md b/packages/zowe-explorer/CHANGELOG.md index d6550315ec..5703f1ed60 100644 --- a/packages/zowe-explorer/CHANGELOG.md +++ b/packages/zowe-explorer/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen ### New features and enhancements - Added "Sort Jobs" feature for job nodes in Jobs tree view. [#2257](https://github.com/zowe/vscode-extension-for-zowe/issues/2251) +- Introduce a new user interface for managing profiles via right-click action "Manage Profile". ### Bug fixes From fb680bb9b955a67067f98be6f96e2ee668730e5f Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Fri, 22 Sep 2023 09:52:20 -0400 Subject: [PATCH 10/35] update strings in different scenarios Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../sample/src/utils/ProfilesUtils.i18n.json | 12 ++++++----- .../zowe-explorer/src/utils/ProfilesUtils.ts | 20 ++++++++++++------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/packages/zowe-explorer/i18n/sample/src/utils/ProfilesUtils.i18n.json b/packages/zowe-explorer/i18n/sample/src/utils/ProfilesUtils.i18n.json index 0c0a0b8f76..e41dd4a0b8 100644 --- a/packages/zowe-explorer/i18n/sample/src/utils/ProfilesUtils.i18n.json +++ b/packages/zowe-explorer/i18n/sample/src/utils/ProfilesUtils.i18n.json @@ -22,13 +22,15 @@ "initializeZoweProfiles.success": "Zowe Profiles initialized successfully.", "initializeZoweTempFolder.success": "Zowe Temp folder initialized successfully.", "profiles.operation.cancelled": "Operation Cancelled", - "editProfileQpItem.editProfile.qpLabel": "Edit profile", - "editProfileQpItem.editProfile.qpDetail": "Update profile information including authentication method", - "updateBasicAuthQpItem.updateCredentials.qpLabel": "Update Credentials", + "editProfileQpItem.editProfile.qpLabel": "$(pencil) Edit profile", + "editProfileQpItem.editProfile.qpDetail": "Update profile connection information", + "updateBasicAuthQpItem.updateCredentials.qpLabel": "$(refresh) Update Credentials", "updateBasicAuthQpItem.updateCredentials.qpDetail": "Update stored username and password", - "loginQpItem.login.qpLabel": "Login to authentication service", + "addBasicAuthQpItem.addCredentials.qpLabel": "$(plus) Add Credentials", + "addBasicAuthQpItem.addCredentials.qpDetail": "Add username and password for basic authentication", + "loginQpItem.login.qpLabel": "$(arrow-right) Login to authentication service", "loginQpItem.login.qpDetail": "Login to obtain and update stored token value", - "logoutQpItem.logout.qpLabel": "Log out of authentication service", + "logoutQpItem.logout.qpLabel": "$(arrow-left) Log out of authentication service", "logoutQpItem.logout.qpDetail": "Log out to invalidate and remove stored token value", "qpPlaceholders.qp.basic": "Profile is using basic authentication. Choose a profile action.", "qpPlaceholders.qp.token": "Profile is using token authentication. Choose a profile action.", diff --git a/packages/zowe-explorer/src/utils/ProfilesUtils.ts b/packages/zowe-explorer/src/utils/ProfilesUtils.ts index 3039737640..8bfa3fdaf4 100644 --- a/packages/zowe-explorer/src/utils/ProfilesUtils.ts +++ b/packages/zowe-explorer/src/utils/ProfilesUtils.ts @@ -519,25 +519,31 @@ export class ProfilesUtils { }; private static editProfileQpItem: Record = { [this.AuthQpLabels.edit]: { - label: localize("editProfileQpItem.editProfile.qpLabel", "Edit profile"), - description: localize("editProfileQpItem.editProfile.qpDetail", "Update profile information including authentication method"), + label: localize("editProfileQpItem.editProfile.qpLabel", "$(pencil) Edit profile"), + description: localize("editProfileQpItem.editProfile.qpDetail", "Update profile connection information"), }, }; private static updateBasicAuthQpItem: Record = { [this.AuthQpLabels.update]: { - label: localize("updateBasicAuthQpItem.updateCredentials.qpLabel", "Update Credentials"), + label: localize("updateBasicAuthQpItem.updateCredentials.qpLabel", "$(refresh) Update Credentials"), description: localize("updateBasicAuthQpItem.updateCredentials.qpDetail", "Update stored username and password"), }, }; + private static addBasicAuthQpItem: Record = { + [this.AuthQpLabels.update]: { + label: localize("addBasicAuthQpItem.addCredentials.qpLabel", "$(plus) Add Credentials"), + description: localize("addBasicAuthQpItem.addCredentials.qpDetail", "Add username and password for basic authentication"), + }, + }; private static loginQpItem: Record = { [this.AuthQpLabels.login]: { - label: localize("loginQpItem.login.qpLabel", "Login to authentication service"), + label: localize("loginQpItem.login.qpLabel", "$(arrow-right) Login to authentication service"), description: localize("loginQpItem.login.qpDetail", "Login to obtain and update stored token value"), }, }; private static logoutQpItem: Record = { [this.AuthQpLabels.logout]: { - label: localize("logoutQpItem.logout.qpLabel", "Log out of authentication service"), + label: localize("logoutQpItem.logout.qpLabel", "$(arrow-left) Log out of authentication service"), description: localize("logoutQpItem.logout.qpDetail", "Log out to invalidate and remove stored token value"), }, }; @@ -623,14 +629,14 @@ export class ProfilesUtils { } private static tokenAuthQp(profile: imperative.IProfileLoaded): vscode.QuickPickItem[] { const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.loginQpItem); - quickPickOptions.push(this.editProfileQpItem[this.AuthQpLabels.edit]); if (profile.profile.tokenType) { quickPickOptions.push(this.logoutQpItem[this.AuthQpLabels.logout]); } + quickPickOptions.push(this.editProfileQpItem[this.AuthQpLabels.edit]); return quickPickOptions; } private static chooseAuthQp(): vscode.QuickPickItem[] { - const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.updateBasicAuthQpItem); + const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.addBasicAuthQpItem); quickPickOptions.push(this.loginQpItem[this.AuthQpLabels.login]); quickPickOptions.push(this.editProfileQpItem[this.AuthQpLabels.edit]); return quickPickOptions; From 6a4d068f60751e5354f620387c58062f3c2e164c Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Fri, 22 Sep 2023 11:18:33 -0400 Subject: [PATCH 11/35] separate the work Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../src/utils/ProfileManagement.i18n.json | 16 ++ .../sample/src/utils/ProfilesUtils.i18n.json | 14 -- packages/zowe-explorer/src/shared/init.ts | 3 +- .../src/utils/ProfileManagement.ts | 178 ++++++++++++++++++ .../zowe-explorer/src/utils/ProfilesUtils.ts | 150 --------------- 5 files changed, 196 insertions(+), 165 deletions(-) create mode 100644 packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json create mode 100644 packages/zowe-explorer/src/utils/ProfileManagement.ts diff --git a/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json b/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json new file mode 100644 index 0000000000..05e99d6246 --- /dev/null +++ b/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json @@ -0,0 +1,16 @@ +{ + "profiles.operation.cancelled": "Operation Cancelled", + "editProfileQpItem.editProfile.qpLabel": "$(pencil) Edit profile", + "editProfileQpItem.editProfile.qpDetail": "Update profile connection information", + "updateBasicAuthQpItem.updateCredentials.qpLabel": "$(refresh) Update Credentials", + "updateBasicAuthQpItem.updateCredentials.qpDetail": "Update stored username and password", + "addBasicAuthQpItem.addCredentials.qpLabel": "$(plus) Add Credentials", + "addBasicAuthQpItem.addCredentials.qpDetail": "Add username and password for basic authentication", + "loginQpItem.login.qpLabel": "$(arrow-right) Log in to authentication service", + "loginQpItem.login.qpDetail": "Log in to obtain a new token value", + "logoutQpItem.logout.qpLabel": "$(arrow-left) Log out of authentication service", + "logoutQpItem.logout.qpDetail": "Log out to invalidate and remove stored token value", + "qpPlaceholders.qp.basic": "Profile is using basic authentication. Choose a profile action.", + "qpPlaceholders.qp.token": "Profile is using token authentication. Choose a profile action.", + "qpPlaceholders.qp.choose": "Profile doesn't specify an authentication method. Choose a profile action." +} diff --git a/packages/zowe-explorer/i18n/sample/src/utils/ProfilesUtils.i18n.json b/packages/zowe-explorer/i18n/sample/src/utils/ProfilesUtils.i18n.json index e41dd4a0b8..2ed2cbc4ff 100644 --- a/packages/zowe-explorer/i18n/sample/src/utils/ProfilesUtils.i18n.json +++ b/packages/zowe-explorer/i18n/sample/src/utils/ProfilesUtils.i18n.json @@ -21,19 +21,5 @@ "initializeZoweFolder.error": "Failed to initialize Zowe folder: {0}", "initializeZoweProfiles.success": "Zowe Profiles initialized successfully.", "initializeZoweTempFolder.success": "Zowe Temp folder initialized successfully.", - "profiles.operation.cancelled": "Operation Cancelled", - "editProfileQpItem.editProfile.qpLabel": "$(pencil) Edit profile", - "editProfileQpItem.editProfile.qpDetail": "Update profile connection information", - "updateBasicAuthQpItem.updateCredentials.qpLabel": "$(refresh) Update Credentials", - "updateBasicAuthQpItem.updateCredentials.qpDetail": "Update stored username and password", - "addBasicAuthQpItem.addCredentials.qpLabel": "$(plus) Add Credentials", - "addBasicAuthQpItem.addCredentials.qpDetail": "Add username and password for basic authentication", - "loginQpItem.login.qpLabel": "$(arrow-right) Login to authentication service", - "loginQpItem.login.qpDetail": "Login to obtain and update stored token value", - "logoutQpItem.logout.qpLabel": "$(arrow-left) Log out of authentication service", - "logoutQpItem.logout.qpDetail": "Log out to invalidate and remove stored token value", - "qpPlaceholders.qp.basic": "Profile is using basic authentication. Choose a profile action.", - "qpPlaceholders.qp.token": "Profile is using token authentication. Choose a profile action.", - "qpPlaceholders.qp.choose": "Profile doesn't specify an authentication method. Choose a profile action.", "getProfile.notTreeItem": "Tree Item is not a Zowe Explorer item." } diff --git a/packages/zowe-explorer/src/shared/init.ts b/packages/zowe-explorer/src/shared/init.ts index 6efb21cad4..67fc00fb3b 100644 --- a/packages/zowe-explorer/src/shared/init.ts +++ b/packages/zowe-explorer/src/shared/init.ts @@ -27,6 +27,7 @@ import { ZoweLogger } from "../utils/LoggerUtils"; import { ZoweSaveQueue } from "../abstract/ZoweSaveQueue"; import { SettingsConfig } from "../utils/SettingsConfig"; import { spoolFilePollEvent } from "../job/actions"; +import { ProfileManagement } from "../utils/ProfileManagement"; // Set up localization nls.config({ @@ -94,7 +95,7 @@ export function registerCommonCommands(context: vscode.ExtensionContext, provide context.subscriptions.push( vscode.commands.registerCommand("zowe.profileManagement", async (node: IZoweTreeNode) => { - await ProfilesUtils.manageProfile(node); + await ProfileManagement.manageProfile(node); }) ); diff --git a/packages/zowe-explorer/src/utils/ProfileManagement.ts b/packages/zowe-explorer/src/utils/ProfileManagement.ts new file mode 100644 index 0000000000..8a4c893561 --- /dev/null +++ b/packages/zowe-explorer/src/utils/ProfileManagement.ts @@ -0,0 +1,178 @@ +/** + * This program and the accompanying materials are made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Copyright Contributors to the Zowe Project. + * + */ + +import * as vscode from "vscode"; +import { Gui, IZoweTreeNode, imperative } from "@zowe/zowe-explorer-api"; +import { ZoweLogger } from "./LoggerUtils"; +import { ProfilesUtils } from "./ProfilesUtils"; +import * as nls from "vscode-nls"; +import { Profiles } from "../Profiles"; + +// Set up localization +nls.config({ + messageFormat: nls.MessageFormat.bundle, + bundleFormat: nls.BundleFormat.standalone, +})(); +const localize: nls.LocalizeFunc = nls.loadMessageBundle(); + +export class ProfileManagement { + public static async manageProfile(node: IZoweTreeNode): Promise { + const profile = node.getProfile(); + switch (true) { + case ProfilesUtils.isProfileUsingBasicAuth(profile): { + ZoweLogger.debug(`Profile ${profile.name} is using basic authentication.`); + await this.basicAuthProfileManagement(node); + break; + } + case await ProfilesUtils.isUsingTokenAuth(profile.name): { + ZoweLogger.debug(`Profile ${profile.name} is using token authentication.`); + await this.tokenAuthProfileManagement(node); + break; + } + // will need a case for isUsingCertAuth + default: { + ZoweLogger.debug(`Profile ${profile.name} authentication method is unkown.`); + await this.chooseAuthProfileManagement(node); + break; + } + } + } + private static AuthQpLabels = { + update: "update-credentials", + edit: "edit-profile", + login: "obtain-token", + logout: "invalidate-token", + }; + private static editProfileQpItem: Record = { + [this.AuthQpLabels.edit]: { + label: localize("editProfileQpItem.editProfile.qpLabel", "$(pencil) Edit profile"), + description: localize("editProfileQpItem.editProfile.qpDetail", "Update profile connection information"), + }, + }; + private static updateBasicAuthQpItem: Record = { + [this.AuthQpLabels.update]: { + label: localize("updateBasicAuthQpItem.updateCredentials.qpLabel", "$(refresh) Update Credentials"), + description: localize("updateBasicAuthQpItem.updateCredentials.qpDetail", "Update stored username and password"), + }, + }; + private static addBasicAuthQpItem: Record = { + [this.AuthQpLabels.update]: { + label: localize("addBasicAuthQpItem.addCredentials.qpLabel", "$(plus) Add Credentials"), + description: localize("addBasicAuthQpItem.addCredentials.qpDetail", "Add username and password for basic authentication"), + }, + }; + private static loginQpItem: Record = { + [this.AuthQpLabels.login]: { + label: localize("loginQpItem.login.qpLabel", "$(arrow-right) Log in to authentication service"), + description: localize("loginQpItem.login.qpDetail", "Log in to obtain a new token value"), + }, + }; + private static logoutQpItem: Record = { + [this.AuthQpLabels.logout]: { + label: localize("logoutQpItem.logout.qpLabel", "$(arrow-left) Log out of authentication service"), + description: localize("logoutQpItem.logout.qpDetail", "Log out to invalidate and remove stored token value"), + }, + }; + + private static async basicAuthProfileManagement(node: IZoweTreeNode): Promise { + const profile = node.getProfile(); + const selected = await this.setupProfileManagementQp(imperative.SessConstants.AUTH_TYPE_BASIC, profile); + await this.handleAuthSelection(selected, node, profile); + } + private static async tokenAuthProfileManagement(node: IZoweTreeNode): Promise { + const profile = node.getProfile(); + const selected = await this.setupProfileManagementQp("token", profile); + await this.handleAuthSelection(selected, node, profile); + } + private static async chooseAuthProfileManagement(node: IZoweTreeNode): Promise { + const profile = node.getProfile(); + const selected = await this.setupProfileManagementQp(null, profile); + await this.handleAuthSelection(selected, node, profile); + } + private static async setupProfileManagementQp(managementType: string, profile: imperative.IProfileLoaded): Promise { + const qp = Gui.createQuickPick(); + let quickPickOptions: vscode.QuickPickItem[]; + switch (managementType) { + case imperative.SessConstants.AUTH_TYPE_BASIC: { + quickPickOptions = this.basicAuthQp(); + qp.placeholder = this.qpPlaceholders.basicAuth; + break; + } + case "token": { + quickPickOptions = this.tokenAuthQp(profile); + qp.placeholder = this.qpPlaceholders.tokenAuth; + break; + } + default: { + quickPickOptions = this.chooseAuthQp(); + qp.placeholder = this.qpPlaceholders.chooseAuth; + break; + } + } + let selectedItem = quickPickOptions[0]; + qp.items = quickPickOptions; + qp.activeItems = [selectedItem]; + qp.show(); + selectedItem = await Gui.resolveQuickPick(qp); + qp.hide(); + return selectedItem; + } + private static async handleAuthSelection(selected: vscode.QuickPickItem, node: IZoweTreeNode, profile: imperative.IProfileLoaded): Promise { + switch (selected) { + case this.loginQpItem[this.AuthQpLabels.login]: { + await Profiles.getInstance().ssoLogin(node, profile.name); + break; + } + case this.editProfileQpItem[this.AuthQpLabels.edit]: { + await Profiles.getInstance().editSession(profile, profile.name); + break; + } + case this.logoutQpItem[this.AuthQpLabels.logout]: { + await Profiles.getInstance().ssoLogout(node); + break; + } + case this.updateBasicAuthQpItem[this.AuthQpLabels.update]: { + await ProfilesUtils.promptCredentials(node); + break; + } + default: { + Gui.infoMessage(localize("profiles.operation.cancelled", "Operation Cancelled")); + break; + } + } + } + + private static qpPlaceholders = { + basicAuth: localize("qpPlaceholders.qp.basic", "Profile is using basic authentication. Choose a profile action."), + tokenAuth: localize("qpPlaceholders.qp.token", "Profile is using token authentication. Choose a profile action."), + chooseAuth: localize("qpPlaceholders.qp.choose", "Profile doesn't specify an authentication method. Choose a profile action."), + }; + + private static basicAuthQp(): vscode.QuickPickItem[] { + const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.updateBasicAuthQpItem); + quickPickOptions.push(this.editProfileQpItem[this.AuthQpLabels.edit]); + return quickPickOptions; + } + private static tokenAuthQp(profile: imperative.IProfileLoaded): vscode.QuickPickItem[] { + const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.loginQpItem); + if (profile.profile.tokenType) { + quickPickOptions.push(this.logoutQpItem[this.AuthQpLabels.logout]); + } + quickPickOptions.push(this.editProfileQpItem[this.AuthQpLabels.edit]); + return quickPickOptions; + } + private static chooseAuthQp(): vscode.QuickPickItem[] { + const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.addBasicAuthQpItem); + quickPickOptions.push(this.loginQpItem[this.AuthQpLabels.login]); + quickPickOptions.push(this.editProfileQpItem[this.AuthQpLabels.edit]); + return quickPickOptions; + } +} diff --git a/packages/zowe-explorer/src/utils/ProfilesUtils.ts b/packages/zowe-explorer/src/utils/ProfilesUtils.ts index 8bfa3fdaf4..2a8dd2979a 100644 --- a/packages/zowe-explorer/src/utils/ProfilesUtils.ts +++ b/packages/zowe-explorer/src/utils/ProfilesUtils.ts @@ -307,25 +307,6 @@ export class ProfilesUtils { } } - public static async manageProfile(node: IZoweTreeNode): Promise { - const profile = node.getProfile(); - switch (true) { - case this.isProfileUsingBasicAuth(profile): { - await this.basicAuthProfileManagement(node); - break; - } - case await this.isUsingTokenAuth(profile.name): { - await this.tokenAuthProfileManagement(node); - break; - } - // will need a case for isUsingCertAuth - default: { - await this.chooseAuthProfileManagement(node); - break; - } - } - } - /** * Function that checks whether a profile is using basic authentication * @param profile @@ -510,137 +491,6 @@ export class ProfilesUtils { Gui.errorMessage(err.message); } } - - private static AuthQpLabels = { - update: "update-credentials", - edit: "edit-profile", - login: "obtain-token", - logout: "invalidate-token", - }; - private static editProfileQpItem: Record = { - [this.AuthQpLabels.edit]: { - label: localize("editProfileQpItem.editProfile.qpLabel", "$(pencil) Edit profile"), - description: localize("editProfileQpItem.editProfile.qpDetail", "Update profile connection information"), - }, - }; - private static updateBasicAuthQpItem: Record = { - [this.AuthQpLabels.update]: { - label: localize("updateBasicAuthQpItem.updateCredentials.qpLabel", "$(refresh) Update Credentials"), - description: localize("updateBasicAuthQpItem.updateCredentials.qpDetail", "Update stored username and password"), - }, - }; - private static addBasicAuthQpItem: Record = { - [this.AuthQpLabels.update]: { - label: localize("addBasicAuthQpItem.addCredentials.qpLabel", "$(plus) Add Credentials"), - description: localize("addBasicAuthQpItem.addCredentials.qpDetail", "Add username and password for basic authentication"), - }, - }; - private static loginQpItem: Record = { - [this.AuthQpLabels.login]: { - label: localize("loginQpItem.login.qpLabel", "$(arrow-right) Login to authentication service"), - description: localize("loginQpItem.login.qpDetail", "Login to obtain and update stored token value"), - }, - }; - private static logoutQpItem: Record = { - [this.AuthQpLabels.logout]: { - label: localize("logoutQpItem.logout.qpLabel", "$(arrow-left) Log out of authentication service"), - description: localize("logoutQpItem.logout.qpDetail", "Log out to invalidate and remove stored token value"), - }, - }; - - private static async basicAuthProfileManagement(node: IZoweTreeNode): Promise { - const profile = node.getProfile(); - const selected = await this.setupProfileManagementQp(imperative.SessConstants.AUTH_TYPE_BASIC, profile); - await this.handleAuthSelection(selected, node, profile); - } - private static async tokenAuthProfileManagement(node: IZoweTreeNode): Promise { - const profile = node.getProfile(); - const selected = await this.setupProfileManagementQp("token", profile); - await this.handleAuthSelection(selected, node, profile); - } - private static async chooseAuthProfileManagement(node: IZoweTreeNode): Promise { - const profile = node.getProfile(); - const selected = await this.setupProfileManagementQp(null, profile); - await this.handleAuthSelection(selected, node, profile); - } - private static async setupProfileManagementQp(managementType: string, profile: imperative.IProfileLoaded): Promise { - const qp = Gui.createQuickPick(); - let quickPickOptions: vscode.QuickPickItem[]; - switch (managementType) { - case imperative.SessConstants.AUTH_TYPE_BASIC: { - quickPickOptions = this.basicAuthQp(); - qp.placeholder = this.qpPlaceholders.basicAuth; - break; - } - case "token": { - quickPickOptions = this.tokenAuthQp(profile); - qp.placeholder = this.qpPlaceholders.tokenAuth; - break; - } - default: { - quickPickOptions = this.chooseAuthQp(); - qp.placeholder = this.qpPlaceholders.chooseAuth; - break; - } - } - let selectedItem = quickPickOptions[0]; - qp.items = quickPickOptions; - qp.activeItems = [selectedItem]; - qp.show(); - selectedItem = await Gui.resolveQuickPick(qp); - qp.hide(); - return selectedItem; - } - private static async handleAuthSelection(selected: vscode.QuickPickItem, node: IZoweTreeNode, profile: imperative.IProfileLoaded): Promise { - switch (selected) { - case this.loginQpItem[this.AuthQpLabels.login]: { - await Profiles.getInstance().ssoLogin(node, profile.name); - break; - } - case this.editProfileQpItem[this.AuthQpLabels.edit]: { - await Profiles.getInstance().editSession(profile, profile.name); - break; - } - case this.logoutQpItem[this.AuthQpLabels.logout]: { - await Profiles.getInstance().ssoLogout(node); - break; - } - case this.updateBasicAuthQpItem[this.AuthQpLabels.update]: { - await this.promptCredentials(node); - break; - } - default: { - Gui.infoMessage(localize("profiles.operation.cancelled", "Operation Cancelled")); - break; - } - } - } - - private static qpPlaceholders = { - basicAuth: localize("qpPlaceholders.qp.basic", "Profile is using basic authentication. Choose a profile action."), - tokenAuth: localize("qpPlaceholders.qp.token", "Profile is using token authentication. Choose a profile action."), - chooseAuth: localize("qpPlaceholders.qp.choose", "Profile doesn't specify an authentication method. Choose a profile action."), - }; - - private static basicAuthQp(): vscode.QuickPickItem[] { - const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.updateBasicAuthQpItem); - quickPickOptions.push(this.editProfileQpItem[this.AuthQpLabels.edit]); - return quickPickOptions; - } - private static tokenAuthQp(profile: imperative.IProfileLoaded): vscode.QuickPickItem[] { - const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.loginQpItem); - if (profile.profile.tokenType) { - quickPickOptions.push(this.logoutQpItem[this.AuthQpLabels.logout]); - } - quickPickOptions.push(this.editProfileQpItem[this.AuthQpLabels.edit]); - return quickPickOptions; - } - private static chooseAuthQp(): vscode.QuickPickItem[] { - const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.addBasicAuthQpItem); - quickPickOptions.push(this.loginQpItem[this.AuthQpLabels.login]); - quickPickOptions.push(this.editProfileQpItem[this.AuthQpLabels.edit]); - return quickPickOptions; - } } /** From 61a021ad8d8b93c17a854945beb9c75238be50db Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Fri, 22 Sep 2023 11:34:24 -0400 Subject: [PATCH 12/35] update check and strings in Profiles.ssoLogin Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json | 4 +++- packages/zowe-explorer/src/Profiles.ts | 8 +++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json b/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json index 8c54f161a0..db8a613b65 100644 --- a/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json +++ b/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json @@ -26,9 +26,11 @@ "validateProfiles.progress": "Validating {0} Profile.", "validateProfiles.cancelled": "Validating {0} was cancelled.", "validateProfiles.error": "Profile validation failed for {0}.", - "ssoAuth.noBase": "This profile does not support token authentication.", + "ssoLogin.usingBasicAuth": "This profile is using basic authentication and does not support token authentication.", + "ssoLogin.tokenType.error": "Error getting supported tokenType value for profile {0}", "ssoLogin.successful": "Login to authentication service was successful.", "ssoLogin.error": "Unable to log in with {0}. {1}", + "ssoAuth.noBase": "This profile does not support token authentication.", "ssoLogout.successful": "Logout from authentication service was successful for {0}.", "ssoLogout.error": "Unable to log out with {0}. {1}", "getConfigLocationPrompt.placeholder.create": "Select the location where the config file will be initialized", diff --git a/packages/zowe-explorer/src/Profiles.ts b/packages/zowe-explorer/src/Profiles.ts index 47a70a00e4..90c886e27c 100644 --- a/packages/zowe-explorer/src/Profiles.ts +++ b/packages/zowe-explorer/src/Profiles.ts @@ -1165,8 +1165,10 @@ export class Profiles extends ProfilesCache { serviceProfile = this.loadNamedProfile(label.trim()); } // This check will handle service profiles that have username and password - if (serviceProfile.profile.user && serviceProfile.profile.password) { - Gui.showMessage(localize("ssoAuth.noBase", "This profile does not support token authentication.")); + if (ProfilesUtils.isProfileUsingBasicAuth(serviceProfile)) { + Gui.showMessage( + localize("ssoLogin.usingBasicAuth", "This profile is using basic authentication and does not support token authentication.") + ); return; } @@ -1174,7 +1176,7 @@ export class Profiles extends ProfilesCache { loginTokenType = await ZoweExplorerApiRegister.getInstance().getCommonApi(serviceProfile).getTokenTypeName(); } catch (error) { ZoweLogger.warn(error); - Gui.showMessage(localize("ssoAuth.noBase", "This profile does not support token authentication.")); + Gui.showMessage(localize("ssoLogin.tokenType.error", "Error getting supported tokenType value for profile {0}", serviceProfile.name)); return; } try { From 0245bb769b8983ac3d0c41dac99d14f7212f1eb9 Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Fri, 22 Sep 2023 15:16:23 -0400 Subject: [PATCH 13/35] clean up and add some unit tests Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../utils/ProfileManagement.unit.test.ts | 100 +++++++++++++++++ .../i18n/sample/src/Profiles.i18n.json | 3 +- .../src/utils/ProfileManagement.i18n.json | 16 +-- packages/zowe-explorer/src/Profiles.ts | 8 +- .../src/utils/ProfileManagement.ts | 102 +++++++++--------- 5 files changed, 162 insertions(+), 67 deletions(-) create mode 100644 packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts diff --git a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts new file mode 100644 index 0000000000..e93bc43d92 --- /dev/null +++ b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts @@ -0,0 +1,100 @@ +/** + * This program and the accompanying materials are made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Copyright Contributors to the Zowe Project. + * + */ + +import { ZoweDatasetNode } from "../../../src/dataset/ZoweDatasetNode"; +import * as sharedMock from "../../../__mocks__/mockCreators/shared"; +import * as dsMock from "../../../__mocks__/mockCreators/datasets"; +import * as profUtils from "../../../src/utils/ProfilesUtils"; +import { ProfileManagement } from "../../../src/utils/ProfileManagement"; +import { Gui } from "@zowe/zowe-explorer-api"; +import { ZoweLogger } from "../../../src/utils/LoggerUtils"; + +jest.mock("fs"); +jest.mock("vscode"); +jest.mock("@zowe/cli"); + +describe("ProfileManagement unit tests", () => { + afterEach(() => { + jest.clearAllMocks(); + }); + function createGlobalMocks() { + const newMocks = { + mockSession: sharedMock.createISession(), + mockBasicAuthProfile: sharedMock.createValidIProfile(), + mockDsSessionNode: ZoweDatasetNode, + mockUpdateChosen: null as any, + mockAddBasicChosen: null as any, + mockLoginChosen: null as any, + mockLogoutChosen: null as any, + mockEditProfChosen: null as any, + mockCreateQp: jest.fn(), + debugLogSpy: null as any, + }; + newMocks.mockDsSessionNode = dsMock.createDatasetSessionNode(newMocks.mockSession, newMocks.mockBasicAuthProfile) as any; + Object.defineProperty(newMocks.mockDsSessionNode, "getProfile", { + value: jest.fn().mockReturnValue(newMocks.mockBasicAuthProfile), + configurable: true, + }); + newMocks.mockUpdateChosen = ProfileManagement.basicAuthQpItems[ProfileManagement.AuthQpLabels.update]; + newMocks.mockAddBasicChosen = ProfileManagement.basicAuthQpItems[ProfileManagement.AuthQpLabels.add]; + newMocks.mockLoginChosen = ProfileManagement.tokenAuthQpItems[ProfileManagement.AuthQpLabels.login]; + newMocks.mockLogoutChosen = ProfileManagement.tokenAuthQpItems[ProfileManagement.AuthQpLabels.logout]; + newMocks.mockEditProfChosen = ProfileManagement.otherProfileQpItems[ProfileManagement.AuthQpLabels.edit]; + newMocks.mockCreateQp.mockReturnValue({ + show: jest.fn(() => { + return {}; + }), + hide: jest.fn(() => { + return {}; + }), + onDidAccept: jest.fn(() => { + return {}; + }), + }); + Object.defineProperty(profUtils.ProfilesUtils, "promptCredentials", { value: jest.fn(), configurable: true }); + Object.defineProperty(Gui, "createQuickPick", { value: jest.fn(), configurable: true }); + Object.defineProperty(Gui, "createQuickPick", { value: newMocks.mockCreateQp, configurable: true }); + Object.defineProperty(ZoweLogger, "debug", { value: jest.fn(), configurable: true }); + newMocks.debugLogSpy = jest.spyOn(ZoweLogger, "debug"); + // Object.defineProperty(profUtils.ProfilesUtils, "isUsingTokenAuth", { value: jest.fn().mockResolvedValueOnce(false), configurable: true }); + + return newMocks; + } + afterEach(() => { + jest.clearAllMocks(); + jest.resetAllMocks(); + }); + it("profile using basic authentication should see Operation Cancelled when escaping quick pick", async () => { + const globalMocks = createGlobalMocks(); + const logMsg = `Profile ${globalMocks.mockBasicAuthProfile.name} is using basic authentication.`; + Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(undefined), configurable: true }); + const updateSpy = jest.spyOn(profUtils.ProfilesUtils, "promptCredentials"); + const opCancelledSpy = jest.spyOn(Gui, "infoMessage"); + await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); + expect(globalMocks.debugLogSpy).toBeCalledWith(logMsg); + expect(updateSpy).not.toBeCalled(); + expect(opCancelledSpy).toBeCalledWith("Operation Cancelled"); + globalMocks.debugLogSpy.mockClear(); + updateSpy.mockClear(); + opCancelledSpy.mockClear(); + }); + it("profile using basic authentication should see promptCredentials called when Update Credentials chosen", async () => { + const globalMocks = createGlobalMocks(); + const logMsg = `Profile ${globalMocks.mockBasicAuthProfile.name} is using basic authentication.`; + Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(globalMocks.mockUpdateChosen), configurable: true }); + const scenarioSpy = jest.spyOn(profUtils.ProfilesUtils, "promptCredentials"); + await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); + expect(globalMocks.debugLogSpy).toBeCalledWith(logMsg); + expect(scenarioSpy).toBeCalled(); + globalMocks.debugLogSpy.mockClear(); + scenarioSpy.mockClear(); + }); +}); diff --git a/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json b/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json index db8a613b65..b48fbc4ab9 100644 --- a/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json +++ b/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json @@ -26,11 +26,10 @@ "validateProfiles.progress": "Validating {0} Profile.", "validateProfiles.cancelled": "Validating {0} was cancelled.", "validateProfiles.error": "Profile validation failed for {0}.", - "ssoLogin.usingBasicAuth": "This profile is using basic authentication and does not support token authentication.", + "ssoAuth.usingBasicAuth": "This profile is using basic authentication and does not support token authentication.", "ssoLogin.tokenType.error": "Error getting supported tokenType value for profile {0}", "ssoLogin.successful": "Login to authentication service was successful.", "ssoLogin.error": "Unable to log in with {0}. {1}", - "ssoAuth.noBase": "This profile does not support token authentication.", "ssoLogout.successful": "Logout from authentication service was successful for {0}.", "ssoLogout.error": "Unable to log out with {0}. {1}", "getConfigLocationPrompt.placeholder.create": "Select the location where the config file will be initialized", diff --git a/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json b/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json index 05e99d6246..d168f6392d 100644 --- a/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json +++ b/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json @@ -1,16 +1,16 @@ { "profiles.operation.cancelled": "Operation Cancelled", - "editProfileQpItem.editProfile.qpLabel": "$(pencil) Edit profile", - "editProfileQpItem.editProfile.qpDetail": "Update profile connection information", - "updateBasicAuthQpItem.updateCredentials.qpLabel": "$(refresh) Update Credentials", - "updateBasicAuthQpItem.updateCredentials.qpDetail": "Update stored username and password", + "qpPlaceholders.qp.basic": "Profile {0} is using basic authentication. Choose a profile action.", + "qpPlaceholders.qp.token": "Profile {0} is using token authentication. Choose a profile action.", + "qpPlaceholders.qp.choose": "Profile {0} doesn't specify an authentication method. Choose a profile action.", "addBasicAuthQpItem.addCredentials.qpLabel": "$(plus) Add Credentials", "addBasicAuthQpItem.addCredentials.qpDetail": "Add username and password for basic authentication", + "updateBasicAuthQpItem.updateCredentials.qpLabel": "$(refresh) Update Credentials", + "updateBasicAuthQpItem.updateCredentials.qpDetail": "Update stored username and password", + "editProfileQpItem.editProfile.qpLabel": "$(pencil) Edit profile", + "editProfileQpItem.editProfile.qpDetail": "Update profile connection information", "loginQpItem.login.qpLabel": "$(arrow-right) Log in to authentication service", "loginQpItem.login.qpDetail": "Log in to obtain a new token value", "logoutQpItem.logout.qpLabel": "$(arrow-left) Log out of authentication service", - "logoutQpItem.logout.qpDetail": "Log out to invalidate and remove stored token value", - "qpPlaceholders.qp.basic": "Profile is using basic authentication. Choose a profile action.", - "qpPlaceholders.qp.token": "Profile is using token authentication. Choose a profile action.", - "qpPlaceholders.qp.choose": "Profile doesn't specify an authentication method. Choose a profile action." + "logoutQpItem.logout.qpDetail": "Log out to invalidate and remove stored token value" } diff --git a/packages/zowe-explorer/src/Profiles.ts b/packages/zowe-explorer/src/Profiles.ts index 90c886e27c..a32d1801af 100644 --- a/packages/zowe-explorer/src/Profiles.ts +++ b/packages/zowe-explorer/src/Profiles.ts @@ -1167,7 +1167,7 @@ export class Profiles extends ProfilesCache { // This check will handle service profiles that have username and password if (ProfilesUtils.isProfileUsingBasicAuth(serviceProfile)) { Gui.showMessage( - localize("ssoLogin.usingBasicAuth", "This profile is using basic authentication and does not support token authentication.") + localize("ssoAuth.usingBasicAuth", "This profile is using basic authentication and does not support token authentication.") ); return; } @@ -1198,8 +1198,10 @@ export class Profiles extends ProfilesCache { ZoweLogger.trace("Profiles.ssoLogout called."); const serviceProfile = node.getProfile(); // This check will handle service profiles that have username and password - if (serviceProfile.profile?.user && serviceProfile.profile?.password) { - Gui.showMessage(localize("ssoAuth.noBase", "This profile does not support token authentication.")); + if (ProfilesUtils.isProfileUsingBasicAuth(serviceProfile)) { + Gui.showMessage( + localize("ssoAuth.usingBasicAuth", "This profile is using basic authentication and does not support token authentication.") + ); return; } try { diff --git a/packages/zowe-explorer/src/utils/ProfileManagement.ts b/packages/zowe-explorer/src/utils/ProfileManagement.ts index 8a4c893561..b39815a2a7 100644 --- a/packages/zowe-explorer/src/utils/ProfileManagement.ts +++ b/packages/zowe-explorer/src/utils/ProfileManagement.ts @@ -26,94 +26,78 @@ const localize: nls.LocalizeFunc = nls.loadMessageBundle(); export class ProfileManagement { public static async manageProfile(node: IZoweTreeNode): Promise { const profile = node.getProfile(); + let selected: vscode.QuickPickItem; switch (true) { case ProfilesUtils.isProfileUsingBasicAuth(profile): { ZoweLogger.debug(`Profile ${profile.name} is using basic authentication.`); - await this.basicAuthProfileManagement(node); + selected = await this.setupProfileManagementQp(imperative.SessConstants.AUTH_TYPE_BASIC, profile); break; } case await ProfilesUtils.isUsingTokenAuth(profile.name): { ZoweLogger.debug(`Profile ${profile.name} is using token authentication.`); - await this.tokenAuthProfileManagement(node); + selected = await this.setupProfileManagementQp("token", profile); break; } // will need a case for isUsingCertAuth default: { ZoweLogger.debug(`Profile ${profile.name} authentication method is unkown.`); - await this.chooseAuthProfileManagement(node); + selected = await this.setupProfileManagementQp(null, profile); break; } } + await this.handleAuthSelection(selected, node, profile); } - private static AuthQpLabels = { + public static AuthQpLabels = { update: "update-credentials", edit: "edit-profile", login: "obtain-token", logout: "invalidate-token", + add: "add-credentials", }; - private static editProfileQpItem: Record = { - [this.AuthQpLabels.edit]: { - label: localize("editProfileQpItem.editProfile.qpLabel", "$(pencil) Edit profile"), - description: localize("editProfileQpItem.editProfile.qpDetail", "Update profile connection information"), + public static basicAuthQpItems: Record = { + [this.AuthQpLabels.add]: { + label: localize("addBasicAuthQpItem.addCredentials.qpLabel", "$(plus) Add Credentials"), + description: localize("addBasicAuthQpItem.addCredentials.qpDetail", "Add username and password for basic authentication"), }, - }; - private static updateBasicAuthQpItem: Record = { [this.AuthQpLabels.update]: { label: localize("updateBasicAuthQpItem.updateCredentials.qpLabel", "$(refresh) Update Credentials"), description: localize("updateBasicAuthQpItem.updateCredentials.qpDetail", "Update stored username and password"), }, }; - private static addBasicAuthQpItem: Record = { - [this.AuthQpLabels.update]: { - label: localize("addBasicAuthQpItem.addCredentials.qpLabel", "$(plus) Add Credentials"), - description: localize("addBasicAuthQpItem.addCredentials.qpDetail", "Add username and password for basic authentication"), + public static otherProfileQpItems: Record = { + [this.AuthQpLabels.edit]: { + label: localize("editProfileQpItem.editProfile.qpLabel", "$(pencil) Edit profile"), + description: localize("editProfileQpItem.editProfile.qpDetail", "Update profile connection information"), }, }; - private static loginQpItem: Record = { + public static tokenAuthQpItems: Record = { [this.AuthQpLabels.login]: { label: localize("loginQpItem.login.qpLabel", "$(arrow-right) Log in to authentication service"), description: localize("loginQpItem.login.qpDetail", "Log in to obtain a new token value"), }, - }; - private static logoutQpItem: Record = { [this.AuthQpLabels.logout]: { label: localize("logoutQpItem.logout.qpLabel", "$(arrow-left) Log out of authentication service"), description: localize("logoutQpItem.logout.qpDetail", "Log out to invalidate and remove stored token value"), }, }; - - private static async basicAuthProfileManagement(node: IZoweTreeNode): Promise { - const profile = node.getProfile(); - const selected = await this.setupProfileManagementQp(imperative.SessConstants.AUTH_TYPE_BASIC, profile); - await this.handleAuthSelection(selected, node, profile); - } - private static async tokenAuthProfileManagement(node: IZoweTreeNode): Promise { - const profile = node.getProfile(); - const selected = await this.setupProfileManagementQp("token", profile); - await this.handleAuthSelection(selected, node, profile); - } - private static async chooseAuthProfileManagement(node: IZoweTreeNode): Promise { - const profile = node.getProfile(); - const selected = await this.setupProfileManagementQp(null, profile); - await this.handleAuthSelection(selected, node, profile); - } private static async setupProfileManagementQp(managementType: string, profile: imperative.IProfileLoaded): Promise { const qp = Gui.createQuickPick(); let quickPickOptions: vscode.QuickPickItem[]; + const placeholders = this.getQpPlaceholders(profile); switch (managementType) { case imperative.SessConstants.AUTH_TYPE_BASIC: { quickPickOptions = this.basicAuthQp(); - qp.placeholder = this.qpPlaceholders.basicAuth; + qp.placeholder = placeholders.basicAuth; break; } case "token": { quickPickOptions = this.tokenAuthQp(profile); - qp.placeholder = this.qpPlaceholders.tokenAuth; + qp.placeholder = placeholders.tokenAuth; break; } default: { quickPickOptions = this.chooseAuthQp(); - qp.placeholder = this.qpPlaceholders.chooseAuth; + qp.placeholder = placeholders.chooseAuth; break; } } @@ -127,19 +111,23 @@ export class ProfileManagement { } private static async handleAuthSelection(selected: vscode.QuickPickItem, node: IZoweTreeNode, profile: imperative.IProfileLoaded): Promise { switch (selected) { - case this.loginQpItem[this.AuthQpLabels.login]: { - await Profiles.getInstance().ssoLogin(node, profile.name); + case this.basicAuthQpItems[this.AuthQpLabels.add]: { + await ProfilesUtils.promptCredentials(node); break; } - case this.editProfileQpItem[this.AuthQpLabels.edit]: { + case this.otherProfileQpItems[this.AuthQpLabels.edit]: { await Profiles.getInstance().editSession(profile, profile.name); break; } - case this.logoutQpItem[this.AuthQpLabels.logout]: { + case this.tokenAuthQpItems[this.AuthQpLabels.login]: { + await Profiles.getInstance().ssoLogin(node, profile.name); + break; + } + case this.tokenAuthQpItems[this.AuthQpLabels.logout]: { await Profiles.getInstance().ssoLogout(node); break; } - case this.updateBasicAuthQpItem[this.AuthQpLabels.update]: { + case this.basicAuthQpItems[this.AuthQpLabels.update]: { await ProfilesUtils.promptCredentials(node); break; } @@ -150,29 +138,35 @@ export class ProfileManagement { } } - private static qpPlaceholders = { - basicAuth: localize("qpPlaceholders.qp.basic", "Profile is using basic authentication. Choose a profile action."), - tokenAuth: localize("qpPlaceholders.qp.token", "Profile is using token authentication. Choose a profile action."), - chooseAuth: localize("qpPlaceholders.qp.choose", "Profile doesn't specify an authentication method. Choose a profile action."), - }; + private static getQpPlaceholders(profile: imperative.IProfileLoaded) { + return { + basicAuth: localize("qpPlaceholders.qp.basic", "Profile {0} is using basic authentication. Choose a profile action.", profile.name), + tokenAuth: localize("qpPlaceholders.qp.token", "Profile {0} is using token authentication. Choose a profile action.", profile.name), + chooseAuth: localize( + "qpPlaceholders.qp.choose", + "Profile {0} doesn't specify an authentication method. Choose a profile action.", + profile.name + ), + }; + } private static basicAuthQp(): vscode.QuickPickItem[] { - const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.updateBasicAuthQpItem); - quickPickOptions.push(this.editProfileQpItem[this.AuthQpLabels.edit]); + const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.basicAuthQpItems[this.AuthQpLabels.update]); + quickPickOptions.push(this.otherProfileQpItems[this.AuthQpLabels.edit]); return quickPickOptions; } private static tokenAuthQp(profile: imperative.IProfileLoaded): vscode.QuickPickItem[] { - const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.loginQpItem); + const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.tokenAuthQpItems[this.AuthQpLabels.login]); if (profile.profile.tokenType) { - quickPickOptions.push(this.logoutQpItem[this.AuthQpLabels.logout]); + quickPickOptions.push(this.tokenAuthQpItems[this.AuthQpLabels.logout]); } - quickPickOptions.push(this.editProfileQpItem[this.AuthQpLabels.edit]); + quickPickOptions.push(this.otherProfileQpItems[this.AuthQpLabels.edit]); return quickPickOptions; } private static chooseAuthQp(): vscode.QuickPickItem[] { - const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.addBasicAuthQpItem); - quickPickOptions.push(this.loginQpItem[this.AuthQpLabels.login]); - quickPickOptions.push(this.editProfileQpItem[this.AuthQpLabels.edit]); + const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.basicAuthQpItems[this.AuthQpLabels.add]); + quickPickOptions.push(this.tokenAuthQpItems[this.AuthQpLabels.login]); + quickPickOptions.push(this.otherProfileQpItems[this.AuthQpLabels.edit]); return quickPickOptions; } } From 3444400fd18c7f9a4e75054bc85161f953966785 Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Fri, 22 Sep 2023 15:29:44 -0400 Subject: [PATCH 14/35] fix qp labels I broke Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../utils/ProfileManagement.unit.test.ts | 9 +++--- .../src/utils/ProfileManagement.ts | 28 +++++++++++-------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts index e93bc43d92..9f3997a0d9 100644 --- a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts @@ -43,10 +43,10 @@ describe("ProfileManagement unit tests", () => { value: jest.fn().mockReturnValue(newMocks.mockBasicAuthProfile), configurable: true, }); - newMocks.mockUpdateChosen = ProfileManagement.basicAuthQpItems[ProfileManagement.AuthQpLabels.update]; - newMocks.mockAddBasicChosen = ProfileManagement.basicAuthQpItems[ProfileManagement.AuthQpLabels.add]; - newMocks.mockLoginChosen = ProfileManagement.tokenAuthQpItems[ProfileManagement.AuthQpLabels.login]; - newMocks.mockLogoutChosen = ProfileManagement.tokenAuthQpItems[ProfileManagement.AuthQpLabels.logout]; + newMocks.mockUpdateChosen = ProfileManagement.basicAuthUpdateQpItems[ProfileManagement.AuthQpLabels.update]; + newMocks.mockAddBasicChosen = ProfileManagement.basicAuthAddQpItems[ProfileManagement.AuthQpLabels.add]; + newMocks.mockLoginChosen = ProfileManagement.tokenAuthLoginQpItem[ProfileManagement.AuthQpLabels.login]; + newMocks.mockLogoutChosen = ProfileManagement.tokenAuthLogoutQpItem[ProfileManagement.AuthQpLabels.logout]; newMocks.mockEditProfChosen = ProfileManagement.otherProfileQpItems[ProfileManagement.AuthQpLabels.edit]; newMocks.mockCreateQp.mockReturnValue({ show: jest.fn(() => { @@ -60,7 +60,6 @@ describe("ProfileManagement unit tests", () => { }), }); Object.defineProperty(profUtils.ProfilesUtils, "promptCredentials", { value: jest.fn(), configurable: true }); - Object.defineProperty(Gui, "createQuickPick", { value: jest.fn(), configurable: true }); Object.defineProperty(Gui, "createQuickPick", { value: newMocks.mockCreateQp, configurable: true }); Object.defineProperty(ZoweLogger, "debug", { value: jest.fn(), configurable: true }); newMocks.debugLogSpy = jest.spyOn(ZoweLogger, "debug"); diff --git a/packages/zowe-explorer/src/utils/ProfileManagement.ts b/packages/zowe-explorer/src/utils/ProfileManagement.ts index b39815a2a7..efb5f69477 100644 --- a/packages/zowe-explorer/src/utils/ProfileManagement.ts +++ b/packages/zowe-explorer/src/utils/ProfileManagement.ts @@ -54,11 +54,13 @@ export class ProfileManagement { logout: "invalidate-token", add: "add-credentials", }; - public static basicAuthQpItems: Record = { + public static basicAuthAddQpItems: Record = { [this.AuthQpLabels.add]: { label: localize("addBasicAuthQpItem.addCredentials.qpLabel", "$(plus) Add Credentials"), description: localize("addBasicAuthQpItem.addCredentials.qpDetail", "Add username and password for basic authentication"), }, + }; + public static basicAuthUpdateQpItems: Record = { [this.AuthQpLabels.update]: { label: localize("updateBasicAuthQpItem.updateCredentials.qpLabel", "$(refresh) Update Credentials"), description: localize("updateBasicAuthQpItem.updateCredentials.qpDetail", "Update stored username and password"), @@ -70,11 +72,13 @@ export class ProfileManagement { description: localize("editProfileQpItem.editProfile.qpDetail", "Update profile connection information"), }, }; - public static tokenAuthQpItems: Record = { + public static tokenAuthLoginQpItem: Record = { [this.AuthQpLabels.login]: { label: localize("loginQpItem.login.qpLabel", "$(arrow-right) Log in to authentication service"), description: localize("loginQpItem.login.qpDetail", "Log in to obtain a new token value"), }, + }; + public static tokenAuthLogoutQpItem: Record = { [this.AuthQpLabels.logout]: { label: localize("logoutQpItem.logout.qpLabel", "$(arrow-left) Log out of authentication service"), description: localize("logoutQpItem.logout.qpDetail", "Log out to invalidate and remove stored token value"), @@ -111,7 +115,7 @@ export class ProfileManagement { } private static async handleAuthSelection(selected: vscode.QuickPickItem, node: IZoweTreeNode, profile: imperative.IProfileLoaded): Promise { switch (selected) { - case this.basicAuthQpItems[this.AuthQpLabels.add]: { + case this.basicAuthAddQpItems[this.AuthQpLabels.add]: { await ProfilesUtils.promptCredentials(node); break; } @@ -119,15 +123,15 @@ export class ProfileManagement { await Profiles.getInstance().editSession(profile, profile.name); break; } - case this.tokenAuthQpItems[this.AuthQpLabels.login]: { + case this.tokenAuthLoginQpItem[this.AuthQpLabels.login]: { await Profiles.getInstance().ssoLogin(node, profile.name); break; } - case this.tokenAuthQpItems[this.AuthQpLabels.logout]: { + case this.tokenAuthLogoutQpItem[this.AuthQpLabels.logout]: { await Profiles.getInstance().ssoLogout(node); break; } - case this.basicAuthQpItems[this.AuthQpLabels.update]: { + case this.basicAuthUpdateQpItems[this.AuthQpLabels.update]: { await ProfilesUtils.promptCredentials(node); break; } @@ -138,7 +142,7 @@ export class ProfileManagement { } } - private static getQpPlaceholders(profile: imperative.IProfileLoaded) { + private static getQpPlaceholders(profile: imperative.IProfileLoaded): { basicAuth: string; tokenAuth: string; chooseAuth: string } { return { basicAuth: localize("qpPlaceholders.qp.basic", "Profile {0} is using basic authentication. Choose a profile action.", profile.name), tokenAuth: localize("qpPlaceholders.qp.token", "Profile {0} is using token authentication. Choose a profile action.", profile.name), @@ -151,21 +155,21 @@ export class ProfileManagement { } private static basicAuthQp(): vscode.QuickPickItem[] { - const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.basicAuthQpItems[this.AuthQpLabels.update]); + const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.basicAuthUpdateQpItems); quickPickOptions.push(this.otherProfileQpItems[this.AuthQpLabels.edit]); return quickPickOptions; } private static tokenAuthQp(profile: imperative.IProfileLoaded): vscode.QuickPickItem[] { - const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.tokenAuthQpItems[this.AuthQpLabels.login]); + const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.tokenAuthLoginQpItem); if (profile.profile.tokenType) { - quickPickOptions.push(this.tokenAuthQpItems[this.AuthQpLabels.logout]); + quickPickOptions.push(this.tokenAuthLogoutQpItem[this.AuthQpLabels.logout]); } quickPickOptions.push(this.otherProfileQpItems[this.AuthQpLabels.edit]); return quickPickOptions; } private static chooseAuthQp(): vscode.QuickPickItem[] { - const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.basicAuthQpItems[this.AuthQpLabels.add]); - quickPickOptions.push(this.tokenAuthQpItems[this.AuthQpLabels.login]); + const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.basicAuthAddQpItems); + quickPickOptions.push(this.tokenAuthLoginQpItem[this.AuthQpLabels.login]); quickPickOptions.push(this.otherProfileQpItems[this.AuthQpLabels.edit]); return quickPickOptions; } From b5139a5343c83400b79ad9a671488e5daff99aeb Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Fri, 22 Sep 2023 16:42:49 -0400 Subject: [PATCH 15/35] add unit tests Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../__mocks__/mockCreators/shared.ts | 18 ++ .../utils/ProfileManagement.unit.test.ts | 259 +++++++++++++++--- 2 files changed, 245 insertions(+), 32 deletions(-) diff --git a/packages/zowe-explorer/__mocks__/mockCreators/shared.ts b/packages/zowe-explorer/__mocks__/mockCreators/shared.ts index 1133c38687..82b4039698 100644 --- a/packages/zowe-explorer/__mocks__/mockCreators/shared.ts +++ b/packages/zowe-explorer/__mocks__/mockCreators/shared.ts @@ -218,6 +218,24 @@ export function createValidIProfile(): imperative.IProfileLoaded { }; } +export function createTokenAuthIProfile(): imperative.IProfileLoaded { + return { + name: "sestest", + profile: { + type: "zosmf", + host: "test", + port: 1443, + rejectUnauthorized: false, + tokenType: "apimlAuthenticationToken", + tokenValue: "stringofletters", + name: "testName", + }, + type: "zosmf", + message: "", + failNotFound: false, + }; +} + export function createAltTypeIProfile(): imperative.IProfileLoaded { return { name: "altTypeProfile", diff --git a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts index 9f3997a0d9..e324c714aa 100644 --- a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts @@ -16,6 +16,7 @@ import * as profUtils from "../../../src/utils/ProfilesUtils"; import { ProfileManagement } from "../../../src/utils/ProfileManagement"; import { Gui } from "@zowe/zowe-explorer-api"; import { ZoweLogger } from "../../../src/utils/LoggerUtils"; +import { Profiles } from "../../../src/Profiles"; jest.mock("fs"); jest.mock("vscode"); @@ -24,11 +25,14 @@ jest.mock("@zowe/cli"); describe("ProfileManagement unit tests", () => { afterEach(() => { jest.clearAllMocks(); + jest.resetAllMocks(); }); function createGlobalMocks() { const newMocks = { mockSession: sharedMock.createISession(), mockBasicAuthProfile: sharedMock.createValidIProfile(), + mockTokenAuthProfile: sharedMock.createTokenAuthIProfile(), + mockNoAuthProfile: sharedMock.createInvalidIProfile(), mockDsSessionNode: ZoweDatasetNode, mockUpdateChosen: null as any, mockAddBasicChosen: null as any, @@ -37,12 +41,8 @@ describe("ProfileManagement unit tests", () => { mockEditProfChosen: null as any, mockCreateQp: jest.fn(), debugLogSpy: null as any, + opCancelledSpy: jest.spyOn(Gui, "infoMessage"), }; - newMocks.mockDsSessionNode = dsMock.createDatasetSessionNode(newMocks.mockSession, newMocks.mockBasicAuthProfile) as any; - Object.defineProperty(newMocks.mockDsSessionNode, "getProfile", { - value: jest.fn().mockReturnValue(newMocks.mockBasicAuthProfile), - configurable: true, - }); newMocks.mockUpdateChosen = ProfileManagement.basicAuthUpdateQpItems[ProfileManagement.AuthQpLabels.update]; newMocks.mockAddBasicChosen = ProfileManagement.basicAuthAddQpItems[ProfileManagement.AuthQpLabels.add]; newMocks.mockLoginChosen = ProfileManagement.tokenAuthLoginQpItem[ProfileManagement.AuthQpLabels.login]; @@ -63,37 +63,232 @@ describe("ProfileManagement unit tests", () => { Object.defineProperty(Gui, "createQuickPick", { value: newMocks.mockCreateQp, configurable: true }); Object.defineProperty(ZoweLogger, "debug", { value: jest.fn(), configurable: true }); newMocks.debugLogSpy = jest.spyOn(ZoweLogger, "debug"); - // Object.defineProperty(profUtils.ProfilesUtils, "isUsingTokenAuth", { value: jest.fn().mockResolvedValueOnce(false), configurable: true }); return newMocks; } - afterEach(() => { - jest.clearAllMocks(); - jest.resetAllMocks(); + + describe("unit tests around basic auth selections", () => { + function createBlockMocks(globalMocks) { + const newMocks = { + mockProfileInstance: null as any, + editSpy: null as any, + promptSpy: jest.spyOn(profUtils.ProfilesUtils, "promptCredentials"), + logMsg: `Profile ${globalMocks.mockBasicAuthProfile.name} is using basic authentication.`, + }; + newMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(globalMocks.mockBasicAuthProfile); + Object.defineProperty(Profiles, "getInstance", { + value: jest.fn().mockReturnValue(newMocks.mockProfileInstance), + configurable: true, + }); + Object.defineProperty(newMocks.mockProfileInstance, "editSession", { value: jest.fn(), configurable: true }); + newMocks.editSpy = jest.spyOn(newMocks.mockProfileInstance, "editSession"); + globalMocks.mockDsSessionNode = dsMock.createDatasetSessionNode(globalMocks.mockSession, globalMocks.mockBasicAuthProfile) as any; + Object.defineProperty(globalMocks.mockDsSessionNode, "getProfile", { + value: jest.fn().mockReturnValue(globalMocks.mockBasicAuthProfile), + configurable: true, + }); + return newMocks; + } + afterEach(() => { + jest.clearAllMocks(); + jest.resetAllMocks(); + }); + it("profile using basic authentication should see Operation Cancelled when escaping quick pick", async () => { + const globalMocks = createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(undefined), configurable: true }); + await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); + expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); + expect(blockMocks.promptSpy).not.toBeCalled(); + expect(globalMocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); + globalMocks.debugLogSpy.mockClear(); + blockMocks.promptSpy.mockClear(); + globalMocks.opCancelledSpy.mockClear(); + }); + it("profile using basic authentication should see promptCredentials called when Update Credentials chosen", async () => { + const globalMocks = createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + Object.defineProperty(Gui, "resolveQuickPick", { + value: jest.fn().mockResolvedValueOnce(globalMocks.mockUpdateChosen), + configurable: true, + }); + await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); + expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); + expect(blockMocks.promptSpy).toBeCalled(); + globalMocks.debugLogSpy.mockClear(); + blockMocks.promptSpy.mockClear(); + }); + it("profile using basic authentication should see editSession called when Edit Profile chosen", async () => { + const globalMocks = createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + Object.defineProperty(Gui, "resolveQuickPick", { + value: jest.fn().mockResolvedValueOnce(globalMocks.mockEditProfChosen), + configurable: true, + }); + await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); + expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); + expect(blockMocks.promptSpy).not.toBeCalled(); + expect(blockMocks.editSpy).toBeCalled(); + globalMocks.debugLogSpy.mockClear(); + blockMocks.promptSpy.mockClear(); + blockMocks.editSpy.mockClear(); + }); }); - it("profile using basic authentication should see Operation Cancelled when escaping quick pick", async () => { - const globalMocks = createGlobalMocks(); - const logMsg = `Profile ${globalMocks.mockBasicAuthProfile.name} is using basic authentication.`; - Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(undefined), configurable: true }); - const updateSpy = jest.spyOn(profUtils.ProfilesUtils, "promptCredentials"); - const opCancelledSpy = jest.spyOn(Gui, "infoMessage"); - await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(logMsg); - expect(updateSpy).not.toBeCalled(); - expect(opCancelledSpy).toBeCalledWith("Operation Cancelled"); - globalMocks.debugLogSpy.mockClear(); - updateSpy.mockClear(); - opCancelledSpy.mockClear(); + describe("unit tests around token auth selections", () => { + function createBlockMocks(globalMocks) { + const newMocks = { + mockProfileInstance: null as any, + loginSpy: null as any, + logoutSpy: null as any, + editSpy: null as any, + logMsg: `Profile ${globalMocks.mockTokenAuthProfile.name} is using token authentication.`, + }; + newMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(globalMocks.mockTokenAuthProfile); + Object.defineProperty(Profiles, "getInstance", { + value: jest.fn().mockReturnValue(newMocks.mockProfileInstance), + configurable: true, + }); + Object.defineProperty(newMocks.mockProfileInstance, "editSession", { value: jest.fn(), configurable: true }); + newMocks.editSpy = jest.spyOn(newMocks.mockProfileInstance, "editSession"); + Object.defineProperty(newMocks.mockProfileInstance, "ssoLogin", { value: jest.fn(), configurable: true }); + newMocks.loginSpy = jest.spyOn(Profiles.getInstance(), "ssoLogin"); + Object.defineProperty(newMocks.mockProfileInstance, "ssoLogout", { value: jest.fn(), configurable: true }); + newMocks.logoutSpy = jest.spyOn(Profiles.getInstance(), "ssoLogout"); + Object.defineProperty(profUtils.ProfilesUtils, "isUsingTokenAuth", { value: jest.fn().mockResolvedValueOnce(true), configurable: true }); + globalMocks.mockDsSessionNode = dsMock.createDatasetSessionNode(globalMocks.mockSession, globalMocks.mockTokenAuthProfile) as any; + Object.defineProperty(globalMocks.mockDsSessionNode, "getProfile", { + value: jest.fn().mockReturnValue(globalMocks.mockTokenAuthProfile), + configurable: true, + }); + return newMocks; + } + afterEach(() => { + jest.clearAllMocks(); + jest.resetAllMocks(); + }); + it("profile using token authentication should see Operation Cancelled when escaping quick pick", async () => { + const globalMocks = createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(undefined), configurable: true }); + await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); + expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); + expect(blockMocks.loginSpy).not.toBeCalled(); + expect(globalMocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); + globalMocks.debugLogSpy.mockClear(); + blockMocks.loginSpy.mockClear(); + globalMocks.opCancelledSpy.mockClear(); + }); + it("profile using token authentication should see ssoLogin called when Log in to authentication service chosen", async () => { + const globalMocks = createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + Object.defineProperty(Gui, "resolveQuickPick", { + value: jest.fn().mockResolvedValueOnce(globalMocks.mockLoginChosen), + configurable: true, + }); + await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); + expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); + expect(blockMocks.loginSpy).toBeCalled(); + globalMocks.debugLogSpy.mockClear(); + blockMocks.loginSpy.mockClear(); + }); + it("profile using token authentication should see ssoLogout called when Log out from authentication service chosen", async () => { + const globalMocks = createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + Object.defineProperty(Gui, "resolveQuickPick", { + value: jest.fn().mockResolvedValueOnce(globalMocks.mockLogoutChosen), + configurable: true, + }); + await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); + expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); + expect(blockMocks.loginSpy).not.toBeCalled(); + expect(blockMocks.logoutSpy).toBeCalled(); + globalMocks.debugLogSpy.mockClear(); + blockMocks.loginSpy.mockClear(); + blockMocks.logoutSpy.mockClear(); + }); }); - it("profile using basic authentication should see promptCredentials called when Update Credentials chosen", async () => { - const globalMocks = createGlobalMocks(); - const logMsg = `Profile ${globalMocks.mockBasicAuthProfile.name} is using basic authentication.`; - Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(globalMocks.mockUpdateChosen), configurable: true }); - const scenarioSpy = jest.spyOn(profUtils.ProfilesUtils, "promptCredentials"); - await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(logMsg); - expect(scenarioSpy).toBeCalled(); - globalMocks.debugLogSpy.mockClear(); - scenarioSpy.mockClear(); + describe("unit tests around no auth declared selections", () => { + function createBlockMocks(globalMocks) { + const newMocks = { + mockProfileInstance: null as any, + loginSpy: null as any, + editSpy: null as any, + promptSpy: jest.spyOn(profUtils.ProfilesUtils, "promptCredentials"), + logMsg: `Profile ${globalMocks.mockNoAuthProfile.name} authentication method is unkown.`, + }; + newMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(globalMocks.mockNoAuthProfile); + Object.defineProperty(Profiles, "getInstance", { + value: jest.fn().mockReturnValue(newMocks.mockProfileInstance), + configurable: true, + }); + Object.defineProperty(newMocks.mockProfileInstance, "editSession", { value: jest.fn(), configurable: true }); + newMocks.editSpy = jest.spyOn(newMocks.mockProfileInstance, "editSession"); + Object.defineProperty(newMocks.mockProfileInstance, "ssoLogin", { value: jest.fn(), configurable: true }); + newMocks.loginSpy = jest.spyOn(Profiles.getInstance(), "ssoLogin"); + Object.defineProperty(profUtils.ProfilesUtils, "isUsingTokenAuth", { value: jest.fn().mockResolvedValueOnce(false), configurable: true }); + globalMocks.mockDsSessionNode = dsMock.createDatasetSessionNode(globalMocks.mockSession, globalMocks.mockTokenAuthProfile) as any; + Object.defineProperty(globalMocks.mockDsSessionNode, "getProfile", { + value: jest.fn().mockReturnValue(globalMocks.mockNoAuthProfile), + configurable: true, + }); + return newMocks; + } + afterEach(() => { + jest.clearAllMocks(); + jest.resetAllMocks(); + }); + it("profile with no authentication method should see Operation Cancelled when escaping quick pick", async () => { + const globalMocks = createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(undefined), configurable: true }); + await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); + expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); + expect(blockMocks.loginSpy).not.toBeCalled(); + expect(globalMocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); + globalMocks.debugLogSpy.mockClear(); + blockMocks.loginSpy.mockClear(); + globalMocks.opCancelledSpy.mockClear(); + }); + it("profile with no authentication method should see promptCredentials called when Add Basic Credentials chosen", async () => { + const globalMocks = createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + Object.defineProperty(Gui, "resolveQuickPick", { + value: jest.fn().mockResolvedValueOnce(globalMocks.mockAddBasicChosen), + configurable: true, + }); + await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); + expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); + expect(blockMocks.promptSpy).toBeCalled(); + globalMocks.debugLogSpy.mockClear(); + blockMocks.promptSpy.mockClear(); + }); + it("profile with no authentication method should see ssoLogin called when Log in to authentication service chosen", async () => { + const globalMocks = createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + Object.defineProperty(Gui, "resolveQuickPick", { + value: jest.fn().mockResolvedValueOnce(globalMocks.mockLoginChosen), + configurable: true, + }); + await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); + expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); + expect(blockMocks.loginSpy).toBeCalled(); + globalMocks.debugLogSpy.mockClear(); + blockMocks.loginSpy.mockClear(); + }); + it("profile with no authentication method should see editSession called when Edit Profile chosen", async () => { + const globalMocks = createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + Object.defineProperty(Gui, "resolveQuickPick", { + value: jest.fn().mockResolvedValueOnce(globalMocks.mockEditProfChosen), + configurable: true, + }); + await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); + expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); + expect(blockMocks.promptSpy).not.toBeCalled(); + expect(blockMocks.editSpy).toBeCalled(); + globalMocks.debugLogSpy.mockClear(); + blockMocks.promptSpy.mockClear(); + blockMocks.editSpy.mockClear(); + }); }); }); From 29987e64d5b938e90b2d9fb0d584e4590178ac3e Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Fri, 22 Sep 2023 17:02:34 -0400 Subject: [PATCH 16/35] cut down on duplication of test code Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../utils/ProfileManagement.unit.test.ts | 61 ++++++++----------- 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts index e324c714aa..efd7bf90d6 100644 --- a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts @@ -20,7 +20,6 @@ import { Profiles } from "../../../src/Profiles"; jest.mock("fs"); jest.mock("vscode"); -jest.mock("@zowe/cli"); describe("ProfileManagement unit tests", () => { afterEach(() => { @@ -42,6 +41,7 @@ describe("ProfileManagement unit tests", () => { mockCreateQp: jest.fn(), debugLogSpy: null as any, opCancelledSpy: jest.spyOn(Gui, "infoMessage"), + promptSpy: null as any, }; newMocks.mockUpdateChosen = ProfileManagement.basicAuthUpdateQpItems[ProfileManagement.AuthQpLabels.update]; newMocks.mockAddBasicChosen = ProfileManagement.basicAuthAddQpItems[ProfileManagement.AuthQpLabels.add]; @@ -60,6 +60,7 @@ describe("ProfileManagement unit tests", () => { }), }); Object.defineProperty(profUtils.ProfilesUtils, "promptCredentials", { value: jest.fn(), configurable: true }); + newMocks.promptSpy = jest.spyOn(profUtils.ProfilesUtils, "promptCredentials"); Object.defineProperty(Gui, "createQuickPick", { value: newMocks.mockCreateQp, configurable: true }); Object.defineProperty(ZoweLogger, "debug", { value: jest.fn(), configurable: true }); newMocks.debugLogSpy = jest.spyOn(ZoweLogger, "debug"); @@ -72,7 +73,6 @@ describe("ProfileManagement unit tests", () => { const newMocks = { mockProfileInstance: null as any, editSpy: null as any, - promptSpy: jest.spyOn(profUtils.ProfilesUtils, "promptCredentials"), logMsg: `Profile ${globalMocks.mockBasicAuthProfile.name} is using basic authentication.`, }; newMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(globalMocks.mockBasicAuthProfile); @@ -90,6 +90,12 @@ describe("ProfileManagement unit tests", () => { return newMocks; } afterEach(() => { + const globalMocks = createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + globalMocks.debugLogSpy.mockClear(); + globalMocks.promptSpy.mockClear(); + blockMocks.editSpy.mockClear(); + globalMocks.opCancelledSpy.mockClear(); jest.clearAllMocks(); jest.resetAllMocks(); }); @@ -99,11 +105,8 @@ describe("ProfileManagement unit tests", () => { Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(undefined), configurable: true }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); - expect(blockMocks.promptSpy).not.toBeCalled(); + expect(globalMocks.promptSpy).not.toBeCalled(); expect(globalMocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); - globalMocks.debugLogSpy.mockClear(); - blockMocks.promptSpy.mockClear(); - globalMocks.opCancelledSpy.mockClear(); }); it("profile using basic authentication should see promptCredentials called when Update Credentials chosen", async () => { const globalMocks = createGlobalMocks(); @@ -114,9 +117,7 @@ describe("ProfileManagement unit tests", () => { }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); - expect(blockMocks.promptSpy).toBeCalled(); - globalMocks.debugLogSpy.mockClear(); - blockMocks.promptSpy.mockClear(); + expect(globalMocks.promptSpy).toBeCalled(); }); it("profile using basic authentication should see editSession called when Edit Profile chosen", async () => { const globalMocks = createGlobalMocks(); @@ -127,11 +128,8 @@ describe("ProfileManagement unit tests", () => { }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); - expect(blockMocks.promptSpy).not.toBeCalled(); + expect(globalMocks.promptSpy).not.toBeCalled(); expect(blockMocks.editSpy).toBeCalled(); - globalMocks.debugLogSpy.mockClear(); - blockMocks.promptSpy.mockClear(); - blockMocks.editSpy.mockClear(); }); }); describe("unit tests around token auth selections", () => { @@ -163,6 +161,13 @@ describe("ProfileManagement unit tests", () => { return newMocks; } afterEach(() => { + const globalMocks = createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + globalMocks.debugLogSpy.mockClear(); + blockMocks.loginSpy.mockClear(); + blockMocks.logoutSpy.mockClear(); + globalMocks.opCancelledSpy.mockClear(); + blockMocks.editSpy.mockClear(); jest.clearAllMocks(); jest.resetAllMocks(); }); @@ -174,9 +179,6 @@ describe("ProfileManagement unit tests", () => { expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); expect(blockMocks.loginSpy).not.toBeCalled(); expect(globalMocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); - globalMocks.debugLogSpy.mockClear(); - blockMocks.loginSpy.mockClear(); - globalMocks.opCancelledSpy.mockClear(); }); it("profile using token authentication should see ssoLogin called when Log in to authentication service chosen", async () => { const globalMocks = createGlobalMocks(); @@ -188,8 +190,6 @@ describe("ProfileManagement unit tests", () => { await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); expect(blockMocks.loginSpy).toBeCalled(); - globalMocks.debugLogSpy.mockClear(); - blockMocks.loginSpy.mockClear(); }); it("profile using token authentication should see ssoLogout called when Log out from authentication service chosen", async () => { const globalMocks = createGlobalMocks(); @@ -202,9 +202,6 @@ describe("ProfileManagement unit tests", () => { expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); expect(blockMocks.loginSpy).not.toBeCalled(); expect(blockMocks.logoutSpy).toBeCalled(); - globalMocks.debugLogSpy.mockClear(); - blockMocks.loginSpy.mockClear(); - blockMocks.logoutSpy.mockClear(); }); }); describe("unit tests around no auth declared selections", () => { @@ -213,7 +210,6 @@ describe("ProfileManagement unit tests", () => { mockProfileInstance: null as any, loginSpy: null as any, editSpy: null as any, - promptSpy: jest.spyOn(profUtils.ProfilesUtils, "promptCredentials"), logMsg: `Profile ${globalMocks.mockNoAuthProfile.name} authentication method is unkown.`, }; newMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(globalMocks.mockNoAuthProfile); @@ -234,6 +230,13 @@ describe("ProfileManagement unit tests", () => { return newMocks; } afterEach(() => { + const globalMocks = createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + globalMocks.debugLogSpy.mockClear(); + blockMocks.loginSpy.mockClear(); + globalMocks.opCancelledSpy.mockClear(); + globalMocks.promptSpy.mockClear(); + blockMocks.editSpy.mockClear(); jest.clearAllMocks(); jest.resetAllMocks(); }); @@ -245,9 +248,6 @@ describe("ProfileManagement unit tests", () => { expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); expect(blockMocks.loginSpy).not.toBeCalled(); expect(globalMocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); - globalMocks.debugLogSpy.mockClear(); - blockMocks.loginSpy.mockClear(); - globalMocks.opCancelledSpy.mockClear(); }); it("profile with no authentication method should see promptCredentials called when Add Basic Credentials chosen", async () => { const globalMocks = createGlobalMocks(); @@ -258,9 +258,7 @@ describe("ProfileManagement unit tests", () => { }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); - expect(blockMocks.promptSpy).toBeCalled(); - globalMocks.debugLogSpy.mockClear(); - blockMocks.promptSpy.mockClear(); + expect(globalMocks.promptSpy).toBeCalled(); }); it("profile with no authentication method should see ssoLogin called when Log in to authentication service chosen", async () => { const globalMocks = createGlobalMocks(); @@ -272,8 +270,6 @@ describe("ProfileManagement unit tests", () => { await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); expect(blockMocks.loginSpy).toBeCalled(); - globalMocks.debugLogSpy.mockClear(); - blockMocks.loginSpy.mockClear(); }); it("profile with no authentication method should see editSession called when Edit Profile chosen", async () => { const globalMocks = createGlobalMocks(); @@ -284,11 +280,8 @@ describe("ProfileManagement unit tests", () => { }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); - expect(blockMocks.promptSpy).not.toBeCalled(); + expect(globalMocks.promptSpy).not.toBeCalled(); expect(blockMocks.editSpy).toBeCalled(); - globalMocks.debugLogSpy.mockClear(); - blockMocks.promptSpy.mockClear(); - blockMocks.editSpy.mockClear(); }); }); }); From 4484235e38754604112a1b3350aaea1d934e8059 Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Fri, 22 Sep 2023 17:18:25 -0400 Subject: [PATCH 17/35] clear more duplication Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../utils/ProfileManagement.unit.test.ts | 97 ++++++------------- 1 file changed, 30 insertions(+), 67 deletions(-) diff --git a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts index efd7bf90d6..234de03e8e 100644 --- a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts @@ -28,6 +28,7 @@ describe("ProfileManagement unit tests", () => { }); function createGlobalMocks() { const newMocks = { + mockProfileInstance: null as any, mockSession: sharedMock.createISession(), mockBasicAuthProfile: sharedMock.createValidIProfile(), mockTokenAuthProfile: sharedMock.createTokenAuthIProfile(), @@ -42,6 +43,9 @@ describe("ProfileManagement unit tests", () => { debugLogSpy: null as any, opCancelledSpy: jest.spyOn(Gui, "infoMessage"), promptSpy: null as any, + editSpy: null as any, + loginSpy: null as any, + logoutSpy: null as any, }; newMocks.mockUpdateChosen = ProfileManagement.basicAuthUpdateQpItems[ProfileManagement.AuthQpLabels.update]; newMocks.mockAddBasicChosen = ProfileManagement.basicAuthAddQpItems[ProfileManagement.AuthQpLabels.add]; @@ -71,17 +75,15 @@ describe("ProfileManagement unit tests", () => { describe("unit tests around basic auth selections", () => { function createBlockMocks(globalMocks) { const newMocks = { - mockProfileInstance: null as any, - editSpy: null as any, logMsg: `Profile ${globalMocks.mockBasicAuthProfile.name} is using basic authentication.`, }; - newMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(globalMocks.mockBasicAuthProfile); + globalMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(globalMocks.mockBasicAuthProfile); Object.defineProperty(Profiles, "getInstance", { - value: jest.fn().mockReturnValue(newMocks.mockProfileInstance), + value: jest.fn().mockReturnValue(globalMocks.mockProfileInstance), configurable: true, }); - Object.defineProperty(newMocks.mockProfileInstance, "editSession", { value: jest.fn(), configurable: true }); - newMocks.editSpy = jest.spyOn(newMocks.mockProfileInstance, "editSession"); + Object.defineProperty(globalMocks.mockProfileInstance, "editSession", { value: jest.fn(), configurable: true }); + globalMocks.editSpy = jest.spyOn(globalMocks.mockProfileInstance, "editSession"); globalMocks.mockDsSessionNode = dsMock.createDatasetSessionNode(globalMocks.mockSession, globalMocks.mockBasicAuthProfile) as any; Object.defineProperty(globalMocks.mockDsSessionNode, "getProfile", { value: jest.fn().mockReturnValue(globalMocks.mockBasicAuthProfile), @@ -89,16 +91,6 @@ describe("ProfileManagement unit tests", () => { }); return newMocks; } - afterEach(() => { - const globalMocks = createGlobalMocks(); - const blockMocks = createBlockMocks(globalMocks); - globalMocks.debugLogSpy.mockClear(); - globalMocks.promptSpy.mockClear(); - blockMocks.editSpy.mockClear(); - globalMocks.opCancelledSpy.mockClear(); - jest.clearAllMocks(); - jest.resetAllMocks(); - }); it("profile using basic authentication should see Operation Cancelled when escaping quick pick", async () => { const globalMocks = createGlobalMocks(); const blockMocks = createBlockMocks(globalMocks); @@ -129,29 +121,25 @@ describe("ProfileManagement unit tests", () => { await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); expect(globalMocks.promptSpy).not.toBeCalled(); - expect(blockMocks.editSpy).toBeCalled(); + expect(globalMocks.editSpy).toBeCalled(); }); }); describe("unit tests around token auth selections", () => { function createBlockMocks(globalMocks) { const newMocks = { - mockProfileInstance: null as any, - loginSpy: null as any, - logoutSpy: null as any, - editSpy: null as any, logMsg: `Profile ${globalMocks.mockTokenAuthProfile.name} is using token authentication.`, }; - newMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(globalMocks.mockTokenAuthProfile); + globalMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(globalMocks.mockTokenAuthProfile); Object.defineProperty(Profiles, "getInstance", { - value: jest.fn().mockReturnValue(newMocks.mockProfileInstance), + value: jest.fn().mockReturnValue(globalMocks.mockProfileInstance), configurable: true, }); - Object.defineProperty(newMocks.mockProfileInstance, "editSession", { value: jest.fn(), configurable: true }); - newMocks.editSpy = jest.spyOn(newMocks.mockProfileInstance, "editSession"); - Object.defineProperty(newMocks.mockProfileInstance, "ssoLogin", { value: jest.fn(), configurable: true }); - newMocks.loginSpy = jest.spyOn(Profiles.getInstance(), "ssoLogin"); - Object.defineProperty(newMocks.mockProfileInstance, "ssoLogout", { value: jest.fn(), configurable: true }); - newMocks.logoutSpy = jest.spyOn(Profiles.getInstance(), "ssoLogout"); + Object.defineProperty(globalMocks.mockProfileInstance, "editSession", { value: jest.fn(), configurable: true }); + globalMocks.editSpy = jest.spyOn(globalMocks.mockProfileInstance, "editSession"); + Object.defineProperty(globalMocks.mockProfileInstance, "ssoLogin", { value: jest.fn(), configurable: true }); + globalMocks.loginSpy = jest.spyOn(Profiles.getInstance(), "ssoLogin"); + Object.defineProperty(globalMocks.mockProfileInstance, "ssoLogout", { value: jest.fn(), configurable: true }); + globalMocks.logoutSpy = jest.spyOn(Profiles.getInstance(), "ssoLogout"); Object.defineProperty(profUtils.ProfilesUtils, "isUsingTokenAuth", { value: jest.fn().mockResolvedValueOnce(true), configurable: true }); globalMocks.mockDsSessionNode = dsMock.createDatasetSessionNode(globalMocks.mockSession, globalMocks.mockTokenAuthProfile) as any; Object.defineProperty(globalMocks.mockDsSessionNode, "getProfile", { @@ -160,24 +148,13 @@ describe("ProfileManagement unit tests", () => { }); return newMocks; } - afterEach(() => { - const globalMocks = createGlobalMocks(); - const blockMocks = createBlockMocks(globalMocks); - globalMocks.debugLogSpy.mockClear(); - blockMocks.loginSpy.mockClear(); - blockMocks.logoutSpy.mockClear(); - globalMocks.opCancelledSpy.mockClear(); - blockMocks.editSpy.mockClear(); - jest.clearAllMocks(); - jest.resetAllMocks(); - }); it("profile using token authentication should see Operation Cancelled when escaping quick pick", async () => { const globalMocks = createGlobalMocks(); const blockMocks = createBlockMocks(globalMocks); Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(undefined), configurable: true }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); - expect(blockMocks.loginSpy).not.toBeCalled(); + expect(globalMocks.loginSpy).not.toBeCalled(); expect(globalMocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); }); it("profile using token authentication should see ssoLogin called when Log in to authentication service chosen", async () => { @@ -189,7 +166,7 @@ describe("ProfileManagement unit tests", () => { }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); - expect(blockMocks.loginSpy).toBeCalled(); + expect(globalMocks.loginSpy).toBeCalled(); }); it("profile using token authentication should see ssoLogout called when Log out from authentication service chosen", async () => { const globalMocks = createGlobalMocks(); @@ -200,27 +177,24 @@ describe("ProfileManagement unit tests", () => { }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); - expect(blockMocks.loginSpy).not.toBeCalled(); - expect(blockMocks.logoutSpy).toBeCalled(); + expect(globalMocks.loginSpy).not.toBeCalled(); + expect(globalMocks.logoutSpy).toBeCalled(); }); }); describe("unit tests around no auth declared selections", () => { function createBlockMocks(globalMocks) { const newMocks = { - mockProfileInstance: null as any, - loginSpy: null as any, - editSpy: null as any, logMsg: `Profile ${globalMocks.mockNoAuthProfile.name} authentication method is unkown.`, }; - newMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(globalMocks.mockNoAuthProfile); + globalMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(globalMocks.mockNoAuthProfile); Object.defineProperty(Profiles, "getInstance", { - value: jest.fn().mockReturnValue(newMocks.mockProfileInstance), + value: jest.fn().mockReturnValue(globalMocks.mockProfileInstance), configurable: true, }); - Object.defineProperty(newMocks.mockProfileInstance, "editSession", { value: jest.fn(), configurable: true }); - newMocks.editSpy = jest.spyOn(newMocks.mockProfileInstance, "editSession"); - Object.defineProperty(newMocks.mockProfileInstance, "ssoLogin", { value: jest.fn(), configurable: true }); - newMocks.loginSpy = jest.spyOn(Profiles.getInstance(), "ssoLogin"); + Object.defineProperty(globalMocks.mockProfileInstance, "editSession", { value: jest.fn(), configurable: true }); + globalMocks.editSpy = jest.spyOn(globalMocks.mockProfileInstance, "editSession"); + Object.defineProperty(globalMocks.mockProfileInstance, "ssoLogin", { value: jest.fn(), configurable: true }); + globalMocks.loginSpy = jest.spyOn(Profiles.getInstance(), "ssoLogin"); Object.defineProperty(profUtils.ProfilesUtils, "isUsingTokenAuth", { value: jest.fn().mockResolvedValueOnce(false), configurable: true }); globalMocks.mockDsSessionNode = dsMock.createDatasetSessionNode(globalMocks.mockSession, globalMocks.mockTokenAuthProfile) as any; Object.defineProperty(globalMocks.mockDsSessionNode, "getProfile", { @@ -229,24 +203,13 @@ describe("ProfileManagement unit tests", () => { }); return newMocks; } - afterEach(() => { - const globalMocks = createGlobalMocks(); - const blockMocks = createBlockMocks(globalMocks); - globalMocks.debugLogSpy.mockClear(); - blockMocks.loginSpy.mockClear(); - globalMocks.opCancelledSpy.mockClear(); - globalMocks.promptSpy.mockClear(); - blockMocks.editSpy.mockClear(); - jest.clearAllMocks(); - jest.resetAllMocks(); - }); it("profile with no authentication method should see Operation Cancelled when escaping quick pick", async () => { const globalMocks = createGlobalMocks(); const blockMocks = createBlockMocks(globalMocks); Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(undefined), configurable: true }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); - expect(blockMocks.loginSpy).not.toBeCalled(); + expect(globalMocks.loginSpy).not.toBeCalled(); expect(globalMocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); }); it("profile with no authentication method should see promptCredentials called when Add Basic Credentials chosen", async () => { @@ -269,7 +232,7 @@ describe("ProfileManagement unit tests", () => { }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); - expect(blockMocks.loginSpy).toBeCalled(); + expect(globalMocks.loginSpy).toBeCalled(); }); it("profile with no authentication method should see editSession called when Edit Profile chosen", async () => { const globalMocks = createGlobalMocks(); @@ -281,7 +244,7 @@ describe("ProfileManagement unit tests", () => { await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); expect(globalMocks.promptSpy).not.toBeCalled(); - expect(blockMocks.editSpy).toBeCalled(); + expect(globalMocks.editSpy).toBeCalled(); }); }); }); From 847982127d30129c05711454aa08ce4f90a9a002 Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Fri, 22 Sep 2023 17:30:23 -0400 Subject: [PATCH 18/35] cleanup Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../utils/ProfileManagement.unit.test.ts | 62 +++++++------------ 1 file changed, 24 insertions(+), 38 deletions(-) diff --git a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts index 234de03e8e..feac872808 100644 --- a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts @@ -46,6 +46,7 @@ describe("ProfileManagement unit tests", () => { editSpy: null as any, loginSpy: null as any, logoutSpy: null as any, + logMsg: null as any, }; newMocks.mockUpdateChosen = ProfileManagement.basicAuthUpdateQpItems[ProfileManagement.AuthQpLabels.update]; newMocks.mockAddBasicChosen = ProfileManagement.basicAuthAddQpItems[ProfileManagement.AuthQpLabels.add]; @@ -74,9 +75,7 @@ describe("ProfileManagement unit tests", () => { describe("unit tests around basic auth selections", () => { function createBlockMocks(globalMocks) { - const newMocks = { - logMsg: `Profile ${globalMocks.mockBasicAuthProfile.name} is using basic authentication.`, - }; + globalMocks.logMsg = `Profile ${globalMocks.mockBasicAuthProfile.name} is using basic authentication.`; globalMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(globalMocks.mockBasicAuthProfile); Object.defineProperty(Profiles, "getInstance", { value: jest.fn().mockReturnValue(globalMocks.mockProfileInstance), @@ -89,46 +88,41 @@ describe("ProfileManagement unit tests", () => { value: jest.fn().mockReturnValue(globalMocks.mockBasicAuthProfile), configurable: true, }); - return newMocks; } it("profile using basic authentication should see Operation Cancelled when escaping quick pick", async () => { const globalMocks = createGlobalMocks(); - const blockMocks = createBlockMocks(globalMocks); + createBlockMocks(globalMocks); Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(undefined), configurable: true }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); - expect(globalMocks.promptSpy).not.toBeCalled(); + expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); }); it("profile using basic authentication should see promptCredentials called when Update Credentials chosen", async () => { const globalMocks = createGlobalMocks(); - const blockMocks = createBlockMocks(globalMocks); + createBlockMocks(globalMocks); Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(globalMocks.mockUpdateChosen), configurable: true, }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); + expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.promptSpy).toBeCalled(); }); it("profile using basic authentication should see editSession called when Edit Profile chosen", async () => { const globalMocks = createGlobalMocks(); - const blockMocks = createBlockMocks(globalMocks); + createBlockMocks(globalMocks); Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(globalMocks.mockEditProfChosen), configurable: true, }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); - expect(globalMocks.promptSpy).not.toBeCalled(); + expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.editSpy).toBeCalled(); }); }); describe("unit tests around token auth selections", () => { function createBlockMocks(globalMocks) { - const newMocks = { - logMsg: `Profile ${globalMocks.mockTokenAuthProfile.name} is using token authentication.`, - }; + globalMocks.logMsg = `Profile ${globalMocks.mockTokenAuthProfile.name} is using token authentication.`; globalMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(globalMocks.mockTokenAuthProfile); Object.defineProperty(Profiles, "getInstance", { value: jest.fn().mockReturnValue(globalMocks.mockProfileInstance), @@ -146,46 +140,41 @@ describe("ProfileManagement unit tests", () => { value: jest.fn().mockReturnValue(globalMocks.mockTokenAuthProfile), configurable: true, }); - return newMocks; } it("profile using token authentication should see Operation Cancelled when escaping quick pick", async () => { const globalMocks = createGlobalMocks(); - const blockMocks = createBlockMocks(globalMocks); + createBlockMocks(globalMocks); Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(undefined), configurable: true }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); - expect(globalMocks.loginSpy).not.toBeCalled(); + expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); }); it("profile using token authentication should see ssoLogin called when Log in to authentication service chosen", async () => { const globalMocks = createGlobalMocks(); - const blockMocks = createBlockMocks(globalMocks); + createBlockMocks(globalMocks); Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(globalMocks.mockLoginChosen), configurable: true, }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); + expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.loginSpy).toBeCalled(); }); it("profile using token authentication should see ssoLogout called when Log out from authentication service chosen", async () => { const globalMocks = createGlobalMocks(); - const blockMocks = createBlockMocks(globalMocks); + createBlockMocks(globalMocks); Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(globalMocks.mockLogoutChosen), configurable: true, }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); - expect(globalMocks.loginSpy).not.toBeCalled(); + expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.logoutSpy).toBeCalled(); }); }); describe("unit tests around no auth declared selections", () => { function createBlockMocks(globalMocks) { - const newMocks = { - logMsg: `Profile ${globalMocks.mockNoAuthProfile.name} authentication method is unkown.`, - }; + globalMocks.logMsg = `Profile ${globalMocks.mockNoAuthProfile.name} authentication method is unkown.`; globalMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(globalMocks.mockNoAuthProfile); Object.defineProperty(Profiles, "getInstance", { value: jest.fn().mockReturnValue(globalMocks.mockProfileInstance), @@ -201,49 +190,46 @@ describe("ProfileManagement unit tests", () => { value: jest.fn().mockReturnValue(globalMocks.mockNoAuthProfile), configurable: true, }); - return newMocks; } it("profile with no authentication method should see Operation Cancelled when escaping quick pick", async () => { const globalMocks = createGlobalMocks(); - const blockMocks = createBlockMocks(globalMocks); + createBlockMocks(globalMocks); Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(undefined), configurable: true }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); - expect(globalMocks.loginSpy).not.toBeCalled(); + expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); }); it("profile with no authentication method should see promptCredentials called when Add Basic Credentials chosen", async () => { const globalMocks = createGlobalMocks(); - const blockMocks = createBlockMocks(globalMocks); + createBlockMocks(globalMocks); Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(globalMocks.mockAddBasicChosen), configurable: true, }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); + expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.promptSpy).toBeCalled(); }); it("profile with no authentication method should see ssoLogin called when Log in to authentication service chosen", async () => { const globalMocks = createGlobalMocks(); - const blockMocks = createBlockMocks(globalMocks); + createBlockMocks(globalMocks); Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(globalMocks.mockLoginChosen), configurable: true, }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); + expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.loginSpy).toBeCalled(); }); it("profile with no authentication method should see editSession called when Edit Profile chosen", async () => { const globalMocks = createGlobalMocks(); - const blockMocks = createBlockMocks(globalMocks); + createBlockMocks(globalMocks); Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(globalMocks.mockEditProfChosen), configurable: true, }); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(blockMocks.logMsg); - expect(globalMocks.promptSpy).not.toBeCalled(); + expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.editSpy).toBeCalled(); }); }); From c046daa4de3efec25b553789e678c391c24c0d04 Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Fri, 22 Sep 2023 18:01:11 -0400 Subject: [PATCH 19/35] clean duplication unit testing Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../utils/ProfileManagement.unit.test.ts | 70 ++++++------------- 1 file changed, 23 insertions(+), 47 deletions(-) diff --git a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts index feac872808..cb6766e044 100644 --- a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts @@ -28,31 +28,32 @@ describe("ProfileManagement unit tests", () => { }); function createGlobalMocks() { const newMocks = { - mockProfileInstance: null as any, mockSession: sharedMock.createISession(), mockBasicAuthProfile: sharedMock.createValidIProfile(), mockTokenAuthProfile: sharedMock.createTokenAuthIProfile(), mockNoAuthProfile: sharedMock.createInvalidIProfile(), + opCancelledSpy: jest.spyOn(Gui, "infoMessage"), mockDsSessionNode: ZoweDatasetNode, - mockUpdateChosen: null as any, - mockAddBasicChosen: null as any, - mockLoginChosen: null as any, - mockLogoutChosen: null as any, - mockEditProfChosen: null as any, + mockResolveQp: jest.fn(), mockCreateQp: jest.fn(), + mockUpdateChosen: ProfileManagement.basicAuthUpdateQpItems[ProfileManagement.AuthQpLabels.update], + mockAddBasicChosen: ProfileManagement.basicAuthAddQpItems[ProfileManagement.AuthQpLabels.add], + mockLoginChosen: ProfileManagement.tokenAuthLoginQpItem[ProfileManagement.AuthQpLabels.login], + mockLogoutChosen: ProfileManagement.tokenAuthLogoutQpItem[ProfileManagement.AuthQpLabels.logout], + mockEditProfChosen: ProfileManagement.otherProfileQpItems[ProfileManagement.AuthQpLabels.edit], + mockProfileInstance: null as any, debugLogSpy: null as any, - opCancelledSpy: jest.spyOn(Gui, "infoMessage"), promptSpy: null as any, editSpy: null as any, loginSpy: null as any, logoutSpy: null as any, logMsg: null as any, }; - newMocks.mockUpdateChosen = ProfileManagement.basicAuthUpdateQpItems[ProfileManagement.AuthQpLabels.update]; - newMocks.mockAddBasicChosen = ProfileManagement.basicAuthAddQpItems[ProfileManagement.AuthQpLabels.add]; - newMocks.mockLoginChosen = ProfileManagement.tokenAuthLoginQpItem[ProfileManagement.AuthQpLabels.login]; - newMocks.mockLogoutChosen = ProfileManagement.tokenAuthLogoutQpItem[ProfileManagement.AuthQpLabels.logout]; - newMocks.mockEditProfChosen = ProfileManagement.otherProfileQpItems[ProfileManagement.AuthQpLabels.edit]; + Object.defineProperty(profUtils.ProfilesUtils, "promptCredentials", { value: jest.fn(), configurable: true }); + newMocks.promptSpy = jest.spyOn(profUtils.ProfilesUtils, "promptCredentials"); + Object.defineProperty(ZoweLogger, "debug", { value: jest.fn(), configurable: true }); + newMocks.debugLogSpy = jest.spyOn(ZoweLogger, "debug"); + Object.defineProperty(Gui, "resolveQuickPick", { value: newMocks.mockResolveQp, configurable: true }); newMocks.mockCreateQp.mockReturnValue({ show: jest.fn(() => { return {}; @@ -64,11 +65,7 @@ describe("ProfileManagement unit tests", () => { return {}; }), }); - Object.defineProperty(profUtils.ProfilesUtils, "promptCredentials", { value: jest.fn(), configurable: true }); - newMocks.promptSpy = jest.spyOn(profUtils.ProfilesUtils, "promptCredentials"); Object.defineProperty(Gui, "createQuickPick", { value: newMocks.mockCreateQp, configurable: true }); - Object.defineProperty(ZoweLogger, "debug", { value: jest.fn(), configurable: true }); - newMocks.debugLogSpy = jest.spyOn(ZoweLogger, "debug"); return newMocks; } @@ -92,7 +89,7 @@ describe("ProfileManagement unit tests", () => { it("profile using basic authentication should see Operation Cancelled when escaping quick pick", async () => { const globalMocks = createGlobalMocks(); createBlockMocks(globalMocks); - Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(undefined), configurable: true }); + globalMocks.mockResolveQp.mockResolvedValueOnce(undefined); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); @@ -100,10 +97,7 @@ describe("ProfileManagement unit tests", () => { it("profile using basic authentication should see promptCredentials called when Update Credentials chosen", async () => { const globalMocks = createGlobalMocks(); createBlockMocks(globalMocks); - Object.defineProperty(Gui, "resolveQuickPick", { - value: jest.fn().mockResolvedValueOnce(globalMocks.mockUpdateChosen), - configurable: true, - }); + globalMocks.mockResolveQp.mockResolvedValueOnce(globalMocks.mockUpdateChosen); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.promptSpy).toBeCalled(); @@ -111,10 +105,7 @@ describe("ProfileManagement unit tests", () => { it("profile using basic authentication should see editSession called when Edit Profile chosen", async () => { const globalMocks = createGlobalMocks(); createBlockMocks(globalMocks); - Object.defineProperty(Gui, "resolveQuickPick", { - value: jest.fn().mockResolvedValueOnce(globalMocks.mockEditProfChosen), - configurable: true, - }); + globalMocks.mockResolveQp.mockResolvedValueOnce(globalMocks.mockEditProfChosen); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.editSpy).toBeCalled(); @@ -144,7 +135,7 @@ describe("ProfileManagement unit tests", () => { it("profile using token authentication should see Operation Cancelled when escaping quick pick", async () => { const globalMocks = createGlobalMocks(); createBlockMocks(globalMocks); - Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(undefined), configurable: true }); + globalMocks.mockResolveQp.mockResolvedValueOnce(undefined); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); @@ -152,10 +143,7 @@ describe("ProfileManagement unit tests", () => { it("profile using token authentication should see ssoLogin called when Log in to authentication service chosen", async () => { const globalMocks = createGlobalMocks(); createBlockMocks(globalMocks); - Object.defineProperty(Gui, "resolveQuickPick", { - value: jest.fn().mockResolvedValueOnce(globalMocks.mockLoginChosen), - configurable: true, - }); + globalMocks.mockResolveQp.mockResolvedValueOnce(globalMocks.mockLoginChosen); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.loginSpy).toBeCalled(); @@ -163,10 +151,7 @@ describe("ProfileManagement unit tests", () => { it("profile using token authentication should see ssoLogout called when Log out from authentication service chosen", async () => { const globalMocks = createGlobalMocks(); createBlockMocks(globalMocks); - Object.defineProperty(Gui, "resolveQuickPick", { - value: jest.fn().mockResolvedValueOnce(globalMocks.mockLogoutChosen), - configurable: true, - }); + globalMocks.mockResolveQp.mockResolvedValueOnce(globalMocks.mockLogoutChosen); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.logoutSpy).toBeCalled(); @@ -194,7 +179,7 @@ describe("ProfileManagement unit tests", () => { it("profile with no authentication method should see Operation Cancelled when escaping quick pick", async () => { const globalMocks = createGlobalMocks(); createBlockMocks(globalMocks); - Object.defineProperty(Gui, "resolveQuickPick", { value: jest.fn().mockResolvedValueOnce(undefined), configurable: true }); + globalMocks.mockResolveQp.mockResolvedValueOnce(undefined); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); @@ -202,10 +187,7 @@ describe("ProfileManagement unit tests", () => { it("profile with no authentication method should see promptCredentials called when Add Basic Credentials chosen", async () => { const globalMocks = createGlobalMocks(); createBlockMocks(globalMocks); - Object.defineProperty(Gui, "resolveQuickPick", { - value: jest.fn().mockResolvedValueOnce(globalMocks.mockAddBasicChosen), - configurable: true, - }); + globalMocks.mockResolveQp.mockResolvedValueOnce(globalMocks.mockAddBasicChosen); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.promptSpy).toBeCalled(); @@ -213,10 +195,7 @@ describe("ProfileManagement unit tests", () => { it("profile with no authentication method should see ssoLogin called when Log in to authentication service chosen", async () => { const globalMocks = createGlobalMocks(); createBlockMocks(globalMocks); - Object.defineProperty(Gui, "resolveQuickPick", { - value: jest.fn().mockResolvedValueOnce(globalMocks.mockLoginChosen), - configurable: true, - }); + globalMocks.mockResolveQp.mockResolvedValueOnce(globalMocks.mockLoginChosen); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.loginSpy).toBeCalled(); @@ -224,10 +203,7 @@ describe("ProfileManagement unit tests", () => { it("profile with no authentication method should see editSession called when Edit Profile chosen", async () => { const globalMocks = createGlobalMocks(); createBlockMocks(globalMocks); - Object.defineProperty(Gui, "resolveQuickPick", { - value: jest.fn().mockResolvedValueOnce(globalMocks.mockEditProfChosen), - configurable: true, - }); + globalMocks.mockResolveQp.mockResolvedValueOnce(globalMocks.mockEditProfChosen); await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.editSpy).toBeCalled(); From 4d4637c0635b74b02420eaf2c2badae01d0f8c2a Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Fri, 22 Sep 2023 18:10:49 -0400 Subject: [PATCH 20/35] this should fix high duplication failure Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../utils/ProfileManagement.unit.test.ts | 39 ++++++------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts index cb6766e044..39483cfc0e 100644 --- a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts @@ -67,19 +67,24 @@ describe("ProfileManagement unit tests", () => { }); Object.defineProperty(Gui, "createQuickPick", { value: newMocks.mockCreateQp, configurable: true }); + newMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(newMocks.mockBasicAuthProfile); + Object.defineProperty(Profiles, "getInstance", { + value: jest.fn().mockReturnValue(newMocks.mockProfileInstance), + configurable: true, + }); + Object.defineProperty(newMocks.mockProfileInstance, "editSession", { value: jest.fn(), configurable: true }); + newMocks.editSpy = jest.spyOn(newMocks.mockProfileInstance, "editSession"); + Object.defineProperty(newMocks.mockProfileInstance, "ssoLogin", { value: jest.fn(), configurable: true }); + newMocks.loginSpy = jest.spyOn(newMocks.mockProfileInstance, "ssoLogin"); + Object.defineProperty(newMocks.mockProfileInstance, "ssoLogout", { value: jest.fn(), configurable: true }); + newMocks.logoutSpy = jest.spyOn(newMocks.mockProfileInstance, "ssoLogout"); + return newMocks; } describe("unit tests around basic auth selections", () => { function createBlockMocks(globalMocks) { globalMocks.logMsg = `Profile ${globalMocks.mockBasicAuthProfile.name} is using basic authentication.`; - globalMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(globalMocks.mockBasicAuthProfile); - Object.defineProperty(Profiles, "getInstance", { - value: jest.fn().mockReturnValue(globalMocks.mockProfileInstance), - configurable: true, - }); - Object.defineProperty(globalMocks.mockProfileInstance, "editSession", { value: jest.fn(), configurable: true }); - globalMocks.editSpy = jest.spyOn(globalMocks.mockProfileInstance, "editSession"); globalMocks.mockDsSessionNode = dsMock.createDatasetSessionNode(globalMocks.mockSession, globalMocks.mockBasicAuthProfile) as any; Object.defineProperty(globalMocks.mockDsSessionNode, "getProfile", { value: jest.fn().mockReturnValue(globalMocks.mockBasicAuthProfile), @@ -114,17 +119,6 @@ describe("ProfileManagement unit tests", () => { describe("unit tests around token auth selections", () => { function createBlockMocks(globalMocks) { globalMocks.logMsg = `Profile ${globalMocks.mockTokenAuthProfile.name} is using token authentication.`; - globalMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(globalMocks.mockTokenAuthProfile); - Object.defineProperty(Profiles, "getInstance", { - value: jest.fn().mockReturnValue(globalMocks.mockProfileInstance), - configurable: true, - }); - Object.defineProperty(globalMocks.mockProfileInstance, "editSession", { value: jest.fn(), configurable: true }); - globalMocks.editSpy = jest.spyOn(globalMocks.mockProfileInstance, "editSession"); - Object.defineProperty(globalMocks.mockProfileInstance, "ssoLogin", { value: jest.fn(), configurable: true }); - globalMocks.loginSpy = jest.spyOn(Profiles.getInstance(), "ssoLogin"); - Object.defineProperty(globalMocks.mockProfileInstance, "ssoLogout", { value: jest.fn(), configurable: true }); - globalMocks.logoutSpy = jest.spyOn(Profiles.getInstance(), "ssoLogout"); Object.defineProperty(profUtils.ProfilesUtils, "isUsingTokenAuth", { value: jest.fn().mockResolvedValueOnce(true), configurable: true }); globalMocks.mockDsSessionNode = dsMock.createDatasetSessionNode(globalMocks.mockSession, globalMocks.mockTokenAuthProfile) as any; Object.defineProperty(globalMocks.mockDsSessionNode, "getProfile", { @@ -160,15 +154,6 @@ describe("ProfileManagement unit tests", () => { describe("unit tests around no auth declared selections", () => { function createBlockMocks(globalMocks) { globalMocks.logMsg = `Profile ${globalMocks.mockNoAuthProfile.name} authentication method is unkown.`; - globalMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(globalMocks.mockNoAuthProfile); - Object.defineProperty(Profiles, "getInstance", { - value: jest.fn().mockReturnValue(globalMocks.mockProfileInstance), - configurable: true, - }); - Object.defineProperty(globalMocks.mockProfileInstance, "editSession", { value: jest.fn(), configurable: true }); - globalMocks.editSpy = jest.spyOn(globalMocks.mockProfileInstance, "editSession"); - Object.defineProperty(globalMocks.mockProfileInstance, "ssoLogin", { value: jest.fn(), configurable: true }); - globalMocks.loginSpy = jest.spyOn(Profiles.getInstance(), "ssoLogin"); Object.defineProperty(profUtils.ProfilesUtils, "isUsingTokenAuth", { value: jest.fn().mockResolvedValueOnce(false), configurable: true }); globalMocks.mockDsSessionNode = dsMock.createDatasetSessionNode(globalMocks.mockSession, globalMocks.mockTokenAuthProfile) as any; Object.defineProperty(globalMocks.mockDsSessionNode, "getProfile", { From c22dbc26fee2f10623c0169940fbc07d0b12873b Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Fri, 22 Sep 2023 18:18:25 -0400 Subject: [PATCH 21/35] don't think I can condense anything else from file Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../__tests__/__unit__/utils/ProfileManagement.unit.test.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts index 39483cfc0e..c186bd18b3 100644 --- a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts @@ -66,7 +66,7 @@ describe("ProfileManagement unit tests", () => { }), }); Object.defineProperty(Gui, "createQuickPick", { value: newMocks.mockCreateQp, configurable: true }); - + newMocks.mockDsSessionNode = dsMock.createDatasetSessionNode(newMocks.mockSession, newMocks.mockBasicAuthProfile) as any; newMocks.mockProfileInstance = sharedMock.createInstanceOfProfile(newMocks.mockBasicAuthProfile); Object.defineProperty(Profiles, "getInstance", { value: jest.fn().mockReturnValue(newMocks.mockProfileInstance), @@ -85,7 +85,6 @@ describe("ProfileManagement unit tests", () => { describe("unit tests around basic auth selections", () => { function createBlockMocks(globalMocks) { globalMocks.logMsg = `Profile ${globalMocks.mockBasicAuthProfile.name} is using basic authentication.`; - globalMocks.mockDsSessionNode = dsMock.createDatasetSessionNode(globalMocks.mockSession, globalMocks.mockBasicAuthProfile) as any; Object.defineProperty(globalMocks.mockDsSessionNode, "getProfile", { value: jest.fn().mockReturnValue(globalMocks.mockBasicAuthProfile), configurable: true, @@ -120,7 +119,6 @@ describe("ProfileManagement unit tests", () => { function createBlockMocks(globalMocks) { globalMocks.logMsg = `Profile ${globalMocks.mockTokenAuthProfile.name} is using token authentication.`; Object.defineProperty(profUtils.ProfilesUtils, "isUsingTokenAuth", { value: jest.fn().mockResolvedValueOnce(true), configurable: true }); - globalMocks.mockDsSessionNode = dsMock.createDatasetSessionNode(globalMocks.mockSession, globalMocks.mockTokenAuthProfile) as any; Object.defineProperty(globalMocks.mockDsSessionNode, "getProfile", { value: jest.fn().mockReturnValue(globalMocks.mockTokenAuthProfile), configurable: true, @@ -155,7 +153,6 @@ describe("ProfileManagement unit tests", () => { function createBlockMocks(globalMocks) { globalMocks.logMsg = `Profile ${globalMocks.mockNoAuthProfile.name} authentication method is unkown.`; Object.defineProperty(profUtils.ProfilesUtils, "isUsingTokenAuth", { value: jest.fn().mockResolvedValueOnce(false), configurable: true }); - globalMocks.mockDsSessionNode = dsMock.createDatasetSessionNode(globalMocks.mockSession, globalMocks.mockTokenAuthProfile) as any; Object.defineProperty(globalMocks.mockDsSessionNode, "getProfile", { value: jest.fn().mockReturnValue(globalMocks.mockNoAuthProfile), configurable: true, From 39194d0515a61375b91331a840dbf93da7103a82 Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Fri, 22 Sep 2023 19:27:38 -0400 Subject: [PATCH 22/35] add delete to management options and group left profile items Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../utils/ProfileManagement.unit.test.ts | 31 ++++++++++++++- .../src/utils/ProfileManagement.i18n.json | 1 + packages/zowe-explorer/package.json | 39 ++++++------------- .../src/utils/ProfileManagement.ts | 39 ++++++++++++++----- 4 files changed, 73 insertions(+), 37 deletions(-) diff --git a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts index c186bd18b3..12c62e7ca4 100644 --- a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts @@ -17,6 +17,7 @@ import { ProfileManagement } from "../../../src/utils/ProfileManagement"; import { Gui } from "@zowe/zowe-explorer-api"; import { ZoweLogger } from "../../../src/utils/LoggerUtils"; import { Profiles } from "../../../src/Profiles"; +import * as vscode from "vscode"; jest.mock("fs"); jest.mock("vscode"); @@ -40,7 +41,8 @@ describe("ProfileManagement unit tests", () => { mockAddBasicChosen: ProfileManagement.basicAuthAddQpItems[ProfileManagement.AuthQpLabels.add], mockLoginChosen: ProfileManagement.tokenAuthLoginQpItem[ProfileManagement.AuthQpLabels.login], mockLogoutChosen: ProfileManagement.tokenAuthLogoutQpItem[ProfileManagement.AuthQpLabels.logout], - mockEditProfChosen: ProfileManagement.otherProfileQpItems[ProfileManagement.AuthQpLabels.edit], + mockEditProfChosen: ProfileManagement.editProfileQpItems[ProfileManagement.AuthQpLabels.edit], + mockDeleteProfChosen: ProfileManagement.deleteProfileQpItem[ProfileManagement.AuthQpLabels.delete], mockProfileInstance: null as any, debugLogSpy: null as any, promptSpy: null as any, @@ -89,6 +91,7 @@ describe("ProfileManagement unit tests", () => { value: jest.fn().mockReturnValue(globalMocks.mockBasicAuthProfile), configurable: true, }); + Object.defineProperty(vscode.commands, "executeCommand", { value: jest.fn(), configurable: true }); } it("profile using basic authentication should see Operation Cancelled when escaping quick pick", async () => { const globalMocks = createGlobalMocks(); @@ -114,6 +117,32 @@ describe("ProfileManagement unit tests", () => { expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); expect(globalMocks.editSpy).toBeCalled(); }); + it("profile using basic authentication should see editSession called when Delete Profile chosen with v2 profile", async () => { + const globalMocks = createGlobalMocks(); + createBlockMocks(globalMocks); + globalMocks.mockResolveQp.mockResolvedValueOnce(globalMocks.mockDeleteProfChosen); + Object.defineProperty(globalMocks.mockProfileInstance, "getProfileInfo", { + value: jest.fn().mockResolvedValueOnce({ usingTeamConfig: true }), + configurable: true, + }); + await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); + expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); + expect(globalMocks.editSpy).toBeCalled(); + }); + it("profile using basic authentication should see delete commands called when Delete Profile chosen with v1 profile", async () => { + const globalMocks = createGlobalMocks(); + createBlockMocks(globalMocks); + globalMocks.mockResolveQp.mockResolvedValueOnce(globalMocks.mockDeleteProfChosen); + Object.defineProperty(globalMocks.mockProfileInstance, "getProfileInfo", { + value: jest.fn().mockResolvedValueOnce({ usingTeamConfig: false }), + configurable: true, + }); + const commandSpy = jest.spyOn(vscode.commands, "executeCommand"); + await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); + expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); + expect(globalMocks.editSpy).not.toBeCalled(); + expect(commandSpy).toBeCalled(); + }); }); describe("unit tests around token auth selections", () => { function createBlockMocks(globalMocks) { diff --git a/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json b/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json index d168f6392d..1afb08edfe 100644 --- a/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json +++ b/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json @@ -7,6 +7,7 @@ "addBasicAuthQpItem.addCredentials.qpDetail": "Add username and password for basic authentication", "updateBasicAuthQpItem.updateCredentials.qpLabel": "$(refresh) Update Credentials", "updateBasicAuthQpItem.updateCredentials.qpDetail": "Update stored username and password", + "deleteProfileQpItem.delete.qpLabel": "$(trash) Delete Profile", "editProfileQpItem.editProfile.qpLabel": "$(pencil) Edit profile", "editProfileQpItem.editProfile.qpDetail": "Update profile connection information", "loginQpItem.login.qpLabel": "$(arrow-right) Log in to authentication service", diff --git a/packages/zowe-explorer/package.json b/packages/zowe-explorer/package.json index 773b4556e8..398a82c58b 100644 --- a/packages/zowe-explorer/package.json +++ b/packages/zowe-explorer/package.json @@ -961,27 +961,22 @@ { "when": "view == zowe.uss.explorer && viewItem =~ /_validate/ && !listMultiSelection", "command": "zowe.uss.disableValidation", - "group": "098_zowe_ussProfileAuthentication@1" + "group": "099_zowe_ussProfileAuthentication@96" }, { "when": "view == zowe.uss.explorer && viewItem =~ /_noValidate/ && !listMultiSelection", "command": "zowe.uss.enableValidation", - "group": "098_zowe_ussProfileAuthentication@2" + "group": "099_zowe_ussProfileAuthentication@97" }, { "when": "view == zowe.uss.explorer && viewItem =~ /^(?!.*_fav.*)ussSession.*/ && !listMultiSelection", "command": "zowe.profileManagement", - "group": "099_zowe_ussProfileAuthentication@97" + "group": "099_zowe_ussProfileAuthentication@99" }, { "when": "viewItem =~ /^(?!.*_fav.*)ussSession.*/", "command": "zowe.uss.removeSession", - "group": "099_zowe_ussProfileModification@98" - }, - { - "when": "viewItem =~ /^(?!.*_fav.*)ussSession.*/ && !listMultiSelection", - "command": "zowe.uss.deleteProfile", - "group": "099_zowe_ussProfileModification@99" + "group": "099_zowe_ussProfileAuthentication@98" }, { "when": "view == zowe.ds.explorer && viewItem =~ /^(?!.*_fav.*)session.*/ && !listMultiSelection", @@ -1161,27 +1156,22 @@ { "when": "view == zowe.ds.explorer && viewItem =~ /_validate/ && !listMultiSelection", "command": "zowe.ds.disableValidation", - "group": "098_zowe_dsProfileAuthentication@6" + "group": "099_zowe_dsProfileAuthentication@96" }, { "when": "view == zowe.ds.explorer && viewItem =~ /_noValidate/ && !listMultiSelection", "command": "zowe.ds.enableValidation", - "group": "098_zowe_dsProfileAuthentication@7" + "group": "099_zowe_dsProfileAuthentication@97" }, { "when": "view == zowe.ds.explorer && viewItem =~ /^(?!.*_fav.*)session.*/ && !listMultiSelection", "command": "zowe.profileManagement", - "group": "099_zowe_dsProfileAuthentication@97" + "group": "099_zowe_dsProfileAuthentication@99" }, { "when": "view == zowe.ds.explorer && viewItem =~ /^(?!.*_fav.*)session.*/", "command": "zowe.ds.removeSession", - "group": "099_zowe_dsProfileModification@98" - }, - { - "when": "view == zowe.ds.explorer && viewItem =~ /^(?!.*_fav.*)session.*/ && !listMultiSelection", - "command": "zowe.ds.deleteProfile", - "group": "099_zowe_dsProfileModification@99" + "group": "099_zowe_dsProfileAuthentication@98" }, { "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/ && !listMultiSelection", @@ -1311,27 +1301,22 @@ { "when": "view == zowe.jobs.explorer && viewItem =~ /_validate/ && !listMultiSelection", "command": "zowe.jobs.disableValidation", - "group": "098_zowe_jobsProfileAuthentication@3" + "group": "099_zowe_jobsProfileAuthentication@96" }, { "when": "view == zowe.jobs.explorer && viewItem =~ /_noValidate/ && !listMultiSelection", "command": "zowe.jobs.enableValidation", - "group": "098_zowe_jobsProfileAuthentication@4" + "group": "099_zowe_jobsProfileAuthentication@97" }, { "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/ && !listMultiSelection", "command": "zowe.profileManagement", - "group": "098_zowe_jobsProfileAuthentication@97" + "group": "099_zowe_jobsProfileAuthentication@99" }, { "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/", "command": "zowe.jobs.removeJobsSession", - "group": "099_zowe_jobsProfileModification@98" - }, - { - "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/ && !listMultiSelection", - "command": "zowe.jobs.deleteProfile", - "group": "099_zowe_jobsProfileModification@99" + "group": "099_zowe_jobsProfileAuthentication@98" }, { "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/ && !listMultiSelection", diff --git a/packages/zowe-explorer/src/utils/ProfileManagement.ts b/packages/zowe-explorer/src/utils/ProfileManagement.ts index efb5f69477..7369b59ab2 100644 --- a/packages/zowe-explorer/src/utils/ProfileManagement.ts +++ b/packages/zowe-explorer/src/utils/ProfileManagement.ts @@ -48,11 +48,12 @@ export class ProfileManagement { await this.handleAuthSelection(selected, node, profile); } public static AuthQpLabels = { - update: "update-credentials", + add: "add-credentials", + delete: "delete", edit: "edit-profile", login: "obtain-token", logout: "invalidate-token", - add: "add-credentials", + update: "update-credentials", }; public static basicAuthAddQpItems: Record = { [this.AuthQpLabels.add]: { @@ -66,7 +67,12 @@ export class ProfileManagement { description: localize("updateBasicAuthQpItem.updateCredentials.qpDetail", "Update stored username and password"), }, }; - public static otherProfileQpItems: Record = { + public static deleteProfileQpItem: Record = { + [this.AuthQpLabels.delete]: { + label: localize("deleteProfileQpItem.delete.qpLabel", "$(trash) Delete Profile"), + }, + }; + public static editProfileQpItems: Record = { [this.AuthQpLabels.edit]: { label: localize("editProfileQpItem.editProfile.qpLabel", "$(pencil) Edit profile"), description: localize("editProfileQpItem.editProfile.qpDetail", "Update profile connection information"), @@ -119,7 +125,7 @@ export class ProfileManagement { await ProfilesUtils.promptCredentials(node); break; } - case this.otherProfileQpItems[this.AuthQpLabels.edit]: { + case this.editProfileQpItems[this.AuthQpLabels.edit]: { await Profiles.getInstance().editSession(profile, profile.name); break; } @@ -135,6 +141,10 @@ export class ProfileManagement { await ProfilesUtils.promptCredentials(node); break; } + case this.deleteProfileQpItem[this.AuthQpLabels.delete]: { + await this.handleDeleteProfiles(node); + break; + } default: { Gui.infoMessage(localize("profiles.operation.cancelled", "Operation Cancelled")); break; @@ -156,21 +166,32 @@ export class ProfileManagement { private static basicAuthQp(): vscode.QuickPickItem[] { const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.basicAuthUpdateQpItems); - quickPickOptions.push(this.otherProfileQpItems[this.AuthQpLabels.edit]); - return quickPickOptions; + return this.addFinalQpOptions(quickPickOptions); } private static tokenAuthQp(profile: imperative.IProfileLoaded): vscode.QuickPickItem[] { const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.tokenAuthLoginQpItem); if (profile.profile.tokenType) { quickPickOptions.push(this.tokenAuthLogoutQpItem[this.AuthQpLabels.logout]); } - quickPickOptions.push(this.otherProfileQpItems[this.AuthQpLabels.edit]); - return quickPickOptions; + return this.addFinalQpOptions(quickPickOptions); } private static chooseAuthQp(): vscode.QuickPickItem[] { const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.basicAuthAddQpItems); quickPickOptions.push(this.tokenAuthLoginQpItem[this.AuthQpLabels.login]); - quickPickOptions.push(this.otherProfileQpItems[this.AuthQpLabels.edit]); + return this.addFinalQpOptions(quickPickOptions); + } + private static addFinalQpOptions(quickPickOptions: vscode.QuickPickItem[]): vscode.QuickPickItem[] { + quickPickOptions.push(this.editProfileQpItems[this.AuthQpLabels.edit]); + quickPickOptions.push(this.deleteProfileQpItem[this.AuthQpLabels.delete]); return quickPickOptions; } + private static async handleDeleteProfiles(node: IZoweTreeNode): Promise { + const profInfo = await Profiles.getInstance().getProfileInfo(); + if (profInfo.usingTeamConfig) { + const profile = node.getProfile(); + await Profiles.getInstance().editSession(profile, profile.name); + return; + } + await vscode.commands.executeCommand("zowe.ds.deleteProfile", node); + } } From 8daf4114ee1b5d5cb340b8f1117003349dba5645 Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Fri, 22 Sep 2023 20:14:35 -0400 Subject: [PATCH 23/35] should fix theia tests for delete Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../__tests__/__theia__/theia/Locators.ts | 2 +- .../__theia__/theia/extension.theiaChrome.ts | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/zowe-explorer/__tests__/__theia__/theia/Locators.ts b/packages/zowe-explorer/__tests__/__theia__/theia/Locators.ts index 089c6386bc..2b8793dba2 100644 --- a/packages/zowe-explorer/__tests__/__theia__/theia/Locators.ts +++ b/packages/zowe-explorer/__tests__/__theia__/theia/Locators.ts @@ -28,7 +28,7 @@ export const DatasetsLocators = { favoriteProfileInDatasetXpath: "(//div[contains(@id,'Favorites') and contains(@id,'TestSeleniumProfile')])", addToFavoriteOptionXpath: "//li[@data-command='zowe.ds.saveSearch']", removeFavoriteProfileFromDatasetsOptionXpath: "//li[@data-command='zowe.ds.removeFavProfile']", - deleteProfileFromDatasetsXpath: "(//li[@data-command='zowe.ds.deleteProfile'])", + manageProfileFromDatasetsXpath: "(//li[@data-command='zowe.profileManagement'])", }; export const UssLocators = { diff --git a/packages/zowe-explorer/__tests__/__theia__/theia/extension.theiaChrome.ts b/packages/zowe-explorer/__tests__/__theia__/theia/extension.theiaChrome.ts index d9bd97df36..7d79c7eb9b 100644 --- a/packages/zowe-explorer/__tests__/__theia__/theia/extension.theiaChrome.ts +++ b/packages/zowe-explorer/__tests__/__theia__/theia/extension.theiaChrome.ts @@ -170,23 +170,29 @@ export async function verifyProfileIsHideInJobs() { export async function deleteDefaultProfileInDatasets() { const profileName = await driverChrome.wait(until.elementLocated(By.xpath(DatasetsLocators.defaultDatasetsProfileXpath)), WAITTIME); await driverChrome.actions().click(profileName, Button.RIGHT).perform(); - await driverChrome.wait(until.elementLocated(By.xpath(DatasetsLocators.deleteProfileFromDatasetsXpath)), WAITTIME).click(); + await driverChrome.wait(until.elementLocated(By.xpath(DatasetsLocators.manageProfileFromDatasetsXpath)), WAITTIME).click(); + await driverChrome.sleep(SHORTSLEEPTIME); + const manageProfile = driverChrome.wait(until.elementLocated(By.xpath(DatasetsLocators.emptyInputBoxXpath)), WAITTIME); + manageProfile.sendKeys("Delete Profile"); + manageProfile.sendKeys(Key.ENTER); await driverChrome.sleep(SHORTSLEEPTIME); const deleteProfile = driverChrome.wait(until.elementLocated(By.xpath(DatasetsLocators.emptyInputBoxXpath)), WAITTIME); deleteProfile.sendKeys("Delete"); deleteProfile.sendKeys(Key.ENTER); - return; } export async function deleteProfileInDatasets() { const favprofile = await driverChrome.wait(until.elementLocated(By.xpath(DatasetsLocators.secondDatasetProfileXpath)), WAITTIME); await driverChrome.actions().click(favprofile, Button.RIGHT).perform(); - await driverChrome.wait(until.elementLocated(By.xpath(DatasetsLocators.deleteProfileFromDatasetsXpath)), WAITTIME).click(); + await driverChrome.wait(until.elementLocated(By.xpath(DatasetsLocators.manageProfileFromDatasetsXpath)), WAITTIME).click(); + await driverChrome.sleep(SHORTSLEEPTIME); + const manageProfile = driverChrome.wait(until.elementLocated(By.xpath(DatasetsLocators.emptyInputBoxXpath)), WAITTIME); + manageProfile.sendKeys("Delete Profile"); + manageProfile.sendKeys(Key.ENTER); await driverChrome.sleep(SHORTSLEEPTIME); const deleteProfile = driverChrome.wait(until.elementLocated(By.xpath(DatasetsLocators.emptyInputBoxXpath)), WAITTIME); deleteProfile.sendKeys("Delete"); deleteProfile.sendKeys(Key.ENTER); - return; } export async function verifyRemovedFavoriteProfileInDatasets() { From 6d491d816e3a4738f41fb5ef955146a977c37d1f Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Fri, 22 Sep 2023 20:41:21 -0400 Subject: [PATCH 24/35] about as clean as test file can get Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../utils/ProfileManagement.unit.test.ts | 169 ++++++++---------- 1 file changed, 75 insertions(+), 94 deletions(-) diff --git a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts index 12c62e7ca4..616f590df1 100644 --- a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts @@ -18,6 +18,7 @@ import { Gui } from "@zowe/zowe-explorer-api"; import { ZoweLogger } from "../../../src/utils/LoggerUtils"; import { Profiles } from "../../../src/Profiles"; import * as vscode from "vscode"; +import { imperative } from "@zowe/cli"; jest.mock("fs"); jest.mock("vscode"); @@ -27,7 +28,7 @@ describe("ProfileManagement unit tests", () => { jest.clearAllMocks(); jest.resetAllMocks(); }); - function createGlobalMocks() { + function createGlobalMocks(): any { const newMocks = { mockSession: sharedMock.createISession(), mockBasicAuthProfile: sharedMock.createValidIProfile(), @@ -43,6 +44,7 @@ describe("ProfileManagement unit tests", () => { mockLogoutChosen: ProfileManagement.tokenAuthLogoutQpItem[ProfileManagement.AuthQpLabels.logout], mockEditProfChosen: ProfileManagement.editProfileQpItems[ProfileManagement.AuthQpLabels.edit], mockDeleteProfChosen: ProfileManagement.deleteProfileQpItem[ProfileManagement.AuthQpLabels.delete], + mockProfileInfo: { usingTeamConfig: true }, mockProfileInstance: null as any, debugLogSpy: null as any, promptSpy: null as any, @@ -85,139 +87,118 @@ describe("ProfileManagement unit tests", () => { } describe("unit tests around basic auth selections", () => { - function createBlockMocks(globalMocks) { + function createBlockMocks(globalMocks): any { globalMocks.logMsg = `Profile ${globalMocks.mockBasicAuthProfile.name} is using basic authentication.`; - Object.defineProperty(globalMocks.mockDsSessionNode, "getProfile", { - value: jest.fn().mockReturnValue(globalMocks.mockBasicAuthProfile), - configurable: true, - }); + globalMocks.mockDsSessionNode.getProfile = jest.fn().mockReturnValue(globalMocks.mockBasicAuthProfile); Object.defineProperty(vscode.commands, "executeCommand", { value: jest.fn(), configurable: true }); + return globalMocks; } it("profile using basic authentication should see Operation Cancelled when escaping quick pick", async () => { - const globalMocks = createGlobalMocks(); - createBlockMocks(globalMocks); - globalMocks.mockResolveQp.mockResolvedValueOnce(undefined); - await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); - expect(globalMocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); + const mocks = createBlockMocks(createGlobalMocks()); + mocks.mockResolveQp.mockResolvedValueOnce(undefined); + await ProfileManagement.manageProfile(mocks.mockDsSessionNode); + expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); + expect(mocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); }); it("profile using basic authentication should see promptCredentials called when Update Credentials chosen", async () => { - const globalMocks = createGlobalMocks(); - createBlockMocks(globalMocks); - globalMocks.mockResolveQp.mockResolvedValueOnce(globalMocks.mockUpdateChosen); - await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); - expect(globalMocks.promptSpy).toBeCalled(); + const mocks = createBlockMocks(createGlobalMocks()); + mocks.mockResolveQp.mockResolvedValueOnce(mocks.mockUpdateChosen); + await ProfileManagement.manageProfile(mocks.mockDsSessionNode); + expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); + expect(mocks.promptSpy).toBeCalled(); }); it("profile using basic authentication should see editSession called when Edit Profile chosen", async () => { - const globalMocks = createGlobalMocks(); - createBlockMocks(globalMocks); - globalMocks.mockResolveQp.mockResolvedValueOnce(globalMocks.mockEditProfChosen); - await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); - expect(globalMocks.editSpy).toBeCalled(); + const mocks = createBlockMocks(createGlobalMocks()); + mocks.mockResolveQp.mockResolvedValueOnce(mocks.mockEditProfChosen); + await ProfileManagement.manageProfile(mocks.mockDsSessionNode); + expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); + expect(mocks.editSpy).toBeCalled(); }); it("profile using basic authentication should see editSession called when Delete Profile chosen with v2 profile", async () => { - const globalMocks = createGlobalMocks(); - createBlockMocks(globalMocks); - globalMocks.mockResolveQp.mockResolvedValueOnce(globalMocks.mockDeleteProfChosen); - Object.defineProperty(globalMocks.mockProfileInstance, "getProfileInfo", { - value: jest.fn().mockResolvedValueOnce({ usingTeamConfig: true }), + const mocks = createBlockMocks(createGlobalMocks()); + Object.defineProperty(mocks.mockProfileInstance, "getProfileInfo", { + value: jest.fn().mockResolvedValue(mocks.mockProfileInfo as imperative.ProfileInfo), configurable: true, }); - await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); - expect(globalMocks.editSpy).toBeCalled(); + mocks.mockResolveQp.mockResolvedValueOnce(mocks.mockDeleteProfChosen); + await ProfileManagement.manageProfile(mocks.mockDsSessionNode); + expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); + expect(mocks.editSpy).toBeCalled(); }); it("profile using basic authentication should see delete commands called when Delete Profile chosen with v1 profile", async () => { - const globalMocks = createGlobalMocks(); - createBlockMocks(globalMocks); - globalMocks.mockResolveQp.mockResolvedValueOnce(globalMocks.mockDeleteProfChosen); - Object.defineProperty(globalMocks.mockProfileInstance, "getProfileInfo", { - value: jest.fn().mockResolvedValueOnce({ usingTeamConfig: false }), - configurable: true, - }); + const mocks = createBlockMocks(createGlobalMocks()); + mocks.mockResolveQp.mockResolvedValueOnce(mocks.mockDeleteProfChosen); + mocks.mockProfileInfo.usingTeamConfig = false; const commandSpy = jest.spyOn(vscode.commands, "executeCommand"); - await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); - expect(globalMocks.editSpy).not.toBeCalled(); + await ProfileManagement.manageProfile(mocks.mockDsSessionNode); + expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); + expect(mocks.editSpy).not.toBeCalled(); expect(commandSpy).toBeCalled(); }); }); describe("unit tests around token auth selections", () => { - function createBlockMocks(globalMocks) { + function createBlockMocks(globalMocks): any { globalMocks.logMsg = `Profile ${globalMocks.mockTokenAuthProfile.name} is using token authentication.`; Object.defineProperty(profUtils.ProfilesUtils, "isUsingTokenAuth", { value: jest.fn().mockResolvedValueOnce(true), configurable: true }); - Object.defineProperty(globalMocks.mockDsSessionNode, "getProfile", { - value: jest.fn().mockReturnValue(globalMocks.mockTokenAuthProfile), - configurable: true, - }); + globalMocks.mockDsSessionNode.getProfile = jest.fn().mockReturnValue(globalMocks.mockTokenAuthProfile); + return globalMocks; } it("profile using token authentication should see Operation Cancelled when escaping quick pick", async () => { - const globalMocks = createGlobalMocks(); - createBlockMocks(globalMocks); - globalMocks.mockResolveQp.mockResolvedValueOnce(undefined); - await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); - expect(globalMocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); + const mocks = createBlockMocks(createGlobalMocks()); + mocks.mockResolveQp.mockResolvedValueOnce(undefined); + await ProfileManagement.manageProfile(mocks.mockDsSessionNode); + expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); + expect(mocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); }); it("profile using token authentication should see ssoLogin called when Log in to authentication service chosen", async () => { - const globalMocks = createGlobalMocks(); - createBlockMocks(globalMocks); - globalMocks.mockResolveQp.mockResolvedValueOnce(globalMocks.mockLoginChosen); - await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); - expect(globalMocks.loginSpy).toBeCalled(); + const mocks = createBlockMocks(createGlobalMocks()); + mocks.mockResolveQp.mockResolvedValueOnce(mocks.mockLoginChosen); + await ProfileManagement.manageProfile(mocks.mockDsSessionNode); + expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); + expect(mocks.loginSpy).toBeCalled(); }); it("profile using token authentication should see ssoLogout called when Log out from authentication service chosen", async () => { - const globalMocks = createGlobalMocks(); - createBlockMocks(globalMocks); - globalMocks.mockResolveQp.mockResolvedValueOnce(globalMocks.mockLogoutChosen); - await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); - expect(globalMocks.logoutSpy).toBeCalled(); + const mocks = createBlockMocks(createGlobalMocks()); + mocks.mockResolveQp.mockResolvedValueOnce(mocks.mockLogoutChosen); + await ProfileManagement.manageProfile(mocks.mockDsSessionNode); + expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); + expect(mocks.logoutSpy).toBeCalled(); }); }); describe("unit tests around no auth declared selections", () => { - function createBlockMocks(globalMocks) { + function createBlockMocks(globalMocks): any { globalMocks.logMsg = `Profile ${globalMocks.mockNoAuthProfile.name} authentication method is unkown.`; Object.defineProperty(profUtils.ProfilesUtils, "isUsingTokenAuth", { value: jest.fn().mockResolvedValueOnce(false), configurable: true }); - Object.defineProperty(globalMocks.mockDsSessionNode, "getProfile", { - value: jest.fn().mockReturnValue(globalMocks.mockNoAuthProfile), - configurable: true, - }); + globalMocks.mockDsSessionNode.getProfile = jest.fn().mockReturnValue(globalMocks.mockNoAuthProfile); + return globalMocks; } it("profile with no authentication method should see Operation Cancelled when escaping quick pick", async () => { - const globalMocks = createGlobalMocks(); - createBlockMocks(globalMocks); - globalMocks.mockResolveQp.mockResolvedValueOnce(undefined); - await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); - expect(globalMocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); + const mocks = createBlockMocks(createGlobalMocks()); + mocks.mockResolveQp.mockResolvedValueOnce(undefined); + await ProfileManagement.manageProfile(mocks.mockDsSessionNode); + expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); + expect(mocks.opCancelledSpy).toBeCalledWith("Operation Cancelled"); }); it("profile with no authentication method should see promptCredentials called when Add Basic Credentials chosen", async () => { - const globalMocks = createGlobalMocks(); - createBlockMocks(globalMocks); - globalMocks.mockResolveQp.mockResolvedValueOnce(globalMocks.mockAddBasicChosen); - await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); - expect(globalMocks.promptSpy).toBeCalled(); + const mocks = createBlockMocks(createGlobalMocks()); + mocks.mockResolveQp.mockResolvedValueOnce(mocks.mockAddBasicChosen); + await ProfileManagement.manageProfile(mocks.mockDsSessionNode); + expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); + expect(mocks.promptSpy).toBeCalled(); }); it("profile with no authentication method should see ssoLogin called when Log in to authentication service chosen", async () => { - const globalMocks = createGlobalMocks(); - createBlockMocks(globalMocks); - globalMocks.mockResolveQp.mockResolvedValueOnce(globalMocks.mockLoginChosen); - await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); - expect(globalMocks.loginSpy).toBeCalled(); + const mocks = createBlockMocks(createGlobalMocks()); + mocks.mockResolveQp.mockResolvedValueOnce(mocks.mockLoginChosen); + await ProfileManagement.manageProfile(mocks.mockDsSessionNode); + expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); + expect(mocks.loginSpy).toBeCalled(); }); it("profile with no authentication method should see editSession called when Edit Profile chosen", async () => { - const globalMocks = createGlobalMocks(); - createBlockMocks(globalMocks); - globalMocks.mockResolveQp.mockResolvedValueOnce(globalMocks.mockEditProfChosen); - await ProfileManagement.manageProfile(globalMocks.mockDsSessionNode as any); - expect(globalMocks.debugLogSpy).toBeCalledWith(globalMocks.logMsg); - expect(globalMocks.editSpy).toBeCalled(); + const mocks = createBlockMocks(createGlobalMocks()); + mocks.mockResolveQp.mockResolvedValueOnce(mocks.mockEditProfChosen); + await ProfileManagement.manageProfile(mocks.mockDsSessionNode); + expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); + expect(mocks.editSpy).toBeCalled(); }); }); }); From eaeec46da4c8e69d0204126ae770bb6d83cf54bc Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Fri, 22 Sep 2023 21:08:50 -0400 Subject: [PATCH 25/35] add message for manual editing with opening of config Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json | 1 + packages/zowe-explorer/src/Profiles.ts | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json b/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json index b48fbc4ab9..520e59516f 100644 --- a/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json +++ b/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json @@ -1,5 +1,6 @@ { "profiles.operation.cancelled": "Operation Cancelled", + "profiles.manualEditMsg": "Edit to the config file will need to be done manually.", "checkCurrentProfile.tokenAuthError.msg": "Token auth error", "checkCurrentProfile.tokenAuthError.additionalDetails": "Profile was found using token auth, please log in to continue.", "profiles.createNewConnection": "$(plus) Create a new connection to z/OS", diff --git a/packages/zowe-explorer/src/Profiles.ts b/packages/zowe-explorer/src/Profiles.ts index a32d1801af..6b392b9c8c 100644 --- a/packages/zowe-explorer/src/Profiles.ts +++ b/packages/zowe-explorer/src/Profiles.ts @@ -68,6 +68,7 @@ export class Profiles extends ProfilesCache { private jobsSchema: string = globals.SETTINGS_JOBS_HISTORY; private mProfileInfo: zowe.imperative.ProfileInfo; private profilesOpCancelled = localize("profiles.operation.cancelled", "Operation Cancelled"); + private manualEditMsg = localize("profiles.manualEditMsg", "Editing or removal of profiles will need to be done manually."); public constructor(log: zowe.imperative.Logger, cwd?: string) { super(log, cwd); } @@ -443,6 +444,7 @@ export class Profiles extends ProfilesCache { const currentProfile = await this.getProfileFromConfig(profileLoaded.name); const filePath = currentProfile.profLoc.osLoc[0]; await this.openConfigFile(filePath); + Gui.showMessage(this.manualEditMsg); return; } const editSession = this.loadNamedProfile(profileLoaded.name, profileLoaded.type).profile; @@ -697,6 +699,7 @@ export class Profiles extends ProfilesCache { await this.openConfigFile(file.path); } } + Gui.showMessage(this.manualEditMsg); break; case "global": for (const file of existingLayers) { @@ -704,12 +707,12 @@ export class Profiles extends ProfilesCache { await this.openConfigFile(file.path); } } + Gui.showMessage(this.manualEditMsg); break; default: Gui.showMessage(this.profilesOpCancelled); - return; + break; } - return; } } From 7ff92239fcfc59b79591c9591ac4f195b673d821 Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Fri, 22 Sep 2023 21:12:01 -0400 Subject: [PATCH 26/35] missed one Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- packages/zowe-explorer/src/Profiles.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/zowe-explorer/src/Profiles.ts b/packages/zowe-explorer/src/Profiles.ts index 6b392b9c8c..0100edc162 100644 --- a/packages/zowe-explorer/src/Profiles.ts +++ b/packages/zowe-explorer/src/Profiles.ts @@ -689,6 +689,7 @@ export class Profiles extends ProfilesCache { const existingLayers = await this.getConfigLayers(); if (existingLayers.length === 1) { await this.openConfigFile(existingLayers[0].path); + Gui.showMessage(this.manualEditMsg); } if (existingLayers && existingLayers.length > 1) { const choice = await this.getConfigLocationPrompt("edit"); From b9cd91cdac0431b091134c61d288b1d0efa63c9b Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Tue, 26 Sep 2023 07:59:11 -0400 Subject: [PATCH 27/35] address feedback Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../i18n/sample/src/Profiles.i18n.json | 2 +- .../sample/src/utils/ProfileManagement.i18n.json | 2 +- .../zowe-explorer/src/utils/ProfileManagement.ts | 2 +- packages/zowe-explorer/src/utils/ProfilesUtils.ts | 14 +++++++------- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json b/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json index 520e59516f..b2e9851127 100644 --- a/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json +++ b/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json @@ -1,6 +1,6 @@ { "profiles.operation.cancelled": "Operation Cancelled", - "profiles.manualEditMsg": "Edit to the config file will need to be done manually.", + "profiles.manualEditMsg": "Editing or removal of profiles will need to be done manually.", "checkCurrentProfile.tokenAuthError.msg": "Token auth error", "checkCurrentProfile.tokenAuthError.additionalDetails": "Profile was found using token auth, please log in to continue.", "profiles.createNewConnection": "$(plus) Create a new connection to z/OS", diff --git a/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json b/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json index 1afb08edfe..0b0107edb9 100644 --- a/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json +++ b/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json @@ -8,7 +8,7 @@ "updateBasicAuthQpItem.updateCredentials.qpLabel": "$(refresh) Update Credentials", "updateBasicAuthQpItem.updateCredentials.qpDetail": "Update stored username and password", "deleteProfileQpItem.delete.qpLabel": "$(trash) Delete Profile", - "editProfileQpItem.editProfile.qpLabel": "$(pencil) Edit profile", + "editProfileQpItem.editProfile.qpLabel": "$(pencil) Edit Profile", "editProfileQpItem.editProfile.qpDetail": "Update profile connection information", "loginQpItem.login.qpLabel": "$(arrow-right) Log in to authentication service", "loginQpItem.login.qpDetail": "Log in to obtain a new token value", diff --git a/packages/zowe-explorer/src/utils/ProfileManagement.ts b/packages/zowe-explorer/src/utils/ProfileManagement.ts index 7369b59ab2..8a72bb1430 100644 --- a/packages/zowe-explorer/src/utils/ProfileManagement.ts +++ b/packages/zowe-explorer/src/utils/ProfileManagement.ts @@ -74,7 +74,7 @@ export class ProfileManagement { }; public static editProfileQpItems: Record = { [this.AuthQpLabels.edit]: { - label: localize("editProfileQpItem.editProfile.qpLabel", "$(pencil) Edit profile"), + label: localize("editProfileQpItem.editProfile.qpLabel", "$(pencil) Edit Profile"), description: localize("editProfileQpItem.editProfile.qpDetail", "Update profile connection information"), }, }; diff --git a/packages/zowe-explorer/src/utils/ProfilesUtils.ts b/packages/zowe-explorer/src/utils/ProfilesUtils.ts index 2a8dd2979a..46a00b10c7 100644 --- a/packages/zowe-explorer/src/utils/ProfilesUtils.ts +++ b/packages/zowe-explorer/src/utils/ProfilesUtils.ts @@ -313,10 +313,7 @@ export class ProfilesUtils { * @returns {Promise} a boolean representing whether basic auth is being used or not */ public static isProfileUsingBasicAuth(profile: imperative.IProfileLoaded): boolean { - if (profile.profile.user && profile.profile.password) { - return true; - } - return false; + return (profile.profile.user && profile.profile.password) as boolean; } /** @@ -325,11 +322,14 @@ export class ProfilesUtils { * @returns {Promise} a boolean representing whether token based auth is being used or not */ public static async isUsingTokenAuth(profileName: string): Promise { - const baseProfile = Profiles.getInstance().getDefaultProfile("base"); const secureProfileProps = await Profiles.getInstance().getSecurePropsForProfile(profileName); - const secureBaseProfileProps = await Profiles.getInstance().getSecurePropsForProfile(baseProfile?.name); const profileUsesBasicAuth = secureProfileProps.includes("user") && secureProfileProps.includes("password"); - return (secureProfileProps.includes("tokenValue") || secureBaseProfileProps.includes("tokenValue")) && !profileUsesBasicAuth; + if (secureProfileProps.includes("tokenValue")) { + return secureProfileProps.includes("tokenValue") && !profileUsesBasicAuth; + } + const baseProfile = Profiles.getInstance().getDefaultProfile("base"); + const secureBaseProfileProps = await Profiles.getInstance().getSecurePropsForProfile(baseProfile?.name); + return secureBaseProfileProps.includes("tokenValue") && !profileUsesBasicAuth; } public static async promptCredentials(node: IZoweTreeNode): Promise { From 2c5eba7d2b35d856255e73c7b47a811cae64d811 Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Tue, 26 Sep 2023 08:34:23 -0400 Subject: [PATCH 28/35] fix unit tests Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../__mocks__/mockCreators/shared.ts | 16 ++++++++++++++++ .../__unit__/Profiles.extended.unit.test.ts | 1 + .../utils/ProfileManagement.unit.test.ts | 2 +- .../zowe-explorer/src/utils/ProfilesUtils.ts | 3 ++- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/packages/zowe-explorer/__mocks__/mockCreators/shared.ts b/packages/zowe-explorer/__mocks__/mockCreators/shared.ts index 82b4039698..63bb7cd047 100644 --- a/packages/zowe-explorer/__mocks__/mockCreators/shared.ts +++ b/packages/zowe-explorer/__mocks__/mockCreators/shared.ts @@ -236,6 +236,22 @@ export function createTokenAuthIProfile(): imperative.IProfileLoaded { }; } +export function createNoAuthIProfile(): imperative.IProfileLoaded { + return { + name: "sestest", + profile: { + type: "zosmf", + host: null, + port: 1443, + rejectUnauthorized: false, + name: "testName", + }, + type: "zosmf", + message: "", + failNotFound: false, + }; +} + export function createAltTypeIProfile(): imperative.IProfileLoaded { return { name: "altTypeProfile", diff --git a/packages/zowe-explorer/__tests__/__unit__/Profiles.extended.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/Profiles.extended.unit.test.ts index ebe3b57fe3..6d41665a89 100644 --- a/packages/zowe-explorer/__tests__/__unit__/Profiles.extended.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/Profiles.extended.unit.test.ts @@ -1569,6 +1569,7 @@ describe("Profiles Unit Tests - function ssoLogin", () => { ], configurable: true, }); + Object.defineProperty(utils.ProfilesUtils, "isProfileUsingBasicAuth", { value: jest.fn(), configurable: true }); jest.spyOn(Gui, "showMessage").mockImplementation(); }); it("should perform an SSOLogin successfully while fetching the base profile", async () => { diff --git a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts index 616f590df1..44d605e0d4 100644 --- a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts @@ -33,7 +33,7 @@ describe("ProfileManagement unit tests", () => { mockSession: sharedMock.createISession(), mockBasicAuthProfile: sharedMock.createValidIProfile(), mockTokenAuthProfile: sharedMock.createTokenAuthIProfile(), - mockNoAuthProfile: sharedMock.createInvalidIProfile(), + mockNoAuthProfile: sharedMock.createNoAuthIProfile(), opCancelledSpy: jest.spyOn(Gui, "infoMessage"), mockDsSessionNode: ZoweDatasetNode, mockResolveQp: jest.fn(), diff --git a/packages/zowe-explorer/src/utils/ProfilesUtils.ts b/packages/zowe-explorer/src/utils/ProfilesUtils.ts index 46a00b10c7..ec2b9d97e1 100644 --- a/packages/zowe-explorer/src/utils/ProfilesUtils.ts +++ b/packages/zowe-explorer/src/utils/ProfilesUtils.ts @@ -313,7 +313,8 @@ export class ProfilesUtils { * @returns {Promise} a boolean representing whether basic auth is being used or not */ public static isProfileUsingBasicAuth(profile: imperative.IProfileLoaded): boolean { - return (profile.profile.user && profile.profile.password) as boolean; + const prof = profile.profile; + return "user" in prof && "password" in prof; } /** From 6006d3c7d694a9b3dad19501daa2153a066efa44 Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Wed, 27 Sep 2023 15:52:16 -0400 Subject: [PATCH 29/35] address feedback Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../zowe-explorer/i18n/sample/src/Profiles.i18n.json | 2 +- packages/zowe-explorer/src/Profiles.ts | 5 ++++- .../zowe-explorer/src/utils/ProfileManagement.ts | 12 +++++++++--- packages/zowe-explorer/src/utils/ProfilesUtils.ts | 1 + 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json b/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json index b2e9851127..57a7772513 100644 --- a/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json +++ b/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json @@ -1,6 +1,6 @@ { "profiles.operation.cancelled": "Operation Cancelled", - "profiles.manualEditMsg": "Editing or removal of profiles will need to be done manually.", + "profiles.manualEditMsg": "The Team configuration file has been opened in the editor. Editing or removal of profiles will need to be done manually.", "checkCurrentProfile.tokenAuthError.msg": "Token auth error", "checkCurrentProfile.tokenAuthError.additionalDetails": "Profile was found using token auth, please log in to continue.", "profiles.createNewConnection": "$(plus) Create a new connection to z/OS", diff --git a/packages/zowe-explorer/src/Profiles.ts b/packages/zowe-explorer/src/Profiles.ts index 0100edc162..3c69c244e9 100644 --- a/packages/zowe-explorer/src/Profiles.ts +++ b/packages/zowe-explorer/src/Profiles.ts @@ -68,7 +68,10 @@ export class Profiles extends ProfilesCache { private jobsSchema: string = globals.SETTINGS_JOBS_HISTORY; private mProfileInfo: zowe.imperative.ProfileInfo; private profilesOpCancelled = localize("profiles.operation.cancelled", "Operation Cancelled"); - private manualEditMsg = localize("profiles.manualEditMsg", "Editing or removal of profiles will need to be done manually."); + private manualEditMsg = localize( + "profiles.manualEditMsg", + "The Team configuration file has been opened in the editor. Editing or removal of profiles will need to be done manually." + ); public constructor(log: zowe.imperative.Logger, cwd?: string) { super(log, cwd); } diff --git a/packages/zowe-explorer/src/utils/ProfileManagement.ts b/packages/zowe-explorer/src/utils/ProfileManagement.ts index 8a72bb1430..874244e4a1 100644 --- a/packages/zowe-explorer/src/utils/ProfileManagement.ts +++ b/packages/zowe-explorer/src/utils/ProfileManagement.ts @@ -15,6 +15,7 @@ import { ZoweLogger } from "./LoggerUtils"; import { ProfilesUtils } from "./ProfilesUtils"; import * as nls from "vscode-nls"; import { Profiles } from "../Profiles"; +import { ZoweExplorerApiRegister } from "../ZoweExplorerApiRegister"; // Set up localization nls.config({ @@ -106,7 +107,7 @@ export class ProfileManagement { break; } default: { - quickPickOptions = this.chooseAuthQp(); + quickPickOptions = this.chooseAuthQp(profile); qp.placeholder = placeholders.chooseAuth; break; } @@ -175,9 +176,14 @@ export class ProfileManagement { } return this.addFinalQpOptions(quickPickOptions); } - private static chooseAuthQp(): vscode.QuickPickItem[] { + private static chooseAuthQp(profile: imperative.IProfileLoaded): vscode.QuickPickItem[] { const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.basicAuthAddQpItems); - quickPickOptions.push(this.tokenAuthLoginQpItem[this.AuthQpLabels.login]); + try { + ZoweExplorerApiRegister.getInstance().getCommonApi(profile).getTokenTypeName(); + quickPickOptions.push(this.tokenAuthLoginQpItem[this.AuthQpLabels.login]); + } catch { + ZoweLogger.debug(`Profile ${profile.name} doesn't support token authentication.`); + } return this.addFinalQpOptions(quickPickOptions); } private static addFinalQpOptions(quickPickOptions: vscode.QuickPickItem[]): vscode.QuickPickItem[] { diff --git a/packages/zowe-explorer/src/utils/ProfilesUtils.ts b/packages/zowe-explorer/src/utils/ProfilesUtils.ts index ec2b9d97e1..67c55bacfd 100644 --- a/packages/zowe-explorer/src/utils/ProfilesUtils.ts +++ b/packages/zowe-explorer/src/utils/ProfilesUtils.ts @@ -23,6 +23,7 @@ import { imperative, getImperativeConfig } from "@zowe/cli"; import { ZoweExplorerExtender } from "../ZoweExplorerExtender"; import { ZoweLogger } from "./LoggerUtils"; import { SettingsConfig } from "./SettingsConfig"; +import { ZoweExplorerApiRegister } from "../ZoweExplorerApiRegister"; // Set up localization nls.config({ From 5b57f4c246d0b4b485a43e5e85c8680b5aeb5efb Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Wed, 27 Sep 2023 15:54:16 -0400 Subject: [PATCH 30/35] update log string Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- packages/zowe-explorer/src/utils/ProfileManagement.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/zowe-explorer/src/utils/ProfileManagement.ts b/packages/zowe-explorer/src/utils/ProfileManagement.ts index 874244e4a1..b72838721e 100644 --- a/packages/zowe-explorer/src/utils/ProfileManagement.ts +++ b/packages/zowe-explorer/src/utils/ProfileManagement.ts @@ -182,7 +182,7 @@ export class ProfileManagement { ZoweExplorerApiRegister.getInstance().getCommonApi(profile).getTokenTypeName(); quickPickOptions.push(this.tokenAuthLoginQpItem[this.AuthQpLabels.login]); } catch { - ZoweLogger.debug(`Profile ${profile.name} doesn't support token authentication.`); + ZoweLogger.debug(`Profile ${profile.name} doesn't support token authentication, will not provide option.`); } return this.addFinalQpOptions(quickPickOptions); } From c5dd06ca4e9501f7cb347489241db1fd213730ab Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Wed, 27 Sep 2023 15:55:38 -0400 Subject: [PATCH 31/35] address code smell Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- packages/zowe-explorer/src/utils/ProfilesUtils.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/zowe-explorer/src/utils/ProfilesUtils.ts b/packages/zowe-explorer/src/utils/ProfilesUtils.ts index 67c55bacfd..ec2b9d97e1 100644 --- a/packages/zowe-explorer/src/utils/ProfilesUtils.ts +++ b/packages/zowe-explorer/src/utils/ProfilesUtils.ts @@ -23,7 +23,6 @@ import { imperative, getImperativeConfig } from "@zowe/cli"; import { ZoweExplorerExtender } from "../ZoweExplorerExtender"; import { ZoweLogger } from "./LoggerUtils"; import { SettingsConfig } from "./SettingsConfig"; -import { ZoweExplorerApiRegister } from "../ZoweExplorerApiRegister"; // Set up localization nls.config({ From fdace6e445eda9c153a7841b4e39af2b75c6deeb Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Mon, 2 Oct 2023 10:28:17 -0400 Subject: [PATCH 32/35] address login feedback Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- packages/zowe-explorer/src/Profiles.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/zowe-explorer/src/Profiles.ts b/packages/zowe-explorer/src/Profiles.ts index 3c69c244e9..23d73b7e5d 100644 --- a/packages/zowe-explorer/src/Profiles.ts +++ b/packages/zowe-explorer/src/Profiles.ts @@ -1192,7 +1192,6 @@ export class Profiles extends ProfilesCache { } else { await this.loginWithBaseProfile(serviceProfile, loginTokenType, node); } - Gui.showMessage(localize("ssoLogin.successful", "Login to authentication service was successful.")); } catch (err) { const message = localize("ssoLogin.error", "Unable to log in with {0}. {1}", serviceProfile.name, err?.message); ZoweLogger.error(message); @@ -1297,6 +1296,7 @@ export class Profiles extends ProfilesCache { profile: { ...node.getProfile().profile, ...updBaseProfile }, }); } + Gui.showMessage(localize("ssoLogin.successful", "Login to authentication service was successful.")); } } @@ -1322,6 +1322,7 @@ export class Profiles extends ProfilesCache { profile: { ...node.getProfile().profile, ...session }, }); } + Gui.showMessage(localize("ssoLogin.successful", "Login to authentication service was successful.")); } private async getConfigLocationPrompt(action: string): Promise { From 71cd777833bdd7fd24c6af196e895b2fe81a3d5b Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Mon, 2 Oct 2023 13:51:35 -0400 Subject: [PATCH 33/35] move enable, disable, and delete to quickpick Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../__tests__/__theia__/theia/Locators.ts | 2 + .../__theia__/theia/extension.theiaChrome.ts | 12 +- .../i18n/sample/src/Profiles.i18n.json | 2 +- .../src/utils/ProfileManagement.i18n.json | 6 + packages/zowe-explorer/package.json | 45 -------- .../src/utils/ProfileManagement.ts | 104 +++++++++++++++--- 6 files changed, 108 insertions(+), 63 deletions(-) diff --git a/packages/zowe-explorer/__tests__/__theia__/theia/Locators.ts b/packages/zowe-explorer/__tests__/__theia__/theia/Locators.ts index 2b8793dba2..5e3eb996bc 100644 --- a/packages/zowe-explorer/__tests__/__theia__/theia/Locators.ts +++ b/packages/zowe-explorer/__tests__/__theia__/theia/Locators.ts @@ -44,6 +44,7 @@ export const UssLocators = { addToFavoriteOptionXpath: "//li[@data-command='zowe.uss.addFavorite']", removeFavoriteProfileFromUssOptionXpath: "//li[@data-command='zowe.uss.removeFavProfile']", hideProfileFromUssOptionXpath: "//li[@data-command='zowe.uss.removeSession']", + manageProfileFromUnixXpath: "(//li[@data-command='zowe.profileManagement'])", }; export const JobsLocators = { @@ -60,6 +61,7 @@ export const JobsLocators = { removeFavoriteProfileFromJobsOptionXpath: "//li[@data-command='zowe.jobs.removeFavProfile']", hideProfileFromJobsOptionXpath: "//li[@data-command='zowe.jobs.removeJobsSession']", secondJobsProfileBeforeHidingXpath: "(//div[contains(@id,'TestSeleniumProfile')])[2]", + manageProfileFromJobsXpath: "(//li[@data-command='zowe.profileManagement'])", }; export const TheiaNotificationMessages = { diff --git a/packages/zowe-explorer/__tests__/__theia__/theia/extension.theiaChrome.ts b/packages/zowe-explorer/__tests__/__theia__/theia/extension.theiaChrome.ts index 7d79c7eb9b..239aadb46a 100644 --- a/packages/zowe-explorer/__tests__/__theia__/theia/extension.theiaChrome.ts +++ b/packages/zowe-explorer/__tests__/__theia__/theia/extension.theiaChrome.ts @@ -138,13 +138,21 @@ export async function addProfileToFavoritesInJobs() { export async function hideProfileInUss() { const hideProfileFromUss = await driverChrome.wait(until.elementLocated(By.xpath(UssLocators.secondUssProfileXpath)), WAITTIME); await driverChrome.actions().click(hideProfileFromUss, Button.RIGHT).perform(); - await driverChrome.wait(until.elementLocated(By.xpath(UssLocators.hideProfileFromUssOptionXpath)), WAITTIME).click(); + driverChrome.wait(until.elementLocated(By.xpath(UssLocators.manageProfileFromUnixXpath)), WAITTIME).click(); + await driverChrome.sleep(SHORTSLEEPTIME); + const manageProfile = driverChrome.wait(until.elementLocated(By.xpath(UssLocators.emptyInputBoxXpath)), WAITTIME); + manageProfile.sendKeys("Hide Profile"); + manageProfile.sendKeys(Key.ENTER); } export async function hideProfileInJobs() { const hideProfileFromJobs = await driverChrome.wait(until.elementLocated(By.xpath(JobsLocators.secondJobsProfileBeforeHidingXpath)), WAITTIME); await driverChrome.actions().click(hideProfileFromJobs, Button.RIGHT).perform(); - await driverChrome.wait(until.elementLocated(By.xpath(JobsLocators.hideProfileFromJobsOptionXpath)), WAITTIME).click(); + driverChrome.wait(until.elementLocated(By.xpath(JobsLocators.manageProfileFromJobsXpath)), WAITTIME).click(); + await driverChrome.sleep(SHORTSLEEPTIME); + const manageProfile = driverChrome.wait(until.elementLocated(By.xpath(JobsLocators.emptyInputBoxXpath)), WAITTIME); + manageProfile.sendKeys("Hide Profile"); + manageProfile.sendKeys(Key.ENTER); } export async function verifyProfileIsHideInUss() { diff --git a/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json b/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json index 57a7772513..a7bdfe81e4 100644 --- a/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json +++ b/packages/zowe-explorer/i18n/sample/src/Profiles.i18n.json @@ -29,10 +29,10 @@ "validateProfiles.error": "Profile validation failed for {0}.", "ssoAuth.usingBasicAuth": "This profile is using basic authentication and does not support token authentication.", "ssoLogin.tokenType.error": "Error getting supported tokenType value for profile {0}", - "ssoLogin.successful": "Login to authentication service was successful.", "ssoLogin.error": "Unable to log in with {0}. {1}", "ssoLogout.successful": "Logout from authentication service was successful for {0}.", "ssoLogout.error": "Unable to log out with {0}. {1}", + "ssoLogin.successful": "Login to authentication service was successful.", "getConfigLocationPrompt.placeholder.create": "Select the location where the config file will be initialized", "getConfigLocationPrompt.placeholder.edit": "Select the location of the config file to edit", "getConfigLocationPrompt.showQuickPick.global": "Global: in the Zowe home directory", diff --git a/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json b/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json index 0b0107edb9..56776e1f3b 100644 --- a/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json +++ b/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json @@ -8,8 +8,14 @@ "updateBasicAuthQpItem.updateCredentials.qpLabel": "$(refresh) Update Credentials", "updateBasicAuthQpItem.updateCredentials.qpDetail": "Update stored username and password", "deleteProfileQpItem.delete.qpLabel": "$(trash) Delete Profile", + "disableProfileValildationQpItem.disableValidation.qpLabel": "$(workspace-untrusted) Disable Profile Validation", + "disableProfileValildationQpItem.disableValidation.qpDetail": "Disable validation of server check for profile.", + "enableProfileValildationQpItem.enableValidation.qpLabel": "$(workspace-trusted) Enable Profile Validation", + "enableProfileValildationQpItem.enableValidation.qpDetail": "Enable validation of server check for profile.", "editProfileQpItem.editProfile.qpLabel": "$(pencil) Edit Profile", "editProfileQpItem.editProfile.qpDetail": "Update profile connection information", + "hideProfileQpItems.hideProfile.qpLabel": "$(eye-closed) Hide Profile", + "hideProfileQpItems.hideProfile.qpDetail": "Hide profile name from tree view.", "loginQpItem.login.qpLabel": "$(arrow-right) Log in to authentication service", "loginQpItem.login.qpDetail": "Log in to obtain a new token value", "logoutQpItem.logout.qpLabel": "$(arrow-left) Log out of authentication service", diff --git a/packages/zowe-explorer/package.json b/packages/zowe-explorer/package.json index 398a82c58b..b50a2b6557 100644 --- a/packages/zowe-explorer/package.json +++ b/packages/zowe-explorer/package.json @@ -958,26 +958,11 @@ "command": "zowe.uss.deleteNode", "group": "099_zowe_ussModification:@4" }, - { - "when": "view == zowe.uss.explorer && viewItem =~ /_validate/ && !listMultiSelection", - "command": "zowe.uss.disableValidation", - "group": "099_zowe_ussProfileAuthentication@96" - }, - { - "when": "view == zowe.uss.explorer && viewItem =~ /_noValidate/ && !listMultiSelection", - "command": "zowe.uss.enableValidation", - "group": "099_zowe_ussProfileAuthentication@97" - }, { "when": "view == zowe.uss.explorer && viewItem =~ /^(?!.*_fav.*)ussSession.*/ && !listMultiSelection", "command": "zowe.profileManagement", "group": "099_zowe_ussProfileAuthentication@99" }, - { - "when": "viewItem =~ /^(?!.*_fav.*)ussSession.*/", - "command": "zowe.uss.removeSession", - "group": "099_zowe_ussProfileAuthentication@98" - }, { "when": "view == zowe.ds.explorer && viewItem =~ /^(?!.*_fav.*)session.*/ && !listMultiSelection", "command": "zowe.ds.pattern", @@ -1153,26 +1138,11 @@ "command": "zowe.ds.deleteDataset", "group": "099_zowe_dsModification@5" }, - { - "when": "view == zowe.ds.explorer && viewItem =~ /_validate/ && !listMultiSelection", - "command": "zowe.ds.disableValidation", - "group": "099_zowe_dsProfileAuthentication@96" - }, - { - "when": "view == zowe.ds.explorer && viewItem =~ /_noValidate/ && !listMultiSelection", - "command": "zowe.ds.enableValidation", - "group": "099_zowe_dsProfileAuthentication@97" - }, { "when": "view == zowe.ds.explorer && viewItem =~ /^(?!.*_fav.*)session.*/ && !listMultiSelection", "command": "zowe.profileManagement", "group": "099_zowe_dsProfileAuthentication@99" }, - { - "when": "view == zowe.ds.explorer && viewItem =~ /^(?!.*_fav.*)session.*/", - "command": "zowe.ds.removeSession", - "group": "099_zowe_dsProfileAuthentication@98" - }, { "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/ && !listMultiSelection", "command": "zowe.jobs.search", @@ -1298,26 +1268,11 @@ "command": "zowe.jobs.cancelJob", "group": "099_zowe_jobsModification" }, - { - "when": "view == zowe.jobs.explorer && viewItem =~ /_validate/ && !listMultiSelection", - "command": "zowe.jobs.disableValidation", - "group": "099_zowe_jobsProfileAuthentication@96" - }, - { - "when": "view == zowe.jobs.explorer && viewItem =~ /_noValidate/ && !listMultiSelection", - "command": "zowe.jobs.enableValidation", - "group": "099_zowe_jobsProfileAuthentication@97" - }, { "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/ && !listMultiSelection", "command": "zowe.profileManagement", "group": "099_zowe_jobsProfileAuthentication@99" }, - { - "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/", - "command": "zowe.jobs.removeJobsSession", - "group": "099_zowe_jobsProfileAuthentication@98" - }, { "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/ && !listMultiSelection", "command": "zowe.jobs.sortbyid", diff --git a/packages/zowe-explorer/src/utils/ProfileManagement.ts b/packages/zowe-explorer/src/utils/ProfileManagement.ts index b72838721e..55a2f57eae 100644 --- a/packages/zowe-explorer/src/utils/ProfileManagement.ts +++ b/packages/zowe-explorer/src/utils/ProfileManagement.ts @@ -10,12 +10,14 @@ */ import * as vscode from "vscode"; +import * as globals from "../globals"; import { Gui, IZoweTreeNode, imperative } from "@zowe/zowe-explorer-api"; import { ZoweLogger } from "./LoggerUtils"; import { ProfilesUtils } from "./ProfilesUtils"; import * as nls from "vscode-nls"; import { Profiles } from "../Profiles"; import { ZoweExplorerApiRegister } from "../ZoweExplorerApiRegister"; +import { isZoweDatasetTreeNode, isZoweUSSTreeNode } from "../shared/utils"; // Set up localization nls.config({ @@ -31,18 +33,18 @@ export class ProfileManagement { switch (true) { case ProfilesUtils.isProfileUsingBasicAuth(profile): { ZoweLogger.debug(`Profile ${profile.name} is using basic authentication.`); - selected = await this.setupProfileManagementQp(imperative.SessConstants.AUTH_TYPE_BASIC, profile); + selected = await this.setupProfileManagementQp(imperative.SessConstants.AUTH_TYPE_BASIC, node); break; } case await ProfilesUtils.isUsingTokenAuth(profile.name): { ZoweLogger.debug(`Profile ${profile.name} is using token authentication.`); - selected = await this.setupProfileManagementQp("token", profile); + selected = await this.setupProfileManagementQp("token", node); break; } // will need a case for isUsingCertAuth default: { ZoweLogger.debug(`Profile ${profile.name} authentication method is unkown.`); - selected = await this.setupProfileManagementQp(null, profile); + selected = await this.setupProfileManagementQp(null, node); break; } } @@ -50,8 +52,11 @@ export class ProfileManagement { } public static AuthQpLabels = { add: "add-credentials", - delete: "delete", + delete: "delete-profile", + disable: "disable-validation", edit: "edit-profile", + enable: "enable-validation", + hide: "hide-profile", login: "obtain-token", logout: "invalidate-token", update: "update-credentials", @@ -73,12 +78,30 @@ export class ProfileManagement { label: localize("deleteProfileQpItem.delete.qpLabel", "$(trash) Delete Profile"), }, }; + public static disableProfileValildationQpItem: Record = { + [this.AuthQpLabels.disable]: { + label: localize("disableProfileValildationQpItem.disableValidation.qpLabel", "$(workspace-untrusted) Disable Profile Validation"), + description: localize("disableProfileValildationQpItem.disableValidation.qpDetail", "Disable validation of server check for profile."), + }, + }; + public static enableProfileValildationQpItem: Record = { + [this.AuthQpLabels.enable]: { + label: localize("enableProfileValildationQpItem.enableValidation.qpLabel", "$(workspace-trusted) Enable Profile Validation"), + description: localize("enableProfileValildationQpItem.enableValidation.qpDetail", "Enable validation of server check for profile."), + }, + }; public static editProfileQpItems: Record = { [this.AuthQpLabels.edit]: { label: localize("editProfileQpItem.editProfile.qpLabel", "$(pencil) Edit Profile"), description: localize("editProfileQpItem.editProfile.qpDetail", "Update profile connection information"), }, }; + public static hideProfileQpItems: Record = { + [this.AuthQpLabels.hide]: { + label: localize("hideProfileQpItems.hideProfile.qpLabel", "$(eye-closed) Hide Profile"), + description: localize("hideProfileQpItems.hideProfile.qpDetail", "Hide profile name from tree view."), + }, + }; public static tokenAuthLoginQpItem: Record = { [this.AuthQpLabels.login]: { label: localize("loginQpItem.login.qpLabel", "$(arrow-right) Log in to authentication service"), @@ -91,23 +114,24 @@ export class ProfileManagement { description: localize("logoutQpItem.logout.qpDetail", "Log out to invalidate and remove stored token value"), }, }; - private static async setupProfileManagementQp(managementType: string, profile: imperative.IProfileLoaded): Promise { + private static async setupProfileManagementQp(managementType: string, node: IZoweTreeNode): Promise { + const profile = node.getProfile(); const qp = Gui.createQuickPick(); let quickPickOptions: vscode.QuickPickItem[]; const placeholders = this.getQpPlaceholders(profile); switch (managementType) { case imperative.SessConstants.AUTH_TYPE_BASIC: { - quickPickOptions = this.basicAuthQp(); + quickPickOptions = this.basicAuthQp(node); qp.placeholder = placeholders.basicAuth; break; } case "token": { - quickPickOptions = this.tokenAuthQp(profile); + quickPickOptions = this.tokenAuthQp(node); qp.placeholder = placeholders.tokenAuth; break; } default: { - quickPickOptions = this.chooseAuthQp(profile); + quickPickOptions = this.chooseAuthQp(node); qp.placeholder = placeholders.chooseAuth; break; } @@ -142,10 +166,22 @@ export class ProfileManagement { await ProfilesUtils.promptCredentials(node); break; } + case this.hideProfileQpItems[this.AuthQpLabels.hide]: { + await this.handleHideProfiles(node); + break; + } case this.deleteProfileQpItem[this.AuthQpLabels.delete]: { await this.handleDeleteProfiles(node); break; } + case this.enableProfileValildationQpItem[this.AuthQpLabels.enable]: { + await this.handleEnableProfileValidation(node); + break; + } + case this.disableProfileValildationQpItem[this.AuthQpLabels.disable]: { + await this.handleDisableProfileValidation(node); + break; + } default: { Gui.infoMessage(localize("profiles.operation.cancelled", "Operation Cancelled")); break; @@ -165,18 +201,20 @@ export class ProfileManagement { }; } - private static basicAuthQp(): vscode.QuickPickItem[] { + private static basicAuthQp(node: IZoweTreeNode): vscode.QuickPickItem[] { const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.basicAuthUpdateQpItems); - return this.addFinalQpOptions(quickPickOptions); + return this.addFinalQpOptions(node, quickPickOptions); } - private static tokenAuthQp(profile: imperative.IProfileLoaded): vscode.QuickPickItem[] { + private static tokenAuthQp(node: IZoweTreeNode): vscode.QuickPickItem[] { + const profile = node.getProfile(); const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.tokenAuthLoginQpItem); if (profile.profile.tokenType) { quickPickOptions.push(this.tokenAuthLogoutQpItem[this.AuthQpLabels.logout]); } - return this.addFinalQpOptions(quickPickOptions); + return this.addFinalQpOptions(node, quickPickOptions); } - private static chooseAuthQp(profile: imperative.IProfileLoaded): vscode.QuickPickItem[] { + private static chooseAuthQp(node: IZoweTreeNode): vscode.QuickPickItem[] { + const profile = node.getProfile(); const quickPickOptions: vscode.QuickPickItem[] = Object.values(this.basicAuthAddQpItems); try { ZoweExplorerApiRegister.getInstance().getCommonApi(profile).getTokenTypeName(); @@ -184,10 +222,16 @@ export class ProfileManagement { } catch { ZoweLogger.debug(`Profile ${profile.name} doesn't support token authentication, will not provide option.`); } - return this.addFinalQpOptions(quickPickOptions); + return this.addFinalQpOptions(node, quickPickOptions); } - private static addFinalQpOptions(quickPickOptions: vscode.QuickPickItem[]): vscode.QuickPickItem[] { + private static addFinalQpOptions(node: IZoweTreeNode, quickPickOptions: vscode.QuickPickItem[]): vscode.QuickPickItem[] { + if (node.contextValue.includes(globals.NO_VALIDATE_SUFFIX)) { + quickPickOptions.push(this.enableProfileValildationQpItem[this.AuthQpLabels.enable]); + } else { + quickPickOptions.push(this.disableProfileValildationQpItem[this.AuthQpLabels.disable]); + } quickPickOptions.push(this.editProfileQpItems[this.AuthQpLabels.edit]); + quickPickOptions.push(this.hideProfileQpItems[this.AuthQpLabels.hide]); quickPickOptions.push(this.deleteProfileQpItem[this.AuthQpLabels.delete]); return quickPickOptions; } @@ -200,4 +244,34 @@ export class ProfileManagement { } await vscode.commands.executeCommand("zowe.ds.deleteProfile", node); } + + private static async handleHideProfiles(node: IZoweTreeNode): Promise { + if (isZoweDatasetTreeNode(node)) { + return vscode.commands.executeCommand("zowe.ds.removeSession", node); + } + if (isZoweUSSTreeNode(node)) { + return vscode.commands.executeCommand("zowe.uss.removeSession", node); + } + return vscode.commands.executeCommand("zowe.jobs.removeJobsSession", node); + } + + private static async handleEnableProfileValidation(node: IZoweTreeNode): Promise { + if (isZoweDatasetTreeNode(node)) { + return vscode.commands.executeCommand("zowe.ds.enableValidation", node); + } + if (isZoweUSSTreeNode(node)) { + return vscode.commands.executeCommand("zowe.uss.enableValidation", node); + } + return vscode.commands.executeCommand("zowe.jobs.enableValidation", node); + } + + private static async handleDisableProfileValidation(node: IZoweTreeNode): Promise { + if (isZoweDatasetTreeNode(node)) { + return vscode.commands.executeCommand("zowe.ds.disableValidation", node); + } + if (isZoweUSSTreeNode(node)) { + return vscode.commands.executeCommand("zowe.uss.disableValidation", node); + } + return vscode.commands.executeCommand("zowe.jobs.disableValidation", node); + } } From 00af76309c21583b9981be9aa0287976f80da7e8 Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Mon, 2 Oct 2023 18:35:28 -0400 Subject: [PATCH 34/35] add unit tests Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../utils/ProfileManagement.unit.test.ts | 61 ++++++++++++++++++- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts index 44d605e0d4..2cd395f690 100644 --- a/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/utils/ProfileManagement.unit.test.ts @@ -12,6 +12,7 @@ import { ZoweDatasetNode } from "../../../src/dataset/ZoweDatasetNode"; import * as sharedMock from "../../../__mocks__/mockCreators/shared"; import * as dsMock from "../../../__mocks__/mockCreators/datasets"; +import * as unixMock from "../../../__mocks__/mockCreators/uss"; import * as profUtils from "../../../src/utils/ProfilesUtils"; import { ProfileManagement } from "../../../src/utils/ProfileManagement"; import { Gui } from "@zowe/zowe-explorer-api"; @@ -19,6 +20,7 @@ import { ZoweLogger } from "../../../src/utils/LoggerUtils"; import { Profiles } from "../../../src/Profiles"; import * as vscode from "vscode"; import { imperative } from "@zowe/cli"; +import { ZoweUSSNode } from "../../../src/uss/ZoweUSSNode"; jest.mock("fs"); jest.mock("vscode"); @@ -36,6 +38,7 @@ describe("ProfileManagement unit tests", () => { mockNoAuthProfile: sharedMock.createNoAuthIProfile(), opCancelledSpy: jest.spyOn(Gui, "infoMessage"), mockDsSessionNode: ZoweDatasetNode, + mockUnixSessionNode: ZoweUSSNode, mockResolveQp: jest.fn(), mockCreateQp: jest.fn(), mockUpdateChosen: ProfileManagement.basicAuthUpdateQpItems[ProfileManagement.AuthQpLabels.update], @@ -44,6 +47,9 @@ describe("ProfileManagement unit tests", () => { mockLogoutChosen: ProfileManagement.tokenAuthLogoutQpItem[ProfileManagement.AuthQpLabels.logout], mockEditProfChosen: ProfileManagement.editProfileQpItems[ProfileManagement.AuthQpLabels.edit], mockDeleteProfChosen: ProfileManagement.deleteProfileQpItem[ProfileManagement.AuthQpLabels.delete], + mockHideProfChosen: ProfileManagement.hideProfileQpItems[ProfileManagement.AuthQpLabels.hide], + mockEnableValidationChosen: ProfileManagement.enableProfileValildationQpItem[ProfileManagement.AuthQpLabels.enable], + mockDisableValidationChosen: ProfileManagement.disableProfileValildationQpItem[ProfileManagement.AuthQpLabels.disable], mockProfileInfo: { usingTeamConfig: true }, mockProfileInstance: null as any, debugLogSpy: null as any, @@ -52,6 +58,7 @@ describe("ProfileManagement unit tests", () => { loginSpy: null as any, logoutSpy: null as any, logMsg: null as any, + commandSpy: null as any, }; Object.defineProperty(profUtils.ProfilesUtils, "promptCredentials", { value: jest.fn(), configurable: true }); newMocks.promptSpy = jest.spyOn(profUtils.ProfilesUtils, "promptCredentials"); @@ -82,6 +89,8 @@ describe("ProfileManagement unit tests", () => { newMocks.loginSpy = jest.spyOn(newMocks.mockProfileInstance, "ssoLogin"); Object.defineProperty(newMocks.mockProfileInstance, "ssoLogout", { value: jest.fn(), configurable: true }); newMocks.logoutSpy = jest.spyOn(newMocks.mockProfileInstance, "ssoLogout"); + Object.defineProperty(vscode.commands, "executeCommand", { value: jest.fn(), configurable: true }); + newMocks.commandSpy = jest.spyOn(vscode.commands, "executeCommand"); return newMocks; } @@ -90,7 +99,6 @@ describe("ProfileManagement unit tests", () => { function createBlockMocks(globalMocks): any { globalMocks.logMsg = `Profile ${globalMocks.mockBasicAuthProfile.name} is using basic authentication.`; globalMocks.mockDsSessionNode.getProfile = jest.fn().mockReturnValue(globalMocks.mockBasicAuthProfile); - Object.defineProperty(vscode.commands, "executeCommand", { value: jest.fn(), configurable: true }); return globalMocks; } it("profile using basic authentication should see Operation Cancelled when escaping quick pick", async () => { @@ -125,22 +133,34 @@ describe("ProfileManagement unit tests", () => { expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); expect(mocks.editSpy).toBeCalled(); }); + it("profile using basic authentication should see hide session command called for profile in data set tree view", async () => { + const mocks = createBlockMocks(createGlobalMocks()); + Object.defineProperty(mocks.mockProfileInstance, "getProfileInfo", { + value: jest.fn().mockResolvedValue(mocks.mockProfileInfo as imperative.ProfileInfo), + configurable: true, + }); + mocks.mockResolveQp.mockResolvedValueOnce(mocks.mockHideProfChosen); + await ProfileManagement.manageProfile(mocks.mockDsSessionNode); + expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); + expect(mocks.commandSpy).toHaveBeenLastCalledWith("zowe.ds.removeSession", mocks.mockDsSessionNode); + }); it("profile using basic authentication should see delete commands called when Delete Profile chosen with v1 profile", async () => { const mocks = createBlockMocks(createGlobalMocks()); mocks.mockResolveQp.mockResolvedValueOnce(mocks.mockDeleteProfChosen); mocks.mockProfileInfo.usingTeamConfig = false; - const commandSpy = jest.spyOn(vscode.commands, "executeCommand"); await ProfileManagement.manageProfile(mocks.mockDsSessionNode); expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); expect(mocks.editSpy).not.toBeCalled(); - expect(commandSpy).toBeCalled(); + expect(mocks.commandSpy).toHaveBeenLastCalledWith("zowe.ds.deleteProfile", mocks.mockDsSessionNode); }); }); describe("unit tests around token auth selections", () => { function createBlockMocks(globalMocks): any { globalMocks.logMsg = `Profile ${globalMocks.mockTokenAuthProfile.name} is using token authentication.`; + globalMocks.mockUnixSessionNode = unixMock.createUSSSessionNode(globalMocks.mockSession, globalMocks.mockBasicAuthProfile) as any; Object.defineProperty(profUtils.ProfilesUtils, "isUsingTokenAuth", { value: jest.fn().mockResolvedValueOnce(true), configurable: true }); globalMocks.mockDsSessionNode.getProfile = jest.fn().mockReturnValue(globalMocks.mockTokenAuthProfile); + globalMocks.mockUnixSessionNode.getProfile = jest.fn().mockReturnValue(globalMocks.mockTokenAuthProfile); return globalMocks; } it("profile using token authentication should see Operation Cancelled when escaping quick pick", async () => { @@ -164,6 +184,27 @@ describe("ProfileManagement unit tests", () => { expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); expect(mocks.logoutSpy).toBeCalled(); }); + it("profile using token authentication should see correct command called for hiding a unix tree session node", async () => { + const mocks = createBlockMocks(createGlobalMocks()); + mocks.mockResolveQp.mockResolvedValueOnce(mocks.mockHideProfChosen); + await ProfileManagement.manageProfile(mocks.mockUnixSessionNode); + expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); + expect(mocks.commandSpy).toHaveBeenLastCalledWith("zowe.uss.removeSession", mocks.mockUnixSessionNode); + }); + it("profile using token authentication should see correct command called for enabling validation a unix tree session node", async () => { + const mocks = createBlockMocks(createGlobalMocks()); + mocks.mockResolveQp.mockResolvedValueOnce(mocks.mockEnableValidationChosen); + await ProfileManagement.manageProfile(mocks.mockUnixSessionNode); + expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); + expect(mocks.commandSpy).toHaveBeenLastCalledWith("zowe.uss.enableValidation", mocks.mockUnixSessionNode); + }); + it("profile using token authentication should see correct command called for disabling validation a unix tree session node", async () => { + const mocks = createBlockMocks(createGlobalMocks()); + mocks.mockResolveQp.mockResolvedValueOnce(mocks.mockDisableValidationChosen); + await ProfileManagement.manageProfile(mocks.mockUnixSessionNode); + expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); + expect(mocks.commandSpy).toHaveBeenLastCalledWith("zowe.uss.disableValidation", mocks.mockUnixSessionNode); + }); }); describe("unit tests around no auth declared selections", () => { function createBlockMocks(globalMocks): any { @@ -200,5 +241,19 @@ describe("ProfileManagement unit tests", () => { expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); expect(mocks.editSpy).toBeCalled(); }); + it("profile using token authentication should see correct command called for enabling validation a data set tree session node", async () => { + const mocks = createBlockMocks(createGlobalMocks()); + mocks.mockResolveQp.mockResolvedValueOnce(mocks.mockEnableValidationChosen); + await ProfileManagement.manageProfile(mocks.mockDsSessionNode); + expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); + expect(mocks.commandSpy).toHaveBeenLastCalledWith("zowe.ds.enableValidation", mocks.mockDsSessionNode); + }); + it("profile using token authentication should see correct command called for disabling validation a data set tree session node", async () => { + const mocks = createBlockMocks(createGlobalMocks()); + mocks.mockResolveQp.mockResolvedValueOnce(mocks.mockDisableValidationChosen); + await ProfileManagement.manageProfile(mocks.mockDsSessionNode); + expect(mocks.debugLogSpy).toBeCalledWith(mocks.logMsg); + expect(mocks.commandSpy).toHaveBeenLastCalledWith("zowe.ds.disableValidation", mocks.mockDsSessionNode); + }); }); }); From 742a90e8065fadbbe4fef118aa1f06600996f79e Mon Sep 17 00:00:00 2001 From: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> Date: Fri, 6 Oct 2023 09:05:15 -0400 Subject: [PATCH 35/35] address feedback Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com> --- .../i18n/sample/src/utils/ProfileManagement.i18n.json | 6 +++--- packages/zowe-explorer/src/utils/ProfileManagement.ts | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json b/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json index 56776e1f3b..f487573b50 100644 --- a/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json +++ b/packages/zowe-explorer/i18n/sample/src/utils/ProfileManagement.i18n.json @@ -9,13 +9,13 @@ "updateBasicAuthQpItem.updateCredentials.qpDetail": "Update stored username and password", "deleteProfileQpItem.delete.qpLabel": "$(trash) Delete Profile", "disableProfileValildationQpItem.disableValidation.qpLabel": "$(workspace-untrusted) Disable Profile Validation", - "disableProfileValildationQpItem.disableValidation.qpDetail": "Disable validation of server check for profile.", + "disableProfileValildationQpItem.disableValidation.qpDetail": "Disable validation of server check for profile", "enableProfileValildationQpItem.enableValidation.qpLabel": "$(workspace-trusted) Enable Profile Validation", - "enableProfileValildationQpItem.enableValidation.qpDetail": "Enable validation of server check for profile.", + "enableProfileValildationQpItem.enableValidation.qpDetail": "Enable validation of server check for profile", "editProfileQpItem.editProfile.qpLabel": "$(pencil) Edit Profile", "editProfileQpItem.editProfile.qpDetail": "Update profile connection information", "hideProfileQpItems.hideProfile.qpLabel": "$(eye-closed) Hide Profile", - "hideProfileQpItems.hideProfile.qpDetail": "Hide profile name from tree view.", + "hideProfileQpItems.hideProfile.qpDetail": "Hide profile name from tree view", "loginQpItem.login.qpLabel": "$(arrow-right) Log in to authentication service", "loginQpItem.login.qpDetail": "Log in to obtain a new token value", "logoutQpItem.logout.qpLabel": "$(arrow-left) Log out of authentication service", diff --git a/packages/zowe-explorer/src/utils/ProfileManagement.ts b/packages/zowe-explorer/src/utils/ProfileManagement.ts index 55a2f57eae..5825a8fdac 100644 --- a/packages/zowe-explorer/src/utils/ProfileManagement.ts +++ b/packages/zowe-explorer/src/utils/ProfileManagement.ts @@ -81,13 +81,13 @@ export class ProfileManagement { public static disableProfileValildationQpItem: Record = { [this.AuthQpLabels.disable]: { label: localize("disableProfileValildationQpItem.disableValidation.qpLabel", "$(workspace-untrusted) Disable Profile Validation"), - description: localize("disableProfileValildationQpItem.disableValidation.qpDetail", "Disable validation of server check for profile."), + description: localize("disableProfileValildationQpItem.disableValidation.qpDetail", "Disable validation of server check for profile"), }, }; public static enableProfileValildationQpItem: Record = { [this.AuthQpLabels.enable]: { label: localize("enableProfileValildationQpItem.enableValidation.qpLabel", "$(workspace-trusted) Enable Profile Validation"), - description: localize("enableProfileValildationQpItem.enableValidation.qpDetail", "Enable validation of server check for profile."), + description: localize("enableProfileValildationQpItem.enableValidation.qpDetail", "Enable validation of server check for profile"), }, }; public static editProfileQpItems: Record = { @@ -99,7 +99,7 @@ export class ProfileManagement { public static hideProfileQpItems: Record = { [this.AuthQpLabels.hide]: { label: localize("hideProfileQpItems.hideProfile.qpLabel", "$(eye-closed) Hide Profile"), - description: localize("hideProfileQpItems.hideProfile.qpDetail", "Hide profile name from tree view."), + description: localize("hideProfileQpItems.hideProfile.qpDetail", "Hide profile name from tree view"), }, }; public static tokenAuthLoginQpItem: Record = { @@ -225,13 +225,13 @@ export class ProfileManagement { return this.addFinalQpOptions(node, quickPickOptions); } private static addFinalQpOptions(node: IZoweTreeNode, quickPickOptions: vscode.QuickPickItem[]): vscode.QuickPickItem[] { + quickPickOptions.push(this.editProfileQpItems[this.AuthQpLabels.edit]); + quickPickOptions.push(this.hideProfileQpItems[this.AuthQpLabels.hide]); if (node.contextValue.includes(globals.NO_VALIDATE_SUFFIX)) { quickPickOptions.push(this.enableProfileValildationQpItem[this.AuthQpLabels.enable]); } else { quickPickOptions.push(this.disableProfileValildationQpItem[this.AuthQpLabels.disable]); } - quickPickOptions.push(this.editProfileQpItems[this.AuthQpLabels.edit]); - quickPickOptions.push(this.hideProfileQpItems[this.AuthQpLabels.hide]); quickPickOptions.push(this.deleteProfileQpItem[this.AuthQpLabels.delete]); return quickPickOptions; }