From 6c46e331ccb07c369d79404fd4b4c4648d788a04 Mon Sep 17 00:00:00 2001 From: Richelle Anne Craw Date: Tue, 14 Apr 2020 10:53:47 +0200 Subject: [PATCH 01/16] Add deletion of profiles Signed-off-by: Richelle Anne Craw --- i18n/sample/package.i18n.json | 2 + i18n/sample/src/Profiles.i18n.json | 9 +++- package.json | 40 ++++++++++++++ package.nls.json | 2 + src/DatasetTree.ts | 10 ++++ src/Profiles.ts | 87 +++++++++++++++++++++++++++++- src/USSTree.ts | 9 ++++ src/ZosJobsProvider.ts | 9 ++++ src/api/IZoweTree.ts | 5 ++ src/extension.ts | 5 ++ 10 files changed, 176 insertions(+), 2 deletions(-) diff --git a/i18n/sample/package.i18n.json b/i18n/sample/package.i18n.json index 4e37fb6992..2708af7956 100644 --- a/i18n/sample/package.i18n.json +++ b/i18n/sample/package.i18n.json @@ -68,6 +68,8 @@ "Zowe-Default-Commands-Persistent-Favorites": "Toggle if Commands persist locally", "Zowe-Environment": "Environment where the extension is running, default is VSCode", "issueMvsCmd": "Zowe: Issue MVS Command...", + "deleteProfile": "Delete Profile", + "cmd.deleteProfile": "Zowe: Delete a Profile Permanently...", "rename": "Rename", "copy": "Copy", "paste": "Paste", diff --git a/i18n/sample/src/Profiles.i18n.json b/i18n/sample/src/Profiles.i18n.json index defd7a09e6..6153b3afb8 100644 --- a/i18n/sample/src/Profiles.i18n.json +++ b/i18n/sample/src/Profiles.i18n.json @@ -19,5 +19,12 @@ "promptcredentials.invalidusername": "Please enter your z/OS username. Operation Cancelled", "promptcredentials.option.prompt.password.placeholder": "Password", "promptcredentials.option.prompt.password": "Enter a password for the connection", - "promptcredentials.invalidpassword": "Please enter your z/OS password. Operation Cancelled" + "promptcredentials.invalidpassword": "Please enter your z/OS password. Operation Cancelled", + "deleteProfile.quickPickOption": "Are you sure you want to permanently delete ", + "deleteProfile.noProfilesLoaded": "No profiles available", + "deleteProfile.log.debug": "Deleting profile ", + "deleteProfile.showQuickPick.yes": "Yes", + "deleteProfile.showQuickPick.no": "No", + "deleteProfile.showQuickPick.log.debug": "User picked no. Cancelling delete of profile", + "deleteProfile.delete.log.error": "Error encountered when deleting profile! " } \ No newline at end of file diff --git a/package.json b/package.json index 918a2bd73a..3f106137e4 100644 --- a/package.json +++ b/package.json @@ -107,6 +107,14 @@ "dark": "./resources/dark/plus.svg" } }, + { + "command": "zowe.deleteProfile", + "title": "%deleteProfile%" + }, + { + "command": "zowe.cmd.deleteProfile", + "title": "%cmd.deleteProfile%" + }, { "command": "zowe.createDataset", "title": "%createDataset%", @@ -227,6 +235,10 @@ "dark": "./resources/dark/plus.svg" } }, + { + "command": "zowe.uss.deleteProfile", + "title": "%deleteProfile%" + }, { "command": "zowe.uss.createDirectory", "title": "%uss.createDirectory%", @@ -347,6 +359,10 @@ "dark": "./resources/dark/refresh.svg" } }, + { + "command": "zowe.jobs.deleteProfile", + "title": "%deleteProfile%" + }, { "command": "zowe.refreshAllJobs", "title": "%refreshAll%", @@ -819,6 +835,10 @@ "command": "zowe.createDataset", "group": "inline" }, + { + "when": "view == zowe.explorer && viewItem == session", + "command": "zowe.deleteProfile" + }, { "when": "view == zowe.explorer && viewItem == session", "command": "zowe.removeSession" @@ -847,6 +867,10 @@ "command": "zowe.uss.createNode", "group": "inline" }, + { + "when": "viewItem == uss_session", + "command": "zowe.uss.deleteProfile" + }, { "when": "viewItem == uss_session", "command": "zowe.uss.removeSession" @@ -871,6 +895,10 @@ "command": "zowe.jobs.search", "group": "inline" }, + { + "when": "view == zowe.jobs && viewItem == server", + "command": "zowe.jobs.deleteProfile" + }, { "when": "view == zowe.jobs && viewItem == server", "command": "zowe.setOwner" @@ -971,6 +999,10 @@ "command": "zowe.removeSession", "when": "never" }, + { + "command": "zowe.deleteProfile", + "when": "never" + }, { "command": "zowe.saveSearch", "when": "never" @@ -995,6 +1027,10 @@ "command": "zowe.uss.saveSearch", "when": "never" }, + { + "command": "zowe.uss.deleteProfile", + "when": "never" + }, { "command": "zowe.uss.removeSavedSearch", "when": "never" @@ -1035,6 +1071,10 @@ "command": "zowe.jobs.saveSearch", "when": "never" }, + { + "command": "zowe.jobs.deleteProfile", + "when": "never" + }, { "command": "zowe.issueMvsCmd", "when": "never" diff --git a/package.nls.json b/package.nls.json index b971910367..0bd7d447da 100644 --- a/package.nls.json +++ b/package.nls.json @@ -68,6 +68,8 @@ "Zowe-Default-Commands-Persistent-Favorites": "Toggle if Commands persist locally", "Zowe-Environment": "Environment where the extension is running, default is VSCode", "issueMvsCmd" : "Zowe: Issue MVS Command...", + "deleteProfile" : "Delete Profile", + "cmd.deleteProfile" : "Zowe: Delete a Profile Permanently...", "rename" : "Rename", "copy" : "Copy", "paste" : "Paste", diff --git a/src/DatasetTree.ts b/src/DatasetTree.ts index c579a59165..f22051b168 100644 --- a/src/DatasetTree.ts +++ b/src/DatasetTree.ts @@ -261,6 +261,16 @@ export class DatasetTree extends ZoweTreeProvider implements IZoweTree { + return temprofile.name; + }); + if (profileNamesList.length) { + const quickPickList: vscode.QuickPickOptions = { + placeHolder: localize("deleteProfile.quickPickOption", "Select the profile you want to delete"), + ignoreFocusOut: true, + canPickMany: false + }; + const sesName = await vscode.window.showQuickPick(profileNamesList, quickPickList); + zosmfProfile = allProfiles.filter((temprofile) => temprofile.name === sesName)[0]; + const delProfile = zosmfProfile.profile as ISession; + const session = zowe.ZosmfSession.createBasicZosmfSession(delProfile as IProfile); + } else { + vscode.window.showInformationMessage(localize("deleteProfile.noProfilesLoaded", "No profiles available")); + return; + } + + this.log.debug(localize("deleteProfile.log.debug", "Deleting profile ") + zosmfProfile.name); + const quickPickOptions: vscode.QuickPickOptions = { + placeHolder: localize("deleteProfile.quickPickOption", "Are you sure you want to permanently delete ") + zosmfProfile.name, + ignoreFocusOut: true, + canPickMany: false + }; + // confirm that the user really wants to delete + if (await vscode.window.showQuickPick([localize("deleteProfile.showQuickPick.yes", "Yes"), + localize("deleteProfile.showQuickPick.no", "No")], quickPickOptions) !== localize("deleteProfile.showQuickPick.yes", "Yes")) { + this.log.debug(localize("deleteProfile.showQuickPick.log.debug", "User picked no. Cancelling delete of profile")); + return; + } + + try { + this.deleteProf(zosmfProfile, zosmfProfile.name, zosmfProfile.type); + } catch (error) { + this.log.error(localize("deleteProfile.delete.log.error", "Error encountered when deleting profile! ") + JSON.stringify(error)); + await errorHandling(error, zosmfProfile.name, error.message); + throw error; + } + vscode.window.showInformationMessage("Profile " + zosmfProfile.name + " was deleted."); + } + public async deleteProfile(node: IZoweNodeType) { + const profileName = node.getProfileName(); + this.log.debug(localize("deleteProfile.log.debug", "Deleting profile ") + profileName); + const quickPickOptions: vscode.QuickPickOptions = { + placeHolder: localize("deleteProfile.quickPickOption", "Are you sure you want to permanently delete ") + profileName, + ignoreFocusOut: true, + canPickMany: false + }; + // confirm that the user really wants to delete + if (await vscode.window.showQuickPick([localize("deleteProfile.showQuickPick.yes", "Yes"), + localize("deleteProfile.showQuickPick.no", "No")], quickPickOptions) !== localize("deleteProfile.showQuickPick.yes", "Yes")) { + this.log.debug(localize("deleteProfile.showQuickPick.log.debug", "User picked no. Cancelling delete of profile")); + return; + } + + const profile = node.getProfile(); + const profileType = ZoweExplorerApiRegister.getMvsApi(profile).getProfileTypeName(); + try { + this.deleteProf(profile, profileName, profileType); + } catch (error) { + this.log.error(localize("deleteProfile.delete.log.error", "Error encountered when deleting profile! ") + JSON.stringify(error)); + await errorHandling(error, profileName, error.message); + throw error; + } + + vscode.window.showInformationMessage("Profile " + profileName + " was deleted."); + } + + public async deleteProf(ProfileInfo, ProfileName, ProfileType) { + let zosmfProfile: IProfile; + try { + zosmfProfile = await (await this.getCliProfileManager(ProfileType)) + .delete({ profile: ProfileInfo, name: ProfileName, type: ProfileType }); + } catch (error) { + vscode.window.showErrorMessage(error.message); + } + return zosmfProfile.profile; + } + + private async updateProfile(ProfileInfo) { for (const type of ZoweExplorerApiRegister.getInstance().registeredApiTypes()) { diff --git a/src/USSTree.ts b/src/USSTree.ts index e093742857..7f6521ef07 100644 --- a/src/USSTree.ts +++ b/src/USSTree.ts @@ -192,6 +192,15 @@ export class USSTree extends ZoweTreeProvider implements IZoweTree tempNode.label.trim() !== node.label.trim()); this.deleteSessionByLabel(node.getLabel()); } + /** + * Deletes a profile from the zowe folder + * + * @param node + */ + public async deleteProfile(node: IZoweJobTreeNode) { + await Profiles.getInstance().deleteProfile(node); + await this.deleteSession(node); + } /** * Creates a display string to represent a search diff --git a/src/api/IZoweTree.ts b/src/api/IZoweTree.ts index 4bb3f17fd6..d641e23180 100644 --- a/src/api/IZoweTree.ts +++ b/src/api/IZoweTree.ts @@ -98,6 +98,11 @@ export interface IZoweTree extends vscode.TreeDataProvider { * @param node: the node to be deleted */ delete(node: IZoweNodeType); + /** + * Deletes a profile + * @param node: the node containing the profile to be deleted + */ + deleteProfile(node: IZoweNodeType); /** * Reveals and selects a node within the tree. * @param treeView: the vscode tree container diff --git a/src/extension.ts b/src/extension.ts index 8c9192aca5..562eec4cf1 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -216,6 +216,9 @@ export async function activate(context: vscode.ExtensionContext): Promise pasteDataSet(node, datasetProvider)); vscode.commands.registerCommand("zowe.renameDataSetMember", (node) => datasetProvider.rename(node)); vscode.commands.registerCommand("zowe.hMigrateDataSet", (node) => hMigrateDataSet(node)); + vscode.commands.registerCommand("zowe.deleteProfile", async (node) => datasetProvider.deleteProfile(node)); + vscode.commands.registerCommand("zowe.cmd.deleteProfile", async (node) => + Profiles.getInstance().deleteProfileCommand()); vscode.workspace.onDidChangeConfiguration(async (e) => { datasetProvider.onDidChangeConfiguration(e); }); @@ -268,6 +271,7 @@ export async function activate(context: vscode.ExtensionContext): Promise node.openUSS(false, false, ussFileProvider)); vscode.commands.registerCommand("zowe.uss.saveSearch", async (node: IZoweUSSTreeNode) => ussFileProvider.saveSearch(node)); vscode.commands.registerCommand("zowe.uss.removeSavedSearch", async (node: IZoweUSSTreeNode) => ussFileProvider.removeFavorite(node)); + vscode.commands.registerCommand("zowe.uss.deleteProfile", async (node) => ussFileProvider.deleteProfile(node)); vscode.workspace.onDidChangeConfiguration(async (e) => { ussFileProvider.onDidChangeConfiguration(e); }); @@ -331,6 +335,7 @@ export async function activate(context: vscode.ExtensionContext): Promise jobsProvider.removeFavorite(node)); vscode.commands.registerCommand("zowe.jobs.saveSearch", async (node) => jobsProvider.saveSearch(node)); vscode.commands.registerCommand("zowe.jobs.removeSearchFavorite", async (node) => jobsProvider.removeFavorite(node)); + vscode.commands.registerCommand("zowe.jobs.deleteProfile", async (node) => jobsProvider.deleteProfile(node)); const theTreeView = jobsProvider.getTreeView(); context.subscriptions.push(theTreeView); if (!ISTHEIA) { From f7458ae5aab94495e66d9314d4f70eead0b2c3ce Mon Sep 17 00:00:00 2001 From: Richelle Anne Craw Date: Wed, 15 Apr 2020 14:25:32 +0200 Subject: [PATCH 02/16] Change text from Remove to Hide Signed-off-by: Richelle Anne Craw --- i18n/sample/package.i18n.json | 6 +- i18n/sample/src/Profiles.i18n.json | 1 + package.json | 18 ++++-- package.nls.json | 6 +- src/Profiles.ts | 13 +++- src/extension.ts | 100 +++++++++++++++++++++++++++-- 6 files changed, 126 insertions(+), 18 deletions(-) diff --git a/i18n/sample/package.i18n.json b/i18n/sample/package.i18n.json index 2708af7956..521bf398bc 100644 --- a/i18n/sample/package.i18n.json +++ b/i18n/sample/package.i18n.json @@ -26,7 +26,7 @@ "removeFavorite": "Remove Favorite", "uss.removeFavorite": "Remove Favorite", "removeSavedSearch": "Remove Search", - "removeSession": "Remove Profile", + "removeSession": "Hide Profile", "saveSearch": "Add to Favorites", "submitJcl": "Submit JCL", "submitMember": "Submit Job", @@ -37,7 +37,7 @@ "uss.editFile": "Edit", "uss.fullPath": "Search Unix System Services (USS) by Entering a Path", "uss.refreshUSS": "Pull from Mainframe", - "uss.removeSession": "Remove Profile", + "uss.removeSession": "Hide Profile", "uss.binary": "Toggle Binary", "uss.uploadDialog": "Upload Files...", "uss.text": "Toggle Text", @@ -50,7 +50,7 @@ "refreshJobsServer": "Refresh", "refreshAll": "Refresh All", "addJobsSession": "Add Profile", - "removeJobsSession": "Remove Profile", + "removeJobsSession": "Hide Profile", "downloadSpool": "Download Spool", "getJobJcl": "Get JCL", "setJobSpool": "Set Spool", diff --git a/i18n/sample/src/Profiles.i18n.json b/i18n/sample/src/Profiles.i18n.json index 6153b3afb8..403b6a5f12 100644 --- a/i18n/sample/src/Profiles.i18n.json +++ b/i18n/sample/src/Profiles.i18n.json @@ -21,6 +21,7 @@ "promptcredentials.option.prompt.password": "Enter a password for the connection", "promptcredentials.invalidpassword": "Please enter your z/OS password. Operation Cancelled", "deleteProfile.quickPickOption": "Are you sure you want to permanently delete ", + "deleteProfile.undefined.profilename": "Operation Cancelled", "deleteProfile.noProfilesLoaded": "No profiles available", "deleteProfile.log.debug": "Deleting profile ", "deleteProfile.showQuickPick.yes": "Yes", diff --git a/package.json b/package.json index 3f106137e4..85f15c1e9b 100644 --- a/package.json +++ b/package.json @@ -837,11 +837,13 @@ }, { "when": "view == zowe.explorer && viewItem == session", - "command": "zowe.deleteProfile" + "command": "zowe.deleteProfile", + "group": "6_modification@4" }, { "when": "view == zowe.explorer && viewItem == session", - "command": "zowe.removeSession" + "command": "zowe.removeSession", + "group": "6_modification@3" }, { "when": "view == zowe.explorer && viewItem == session", @@ -869,11 +871,13 @@ }, { "when": "viewItem == uss_session", - "command": "zowe.uss.deleteProfile" + "command": "zowe.uss.deleteProfile", + "group": "6_modification@4" }, { "when": "viewItem == uss_session", - "command": "zowe.uss.removeSession" + "command": "zowe.uss.removeSession", + "group": "6_modification@3" }, { "when": "view == zowe.uss.explorer && viewItem == uss_session", @@ -897,7 +901,8 @@ }, { "when": "view == zowe.jobs && viewItem == server", - "command": "zowe.jobs.deleteProfile" + "command": "zowe.jobs.deleteProfile", + "group": "6_modification@4" }, { "when": "view == zowe.jobs && viewItem == server", @@ -909,7 +914,8 @@ }, { "when": "view == zowe.jobs && viewItem == server", - "command": "zowe.removeJobsSession" + "command": "zowe.removeJobsSession", + "group": "6_modification@3" }, { "when": "view == zowe.jobs && viewItem == job", diff --git a/package.nls.json b/package.nls.json index 0bd7d447da..cbead350b4 100644 --- a/package.nls.json +++ b/package.nls.json @@ -26,7 +26,7 @@ "removeFavorite": "Remove Favorite", "uss.removeFavorite": "Remove Favorite", "removeSavedSearch": "Remove Search", - "removeSession": "Remove Profile", + "removeSession": "Hide Profile", "saveSearch": "Add to Favorites", "submitJcl": "Submit JCL", "submitMember": "Submit Job", @@ -37,7 +37,7 @@ "uss.editFile": "Edit", "uss.fullPath": "Search Unix System Services (USS) by Entering a Path", "uss.refreshUSS": "Pull from Mainframe", - "uss.removeSession": "Remove Profile", + "uss.removeSession": "Hide Profile", "uss.binary": "Toggle Binary", "uss.uploadDialog": "Upload Files...", "uss.text": "Toggle Text", @@ -50,7 +50,7 @@ "refreshJobsServer": "Refresh", "refreshAll": "Refresh All", "addJobsSession": "Add Profile", - "removeJobsSession": "Remove Profile", + "removeJobsSession": "Hide Profile", "downloadSpool": "Download Spool", "getJobJcl": "Get JCL", "setJobSpool": "Set Spool", diff --git a/src/Profiles.ts b/src/Profiles.ts index 2592b03775..2e6f74ee99 100644 --- a/src/Profiles.ts +++ b/src/Profiles.ts @@ -303,6 +303,7 @@ export class Profiles { public async deleteProfileCommand() { let zosmfProfile: IProfileLoaded; + let session: Session; const allProfiles: IProfileLoaded[] = this.allProfiles; const profileNamesList = allProfiles.map((temprofile) => { return temprofile.name; @@ -314,9 +315,16 @@ export class Profiles { canPickMany: false }; const sesName = await vscode.window.showQuickPick(profileNamesList, quickPickList); + + if (sesName === undefined) { + vscode.window.showInformationMessage(localize("deleteProfile.undefined.profilename", + "Operation Cancelled")); + return; + } + zosmfProfile = allProfiles.filter((temprofile) => temprofile.name === sesName)[0]; const delProfile = zosmfProfile.profile as ISession; - const session = zowe.ZosmfSession.createBasicZosmfSession(delProfile as IProfile); + session = zowe.ZosmfSession.createBasicZosmfSession(delProfile as IProfile); } else { vscode.window.showInformationMessage(localize("deleteProfile.noProfilesLoaded", "No profiles available")); return; @@ -342,7 +350,10 @@ export class Profiles { await errorHandling(error, zosmfProfile.name, error.message); throw error; } + vscode.window.showInformationMessage("Profile " + zosmfProfile.name + " was deleted."); + + return zosmfProfile.name; } public async deleteProfile(node: IZoweNodeType) { const profileName = node.getProfileName(); diff --git a/src/extension.ts b/src/extension.ts index 562eec4cf1..d3bcb252ed 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -216,9 +216,9 @@ export async function activate(context: vscode.ExtensionContext): Promise pasteDataSet(node, datasetProvider)); vscode.commands.registerCommand("zowe.renameDataSetMember", (node) => datasetProvider.rename(node)); vscode.commands.registerCommand("zowe.hMigrateDataSet", (node) => hMigrateDataSet(node)); - vscode.commands.registerCommand("zowe.deleteProfile", async (node) => datasetProvider.deleteProfile(node)); - vscode.commands.registerCommand("zowe.cmd.deleteProfile", async (node) => - Profiles.getInstance().deleteProfileCommand()); + vscode.commands.registerCommand("zowe.deleteProfile", async (node) => deleteProfile(node, datasetProvider, ussFileProvider, jobsProvider)); + vscode.commands.registerCommand("zowe.cmd.deleteProfile", async () => + deleteProfileCommand(datasetProvider, ussFileProvider, jobsProvider)); vscode.workspace.onDidChangeConfiguration(async (e) => { datasetProvider.onDidChangeConfiguration(e); }); @@ -271,7 +271,8 @@ export async function activate(context: vscode.ExtensionContext): Promise node.openUSS(false, false, ussFileProvider)); vscode.commands.registerCommand("zowe.uss.saveSearch", async (node: IZoweUSSTreeNode) => ussFileProvider.saveSearch(node)); vscode.commands.registerCommand("zowe.uss.removeSavedSearch", async (node: IZoweUSSTreeNode) => ussFileProvider.removeFavorite(node)); - vscode.commands.registerCommand("zowe.uss.deleteProfile", async (node) => ussFileProvider.deleteProfile(node)); + vscode.commands.registerCommand("zowe.uss.deleteProfile", async (node) => + deleteProfile(node, datasetProvider, ussFileProvider, jobsProvider)); vscode.workspace.onDidChangeConfiguration(async (e) => { ussFileProvider.onDidChangeConfiguration(e); }); @@ -335,7 +336,8 @@ export async function activate(context: vscode.ExtensionContext): Promise jobsProvider.removeFavorite(node)); vscode.commands.registerCommand("zowe.jobs.saveSearch", async (node) => jobsProvider.saveSearch(node)); vscode.commands.registerCommand("zowe.jobs.removeSearchFavorite", async (node) => jobsProvider.removeFavorite(node)); - vscode.commands.registerCommand("zowe.jobs.deleteProfile", async (node) => jobsProvider.deleteProfile(node)); + vscode.commands.registerCommand("zowe.jobs.deleteProfile", async (node) => + deleteProfile(node, datasetProvider, ussFileProvider, jobsProvider)); const theTreeView = jobsProvider.getTreeView(); context.subscriptions.push(theTreeView); if (!ISTHEIA) { @@ -1480,6 +1482,94 @@ export function getDocumentFilePath(label: string, node: IZoweTreeNode) { return path.join(DS_DIR, "/" + getProfile(node) + "/" + appendSuffix(label) ); } +export async function deleteProfile( + node: IZoweNodeType, datasetTree: IZoweTree, + ussTree: IZoweTree, jobsProvider: IZoweTree) { + await Profiles.getInstance().deleteProfile(node); + + const tempNode1 = node; + const tempNode2 = node; + await datasetTree.deleteSession(node); + datasetTree.mSessionNodes.forEach((sessNode) => { + if (sessNode.contextValue === DS_SESSION_CONTEXT) { + utils.labelHack(sessNode); + sessNode.children = []; + sessNode.dirty = true; + utils.refreshTree(sessNode); + } + }); + await datasetTree.refresh(); + + await ussTree.deleteSession(tempNode1); + ussTree.mSessionNodes.forEach((sessNode) => { + if (sessNode.contextValue === USS_SESSION_CONTEXT) { + utils.labelHack(sessNode); + sessNode.children = []; + sessNode.dirty = true; + utils.refreshTree(sessNode); + } + }); + await ussTree.refresh(); + + await jobsProvider.deleteSession(tempNode2); + jobsProvider.mSessionNodes.forEach((jobNode) => { + if (jobNode.contextValue === JOBS_SESSION_CONTEXT) { + utils.labelHack(jobNode); + jobNode.children = []; + jobNode.dirty = true; + utils.refreshTree(jobNode); + } + }); + await jobsProvider.refresh(); +} + +export async function deleteProfileCommand( + datasetTree: IZoweTree, ussTree: IZoweTree, jobsProvider: IZoweTree) { + const sessionName = await Profiles.getInstance().deleteProfileCommand(); + + const datasetNode = await datasetTree.mSessionNodes.find((tempNode) => tempNode.label.trim() === sessionName); + if (datasetNode) { + datasetTree.deleteSession(datasetNode); + } + datasetTree.mSessionNodes.forEach((sessNode) => { + if (sessNode.contextValue === DS_SESSION_CONTEXT) { + utils.labelHack(sessNode); + sessNode.children = []; + sessNode.dirty = true; + utils.refreshTree(sessNode); + } + }); + await datasetTree.refresh(); + + const ussNode = await ussTree.mSessionNodes.find((tempNode) => tempNode.label.trim() === sessionName); + if (ussNode) { + ussTree.deleteSession(ussNode); + } + ussTree.mSessionNodes.forEach((sessNode) => { + if (sessNode.contextValue === USS_SESSION_CONTEXT) { + utils.labelHack(sessNode); + sessNode.children = []; + sessNode.dirty = true; + utils.refreshTree(sessNode); + } + }); + await ussTree.refresh(); + + const jobsNode = await jobsProvider.mSessionNodes.find((tempNode) => tempNode.label.trim() === sessionName); + if (jobsNode) { + jobsProvider.deleteSession(jobsNode); + } + jobsProvider.mSessionNodes.forEach((jobNode) => { + if (jobNode.contextValue === JOBS_SESSION_CONTEXT) { + utils.labelHack(jobNode); + jobNode.children = []; + jobNode.dirty = true; + utils.refreshTree(jobNode); + } + }); + await jobsProvider.refresh(); +} + export async function openRecentMemberPrompt(datasetTree: IZoweTree, ussTree: IZoweTree) { if (log) { log.debug(localize("enterPattern.log.debug.prompt", "Prompting the user to choose a recent member for editing")); From f681858f6a5e25a41fa7b1fdeb967a29dad556e4 Mon Sep 17 00:00:00 2001 From: Richelle Anne Craw Date: Wed, 15 Apr 2020 18:40:40 +0200 Subject: [PATCH 03/16] Fix favorites deletion Signed-off-by: Richelle Anne Craw --- src/extension.ts | 65 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index d3bcb252ed..25c29b3adc 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1487,9 +1487,9 @@ export async function deleteProfile( ussTree: IZoweTree, jobsProvider: IZoweTree) { await Profiles.getInstance().deleteProfile(node); - const tempNode1 = node; - const tempNode2 = node; - await datasetTree.deleteSession(node); + const deleteLabel = node.getProfileName(); + + // Delete from Data Set Tree datasetTree.mSessionNodes.forEach((sessNode) => { if (sessNode.contextValue === DS_SESSION_CONTEXT) { utils.labelHack(sessNode); @@ -1497,10 +1497,21 @@ export async function deleteProfile( sessNode.dirty = true; utils.refreshTree(sessNode); } + if (sessNode.getProfileName() === deleteLabel) { + datasetTree.deleteSession(sessNode); + } + }); + + // Delete from Data Set Favorites + datasetTree.mFavorites.forEach((ses) => { + const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); + if (findNode === deleteLabel) { + datasetTree.removeFavorite(ses); + } }); await datasetTree.refresh(); - await ussTree.deleteSession(tempNode1); + // Delete from USS Tree ussTree.mSessionNodes.forEach((sessNode) => { if (sessNode.contextValue === USS_SESSION_CONTEXT) { utils.labelHack(sessNode); @@ -1508,10 +1519,21 @@ export async function deleteProfile( sessNode.dirty = true; utils.refreshTree(sessNode); } + if (sessNode.getProfileName() === deleteLabel) { + ussTree.deleteSession(sessNode); + } + }); + + // Delete from USS Favorites + ussTree.mFavorites.forEach((ses) => { + const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); + if (findNode === deleteLabel) { + ussTree.removeFavorite(ses); + } }); await ussTree.refresh(); - await jobsProvider.deleteSession(tempNode2); + // Delete from Jobs Tree jobsProvider.mSessionNodes.forEach((jobNode) => { if (jobNode.contextValue === JOBS_SESSION_CONTEXT) { utils.labelHack(jobNode); @@ -1519,6 +1541,17 @@ export async function deleteProfile( jobNode.dirty = true; utils.refreshTree(jobNode); } + if (jobNode.getProfileName() === deleteLabel) { + jobsProvider.deleteSession(jobNode); + } + }); + + // Delete from Jobs Favorites + jobsProvider.mFavorites.forEach((ses) => { + const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); + if (findNode === deleteLabel) { + jobsProvider.removeFavorite(ses); + } }); await jobsProvider.refresh(); } @@ -1539,6 +1572,14 @@ export async function deleteProfileCommand( utils.refreshTree(sessNode); } }); + + // Delete from Data Set Favorites + datasetTree.mFavorites.forEach((ses) => { + const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); + if (findNode === datasetNode.label) { + datasetTree.removeFavorite(ses); + } + }); await datasetTree.refresh(); const ussNode = await ussTree.mSessionNodes.find((tempNode) => tempNode.label.trim() === sessionName); @@ -1553,6 +1594,13 @@ export async function deleteProfileCommand( utils.refreshTree(sessNode); } }); + // Delete from USS Favorites + ussTree.mFavorites.forEach((ses) => { + const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); + if (findNode === ussNode.getProfileName()) { + ussTree.removeFavorite(ses); + } + }); await ussTree.refresh(); const jobsNode = await jobsProvider.mSessionNodes.find((tempNode) => tempNode.label.trim() === sessionName); @@ -1567,6 +1615,13 @@ export async function deleteProfileCommand( utils.refreshTree(jobNode); } }); + // Delete from Jobs Favorites + jobsProvider.mFavorites.forEach((ses) => { + const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); + if (findNode === jobsNode.getProfileName()) { + jobsProvider.removeFavorite(ses); + } + }); await jobsProvider.refresh(); } From ed24ec8ff7bbcef9c298b478511bb3573b87758b Mon Sep 17 00:00:00 2001 From: Richelle Anne Craw Date: Wed, 15 Apr 2020 19:47:12 +0200 Subject: [PATCH 04/16] Streamline function Signed-off-by: Richelle Anne Craw --- src/DatasetTree.ts | 10 --- src/Profiles.ts | 39 ++------- src/USSTree.ts | 9 --- src/ZosJobsProvider.ts | 9 --- src/api/IZoweTree.ts | 5 -- src/extension.ts | 180 +++++++++++++++++++---------------------- 6 files changed, 92 insertions(+), 160 deletions(-) diff --git a/src/DatasetTree.ts b/src/DatasetTree.ts index f22051b168..c579a59165 100644 --- a/src/DatasetTree.ts +++ b/src/DatasetTree.ts @@ -261,16 +261,6 @@ export class DatasetTree extends ZoweTreeProvider implements IZoweTree { return temprofile.name; @@ -323,40 +322,16 @@ export class Profiles { } zosmfProfile = allProfiles.filter((temprofile) => temprofile.name === sesName)[0]; - const delProfile = zosmfProfile.profile as ISession; - session = zowe.ZosmfSession.createBasicZosmfSession(delProfile as IProfile); } else { vscode.window.showInformationMessage(localize("deleteProfile.noProfilesLoaded", "No profiles available")); return; } - this.log.debug(localize("deleteProfile.log.debug", "Deleting profile ") + zosmfProfile.name); - const quickPickOptions: vscode.QuickPickOptions = { - placeHolder: localize("deleteProfile.quickPickOption", "Are you sure you want to permanently delete ") + zosmfProfile.name, - ignoreFocusOut: true, - canPickMany: false - }; - // confirm that the user really wants to delete - if (await vscode.window.showQuickPick([localize("deleteProfile.showQuickPick.yes", "Yes"), - localize("deleteProfile.showQuickPick.no", "No")], quickPickOptions) !== localize("deleteProfile.showQuickPick.yes", "Yes")) { - this.log.debug(localize("deleteProfile.showQuickPick.log.debug", "User picked no. Cancelling delete of profile")); - return; - } - - try { - this.deleteProf(zosmfProfile, zosmfProfile.name, zosmfProfile.type); - } catch (error) { - this.log.error(localize("deleteProfile.delete.log.error", "Error encountered when deleting profile! ") + JSON.stringify(error)); - await errorHandling(error, zosmfProfile.name, error.message); - throw error; - } - - vscode.window.showInformationMessage("Profile " + zosmfProfile.name + " was deleted."); - - return zosmfProfile.name; + return zosmfProfile; } - public async deleteProfile(node: IZoweNodeType) { - const profileName = node.getProfileName(); + + public async deleteProfile(deletedProfile: IProfileLoaded) { + const profileName = deletedProfile.name; this.log.debug(localize("deleteProfile.log.debug", "Deleting profile ") + profileName); const quickPickOptions: vscode.QuickPickOptions = { placeHolder: localize("deleteProfile.quickPickOption", "Are you sure you want to permanently delete ") + profileName, @@ -370,10 +345,9 @@ export class Profiles { return; } - const profile = node.getProfile(); - const profileType = ZoweExplorerApiRegister.getMvsApi(profile).getProfileTypeName(); + const profileType = ZoweExplorerApiRegister.getMvsApi(deletedProfile).getProfileTypeName(); try { - this.deleteProf(profile, profileName, profileType); + this.deleteProf(deletedProfile, profileName, profileType); } catch (error) { this.log.error(localize("deleteProfile.delete.log.error", "Error encountered when deleting profile! ") + JSON.stringify(error)); await errorHandling(error, profileName, error.message); @@ -381,6 +355,7 @@ export class Profiles { } vscode.window.showInformationMessage("Profile " + profileName + " was deleted."); + return profileName; } public async deleteProf(ProfileInfo, ProfileName, ProfileType) { diff --git a/src/USSTree.ts b/src/USSTree.ts index 7f6521ef07..e093742857 100644 --- a/src/USSTree.ts +++ b/src/USSTree.ts @@ -192,15 +192,6 @@ export class USSTree extends ZoweTreeProvider implements IZoweTree tempNode.label.trim() !== node.label.trim()); this.deleteSessionByLabel(node.getLabel()); } - /** - * Deletes a profile from the zowe folder - * - * @param node - */ - public async deleteProfile(node: IZoweJobTreeNode) { - await Profiles.getInstance().deleteProfile(node); - await this.deleteSession(node); - } /** * Creates a display string to represent a search diff --git a/src/api/IZoweTree.ts b/src/api/IZoweTree.ts index d641e23180..4bb3f17fd6 100644 --- a/src/api/IZoweTree.ts +++ b/src/api/IZoweTree.ts @@ -98,11 +98,6 @@ export interface IZoweTree extends vscode.TreeDataProvider { * @param node: the node to be deleted */ delete(node: IZoweNodeType); - /** - * Deletes a profile - * @param node: the node containing the profile to be deleted - */ - deleteProfile(node: IZoweNodeType); /** * Reveals and selects a node within the tree. * @param treeView: the vscode tree container diff --git a/src/extension.ts b/src/extension.ts index 25c29b3adc..b5c930886f 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -216,9 +216,9 @@ export async function activate(context: vscode.ExtensionContext): Promise pasteDataSet(node, datasetProvider)); vscode.commands.registerCommand("zowe.renameDataSetMember", (node) => datasetProvider.rename(node)); vscode.commands.registerCommand("zowe.hMigrateDataSet", (node) => hMigrateDataSet(node)); - vscode.commands.registerCommand("zowe.deleteProfile", async (node) => deleteProfile(node, datasetProvider, ussFileProvider, jobsProvider)); + vscode.commands.registerCommand("zowe.deleteProfile", async (node) => deleteProfile(datasetProvider, ussFileProvider, jobsProvider, node)); vscode.commands.registerCommand("zowe.cmd.deleteProfile", async () => - deleteProfileCommand(datasetProvider, ussFileProvider, jobsProvider)); + deleteProfile(datasetProvider, ussFileProvider, jobsProvider)); vscode.workspace.onDidChangeConfiguration(async (e) => { datasetProvider.onDidChangeConfiguration(e); }); @@ -272,7 +272,7 @@ export async function activate(context: vscode.ExtensionContext): Promise ussFileProvider.saveSearch(node)); vscode.commands.registerCommand("zowe.uss.removeSavedSearch", async (node: IZoweUSSTreeNode) => ussFileProvider.removeFavorite(node)); vscode.commands.registerCommand("zowe.uss.deleteProfile", async (node) => - deleteProfile(node, datasetProvider, ussFileProvider, jobsProvider)); + deleteProfile(datasetProvider, ussFileProvider, jobsProvider, node)); vscode.workspace.onDidChangeConfiguration(async (e) => { ussFileProvider.onDidChangeConfiguration(e); }); @@ -337,7 +337,7 @@ export async function activate(context: vscode.ExtensionContext): Promise jobsProvider.saveSearch(node)); vscode.commands.registerCommand("zowe.jobs.removeSearchFavorite", async (node) => jobsProvider.removeFavorite(node)); vscode.commands.registerCommand("zowe.jobs.deleteProfile", async (node) => - deleteProfile(node, datasetProvider, ussFileProvider, jobsProvider)); + deleteProfile(datasetProvider, ussFileProvider, jobsProvider, node)); const theTreeView = jobsProvider.getTreeView(); context.subscriptions.push(theTreeView); if (!ISTHEIA) { @@ -1483,20 +1483,22 @@ export function getDocumentFilePath(label: string, node: IZoweTreeNode) { } export async function deleteProfile( - node: IZoweNodeType, datasetTree: IZoweTree, - ussTree: IZoweTree, jobsProvider: IZoweTree) { - await Profiles.getInstance().deleteProfile(node); - - const deleteLabel = node.getProfileName(); + datasetTree: IZoweTree, ussTree: IZoweTree, + jobsProvider: IZoweTree, node?: IZoweNodeType) { + + let deleteLabel: string; + let deletedProfile: IProfileLoaded; + if (!node){ + deletedProfile = await Profiles.getInstance().deleteProfileCommand(); + deleteLabel = deletedProfile.name; + } else { + deletedProfile = node.getProfile(); + deleteLabel = node.getProfileName(); + } + await Profiles.getInstance().deleteProfile(deletedProfile); // Delete from Data Set Tree datasetTree.mSessionNodes.forEach((sessNode) => { - if (sessNode.contextValue === DS_SESSION_CONTEXT) { - utils.labelHack(sessNode); - sessNode.children = []; - sessNode.dirty = true; - utils.refreshTree(sessNode); - } if (sessNode.getProfileName() === deleteLabel) { datasetTree.deleteSession(sessNode); } @@ -1513,12 +1515,6 @@ export async function deleteProfile( // Delete from USS Tree ussTree.mSessionNodes.forEach((sessNode) => { - if (sessNode.contextValue === USS_SESSION_CONTEXT) { - utils.labelHack(sessNode); - sessNode.children = []; - sessNode.dirty = true; - utils.refreshTree(sessNode); - } if (sessNode.getProfileName() === deleteLabel) { ussTree.deleteSession(sessNode); } @@ -1535,12 +1531,6 @@ export async function deleteProfile( // Delete from Jobs Tree jobsProvider.mSessionNodes.forEach((jobNode) => { - if (jobNode.contextValue === JOBS_SESSION_CONTEXT) { - utils.labelHack(jobNode); - jobNode.children = []; - jobNode.dirty = true; - utils.refreshTree(jobNode); - } if (jobNode.getProfileName() === deleteLabel) { jobsProvider.deleteSession(jobNode); } @@ -1556,74 +1546,74 @@ export async function deleteProfile( await jobsProvider.refresh(); } -export async function deleteProfileCommand( - datasetTree: IZoweTree, ussTree: IZoweTree, jobsProvider: IZoweTree) { - const sessionName = await Profiles.getInstance().deleteProfileCommand(); - - const datasetNode = await datasetTree.mSessionNodes.find((tempNode) => tempNode.label.trim() === sessionName); - if (datasetNode) { - datasetTree.deleteSession(datasetNode); - } - datasetTree.mSessionNodes.forEach((sessNode) => { - if (sessNode.contextValue === DS_SESSION_CONTEXT) { - utils.labelHack(sessNode); - sessNode.children = []; - sessNode.dirty = true; - utils.refreshTree(sessNode); - } - }); - - // Delete from Data Set Favorites - datasetTree.mFavorites.forEach((ses) => { - const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); - if (findNode === datasetNode.label) { - datasetTree.removeFavorite(ses); - } - }); - await datasetTree.refresh(); - - const ussNode = await ussTree.mSessionNodes.find((tempNode) => tempNode.label.trim() === sessionName); - if (ussNode) { - ussTree.deleteSession(ussNode); - } - ussTree.mSessionNodes.forEach((sessNode) => { - if (sessNode.contextValue === USS_SESSION_CONTEXT) { - utils.labelHack(sessNode); - sessNode.children = []; - sessNode.dirty = true; - utils.refreshTree(sessNode); - } - }); - // Delete from USS Favorites - ussTree.mFavorites.forEach((ses) => { - const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); - if (findNode === ussNode.getProfileName()) { - ussTree.removeFavorite(ses); - } - }); - await ussTree.refresh(); - - const jobsNode = await jobsProvider.mSessionNodes.find((tempNode) => tempNode.label.trim() === sessionName); - if (jobsNode) { - jobsProvider.deleteSession(jobsNode); - } - jobsProvider.mSessionNodes.forEach((jobNode) => { - if (jobNode.contextValue === JOBS_SESSION_CONTEXT) { - utils.labelHack(jobNode); - jobNode.children = []; - jobNode.dirty = true; - utils.refreshTree(jobNode); - } - }); - // Delete from Jobs Favorites - jobsProvider.mFavorites.forEach((ses) => { - const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); - if (findNode === jobsNode.getProfileName()) { - jobsProvider.removeFavorite(ses); - } - }); - await jobsProvider.refresh(); -} +// export async function deleteProfileCommand( +// datasetTree: IZoweTree, ussTree: IZoweTree, jobsProvider: IZoweTree) { +// const sessionName = await Profiles.getInstance().deleteProfileCommand(); + +// const datasetNode = await datasetTree.mSessionNodes.find((tempNode) => tempNode.label.trim() === sessionName); +// if (datasetNode) { +// datasetTree.deleteSession(datasetNode); +// } +// datasetTree.mSessionNodes.forEach((sessNode) => { +// if (sessNode.contextValue === DS_SESSION_CONTEXT) { +// utils.labelHack(sessNode); +// sessNode.children = []; +// sessNode.dirty = true; +// utils.refreshTree(sessNode); +// } +// }); + +// // Delete from Data Set Favorites +// datasetTree.mFavorites.forEach((ses) => { +// const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); +// if (findNode === datasetNode.label) { +// datasetTree.removeFavorite(ses); +// } +// }); +// await datasetTree.refresh(); + +// const ussNode = await ussTree.mSessionNodes.find((tempNode) => tempNode.label.trim() === sessionName); +// if (ussNode) { +// ussTree.deleteSession(ussNode); +// } +// ussTree.mSessionNodes.forEach((sessNode) => { +// if (sessNode.contextValue === USS_SESSION_CONTEXT) { +// utils.labelHack(sessNode); +// sessNode.children = []; +// sessNode.dirty = true; +// utils.refreshTree(sessNode); +// } +// }); +// // Delete from USS Favorites +// ussTree.mFavorites.forEach((ses) => { +// const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); +// if (findNode === ussNode.getProfileName()) { +// ussTree.removeFavorite(ses); +// } +// }); +// await ussTree.refresh(); + +// const jobsNode = await jobsProvider.mSessionNodes.find((tempNode) => tempNode.label.trim() === sessionName); +// if (jobsNode) { +// jobsProvider.deleteSession(jobsNode); +// } +// jobsProvider.mSessionNodes.forEach((jobNode) => { +// if (jobNode.contextValue === JOBS_SESSION_CONTEXT) { +// utils.labelHack(jobNode); +// jobNode.children = []; +// jobNode.dirty = true; +// utils.refreshTree(jobNode); +// } +// }); +// // Delete from Jobs Favorites +// jobsProvider.mFavorites.forEach((ses) => { +// const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); +// if (findNode === jobsNode.getProfileName()) { +// jobsProvider.removeFavorite(ses); +// } +// }); +// await jobsProvider.refresh(); +// } export async function openRecentMemberPrompt(datasetTree: IZoweTree, ussTree: IZoweTree) { if (log) { From 1e8a381bb876d2c94be1f7245354d1094f5909e9 Mon Sep 17 00:00:00 2001 From: Richelle Anne Craw Date: Wed, 15 Apr 2020 20:23:53 +0200 Subject: [PATCH 05/16] Move to Profiles file Signed-off-by: Richelle Anne Craw --- src/Profiles.ts | 73 ++++++++++++++++++++++-- src/extension.ts | 142 ++--------------------------------------------- 2 files changed, 74 insertions(+), 141 deletions(-) diff --git a/src/Profiles.ts b/src/Profiles.ts index e618fa7265..00a40ac5a5 100644 --- a/src/Profiles.ts +++ b/src/Profiles.ts @@ -9,7 +9,7 @@ * * */ -import { IProfileLoaded, Logger, CliProfileManager, IProfile, ISession, Session, IUpdateProfile } from "@zowe/imperative"; +import { IProfileLoaded, Logger, CliProfileManager, IProfile, ISession, IUpdateProfile } from "@zowe/imperative"; import * as nls from "vscode-nls"; import * as path from "path"; import { URL } from "url"; @@ -17,8 +17,9 @@ import * as vscode from "vscode"; import * as zowe from "@zowe/cli"; import { ZoweExplorerApiRegister } from "./api/ZoweExplorerApiRegister"; import { getZoweDir } from "./extension"; // TODO: resolve cyclic dependency -import { IZoweNodeType } from "./api/IZoweTreeNode"; import { errorHandling } from "./utils"; +import { IZoweTree } from "./api/IZoweTree"; +import { IZoweNodeType, IZoweUSSTreeNode, IZoweDatasetTreeNode, IZoweJobTreeNode } from "./api/IZoweTreeNode"; const localize = nls.config({ messageFormat: nls.MessageFormat.file })(); interface IUrlValidator { @@ -301,7 +302,7 @@ export class Profiles { return [updSession.ISession.user, updSession.ISession.password, updSession.ISession.base64EncodedAuth]; } - public async deleteProfileCommand() { + public async getDeleteProfile() { let zosmfProfile: IProfileLoaded; const allProfiles: IProfileLoaded[] = this.allProfiles; const profileNamesList = allProfiles.map((temprofile) => { @@ -330,7 +331,7 @@ export class Profiles { return zosmfProfile; } - public async deleteProfile(deletedProfile: IProfileLoaded) { + public async deletePrompt(deletedProfile: IProfileLoaded) { const profileName = deletedProfile.name; this.log.debug(localize("deleteProfile.log.debug", "Deleting profile ") + profileName); const quickPickOptions: vscode.QuickPickOptions = { @@ -369,6 +370,70 @@ export class Profiles { return zosmfProfile.profile; } + public async deleteProfile( + datasetTree: IZoweTree, ussTree: IZoweTree, + jobsProvider: IZoweTree, node?: IZoweNodeType) { + + let deleteLabel: string; + let deletedProfile: IProfileLoaded; + if (!node){ + deletedProfile = await this.getDeleteProfile(); + deleteLabel = deletedProfile.name; + } else { + deletedProfile = node.getProfile(); + deleteLabel = node.getProfileName(); + } + await this.deletePrompt(deletedProfile); + + // Delete from Data Set Tree + datasetTree.mSessionNodes.forEach((sessNode) => { + if (sessNode.getProfileName() === deleteLabel) { + datasetTree.deleteSession(sessNode); + } + }); + + // Delete from Data Set Favorites + datasetTree.mFavorites.forEach((ses) => { + const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); + if (findNode === deleteLabel) { + datasetTree.removeFavorite(ses); + } + }); + await datasetTree.refresh(); + + // Delete from USS Tree + ussTree.mSessionNodes.forEach((sessNode) => { + if (sessNode.getProfileName() === deleteLabel) { + ussTree.deleteSession(sessNode); + } + }); + + // Delete from USS Favorites + ussTree.mFavorites.forEach((ses) => { + const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); + if (findNode === deleteLabel) { + ussTree.removeFavorite(ses); + } + }); + await ussTree.refresh(); + + // Delete from Jobs Tree + jobsProvider.mSessionNodes.forEach((jobNode) => { + if (jobNode.getProfileName() === deleteLabel) { + jobsProvider.deleteSession(jobNode); + } + }); + + // Delete from Jobs Favorites + jobsProvider.mFavorites.forEach((ses) => { + const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); + if (findNode === deleteLabel) { + jobsProvider.removeFavorite(ses); + } + }); + await jobsProvider.refresh(); + } + private async updateProfile(ProfileInfo) { diff --git a/src/extension.ts b/src/extension.ts index b5c930886f..a7540b8715 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -216,9 +216,10 @@ export async function activate(context: vscode.ExtensionContext): Promise pasteDataSet(node, datasetProvider)); vscode.commands.registerCommand("zowe.renameDataSetMember", (node) => datasetProvider.rename(node)); vscode.commands.registerCommand("zowe.hMigrateDataSet", (node) => hMigrateDataSet(node)); - vscode.commands.registerCommand("zowe.deleteProfile", async (node) => deleteProfile(datasetProvider, ussFileProvider, jobsProvider, node)); + vscode.commands.registerCommand("zowe.deleteProfile", async (node) => + Profiles.getInstance().deleteProfile(datasetProvider, ussFileProvider, jobsProvider, node)); vscode.commands.registerCommand("zowe.cmd.deleteProfile", async () => - deleteProfile(datasetProvider, ussFileProvider, jobsProvider)); + Profiles.getInstance().deleteProfile(datasetProvider, ussFileProvider, jobsProvider)); vscode.workspace.onDidChangeConfiguration(async (e) => { datasetProvider.onDidChangeConfiguration(e); }); @@ -272,7 +273,7 @@ export async function activate(context: vscode.ExtensionContext): Promise ussFileProvider.saveSearch(node)); vscode.commands.registerCommand("zowe.uss.removeSavedSearch", async (node: IZoweUSSTreeNode) => ussFileProvider.removeFavorite(node)); vscode.commands.registerCommand("zowe.uss.deleteProfile", async (node) => - deleteProfile(datasetProvider, ussFileProvider, jobsProvider, node)); + Profiles.getInstance().deleteProfile(datasetProvider, ussFileProvider, jobsProvider, node)); vscode.workspace.onDidChangeConfiguration(async (e) => { ussFileProvider.onDidChangeConfiguration(e); }); @@ -337,7 +338,7 @@ export async function activate(context: vscode.ExtensionContext): Promise jobsProvider.saveSearch(node)); vscode.commands.registerCommand("zowe.jobs.removeSearchFavorite", async (node) => jobsProvider.removeFavorite(node)); vscode.commands.registerCommand("zowe.jobs.deleteProfile", async (node) => - deleteProfile(datasetProvider, ussFileProvider, jobsProvider, node)); + Profiles.getInstance().deleteProfile(datasetProvider, ussFileProvider, jobsProvider, node)); const theTreeView = jobsProvider.getTreeView(); context.subscriptions.push(theTreeView); if (!ISTHEIA) { @@ -1482,139 +1483,6 @@ export function getDocumentFilePath(label: string, node: IZoweTreeNode) { return path.join(DS_DIR, "/" + getProfile(node) + "/" + appendSuffix(label) ); } -export async function deleteProfile( - datasetTree: IZoweTree, ussTree: IZoweTree, - jobsProvider: IZoweTree, node?: IZoweNodeType) { - - let deleteLabel: string; - let deletedProfile: IProfileLoaded; - if (!node){ - deletedProfile = await Profiles.getInstance().deleteProfileCommand(); - deleteLabel = deletedProfile.name; - } else { - deletedProfile = node.getProfile(); - deleteLabel = node.getProfileName(); - } - await Profiles.getInstance().deleteProfile(deletedProfile); - - // Delete from Data Set Tree - datasetTree.mSessionNodes.forEach((sessNode) => { - if (sessNode.getProfileName() === deleteLabel) { - datasetTree.deleteSession(sessNode); - } - }); - - // Delete from Data Set Favorites - datasetTree.mFavorites.forEach((ses) => { - const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); - if (findNode === deleteLabel) { - datasetTree.removeFavorite(ses); - } - }); - await datasetTree.refresh(); - - // Delete from USS Tree - ussTree.mSessionNodes.forEach((sessNode) => { - if (sessNode.getProfileName() === deleteLabel) { - ussTree.deleteSession(sessNode); - } - }); - - // Delete from USS Favorites - ussTree.mFavorites.forEach((ses) => { - const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); - if (findNode === deleteLabel) { - ussTree.removeFavorite(ses); - } - }); - await ussTree.refresh(); - - // Delete from Jobs Tree - jobsProvider.mSessionNodes.forEach((jobNode) => { - if (jobNode.getProfileName() === deleteLabel) { - jobsProvider.deleteSession(jobNode); - } - }); - - // Delete from Jobs Favorites - jobsProvider.mFavorites.forEach((ses) => { - const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); - if (findNode === deleteLabel) { - jobsProvider.removeFavorite(ses); - } - }); - await jobsProvider.refresh(); -} - -// export async function deleteProfileCommand( -// datasetTree: IZoweTree, ussTree: IZoweTree, jobsProvider: IZoweTree) { -// const sessionName = await Profiles.getInstance().deleteProfileCommand(); - -// const datasetNode = await datasetTree.mSessionNodes.find((tempNode) => tempNode.label.trim() === sessionName); -// if (datasetNode) { -// datasetTree.deleteSession(datasetNode); -// } -// datasetTree.mSessionNodes.forEach((sessNode) => { -// if (sessNode.contextValue === DS_SESSION_CONTEXT) { -// utils.labelHack(sessNode); -// sessNode.children = []; -// sessNode.dirty = true; -// utils.refreshTree(sessNode); -// } -// }); - -// // Delete from Data Set Favorites -// datasetTree.mFavorites.forEach((ses) => { -// const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); -// if (findNode === datasetNode.label) { -// datasetTree.removeFavorite(ses); -// } -// }); -// await datasetTree.refresh(); - -// const ussNode = await ussTree.mSessionNodes.find((tempNode) => tempNode.label.trim() === sessionName); -// if (ussNode) { -// ussTree.deleteSession(ussNode); -// } -// ussTree.mSessionNodes.forEach((sessNode) => { -// if (sessNode.contextValue === USS_SESSION_CONTEXT) { -// utils.labelHack(sessNode); -// sessNode.children = []; -// sessNode.dirty = true; -// utils.refreshTree(sessNode); -// } -// }); -// // Delete from USS Favorites -// ussTree.mFavorites.forEach((ses) => { -// const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); -// if (findNode === ussNode.getProfileName()) { -// ussTree.removeFavorite(ses); -// } -// }); -// await ussTree.refresh(); - -// const jobsNode = await jobsProvider.mSessionNodes.find((tempNode) => tempNode.label.trim() === sessionName); -// if (jobsNode) { -// jobsProvider.deleteSession(jobsNode); -// } -// jobsProvider.mSessionNodes.forEach((jobNode) => { -// if (jobNode.contextValue === JOBS_SESSION_CONTEXT) { -// utils.labelHack(jobNode); -// jobNode.children = []; -// jobNode.dirty = true; -// utils.refreshTree(jobNode); -// } -// }); -// // Delete from Jobs Favorites -// jobsProvider.mFavorites.forEach((ses) => { -// const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); -// if (findNode === jobsNode.getProfileName()) { -// jobsProvider.removeFavorite(ses); -// } -// }); -// await jobsProvider.refresh(); -// } - export async function openRecentMemberPrompt(datasetTree: IZoweTree, ussTree: IZoweTree) { if (log) { log.debug(localize("enterPattern.log.debug.prompt", "Prompting the user to choose a recent member for editing")); From f6fcc7e5b7fb8acf86fbf3f3c5ee4087fdaa97c1 Mon Sep 17 00:00:00 2001 From: jellypuno Date: Wed, 15 Apr 2020 21:26:22 +0200 Subject: [PATCH 06/16] fix existing unit test Signed-off-by: jellypuno --- .../__snapshots__/extension.unit.test.ts.snap | 18 ++++++++++++++++++ __tests__/__unit__/extension.unit.test.ts | 6 +++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/__tests__/__unit__/__snapshots__/extension.unit.test.ts.snap b/__tests__/__unit__/__snapshots__/extension.unit.test.ts.snap index e601545fdd..d05efffa3a 100644 --- a/__tests__/__unit__/__snapshots__/extension.unit.test.ts.snap +++ b/__tests__/__unit__/__snapshots__/extension.unit.test.ts.snap @@ -387,8 +387,14 @@ Array [ "group": "inline", "when": "view == zowe.explorer && viewItem == session", }, + Object { + "command": "zowe.deleteProfile", + "group": "6_modification@4", + "when": "view == zowe.explorer && viewItem == session", + }, Object { "command": "zowe.removeSession", + "group": "6_modification@3", "when": "view == zowe.explorer && viewItem == session", }, Object { @@ -415,8 +421,14 @@ Array [ "group": "inline", "when": "viewItem == uss_session", }, + Object { + "command": "zowe.uss.deleteProfile", + "group": "6_modification@4", + "when": "viewItem == uss_session", + }, Object { "command": "zowe.uss.removeSession", + "group": "6_modification@3", "when": "viewItem == uss_session", }, Object { @@ -439,6 +451,11 @@ Array [ "group": "inline", "when": "view == zowe.jobs && viewItem == server", }, + Object { + "command": "zowe.jobs.deleteProfile", + "group": "6_modification@4", + "when": "view == zowe.jobs && viewItem == server", + }, Object { "command": "zowe.setOwner", "when": "view == zowe.jobs && viewItem == server", @@ -449,6 +466,7 @@ Array [ }, Object { "command": "zowe.removeJobsSession", + "group": "6_modification@3", "when": "view == zowe.jobs && viewItem == server", }, Object { diff --git a/__tests__/__unit__/extension.unit.test.ts b/__tests__/__unit__/extension.unit.test.ts index ea43ec3c63..f61cee08d0 100644 --- a/__tests__/__unit__/extension.unit.test.ts +++ b/__tests__/__unit__/extension.unit.test.ts @@ -664,7 +664,7 @@ describe("Extension Unit Tests", () => { expect(createTreeView.mock.calls[0][0]).toBe("zowe.explorer"); expect(createTreeView.mock.calls[1][0]).toBe("zowe.uss.explorer"); // tslint:disable-next-line: no-magic-numbers - expect(registerCommand.mock.calls.length).toBe(68); + expect(registerCommand.mock.calls.length).toBe(72); registerCommand.mock.calls.forEach((call, i ) => { expect(registerCommand.mock.calls[i][1]).toBeInstanceOf(Function); }); @@ -698,6 +698,8 @@ describe("Extension Unit Tests", () => { "zowe.pasteDataSet", "zowe.renameDataSetMember", "zowe.hMigrateDataSet", + "zowe.deleteProfile", + "zowe.cmd.deleteProfile", "zowe.uss.addFavorite", "zowe.uss.removeFavorite", "zowe.uss.addSession", @@ -719,6 +721,7 @@ describe("Extension Unit Tests", () => { "zowe.uss.editFile", "zowe.uss.saveSearch", "zowe.uss.removeSavedSearch", + "zowe.uss.deleteProfile", "zowe.zosJobsOpenspool", "zowe.deleteJob", "zowe.runModifyCommand", @@ -739,6 +742,7 @@ describe("Extension Unit Tests", () => { "zowe.jobs.removeFavorite", "zowe.jobs.saveSearch", "zowe.jobs.removeSearchFavorite", + "zowe.jobs.deleteProfile", "zowe.openRecentMember", "zowe.searchInAllLoadedItems", ]; From d9f6452c3ffd071eb563058f6865dc38787443ee Mon Sep 17 00:00:00 2001 From: Richelle Anne Craw Date: Wed, 15 Apr 2020 21:56:14 +0200 Subject: [PATCH 07/16] Refresh list of profiles Signed-off-by: Richelle Anne Craw --- src/Profiles.ts | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Profiles.ts b/src/Profiles.ts index 00a40ac5a5..598825134c 100644 --- a/src/Profiles.ts +++ b/src/Profiles.ts @@ -320,9 +320,9 @@ export class Profiles { vscode.window.showInformationMessage(localize("deleteProfile.undefined.profilename", "Operation Cancelled")); return; + } else { + zosmfProfile = allProfiles.filter((temprofile) => temprofile.name === sesName)[0]; } - - zosmfProfile = allProfiles.filter((temprofile) => temprofile.name === sesName)[0]; } else { vscode.window.showInformationMessage(localize("deleteProfile.noProfilesLoaded", "No profiles available")); return; @@ -378,12 +378,19 @@ export class Profiles { let deletedProfile: IProfileLoaded; if (!node){ deletedProfile = await this.getDeleteProfile(); - deleteLabel = deletedProfile.name; + if (!deletedProfile) { + return; + } else { + deleteLabel = deletedProfile.name; + } } else { deletedProfile = node.getProfile(); deleteLabel = node.getProfileName(); } - await this.deletePrompt(deletedProfile); + const deleteSuccess = await this.deletePrompt(deletedProfile); + if (!deleteSuccess){ + return; + } // Delete from Data Set Tree datasetTree.mSessionNodes.forEach((sessNode) => { @@ -432,6 +439,12 @@ export class Profiles { } }); await jobsProvider.refresh(); + + // Remove from list of all profiles + const index = this.allProfiles.findIndex((deleteItem) => { + return deleteItem === deletedProfile; + }); + if (index >= 0) { this.allProfiles.splice(index, 1); } } From c5603416d7d6a026c14207cc2c8975dbb77d18b6 Mon Sep 17 00:00:00 2001 From: jellypuno Date: Wed, 15 Apr 2020 22:49:33 +0200 Subject: [PATCH 08/16] Add Unit Test Signed-off-by: jellypuno --- __mocks__/@zowe/imperative.ts | 3 ++ __tests__/__unit__/Profiles.unit.test.ts | 50 +++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/__mocks__/@zowe/imperative.ts b/__mocks__/@zowe/imperative.ts index ecf90910ea..7b41627416 100644 --- a/__mocks__/@zowe/imperative.ts +++ b/__mocks__/@zowe/imperative.ts @@ -68,6 +68,9 @@ export class CliProfileManager { public getAllProfileNames(){ return ["name1", "name2"]; } + public delete(){ + return { name: "profile1", profile: {}, type: "zosmf" }; + } } // tslint:disable-next-line:max-classes-per-file diff --git a/__tests__/__unit__/Profiles.unit.test.ts b/__tests__/__unit__/Profiles.unit.test.ts index e9b4a0586d..97e072d700 100644 --- a/__tests__/__unit__/Profiles.unit.test.ts +++ b/__tests__/__unit__/Profiles.unit.test.ts @@ -15,9 +15,17 @@ import * as path from "path"; import * as os from "os"; import * as vscode from "vscode"; import * as child_process from "child_process"; -import { Logger, ISession, CliProfileManager } from "@zowe/imperative"; +import { Logger, ISession, CliProfileManager, IProfileLoaded, Session } from "@zowe/imperative"; import { Profiles } from "../../src/Profiles"; import { ZosmfSession } from "@zowe/cli"; +import { ZoweUSSNode } from "../../src/ZoweUSSNode"; +import { ZoweDatasetNode } from "../../src/ZoweDatasetNode"; +import { Job } from "../../src/ZoweJobNode"; +import { IZoweDatasetTreeNode, IZoweUSSTreeNode, IZoweJobTreeNode, IZoweNodeType } from "../../src/api/IZoweTreeNode"; +import { IZoweTree } from "../../src/api/IZoweTree"; +import { DatasetTree } from "../../src/DatasetTree"; +import { USSTree } from "../../src/USSTree"; +import { ZosJobsProvider } from "../../src/ZosJobsProvider"; describe("Profile class unit tests", () => { // Mocking log.debug @@ -25,6 +33,25 @@ describe("Profile class unit tests", () => { const profileOne = { name: "profile1", profile: {}, type: "zosmf" }; const profileTwo = { name: "profile2", profile: {}, type: "zosmf" }; + const profileThree: IProfileLoaded = { + name: "sestest", + profile: { + user: undefined, + password: undefined + }, + type: "zosmf", + message: "", + failNotFound: false + }; + + const session = new Session({ + user: "fake", + password: "fake", + hostname: "fake", + protocol: "https", + type: "basic", + }); + const inputBox: vscode.InputBox = { value: "input", title: null, @@ -54,12 +81,18 @@ describe("Profile class unit tests", () => { const createInputBox = jest.fn(); const showQuickPick = jest.fn(); const showErrorMessage = jest.fn(); + const createTreeView = jest.fn(); Object.defineProperty(vscode.window, "showInformationMessage", { value: showInformationMessage }); Object.defineProperty(vscode.window, "showErrorMessage", { value: showErrorMessage }); Object.defineProperty(vscode.window, "showInputBox", { value: showInputBox }); Object.defineProperty(vscode.window, "createInputBox", { value: createInputBox }); Object.defineProperty(vscode.window, "showQuickPick", { value: showQuickPick }); + Object.defineProperty(vscode.window, "createTreeView", { value: createTreeView }); + + const sessNode: IZoweTree = new DatasetTree(); + const ussNode: IZoweTree = new USSTree(); + const jobNode: IZoweTree = new ZosJobsProvider(); beforeEach(() => { mockJSONParse.mockReturnValue({ @@ -135,6 +168,12 @@ describe("Profile class unit tests", () => { updateProfile: jest.fn(()=>{ return {}; }), + getDeleteProfile: jest.fn(()=>{ + return {}; + }), + deletePrompt: jest.fn(()=>{ + return {}; + }) }; }) }); @@ -265,6 +304,15 @@ describe("Profile class unit tests", () => { expect(showInformationMessage.mock.calls[0][0]).toBe("Profile fake2 was created."); }); + it("should delete profile", async () => { + showQuickPick.mockReset(); + showQuickPick.mockResolvedValueOnce("profile1"); + showQuickPick.mockResolvedValueOnce("Yes"); + await profiles.deleteProfile(sessNode, jobNode, ussNode); + expect(showInformationMessage.mock.calls.length).toBe(1); + expect(showInformationMessage.mock.calls[0][0]).toBe("Profile profile1 was deleted."); + }); + it("should prompt credentials", async () => { const promptProfile = {name: "profile1", profile: {user: undefined, password: undefined}}; profiles.loadNamedProfile = jest.fn(() => { From 6634e3213bebc7ddf6989fd68274d0973e336419 Mon Sep 17 00:00:00 2001 From: Richelle Anne Craw Date: Thu, 16 Apr 2020 14:54:15 +0200 Subject: [PATCH 09/16] Add more unit tests Signed-off-by: Richelle Anne Craw --- __tests__/__unit__/Profiles.unit.test.ts | 103 +++++++++++++++++++---- i18n/sample/src/Profiles.i18n.json | 3 +- src/Profiles.ts | 2 + 3 files changed, 92 insertions(+), 16 deletions(-) diff --git a/__tests__/__unit__/Profiles.unit.test.ts b/__tests__/__unit__/Profiles.unit.test.ts index 97e072d700..39eb2ca1c7 100644 --- a/__tests__/__unit__/Profiles.unit.test.ts +++ b/__tests__/__unit__/Profiles.unit.test.ts @@ -168,12 +168,6 @@ describe("Profile class unit tests", () => { updateProfile: jest.fn(()=>{ return {}; }), - getDeleteProfile: jest.fn(()=>{ - return {}; - }), - deletePrompt: jest.fn(()=>{ - return {}; - }) }; }) }); @@ -304,15 +298,6 @@ describe("Profile class unit tests", () => { expect(showInformationMessage.mock.calls[0][0]).toBe("Profile fake2 was created."); }); - it("should delete profile", async () => { - showQuickPick.mockReset(); - showQuickPick.mockResolvedValueOnce("profile1"); - showQuickPick.mockResolvedValueOnce("Yes"); - await profiles.deleteProfile(sessNode, jobNode, ussNode); - expect(showInformationMessage.mock.calls.length).toBe(1); - expect(showInformationMessage.mock.calls[0][0]).toBe("Profile profile1 was deleted."); - }); - it("should prompt credentials", async () => { const promptProfile = {name: "profile1", profile: {user: undefined, password: undefined}}; profiles.loadNamedProfile = jest.fn(() => { @@ -435,6 +420,94 @@ describe("Profile class unit tests", () => { }); + describe("Deleting Profiles", () => { + let profiles: Profiles; + beforeEach(async () => { + profiles = await Profiles.createInstance(log); + Object.defineProperty(Profiles, "getInstance", { + value: jest.fn(() => { + return { + allProfiles: [{name: "profile1"}, {name: "profile2"}], + defaultProfile: {name: "profile1"}, + loadNamedProfile: [{name: "profile1"}, {profile: {user: "fake", password: "1234"}}], + promptCredentials: jest.fn(()=> { + return {}; + }), + createNewConnection: jest.fn(()=>{ + return {}; + }), + listProfile: jest.fn(()=>{ + return {}; + }), + saveProfile: jest.fn(()=>{ + return {profile: {}}; + }), + validateAndParseUrl: jest.fn(()=>{ + return {}; + }), + updateProfile: jest.fn(()=>{ + return {}; + }), + getDeleteProfile: jest.fn(()=>{ + return {}; + }), + deletePrompt: jest.fn(()=>{ + return {}; + }), + deleteProf: jest.fn(()=>{ + return {}; + }) + }; + }) + }); + }); + + afterEach(() => { + showInputBox.mockReset(); + showQuickPick.mockReset(); + createInputBox.mockReset(); + showInformationMessage.mockReset(); + showErrorMessage.mockReset(); + }); + + it("should delete profile from command palette", async () => { + showQuickPick.mockResolvedValueOnce("profile1"); + showQuickPick.mockResolvedValueOnce("Yes"); + await profiles.deleteProfile(sessNode, jobNode, ussNode); + expect(showInformationMessage.mock.calls.length).toBe(1); + expect(showInformationMessage.mock.calls[0][0]).toBe("Profile profile1 was deleted."); + }); + + it("should handle missing selection: profile name", async () => { + showQuickPick.mockResolvedValueOnce(undefined); + await profiles.deleteProfile(sessNode, jobNode, ussNode); + expect(showInformationMessage.mock.calls.length).toBe(1); + expect(showInformationMessage.mock.calls[0][0]).toBe("Operation Cancelled"); + }); + + it("should handle case where user selects No", async () => { + showQuickPick.mockResolvedValueOnce("profile1"); + showQuickPick.mockResolvedValueOnce("No"); + await profiles.deleteProfile(sessNode, jobNode, ussNode); + expect(showInformationMessage.mock.calls.length).toBe(1); + expect(showInformationMessage.mock.calls[0][0]).toBe("Operation Cancelled"); + }); + + it("should handle case where there are no profiles to delete", async () => { + Object.defineProperty(Profiles, "getInstance", { + value: jest.fn(() => { + return { + allProfiles: [] + }; + }) + }); + profiles.refresh(); + await profiles.deleteProfile(sessNode, jobNode, ussNode); + expect(showInformationMessage.mock.calls.length).toBe(1); + expect(showInformationMessage.mock.calls[0][0]).toBe("No profiles available"); + }); + }); + it("should route through to spawn. Covers conditional test", async () => { Object.defineProperty(Profiles, "getInstance", { value: jest.fn(() => { diff --git a/i18n/sample/src/Profiles.i18n.json b/i18n/sample/src/Profiles.i18n.json index 403b6a5f12..ed181111ba 100644 --- a/i18n/sample/src/Profiles.i18n.json +++ b/i18n/sample/src/Profiles.i18n.json @@ -27,5 +27,6 @@ "deleteProfile.showQuickPick.yes": "Yes", "deleteProfile.showQuickPick.no": "No", "deleteProfile.showQuickPick.log.debug": "User picked no. Cancelling delete of profile", - "deleteProfile.delete.log.error": "Error encountered when deleting profile! " + "deleteProfile.delete.log.error": "Error encountered when deleting profile! ", + "deleteProfile.noSelected": "Operation Cancelled" } \ No newline at end of file diff --git a/src/Profiles.ts b/src/Profiles.ts index 598825134c..a3970723ff 100644 --- a/src/Profiles.ts +++ b/src/Profiles.ts @@ -389,6 +389,8 @@ export class Profiles { } const deleteSuccess = await this.deletePrompt(deletedProfile); if (!deleteSuccess){ + vscode.window.showInformationMessage(localize("deleteProfile.noSelected", + "Operation Cancelled")); return; } From cf875f037409edf94819943eeebd73540e7980ad Mon Sep 17 00:00:00 2001 From: Richelle Anne Craw Date: Thu, 16 Apr 2020 20:28:12 +0200 Subject: [PATCH 10/16] Add tests for Favorites Signed-off-by: Richelle Anne Craw --- __tests__/__unit__/Profiles.unit.test.ts | 105 ++++++++++++++++++++--- 1 file changed, 94 insertions(+), 11 deletions(-) diff --git a/__tests__/__unit__/Profiles.unit.test.ts b/__tests__/__unit__/Profiles.unit.test.ts index 39eb2ca1c7..45d4236f90 100644 --- a/__tests__/__unit__/Profiles.unit.test.ts +++ b/__tests__/__unit__/Profiles.unit.test.ts @@ -15,9 +15,10 @@ import * as path from "path"; import * as os from "os"; import * as vscode from "vscode"; import * as child_process from "child_process"; +import * as extension from "../../src/extension"; import { Logger, ISession, CliProfileManager, IProfileLoaded, Session } from "@zowe/imperative"; import { Profiles } from "../../src/Profiles"; -import { ZosmfSession } from "@zowe/cli"; +import { ZosmfSession, IJob } from "@zowe/cli"; import { ZoweUSSNode } from "../../src/ZoweUSSNode"; import { ZoweDatasetNode } from "../../src/ZoweDatasetNode"; import { Job } from "../../src/ZoweJobNode"; @@ -33,8 +34,9 @@ describe("Profile class unit tests", () => { const profileOne = { name: "profile1", profile: {}, type: "zosmf" }; const profileTwo = { name: "profile2", profile: {}, type: "zosmf" }; + const mockLoadNamedProfile = jest.fn(); const profileThree: IProfileLoaded = { - name: "sestest", + name: "profile3", profile: { user: undefined, password: undefined @@ -43,6 +45,7 @@ describe("Profile class unit tests", () => { message: "", failNotFound: false }; + mockLoadNamedProfile.mockReturnValue(profileThree); const session = new Session({ user: "fake", @@ -52,6 +55,32 @@ describe("Profile class unit tests", () => { type: "basic", }); + const iJob: IJob = { + "jobid": "JOB1234", + "jobname": "TESTJOB", + "files-url": "fake/files", + "job-correlator": "correlator", + "phase-name": "PHASE", + "reason-not-running": "", + "step-data": [{ + "proc-step-name": "", + "program-name": "", + "step-name": "", + "step-number": 1, + "active": "", + "smfid": "" + + }], + "class": "A", + "owner": "USER", + "phase": 0, + "retcode": "", + "status": "ACTIVE", + "subsystem": "SYS", + "type": "JOB", + "url": "fake/url" + }; + const inputBox: vscode.InputBox = { value: "input", title: null, @@ -90,9 +119,9 @@ describe("Profile class unit tests", () => { Object.defineProperty(vscode.window, "showQuickPick", { value: showQuickPick }); Object.defineProperty(vscode.window, "createTreeView", { value: createTreeView }); - const sessNode: IZoweTree = new DatasetTree(); - const ussNode: IZoweTree = new USSTree(); - const jobNode: IZoweTree = new ZosJobsProvider(); + const sessTree: IZoweTree = new DatasetTree(); + const ussTree: IZoweTree = new USSTree(); + const jobsTree: IZoweTree = new ZosJobsProvider(); beforeEach(() => { mockJSONParse.mockReturnValue({ @@ -427,9 +456,9 @@ describe("Profile class unit tests", () => { Object.defineProperty(Profiles, "getInstance", { value: jest.fn(() => { return { - allProfiles: [{name: "profile1"}, {name: "profile2"}], + allProfiles: [{name: "profile1"}, {name: "profile2"}, {name: "profile3"}], defaultProfile: {name: "profile1"}, - loadNamedProfile: [{name: "profile1"}, {profile: {user: "fake", password: "1234"}}], + loadNamedProfile: mockLoadNamedProfile, promptCredentials: jest.fn(()=> { return {}; }), @@ -473,14 +502,14 @@ describe("Profile class unit tests", () => { it("should delete profile from command palette", async () => { showQuickPick.mockResolvedValueOnce("profile1"); showQuickPick.mockResolvedValueOnce("Yes"); - await profiles.deleteProfile(sessNode, jobNode, ussNode); + await profiles.deleteProfile(sessTree, ussTree, jobsTree); expect(showInformationMessage.mock.calls.length).toBe(1); expect(showInformationMessage.mock.calls[0][0]).toBe("Profile profile1 was deleted."); }); it("should handle missing selection: profile name", async () => { showQuickPick.mockResolvedValueOnce(undefined); - await profiles.deleteProfile(sessNode, jobNode, ussNode); + await profiles.deleteProfile(sessTree, ussTree, jobsTree); expect(showInformationMessage.mock.calls.length).toBe(1); expect(showInformationMessage.mock.calls[0][0]).toBe("Operation Cancelled"); }); @@ -488,7 +517,7 @@ describe("Profile class unit tests", () => { it("should handle case where user selects No", async () => { showQuickPick.mockResolvedValueOnce("profile1"); showQuickPick.mockResolvedValueOnce("No"); - await profiles.deleteProfile(sessNode, jobNode, ussNode); + await profiles.deleteProfile(sessTree, ussTree, jobsTree); expect(showInformationMessage.mock.calls.length).toBe(1); expect(showInformationMessage.mock.calls[0][0]).toBe("Operation Cancelled"); }); @@ -502,10 +531,64 @@ describe("Profile class unit tests", () => { }) }); profiles.refresh(); - await profiles.deleteProfile(sessNode, jobNode, ussNode); + await profiles.deleteProfile(sessTree, ussTree, jobsTree); expect(showInformationMessage.mock.calls.length).toBe(1); expect(showInformationMessage.mock.calls[0][0]).toBe("No profiles available"); }); + + it("should delete profile from context menu", async () => { + const dsNode = new ZoweDatasetNode("profile3", vscode.TreeItemCollapsibleState.Expanded, null, session, undefined, undefined, profileThree); + dsNode.contextValue = extension.DS_SESSION_CONTEXT; + showQuickPick.mockResolvedValueOnce("Yes"); + await profiles.deleteProfile(sessTree, ussTree, jobsTree, dsNode); + expect(showInformationMessage.mock.calls.length).toBe(1); + expect(showInformationMessage.mock.calls[0][0]).toBe("Profile profile3 was deleted."); + }); + + it("should delete session from Data Set tree", async () => { + const startLength = sessTree.mSessionNodes.length; + const favoriteLength = sessTree.mFavorites.length; + const dsNode = new ZoweDatasetNode("profile3", vscode.TreeItemCollapsibleState.Expanded, null, session, undefined, undefined, profileThree); + dsNode.contextValue = extension.DS_SESSION_CONTEXT; + sessTree.mSessionNodes.push(dsNode); + sessTree.addFavorite(dsNode); + showQuickPick.mockResolvedValueOnce("Yes"); + await profiles.deleteProfile(sessTree, ussTree, jobsTree, dsNode); + expect(showInformationMessage.mock.calls.length).toBe(1); + expect(showInformationMessage.mock.calls[0][0]).toBe("Profile profile3 was deleted."); + expect(sessTree.mSessionNodes.length).toEqual(startLength); + expect(sessTree.mFavorites.length).toEqual(favoriteLength); + }); + + it("should delete session from USS tree", async () => { + const startLength = ussTree.mSessionNodes.length; + const favoriteLength = ussTree.mFavorites.length; + const ussNode = new ZoweUSSNode("profile3", vscode.TreeItemCollapsibleState.Expanded, null, session, null, false, profileThree.name, null, profileThree); + ussNode.contextValue = extension.USS_SESSION_CONTEXT; + ussTree.addSession("profile3"); + ussTree.addFavorite(ussNode); + showQuickPick.mockResolvedValueOnce("Yes"); + await profiles.deleteProfile(sessTree, ussTree, jobsTree, ussNode); + expect(showInformationMessage.mock.calls.length).toBe(1); + expect(showInformationMessage.mock.calls[0][0]).toBe("Profile profile3 was deleted."); + expect(ussTree.mSessionNodes.length).toEqual(startLength); + expect(ussTree.mFavorites.length).toEqual(favoriteLength); + }); + + it("should delete session from Jobs tree", async () => { + const startLength = jobsTree.mSessionNodes.length; + const favoriteLength = jobsTree.mFavorites.length; + const jobNode = new Job("profile3", vscode.TreeItemCollapsibleState.Expanded, null, session, iJob, profileThree); + jobNode.contextValue = extension.JOBS_SESSION_CONTEXT; + jobsTree.mSessionNodes.push(jobNode); + jobsTree.addFavorite(jobNode); + showQuickPick.mockResolvedValueOnce("Yes"); + await profiles.deleteProfile(sessTree, ussTree, jobsTree, jobNode); + expect(showInformationMessage.mock.calls.length).toBe(1); + expect(showInformationMessage.mock.calls[0][0]).toBe("Profile profile3 was deleted."); + expect(jobsTree.mSessionNodes.length).toEqual(startLength); + expect(jobsTree.mFavorites.length).toEqual(favoriteLength); + }); }); it("should route through to spawn. Covers conditional test", async () => { From e13bbe66ee0c376df3a679b6cc6ab05da2542244 Mon Sep 17 00:00:00 2001 From: Richelle Anne Craw Date: Thu, 16 Apr 2020 21:51:10 +0200 Subject: [PATCH 11/16] Fix imports and regex Signed-off-by: Richelle Anne Craw --- __tests__/__unit__/Profiles.unit.test.ts | 38 +++++++++++-------- .../__snapshots__/extension.unit.test.ts.snap | 7 ++-- __tests__/__unit__/extension.unit.test.ts | 10 ++--- package.json | 6 +-- src/extension.ts | 18 +++++---- 5 files changed, 43 insertions(+), 36 deletions(-) diff --git a/__tests__/__unit__/Profiles.unit.test.ts b/__tests__/__unit__/Profiles.unit.test.ts index 7396b7f0e9..24cd55cf5d 100644 --- a/__tests__/__unit__/Profiles.unit.test.ts +++ b/__tests__/__unit__/Profiles.unit.test.ts @@ -15,18 +15,18 @@ import * as path from "path"; import * as os from "os"; import * as vscode from "vscode"; import * as child_process from "child_process"; -import * as extension from "../../src/extension"; +import * as globals from "../../src/globals"; import { Logger, ISession, CliProfileManager, IProfileLoaded, Session } from "@zowe/imperative"; import { Profiles, ValidProfileEnum } from "../../src/Profiles"; import { ZosmfSession, IJob } from "@zowe/cli"; -import { ZoweUSSNode } from "../../src/ZoweUSSNode"; -import { ZoweDatasetNode } from "../../src/ZoweDatasetNode"; -import { Job } from "../../src/ZoweJobNode"; +import { ZoweUSSNode } from "../../src/uss/ZoweUSSNode"; +import { ZoweDatasetNode } from "../../src/dataset/ZoweDatasetNode"; +import { Job } from "../../src/job/ZoweJobNode"; import { IZoweDatasetTreeNode, IZoweUSSTreeNode, IZoweJobTreeNode, IZoweNodeType } from "../../src/api/IZoweTreeNode"; import { IZoweTree } from "../../src/api/IZoweTree"; -import { DatasetTree } from "../../src/DatasetTree"; -import { USSTree } from "../../src/USSTree"; -import { ZosJobsProvider } from "../../src/ZosJobsProvider"; +import { DatasetTree } from "../../src/dataset/DatasetTree"; +import { USSTree } from "../../src/uss/USSTree"; +import { ZosJobsProvider } from "../../src/job/ZosJobsProvider"; import * as testConst from "../../resources/testProfileData"; describe("Profile class unit tests", () => { @@ -123,7 +123,7 @@ describe("Profile class unit tests", () => { Object.defineProperty(vscode.window, "createTreeView", {value: createTreeView}); Object.defineProperty(vscode.workspace, "getConfiguration", { value: getConfiguration }); Object.defineProperty(ZosmfSession, "createBasicZosmfSession", { value: createBasicZosmfSession }); - + const sessTree: IZoweTree = new DatasetTree(); const ussTree: IZoweTree = new USSTree(); const jobsTree: IZoweTree = new ZosJobsProvider(); @@ -545,8 +545,9 @@ describe("Profile class unit tests", () => { }); it("should delete profile from context menu", async () => { - const dsNode = new ZoweDatasetNode("profile3", vscode.TreeItemCollapsibleState.Expanded, null, session, undefined, undefined, profileThree); - dsNode.contextValue = extension.DS_SESSION_CONTEXT; + const dsNode = new ZoweDatasetNode( + "profile3", vscode.TreeItemCollapsibleState.Expanded, null, session, undefined, undefined, profileThree); + dsNode.contextValue = globals.DS_SESSION_CONTEXT; showQuickPick.mockResolvedValueOnce("Yes"); await profiles.deleteProfile(sessTree, ussTree, jobsTree, dsNode); expect(showInformationMessage.mock.calls.length).toBe(1); @@ -556,8 +557,9 @@ describe("Profile class unit tests", () => { it("should delete session from Data Set tree", async () => { const startLength = sessTree.mSessionNodes.length; const favoriteLength = sessTree.mFavorites.length; - const dsNode = new ZoweDatasetNode("profile3", vscode.TreeItemCollapsibleState.Expanded, null, session, undefined, undefined, profileThree); - dsNode.contextValue = extension.DS_SESSION_CONTEXT; + const dsNode = new ZoweDatasetNode( + "profile3", vscode.TreeItemCollapsibleState.Expanded, null, session, undefined, undefined, profileThree); + dsNode.contextValue = globals.DS_SESSION_CONTEXT; sessTree.mSessionNodes.push(dsNode); sessTree.addFavorite(dsNode); showQuickPick.mockResolvedValueOnce("Yes"); @@ -571,8 +573,11 @@ describe("Profile class unit tests", () => { it("should delete session from USS tree", async () => { const startLength = ussTree.mSessionNodes.length; const favoriteLength = ussTree.mFavorites.length; - const ussNode = new ZoweUSSNode("profile3", vscode.TreeItemCollapsibleState.Expanded, null, session, null, false, profileThree.name, null, profileThree); - ussNode.contextValue = extension.USS_SESSION_CONTEXT; + const ussNode = new ZoweUSSNode( + "profile3", vscode.TreeItemCollapsibleState.Expanded, + null, session, null, false, profileThree.name, null, profileThree); + ussNode.contextValue = globals.USS_SESSION_CONTEXT; + ussNode.profile = profileThree; ussTree.addSession("profile3"); ussTree.addFavorite(ussNode); showQuickPick.mockResolvedValueOnce("Yes"); @@ -586,8 +591,9 @@ describe("Profile class unit tests", () => { it("should delete session from Jobs tree", async () => { const startLength = jobsTree.mSessionNodes.length; const favoriteLength = jobsTree.mFavorites.length; - const jobNode = new Job("profile3", vscode.TreeItemCollapsibleState.Expanded, null, session, iJob, profileThree); - jobNode.contextValue = extension.JOBS_SESSION_CONTEXT; + const jobNode = new Job( + "profile3", vscode.TreeItemCollapsibleState.Expanded, null, session, iJob, profileThree); + jobNode.contextValue = globals.JOBS_SESSION_CONTEXT; jobsTree.mSessionNodes.push(jobNode); jobsTree.addFavorite(jobNode); showQuickPick.mockResolvedValueOnce("Yes"); diff --git a/__tests__/__unit__/__snapshots__/extension.unit.test.ts.snap b/__tests__/__unit__/__snapshots__/extension.unit.test.ts.snap index 30aa3990b1..3c95533f70 100644 --- a/__tests__/__unit__/__snapshots__/extension.unit.test.ts.snap +++ b/__tests__/__unit__/__snapshots__/extension.unit.test.ts.snap @@ -195,13 +195,12 @@ Array [ Object { "command": "zowe.deleteProfile", "group": "6_modification@4", - "when": "view == zowe.explorer && viewItem == session", + "when": "view == zowe.explorer && viewItem =~ /^(?!.*_fav.*)session.*/", }, Object { "command": "zowe.removeSession", "group": "6_modification@3", "when": "view == zowe.explorer && viewItem =~ /^(?!.*_fav.*)session.*/", - }, Object { "command": "zowe.saveSearch", @@ -230,7 +229,7 @@ Array [ Object { "command": "zowe.uss.deleteProfile", "group": "6_modification@4", - "when": "viewItem == uss_session", + "when": "viewItem =~ /^(?!.*_fav.*)ussSession.*/", }, Object { "command": "zowe.uss.removeSession", @@ -260,7 +259,7 @@ Array [ Object { "command": "zowe.jobs.deleteProfile", "group": "6_modification@4", - "when": "view == zowe.jobs && viewItem == server", + "when": "view == zowe.jobs && viewItem =~ /^(?!.*_fav.*)server.*/", }, Object { "command": "zowe.setOwner", diff --git a/__tests__/__unit__/extension.unit.test.ts b/__tests__/__unit__/extension.unit.test.ts index 17c8af3d34..96b9e58f77 100644 --- a/__tests__/__unit__/extension.unit.test.ts +++ b/__tests__/__unit__/extension.unit.test.ts @@ -719,8 +719,6 @@ describe("Extension Unit Tests", () => { "zowe.pasteDataSet", "zowe.renameDataSetMember", "zowe.hMigrateDataSet", - "zowe.deleteProfile", - "zowe.cmd.deleteProfile", "zowe.uss.addFavorite", "zowe.uss.removeFavorite", "zowe.uss.addSession", @@ -742,7 +740,6 @@ describe("Extension Unit Tests", () => { "zowe.uss.editFile", "zowe.uss.saveSearch", "zowe.uss.removeSavedSearch", - "zowe.uss.deleteProfile", "zowe.zosJobsOpenspool", "zowe.deleteJob", "zowe.runModifyCommand", @@ -763,9 +760,12 @@ describe("Extension Unit Tests", () => { "zowe.jobs.removeFavorite", "zowe.jobs.saveSearch", "zowe.jobs.removeSearchFavorite", - "zowe.jobs.deleteProfile", "zowe.openRecentMember", - "zowe.searchInAllLoadedItems" + "zowe.searchInAllLoadedItems", + "zowe.deleteProfile", + "zowe.cmd.deleteProfile", + "zowe.uss.deleteProfile", + "zowe.jobs.deleteProfile", ]; expect(actualCommands).toEqual(expectedCommands); expect(onDidSaveTextDocument.mock.calls.length).toBe(1); diff --git a/package.json b/package.json index 9dfd4127e1..b259e510a1 100644 --- a/package.json +++ b/package.json @@ -641,7 +641,7 @@ "group": "inline" }, { - "when": "view == zowe.explorer && viewItem == session", + "when": "view == zowe.explorer && viewItem =~ /^(?!.*_fav.*)session.*/", "command": "zowe.deleteProfile", "group": "6_modification@4" }, @@ -675,7 +675,7 @@ "group": "inline" }, { - "when": "viewItem == uss_session", + "when": "viewItem =~ /^(?!.*_fav.*)ussSession.*/", "command": "zowe.uss.deleteProfile", "group": "6_modification@4" }, @@ -705,7 +705,7 @@ "group": "inline" }, { - "when": "view == zowe.jobs && viewItem == server", + "when": "view == zowe.jobs && viewItem =~ /^(?!.*_fav.*)server.*/", "command": "zowe.jobs.deleteProfile", "group": "6_modification@4" }, diff --git a/src/extension.ts b/src/extension.ts index 1e853a9c01..dedcee2391 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -153,6 +153,16 @@ export async function activate(context: vscode.ExtensionContext): Promise + Profiles.getInstance().deleteProfile(datasetProvider, ussFileProvider, jobsProvider, node)); + vscode.commands.registerCommand("zowe.cmd.deleteProfile", async () => + Profiles.getInstance().deleteProfile(datasetProvider, ussFileProvider, jobsProvider)); + vscode.commands.registerCommand("zowe.uss.deleteProfile", async (node) => + Profiles.getInstance().deleteProfile(datasetProvider, ussFileProvider, jobsProvider, node)); + vscode.commands.registerCommand("zowe.jobs.deleteProfile", async (node) => + Profiles.getInstance().deleteProfile(datasetProvider, ussFileProvider, jobsProvider, node)); + } // return the Extension's API to other extensions that want to register their APIs. return ZoweExplorerApiRegister.getInstance(); @@ -184,10 +194,6 @@ function initDatasetProvider(context: vscode.ExtensionContext, datasetProvider: vscode.commands.registerCommand("zowe.pasteDataSet", (node) => dsActions.pasteDataSet(node, datasetProvider)); vscode.commands.registerCommand("zowe.renameDataSetMember", (node) => datasetProvider.rename(node)); vscode.commands.registerCommand("zowe.hMigrateDataSet", (node) => dsActions.hMigrateDataSet(node)); - vscode.commands.registerCommand("zowe.deleteProfile", async (node) => - Profiles.getInstance().deleteProfile(datasetProvider, ussFileProvider, jobsProvider, node)); - vscode.commands.registerCommand("zowe.cmd.deleteProfile", async () => - Profiles.getInstance().deleteProfile(datasetProvider, ussFileProvider, jobsProvider)); vscode.workspace.onDidChangeConfiguration(async (e) => { datasetProvider.onDidChangeConfiguration(e); }); initSubscribers(context, datasetProvider); @@ -214,8 +220,6 @@ function initUSSProvider(context: vscode.ExtensionContext, ussFileProvider: IZow vscode.commands.registerCommand("zowe.uss.copyPath", async (node: IZoweUSSTreeNode) => ussActions.copyPath(node)); vscode.commands.registerCommand("zowe.uss.editFile", (node: IZoweUSSTreeNode) => node.openUSS(false, false, ussFileProvider)); vscode.commands.registerCommand("zowe.uss.saveSearch", async (node: IZoweUSSTreeNode) => ussFileProvider.saveSearch(node)); - vscode.commands.registerCommand("zowe.uss.deleteProfile", async (node) => - Profiles.getInstance().deleteProfile(datasetProvider, ussFileProvider, jobsProvider, node)); vscode.commands.registerCommand("zowe.uss.removeSavedSearch", async (node: IZoweUSSTreeNode) => ussFileProvider.removeFavorite(node)); vscode.workspace.onDidChangeConfiguration(async (e) => { ussFileProvider.onDidChangeConfiguration(e); }); @@ -251,8 +255,6 @@ function initJobsProvider(context: vscode.ExtensionContext, jobsProvider: IZoweT vscode.commands.registerCommand("zowe.jobs.removeFavorite", async (node) => jobsProvider.removeFavorite(node)); vscode.commands.registerCommand("zowe.jobs.saveSearch", async (node) => jobsProvider.saveSearch(node)); vscode.commands.registerCommand("zowe.jobs.removeSearchFavorite", async (node) => jobsProvider.removeFavorite(node)); - vscode.commands.registerCommand("zowe.jobs.deleteProfile", async (node) => - Profiles.getInstance().deleteProfile(datasetProvider, ussFileProvider, jobsProvider, node)); vscode.workspace.onDidChangeConfiguration(async (e) => { jobsProvider.onDidChangeConfiguration(e); }); initSubscribers(context, jobsProvider); From 4f5a03737311af1f3e7fbcaaecdd23d6d2217cb4 Mon Sep 17 00:00:00 2001 From: jellypuno Date: Thu, 16 Apr 2020 22:31:16 +0200 Subject: [PATCH 12/16] Add more test for deleteProfile USS Signed-off-by: jellypuno --- __tests__/__unit__/Profiles.unit.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/__tests__/__unit__/Profiles.unit.test.ts b/__tests__/__unit__/Profiles.unit.test.ts index 24cd55cf5d..b48be8fee9 100644 --- a/__tests__/__unit__/Profiles.unit.test.ts +++ b/__tests__/__unit__/Profiles.unit.test.ts @@ -574,12 +574,13 @@ describe("Profile class unit tests", () => { const startLength = ussTree.mSessionNodes.length; const favoriteLength = ussTree.mFavorites.length; const ussNode = new ZoweUSSNode( - "profile3", vscode.TreeItemCollapsibleState.Expanded, + "[profile3]: profile3", vscode.TreeItemCollapsibleState.Expanded, null, session, null, false, profileThree.name, null, profileThree); ussNode.contextValue = globals.USS_SESSION_CONTEXT; ussNode.profile = profileThree; ussTree.addSession("profile3"); - ussTree.addFavorite(ussNode); + ussTree.mSessionNodes.push(ussNode); + ussTree.mFavorites.push(ussNode); showQuickPick.mockResolvedValueOnce("Yes"); await profiles.deleteProfile(sessTree, ussTree, jobsTree, ussNode); expect(showInformationMessage.mock.calls.length).toBe(1); From 1bc989e0a856b6895bdcd15f8fcbb16b0e0c034a Mon Sep 17 00:00:00 2001 From: Richelle Anne Craw Date: Wed, 22 Apr 2020 18:07:09 +0200 Subject: [PATCH 13/16] Remove from recall list Signed-off-by: Richelle Anne Craw --- src/PersistentFilters.ts | 1 + src/Profiles.ts | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/PersistentFilters.ts b/src/PersistentFilters.ts index a8a81570c4..864346ac50 100644 --- a/src/PersistentFilters.ts +++ b/src/PersistentFilters.ts @@ -132,6 +132,7 @@ export class PersistentFilters { return recallItem.includes(name); }); if (index >= 0) { this.mRecall.splice(index, 1); } + this.updateRecall(); } public async resetHistory() { diff --git a/src/Profiles.ts b/src/Profiles.ts index 0d3cdfa149..d5bcfebb20 100644 --- a/src/Profiles.ts +++ b/src/Profiles.ts @@ -436,6 +436,7 @@ export class Profiles { datasetTree.deleteSession(sessNode); } }); + await datasetTree.refresh(); // Delete from Data Set Favorites datasetTree.mFavorites.forEach((ses) => { @@ -446,6 +447,17 @@ export class Profiles { }); await datasetTree.refresh(); + // Delete from Data Set Recall + const recallDs: string[] = datasetTree.getRecall(); + for (let i = recallDs.length - 1; i >= 0; i--) { + const findNode = recallDs[i].substring(1, recallDs[i].indexOf("]")).trim(); + if (findNode === deleteLabel) { + datasetTree.removeRecall(recallDs[i]); + } + } + + await datasetTree.refresh(); + // Delete from USS Tree ussTree.mSessionNodes.forEach((sessNode) => { if (sessNode.getProfileName() === deleteLabel) { @@ -462,12 +474,24 @@ export class Profiles { }); await ussTree.refresh(); + // Delete from USS Recall + const recallUSS: string[] = ussTree.getRecall(); + for (let i = recallUSS.length - 1; i >= 0; i--) { + const findNode = recallUSS[i].substring(1, recallUSS[i].indexOf("]")).trim(); + if (findNode === deleteLabel) { + ussTree.removeRecall(recallUSS[i]); + } + } + + await ussTree.refresh(); + // Delete from Jobs Tree jobsProvider.mSessionNodes.forEach((jobNode) => { if (jobNode.getProfileName() === deleteLabel) { jobsProvider.deleteSession(jobNode); } }); + await jobsProvider.refresh(); // Delete from Jobs Favorites jobsProvider.mFavorites.forEach((ses) => { From d4ae34d9609494fb354e1785bc72f4e54b79a129 Mon Sep 17 00:00:00 2001 From: Richelle Anne Craw Date: Sat, 25 Apr 2020 14:19:44 +0200 Subject: [PATCH 14/16] Handle deletion of default profile + fixes Signed-off-by: Richelle Anne Craw --- __tests__/__unit__/Profiles.unit.test.ts | 43 +++++- i18n/sample/src/Profiles.i18n.json | 2 +- i18n/sample/src/uss/ZoweUSSNode.i18n.json | 2 +- src/PersistentFilters.ts | 4 +- src/Profiles.ts | 163 +++++++++++++++------- 5 files changed, 154 insertions(+), 60 deletions(-) diff --git a/__tests__/__unit__/Profiles.unit.test.ts b/__tests__/__unit__/Profiles.unit.test.ts index b48be8fee9..b698a5a03d 100644 --- a/__tests__/__unit__/Profiles.unit.test.ts +++ b/__tests__/__unit__/Profiles.unit.test.ts @@ -111,7 +111,7 @@ describe("Profile class unit tests", () => { const createInputBox = jest.fn(); const showQuickPick = jest.fn(); const showErrorMessage = jest.fn(); - const getConfiguration = jest.fn(); + const getConfigurationMock = jest.fn(); const createTreeView = jest.fn(); const createBasicZosmfSession = jest.fn(); @@ -121,7 +121,8 @@ describe("Profile class unit tests", () => { Object.defineProperty(vscode.window, "createInputBox", { value: createInputBox }); Object.defineProperty(vscode.window, "showQuickPick", { value: showQuickPick }); Object.defineProperty(vscode.window, "createTreeView", {value: createTreeView}); - Object.defineProperty(vscode.workspace, "getConfiguration", { value: getConfiguration }); + Object.defineProperty(vscode.workspace, "getConfiguration", { value: getConfigurationMock }); + Object.defineProperty(vscode, "ConfigurationTarget", { value: getConfigurationMock }); Object.defineProperty(ZosmfSession, "createBasicZosmfSession", { value: createBasicZosmfSession }); const sessTree: IZoweTree = new DatasetTree(); @@ -459,8 +460,12 @@ describe("Profile class unit tests", () => { describe("Deleting Profiles", () => { let profiles: Profiles; + const getRecallMockValue = jest.fn(); + const getRecallUSSMockValue = jest.fn(); beforeEach(async () => { profiles = await Profiles.createInstance(log); + Object.defineProperty(DatasetTree, "getRecall", { value: getRecallMockValue }); + Object.defineProperty(USSTree, "getRecall", { value: getRecallUSSMockValue }); Object.defineProperty(Profiles, "getInstance", { value: jest.fn(() => { return { @@ -497,6 +502,18 @@ describe("Profile class unit tests", () => { }; }) }); + getConfigurationMock.mockReturnValue({ + persistence: true, + get: () => { + return { + sessions: ["profile1"], + favorites: ["[profile1]: /u/myFile.txt{textFile"] + }; + }, + update: jest.fn(()=>{ + return {}; + }) + }); }); afterEach(() => { @@ -505,6 +522,7 @@ describe("Profile class unit tests", () => { createInputBox.mockReset(); showInformationMessage.mockReset(); showErrorMessage.mockReset(); + getConfigurationMock.mockClear(); }); it("should delete profile from command palette", async () => { @@ -604,6 +622,27 @@ describe("Profile class unit tests", () => { expect(jobsTree.mSessionNodes.length).toEqual(startLength); expect(jobsTree.mFavorites.length).toEqual(favoriteLength); }); + + it("should test deletion of recall for DS", async () => { + sessTree.addRecall("[profile1]: TEST.DATA"); + showQuickPick.mockResolvedValueOnce("profile1"); + showQuickPick.mockResolvedValueOnce("Yes"); + await profiles.deleteProfile(sessTree, ussTree, jobsTree); + expect(showInformationMessage.mock.calls.length).toBe(1); + expect(showInformationMessage.mock.calls[0][0]).toBe("Profile profile1 was deleted."); + expect(sessTree.getRecall()[0]).toBeUndefined(); + }); + + it("should test deletion of recall for USS", async () => { + ussTree.addRecall("[profile1]: /node1/node2/node3.txt"); + showQuickPick.mockResolvedValueOnce("profile1"); + showQuickPick.mockResolvedValueOnce("Yes"); + await profiles.deleteProfile(sessTree, ussTree, jobsTree); + expect(showInformationMessage.mock.calls.length).toBe(1); + expect(showInformationMessage.mock.calls[0][0]).toBe("Profile profile1 was deleted."); + expect(ussTree.getRecall()[0]).toBeUndefined(); + }); + }); it("should route through to spawn. Covers conditional test", async () => { diff --git a/i18n/sample/src/Profiles.i18n.json b/i18n/sample/src/Profiles.i18n.json index 690b3b5ae0..8d860c1770 100644 --- a/i18n/sample/src/Profiles.i18n.json +++ b/i18n/sample/src/Profiles.i18n.json @@ -21,9 +21,9 @@ "promptcredentials.option.prompt.password.placeholder": "Password", "promptcredentials.option.prompt.password": "Enter a password for the connection", "promptcredentials.invalidpassword": "Please enter your z/OS password. Operation Cancelled", + "deleteProfile.noProfilesLoaded": "No profiles available", "deleteProfile.quickPickOption": "Are you sure you want to permanently delete ", "deleteProfile.undefined.profilename": "Operation Cancelled", - "deleteProfile.noProfilesLoaded": "No profiles available", "deleteProfile.log.debug": "Deleting profile ", "deleteProfile.showQuickPick.yes": "Yes", "deleteProfile.showQuickPick.no": "No", diff --git a/i18n/sample/src/uss/ZoweUSSNode.i18n.json b/i18n/sample/src/uss/ZoweUSSNode.i18n.json index 5fdaf6a374..5812c8dcc9 100644 --- a/i18n/sample/src/uss/ZoweUSSNode.i18n.json +++ b/i18n/sample/src/uss/ZoweUSSNode.i18n.json @@ -16,4 +16,4 @@ "openUSS.log.info.failedToOpenAsText.yes": "Yes, re-download", "openUSS.log.info.failedToOpenAsText.no": "No", "openUSS.log.info.failedToOpenAsText": "Failed to open file as text. Do you want to try with re-downloading it as binary?" -} +} \ No newline at end of file diff --git a/src/PersistentFilters.ts b/src/PersistentFilters.ts index 864346ac50..2bde8be5e3 100644 --- a/src/PersistentFilters.ts +++ b/src/PersistentFilters.ts @@ -127,12 +127,12 @@ export class PersistentFilters { return this.mRecall; } - public removeRecall(name: string) { + public async removeRecall(name: string) { const index = this.mRecall.findIndex((recallItem) => { return recallItem.includes(name); }); if (index >= 0) { this.mRecall.splice(index, 1); } - this.updateRecall(); + await this.updateRecall(); } public async resetHistory() { diff --git a/src/Profiles.ts b/src/Profiles.ts index d5bcfebb20..b67a5ae00e 100644 --- a/src/Profiles.ts +++ b/src/Profiles.ts @@ -58,6 +58,9 @@ export class Profiles { public allProfiles: IProfileLoaded[] = []; public loadedProfile: IProfileLoaded; public validProfile: ValidProfileEnum = ValidProfileEnum.INVALID; + private dsSchema: string = "Zowe-DS-Persistent"; + private ussSchema: string = "Zowe-USS-Persistent"; + private jobsSchema: string = "Zowe-Jobs-Persistent"; private profilesByType = new Map(); private defaultProfileByType = new Map(); private profileManagerByType= new Map(); @@ -121,7 +124,13 @@ export class Profiles { if (profilesForType && profilesForType.length > 0) { this.allProfiles.push(...profilesForType); this.profilesByType.set(type, profilesForType); - this.defaultProfileByType.set(type, (await profileManager.load({ loadDefault: true }))); + let defaultProfile: IProfileLoaded; + try { + defaultProfile = await profileManager.load({ loadDefault: true }); + } catch (error) { + vscode.window.showInformationMessage(error.message); + } + this.defaultProfileByType.set(type, defaultProfile); } } } @@ -344,26 +353,27 @@ export class Profiles { const profileNamesList = allProfiles.map((temprofile) => { return temprofile.name; }); - if (profileNamesList.length) { - const quickPickList: vscode.QuickPickOptions = { - placeHolder: localize("deleteProfile.quickPickOption", "Select the profile you want to delete"), - ignoreFocusOut: true, - canPickMany: false - }; - const sesName = await vscode.window.showQuickPick(profileNamesList, quickPickList); - if (sesName === undefined) { - vscode.window.showInformationMessage(localize("deleteProfile.undefined.profilename", - "Operation Cancelled")); - return; - } else { - zosmfProfile = allProfiles.filter((temprofile) => temprofile.name === sesName)[0]; - } - } else { + if (!profileNamesList.length) { vscode.window.showInformationMessage(localize("deleteProfile.noProfilesLoaded", "No profiles available")); return; } + const quickPickList: vscode.QuickPickOptions = { + placeHolder: localize("deleteProfile.quickPickOption", "Select the profile you want to delete"), + ignoreFocusOut: true, + canPickMany: false + }; + const sesName = await vscode.window.showQuickPick(profileNamesList, quickPickList); + + if (sesName === undefined) { + vscode.window.showInformationMessage(localize("deleteProfile.undefined.profilename", + "Operation Cancelled")); + return; + } else { + zosmfProfile = allProfiles.filter((temprofile) => temprofile.name === sesName)[0]; + } + return zosmfProfile; } @@ -430,23 +440,6 @@ export class Profiles { return; } - // Delete from Data Set Tree - datasetTree.mSessionNodes.forEach((sessNode) => { - if (sessNode.getProfileName() === deleteLabel) { - datasetTree.deleteSession(sessNode); - } - }); - await datasetTree.refresh(); - - // Delete from Data Set Favorites - datasetTree.mFavorites.forEach((ses) => { - const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); - if (findNode === deleteLabel) { - datasetTree.removeFavorite(ses); - } - }); - await datasetTree.refresh(); - // Delete from Data Set Recall const recallDs: string[] = datasetTree.getRecall(); for (let i = recallDs.length - 1; i >= 0; i--) { @@ -456,23 +449,25 @@ export class Profiles { } } - await datasetTree.refresh(); - - // Delete from USS Tree - ussTree.mSessionNodes.forEach((sessNode) => { - if (sessNode.getProfileName() === deleteLabel) { - ussTree.deleteSession(sessNode); + // Delete from Data Set Favorites + const favoriteDs = datasetTree.mFavorites; + for (let i = favoriteDs.length - 1; i >= 0; i--) { + const findNode = favoriteDs[i].label.substring(1, favoriteDs[i].label.indexOf("]")).trim(); + if (findNode === deleteLabel) { + await datasetTree.removeFavorite(favoriteDs[i]); + favoriteDs[i].dirty = true; + datasetTree.refresh(); } - }); + } - // Delete from USS Favorites - ussTree.mFavorites.forEach((ses) => { - const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); - if (findNode === deleteLabel) { - ussTree.removeFavorite(ses); + // Delete from Data Set Tree + datasetTree.mSessionNodes.forEach((sessNode) => { + if (sessNode.getProfileName() === deleteLabel) { + datasetTree.deleteSession(sessNode); + sessNode.dirty = true; + datasetTree.refresh(); } }); - await ussTree.refresh(); // Delete from USS Recall const recallUSS: string[] = ussTree.getRecall(); @@ -483,24 +478,85 @@ export class Profiles { } } - await ussTree.refresh(); + // Delete from USS Favorites + ussTree.mFavorites.forEach((ses) => { + const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); + if (findNode === deleteLabel) { + ussTree.removeFavorite(ses); + ses.dirty = true; + ussTree.refresh(); + } + }); - // Delete from Jobs Tree - jobsProvider.mSessionNodes.forEach((jobNode) => { - if (jobNode.getProfileName() === deleteLabel) { - jobsProvider.deleteSession(jobNode); + // Delete from USS Tree + ussTree.mSessionNodes.forEach((sessNode) => { + if (sessNode.getProfileName() === deleteLabel) { + ussTree.deleteSession(sessNode); + sessNode.dirty = true; + ussTree.refresh(); } }); - await jobsProvider.refresh(); // Delete from Jobs Favorites jobsProvider.mFavorites.forEach((ses) => { const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); if (findNode === deleteLabel) { jobsProvider.removeFavorite(ses); + ses.dirty = true; + jobsProvider.refresh(); } }); - await jobsProvider.refresh(); + + // Delete from Jobs Tree + jobsProvider.mSessionNodes.forEach((jobNode) => { + if (jobNode.getProfileName() === deleteLabel) { + jobsProvider.deleteSession(jobNode); + jobNode.dirty = true; + jobsProvider.refresh(); + } + }); + + // Delete from Data Set Sessions list + const dsSetting: any = {...vscode.workspace.getConfiguration().get(this.dsSchema)}; + let sessDS: string[] = dsSetting.sessions; + let faveDS: string[] = dsSetting.favorites; + sessDS = sessDS.filter( (element) => { + return element.trim() !== deleteLabel; + }); + faveDS = faveDS.filter( (element) => { + return element.substring(1, element.indexOf("]")).trim() !== deleteLabel; + }); + dsSetting.sessions = sessDS; + dsSetting.favorites = faveDS; + await vscode.workspace.getConfiguration().update(this.dsSchema, dsSetting, vscode.ConfigurationTarget.Global); + + // Delete from USS Sessions list + const ussSetting: any = {...vscode.workspace.getConfiguration().get(this.ussSchema)}; + let sessUSS: string[] = ussSetting.sessions; + let faveUSS: string[] = ussSetting.favorites; + sessUSS = sessUSS.filter( (element) => { + return element.trim() !== deleteLabel; + }); + faveUSS = faveUSS.filter( (element) => { + return element.substring(1, element.indexOf("]")).trim() !== deleteLabel; + }); + ussSetting.sessions = sessUSS; + ussSetting.favorites = faveUSS; + await vscode.workspace.getConfiguration().update(this.ussSchema, ussSetting, vscode.ConfigurationTarget.Global); + + // Delete from Jobs Sessions list + const jobsSetting: any = {...vscode.workspace.getConfiguration().get(this.jobsSchema)}; + let sessJobs: string[] = jobsSetting.sessions; + let faveJobs: string[] = jobsSetting.favorites; + sessJobs = sessJobs.filter( (element) => { + return element.trim() !== deleteLabel; + }); + faveJobs = faveJobs.filter( (element) => { + return element.substring(1, element.indexOf("]")).trim() !== deleteLabel; + }); + jobsSetting.sessions = sessJobs; + jobsSetting.favorites = faveJobs; + await vscode.workspace.getConfiguration().update(this.jobsSchema, jobsSetting, vscode.ConfigurationTarget.Global); // Remove from list of all profiles const index = this.allProfiles.findIndex((deleteItem) => { @@ -509,7 +565,6 @@ export class Profiles { if (index >= 0) { this.allProfiles.splice(index, 1); } } - private async updateProfile(ProfileInfo) { for (const type of ZoweExplorerApiRegister.getInstance().registeredApiTypes()) { From 60231276696f9aea09c3589bcf3fc6f0f5202f2c Mon Sep 17 00:00:00 2001 From: Richelle Anne Craw Date: Mon, 27 Apr 2020 16:25:41 +0200 Subject: [PATCH 15/16] Simplify conditional statements Signed-off-by: Richelle Anne Craw --- src/Profiles.ts | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/src/Profiles.ts b/src/Profiles.ts index b67a5ae00e..8eaea2696d 100644 --- a/src/Profiles.ts +++ b/src/Profiles.ts @@ -370,11 +370,9 @@ export class Profiles { vscode.window.showInformationMessage(localize("deleteProfile.undefined.profilename", "Operation Cancelled")); return; - } else { - zosmfProfile = allProfiles.filter((temprofile) => temprofile.name === sesName)[0]; } - return zosmfProfile; + return allProfiles.find(temprofile => temprofile.name === sesName); } public async deletePrompt(deletedProfile: IProfileLoaded) { @@ -424,15 +422,14 @@ export class Profiles { let deletedProfile: IProfileLoaded; if (!node){ deletedProfile = await this.getDeleteProfile(); - if (!deletedProfile) { - return; - } else { - deleteLabel = deletedProfile.name; - } } else { deletedProfile = node.getProfile(); - deleteLabel = node.getProfileName(); } + if (!deletedProfile) { + return; + } + deleteLabel = deletedProfile.name; + const deleteSuccess = await this.deletePrompt(deletedProfile); if (!deleteSuccess){ vscode.window.showInformationMessage(localize("deleteProfile.noSelected", @@ -442,19 +439,18 @@ export class Profiles { // Delete from Data Set Recall const recallDs: string[] = datasetTree.getRecall(); - for (let i = recallDs.length - 1; i >= 0; i--) { - const findNode = recallDs[i].substring(1, recallDs[i].indexOf("]")).trim(); - if (findNode === deleteLabel) { - datasetTree.removeRecall(recallDs[i]); - } - } + recallDs.slice().reverse() + .filter(ds => ds.substring(1, ds.indexOf("]")).trim() === deleteLabel) + .forEach(ds => { + datasetTree.removeRecall(ds); + }); // Delete from Data Set Favorites const favoriteDs = datasetTree.mFavorites; for (let i = favoriteDs.length - 1; i >= 0; i--) { const findNode = favoriteDs[i].label.substring(1, favoriteDs[i].label.indexOf("]")).trim(); if (findNode === deleteLabel) { - await datasetTree.removeFavorite(favoriteDs[i]); + datasetTree.removeFavorite(favoriteDs[i]); favoriteDs[i].dirty = true; datasetTree.refresh(); } @@ -471,12 +467,11 @@ export class Profiles { // Delete from USS Recall const recallUSS: string[] = ussTree.getRecall(); - for (let i = recallUSS.length - 1; i >= 0; i--) { - const findNode = recallUSS[i].substring(1, recallUSS[i].indexOf("]")).trim(); - if (findNode === deleteLabel) { - ussTree.removeRecall(recallUSS[i]); - } - } + recallUSS.slice().reverse() + .filter(uss => uss.substring(1, uss.indexOf("]")).trim() === deleteLabel) + .forEach(uss => { + ussTree.removeRecall(uss); + }); // Delete from USS Favorites ussTree.mFavorites.forEach((ses) => { From 0d6cb4d37fff3692da126b0d7fe0924704c32f3d Mon Sep 17 00:00:00 2001 From: Richelle Anne Craw Date: Mon, 27 Apr 2020 16:37:42 +0200 Subject: [PATCH 16/16] Simplify conditional statements Signed-off-by: Richelle Anne Craw --- src/Profiles.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Profiles.ts b/src/Profiles.ts index 8eaea2696d..7d9a4f27b5 100644 --- a/src/Profiles.ts +++ b/src/Profiles.ts @@ -348,7 +348,6 @@ export class Profiles { } public async getDeleteProfile() { - let zosmfProfile: IProfileLoaded; const allProfiles: IProfileLoaded[] = this.allProfiles; const profileNamesList = allProfiles.map((temprofile) => { return temprofile.name; @@ -372,7 +371,7 @@ export class Profiles { return; } - return allProfiles.find(temprofile => temprofile.name === sesName); + return allProfiles.find((temprofile) => temprofile.name === sesName); } public async deletePrompt(deletedProfile: IProfileLoaded) { @@ -440,8 +439,8 @@ export class Profiles { // Delete from Data Set Recall const recallDs: string[] = datasetTree.getRecall(); recallDs.slice().reverse() - .filter(ds => ds.substring(1, ds.indexOf("]")).trim() === deleteLabel) - .forEach(ds => { + .filter((ds) => ds.substring(1, ds.indexOf("]")).trim() === deleteLabel) + .forEach((ds) => { datasetTree.removeRecall(ds); }); @@ -468,8 +467,8 @@ export class Profiles { // Delete from USS Recall const recallUSS: string[] = ussTree.getRecall(); recallUSS.slice().reverse() - .filter(uss => uss.substring(1, uss.indexOf("]")).trim() === deleteLabel) - .forEach(uss => { + .filter((uss) => uss.substring(1, uss.indexOf("]")).trim() === deleteLabel) + .forEach((uss) => { ussTree.removeRecall(uss); });