From ae6ce8172d4ec2151ad6e20460b51e4d510106ce Mon Sep 17 00:00:00 2001 From: Lauren Li <45975633+lauren-li@users.noreply.github.com> Date: Sun, 23 Aug 2020 16:37:07 -0400 Subject: [PATCH 01/26] Begin grouping job favorites by profile Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- src/abstract/ZoweTreeNode.ts | 15 +++- src/api/IZoweTreeNode.ts | 12 +++ src/globals.ts | 1 + src/job/ZosJobsProvider.ts | 169 +++++++++++++++++++++++++++-------- src/uss/ZoweUSSNode.ts | 4 +- 5 files changed, 156 insertions(+), 45 deletions(-) diff --git a/src/abstract/ZoweTreeNode.ts b/src/abstract/ZoweTreeNode.ts index 8600f2169c..3f41bf92a7 100644 --- a/src/abstract/ZoweTreeNode.ts +++ b/src/abstract/ZoweTreeNode.ts @@ -99,12 +99,19 @@ export class ZoweTreeNode extends vscode.TreeItem { } /** - * Sets the IProfileLoaded profile for this node. - * Only used by ZoweTreeNode and should be refactored out + * Sets the IProfileLoaded profile for this node to the one chosen in parameters. * - * @param {IProfileLoaded} + * @param {IProfileLoaded} The profile you will set the node to use */ - protected setProfile(aProfile: IProfileLoaded) { + public setProfileToChoice(aProfile: IProfileLoaded) { this.profile = aProfile; } + /** + * Sets the session for this node to the one chosen in parameters. + * + * @param aSession The session you will set the node to use + */ + public setSessionToChoice(aSession: Session) { + this.session = aSession; + } } diff --git a/src/api/IZoweTreeNode.ts b/src/api/IZoweTreeNode.ts index cbd1f9346d..a70d8f4278 100644 --- a/src/api/IZoweTreeNode.ts +++ b/src/api/IZoweTreeNode.ts @@ -85,6 +85,18 @@ export interface IZoweTreeNode { * Retrieves the profile object in use with this node */ getProfile(): IProfileLoaded; + /** + * Set the profile to use for this node to be the one chosen in the parameters + * + * @param profileObj The profile you will set the node to use + */ + setProfileToChoice(profileObj: IProfileLoaded): void; + /** + * Set the session to use for this node to be the one chosen in the parameters + * + * @param sessionObj The session you will set the node to use + */ + setSessionToChoice(sessionObj: Session): void; } /** diff --git a/src/globals.ts b/src/globals.ts index be9d7d0bcb..cc92113d61 100644 --- a/src/globals.ts +++ b/src/globals.ts @@ -24,6 +24,7 @@ export let LOG: Logger; export const COMMAND_COUNT = 77; export const CONTEXT_PREFIX = "_"; export const FAV_SUFFIX = CONTEXT_PREFIX + "fav"; +export const FAV_PROFILE_CONTEXT = "profile_fav"; export const RC_SUFFIX = CONTEXT_PREFIX + "rc="; export const INFORMATION_CONTEXT = "information"; export const FAVORITE_CONTEXT = "favorite"; diff --git a/src/job/ZosJobsProvider.ts b/src/job/ZosJobsProvider.ts index 36c777e7dc..b7ee599ff5 100644 --- a/src/job/ZosJobsProvider.ts +++ b/src/job/ZosJobsProvider.ts @@ -13,7 +13,7 @@ import * as vscode from "vscode"; import * as jobUtils from "../job/utils"; import * as globals from "../globals"; import { ZosmfSession, IJob } from "@zowe/cli"; -import { IProfileLoaded, Logger, IProfile, ISession } from "@zowe/imperative"; +import { IProfileLoaded, Logger, IProfile, ISession, Session } from "@zowe/imperative"; import { Profiles, ValidProfileEnum } from "../Profiles"; import { Job } from "./ZoweJobNode"; import { getAppName, sortTreeItems, labelRefresh } from "../shared/utils"; @@ -138,6 +138,10 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree treeNode.label === profileName ); + } + + /** + * Creates and returns new profile node, and pushes it to mFavorites + * @param profileName Name of profile + * @returns {Job} + */ + public createProfileNodeForFavs(profileName: string): Job { + const favProfileNode = new Job(profileName, vscode.TreeItemCollapsibleState.Collapsed, + this.mFavoriteSession, null, null, null); + favProfileNode.contextValue = globals.FAV_PROFILE_CONTEXT; + const icon = getIconByNode(favProfileNode); + if (icon) { + favProfileNode.iconPath = icon.path; + } + this.mFavorites.push(favProfileNode); + return favProfileNode; + } + /** * Initialize the favorites and history information * @param log - Logger */ public async initializeJobsTree(log: Logger) { this.log = log; - this.log.debug(localize("initializeFavorites.log.debug", "initializing favorites")); + this.log.debug(localize("initializeJobsTree.log.debug", "Initializing profiles with jobs favorites.")); const lines: string[] = this.mHistory.readFavorites(); - lines.forEach((line) => { + if (lines.length === 0) { + this.log.debug(localize("initializeJobsTree.no.favorites", "No jobs favorites found.")); + return; + } + // Parse line + lines.forEach(async (line) => { const profileName = line.substring(1, line.lastIndexOf("]")); - const nodeName = (line.substring(line.indexOf(":") + 1, line.indexOf("{"))).trim(); - const sesName = line.substring(1, line.lastIndexOf("]")).trim(); + const favLabel = (line.substring(line.indexOf(":") + 1, line.indexOf("{"))).trim(); + const favContextValue = line.substring(line.indexOf("{") + 1, line.lastIndexOf("}")); + // The profile node used for grouping respective favorited items. (Undefined if not created yet.) + let profileNodeInFavorites = this.findMatchingProfileInArray(this.mFavorites, profileName); + if (profileNodeInFavorites === undefined) { + // If favorite node for profile doesn't exist yet, create a new one for it + profileNodeInFavorites = this.createProfileNodeForFavs(profileName); + } + // Initialize and attach favorited item nodes under their respective profile node in Favorrites + const favChildNodeForProfile = await this.initializeFavChildNodeForProfile(favLabel, favContextValue, profileNodeInFavorites); + profileNodeInFavorites.children.push(favChildNodeForProfile); + }); + } + + /** + * Creates an individual favorites node WITHOUT profiles or sessions, to be added to the specified profile node in Favorites during activation. + * This allows label and contextValue to be passed into these child nodes. + * @param label The favorited data set's label + * @param contextValue The favorited data set's context value + * @param parentNode The profile node in this.mFavorites that the favorite belongs to + * @returns IZoweDatasetTreeNode + */ + public async initializeFavChildNodeForProfile(label: string, contextValue: string, parentNode: IZoweJobTreeNode){ + let favJob: Job; + if (contextValue.startsWith(globals.JOBS_JOB_CONTEXT)){ + favJob = new Job(label, vscode.TreeItemCollapsibleState.Collapsed, + parentNode, null, new JobDetail(label), null); + favJob.contextValue = globals.JOBS_JOB_CONTEXT + globals.FAV_SUFFIX; + favJob.command = {command: "zowe.zosJobsSelectjob", title: "", arguments: [favJob]}; + } else { // for search + favJob = new Job(label, vscode.TreeItemCollapsibleState.None, + this.mFavoriteSession, null, null, null); + favJob.command = {command: "zowe.jobs.search", title: "", arguments: [favJob]}; + favJob.contextValue = globals.JOBS_SESSION_CONTEXT + globals.FAV_SUFFIX; + } + const icon = getIconByNode(favJob); + if (icon) { + favJob.iconPath = icon.path; + } + return favJob; + } + + /** + * Loads profile for the profile node in Favorites that was clicked on, as well as for its children favorites. + * @param log + * @param parentNode + */ + public async loadProfilesForFavorites(log: Logger, parentNode: IZoweJobTreeNode ) { + const profileName = parentNode.label; + const updatedFavsForProfile: IZoweJobTreeNode[] = []; + let loadedProfile: IProfileLoaded; + let session: Session; + this.log = log; + this.log.debug(localize("loadProfilesForFavorites.log.debug", "Loading profile: {0} for jobs favorites", profileName)); + // Load profile for parent profile node in this.mFavorites array + if (!parentNode.getProfile() || !parentNode.getSession()) { try { - const zosmfProfile = Profiles.getInstance().loadNamedProfile(sesName); - let favJob: Job; - if (line.substring(line.indexOf("{") + 1, line.lastIndexOf("}")).startsWith(globals.JOBS_JOB_CONTEXT)) { - favJob = new Job(line.substring(0, line.indexOf("{")), vscode.TreeItemCollapsibleState.Collapsed, this.mFavoriteSession, - ZosmfSession.createBasicZosmfSession(zosmfProfile.profile), new JobDetail(nodeName), zosmfProfile); - favJob.contextValue = globals.JOBS_JOB_CONTEXT + globals.FAV_SUFFIX; - favJob.command = {command: "zowe.zosJobsSelectjob", title: "", arguments: [favJob]}; - } else { // for search - favJob = new Job( - line.substring(0, line.indexOf("{")), - vscode.TreeItemCollapsibleState.None, - this.mFavoriteSession, - ZosmfSession.createBasicZosmfSession(zosmfProfile.profile), - null, zosmfProfile - ); - favJob.command = {command: "zowe.jobs.search", title: "", arguments: [favJob]}; - favJob.contextValue = globals.JOBS_SESSION_CONTEXT + globals.FAV_SUFFIX; - } - const icon = getIconByNode(favJob); - if (icon) { - favJob.iconPath = icon.path; - } - this.mFavorites.push(favJob); - } catch (e) { + loadedProfile = Profiles.getInstance().loadNamedProfile(profileName); + // session = ZosmfSession.createBasicZosmfSession(loadedProfile.profile); + // tslint:disable-next-line: no-console + // console.log(session); + session = ZoweExplorerApiRegister.getJesApi(loadedProfile).getSession(); + // tslint:disable-next-line: no-console + console.log(session); + } catch(error) { const errMessage: string = - localize("initializeJobsFavorites.error.profile1", - "Error: You have Jobs favorites that refer to a non-existent CLI profile named: ") + profileName + - localize("initializeJobsFavorites.error.profile2", - ". To resolve this, you can create a profile with this name, ") + - localize("initializeJobsFavorites.error.profile3", - "or remove the favorites with this profile name from the Zowe-Jobs-Persistent setting, which can be found in your ") + - getAppName(globals.ISTHEIA) + localize("initializeJobsFavorites.error.profile4", " user settings."); - errorHandling(e, null, errMessage); - return; + localize("initializeJobsFavorites.error.profile1", + "Error: You have Jobs favorites that refer to a non-existent CLI profile named: ") + profileName + + localize("initializeJobsFavorites.error.profile2", + ". To resolve this, you can create a profile with this name, ") + + localize("initializeJobsFavorites.error.profile3", + "or remove the favorites with this profile name from the Zowe-Jobs-Persistent setting, which can be found in your ") + + getAppName(globals.ISTHEIA) + localize("initializeJobsFavorites.error.profile4", " user settings."); + errorHandling(error, null, errMessage); } - }); + } + loadedProfile = parentNode.getProfile(); + session = parentNode.getSession(); + // Pass loaded profile/session to the parent node's favorites children. + const profileInFavs = this.findMatchingProfileInArray(this.mFavorites, profileName); + const favsForProfile = profileInFavs.children; + for (const favorite of favsForProfile ) { + // If profile and session already exists for favorite node, add to updatedFavsForProfile and go to next array item + if (favorite.getProfile() && favorite.getSession()) { + updatedFavsForProfile.push(favorite); + continue; + } + // If no profile/session for favorite node yet, then add session and profile to favorite node: + favorite.setProfileToChoice(loadedProfile); + favorite.setSessionToChoice(session); + updatedFavsForProfile.push(favorite); + } + // This updates the profile node's children in the this.mFavorites array, as well. + return updatedFavsForProfile; } /** diff --git a/src/uss/ZoweUSSNode.ts b/src/uss/ZoweUSSNode.ts index 52e1971228..71dd23b3db 100644 --- a/src/uss/ZoweUSSNode.ts +++ b/src/uss/ZoweUSSNode.ts @@ -99,10 +99,10 @@ export class ZoweUSSNode extends ZoweTreeNode implements IZoweUSSTreeNode { } // TODO: this should not be necessary if each node gets initialized with the profile reference. if (mProfileName) { - this.setProfile(Profiles.getInstance().loadNamedProfile(mProfileName)); + this.setProfileToChoice(Profiles.getInstance().loadNamedProfile(mProfileName)); } else if (mParent && mParent.mProfileName) { this.mProfileName = mParent.mProfileName; - this.setProfile(Profiles.getInstance().loadNamedProfile(mParent.mProfileName)); + this.setProfileToChoice(Profiles.getInstance().loadNamedProfile(mParent.mProfileName)); } this.etag = etag ? etag : ""; const icon = getIconByNode(this); From a615f80c83badda8688597f2122eb5630c3a0f1c Mon Sep 17 00:00:00 2001 From: Lauren Li <45975633+lauren-li@users.noreply.github.com> Date: Sun, 23 Aug 2020 17:49:09 -0400 Subject: [PATCH 02/26] Add loaded profile and session to jobs favorite profile node Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- src/job/ZosJobsProvider.ts | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/job/ZosJobsProvider.ts b/src/job/ZosJobsProvider.ts index b7ee599ff5..2e31336507 100644 --- a/src/job/ZosJobsProvider.ts +++ b/src/job/ZosJobsProvider.ts @@ -292,20 +292,17 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree Date: Mon, 24 Aug 2020 10:06:33 -0400 Subject: [PATCH 03/26] Update Jobs functions for adding a new favorite Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- src/job/ZosJobsProvider.ts | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/job/ZosJobsProvider.ts b/src/job/ZosJobsProvider.ts index 2e31336507..3ca3b582ac 100644 --- a/src/job/ZosJobsProvider.ts +++ b/src/job/ZosJobsProvider.ts @@ -341,10 +341,17 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree tempNode.label === favJob.label)) { - this.mFavorites.push(favJob); - sortTreeItems(this.mFavorites, globals.JOBS_SESSION_CONTEXT + globals.FAV_SUFFIX); + if (!profileNodeInFavorites.children.find((tempNode) => tempNode.label === favJob.label)) { + profileNodeInFavorites.children.push(favJob); + sortTreeItems(profileNodeInFavorites.children, globals.JOBS_SESSION_CONTEXT + globals.FAV_SUFFIX); await this.updateFavorites(); this.refreshElement(this.mFavoriteSession); } @@ -368,10 +375,16 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree fav.label + - "{" + (contextually.isFavoriteJob(fav) ? - globals.JOBS_JOB_CONTEXT : - globals.JOBS_SESSION_CONTEXT) + "}"); + settings.favorites = []; + this.mFavorites.forEach((profileNode) => { + profileNode.children.forEach((fav) => { + const favoriteEntry = "[" + profileNode.label.trim() + "]: " + fav.label + "{" + (contextually.isFavoriteJob(fav) ? + globals.JOBS_JOB_CONTEXT : + globals.JOBS_SESSION_CONTEXT) + "}"; + settings.favorites.push(favoriteEntry); + } + ); + }); await vscode.workspace.getConfiguration().update(ZosJobsProvider.persistenceSchema, settings, vscode.ConfigurationTarget.Global); } } @@ -636,8 +649,7 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree Date: Mon, 24 Aug 2020 11:41:06 -0400 Subject: [PATCH 04/26] Update Jobs removeFavorite for new favorites hierarchy Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- src/abstract/ZoweTreeNode.ts | 5 +---- src/job/ZosJobsProvider.ts | 9 ++++++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/abstract/ZoweTreeNode.ts b/src/abstract/ZoweTreeNode.ts index 3f41bf92a7..556dbb7f45 100644 --- a/src/abstract/ZoweTreeNode.ts +++ b/src/abstract/ZoweTreeNode.ts @@ -84,10 +84,7 @@ export class ZoweTreeNode extends vscode.TreeItem { * @returns {string} */ public getProfileName(): string { - if (this.profile) { - return this.profile.name; - } - return undefined; + return this.getProfile() ? this.getProfile().name : undefined; } /** diff --git a/src/job/ZosJobsProvider.ts b/src/job/ZosJobsProvider.ts index 3ca3b582ac..1a91a933f9 100644 --- a/src/job/ZosJobsProvider.ts +++ b/src/job/ZosJobsProvider.ts @@ -363,10 +363,13 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree + // Get node's profile node in favorites + const profileName = node.getProfileName(); + const profileNodeInFavorites = this.findMatchingProfileInArray(this.mFavorites, profileName); + const startLength = profileNodeInFavorites.children.length; + profileNodeInFavorites.children = profileNodeInFavorites.children.filter((temp) => !((temp.label === node.label) && (temp.contextValue.startsWith(node.contextValue)))); - if (startLength !== this.mFavorites.length) { + if (startLength !== profileNodeInFavorites.children.length) { await this.updateFavorites(); this.refreshElement(this.mFavoriteSession); } From d9b1341b0c8d7de6b2963ec5e838114ac85915cc Mon Sep 17 00:00:00 2001 From: Lauren Li <45975633+lauren-li@users.noreply.github.com> Date: Mon, 24 Aug 2020 15:19:39 -0400 Subject: [PATCH 05/26] Update Jobs addFavorite for saving searches Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- package.json | 2 +- src/job/ZosJobsProvider.ts | 43 ++++++++++++++------------------------ 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/package.json b/package.json index 3089e34aab..db553ddb70 100644 --- a/package.json +++ b/package.json @@ -875,7 +875,7 @@ }, { "when": "view == zowe.jobs && viewItem =~ /^(?!.*_fav.*)server.*/", - "command": "zowe.jobs.saveSearch", + "command": "zowe.jobs.addFavorite", "group": "2_workspace@0" }, { diff --git a/src/job/ZosJobsProvider.ts b/src/job/ZosJobsProvider.ts index 1a91a933f9..d13c04d23a 100644 --- a/src/job/ZosJobsProvider.ts +++ b/src/job/ZosJobsProvider.ts @@ -89,26 +89,16 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree tempNode.label === favJob.label)) { - this.mFavorites.push(favJob); - sortTreeItems(this.mFavorites, favSessionContext); - await this.updateFavorites(); - this.refreshElement(this.mFavoriteSession); - } + return favJob; } public saveFile(document: vscode.TextDocument) { throw new Error("Method not implemented."); @@ -341,6 +331,7 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree tempNode.label === favJob.label)) { profileNodeInFavorites.children.push(favJob); sortTreeItems(profileNodeInFavorites.children, globals.JOBS_SESSION_CONTEXT + globals.FAV_SUFFIX); @@ -402,12 +401,6 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree 0; - let sesNamePrompt: string; - if (contextually.isFavorite(node)) { - sesNamePrompt = node.label.substring(1, node.label.indexOf("]")); - } else { - sesNamePrompt = node.label; - } await this.checkCurrentProfile(node); if (Profiles.getInstance().validProfile === ValidProfileEnum.VALID) { if (contextually.isSessionNotFav(node)) { // This is the profile object context @@ -515,8 +508,8 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree tempNode.label.trim() === session); @@ -651,15 +644,11 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree Date: Mon, 24 Aug 2020 17:31:53 -0400 Subject: [PATCH 06/26] Fix tooltips in Job favorites Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- src/api/IZoweTreeNode.ts | 4 ++++ src/job/ZosJobsProvider.ts | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/src/api/IZoweTreeNode.ts b/src/api/IZoweTreeNode.ts index a70d8f4278..c9766f5a38 100644 --- a/src/api/IZoweTreeNode.ts +++ b/src/api/IZoweTreeNode.ts @@ -240,6 +240,10 @@ export interface IZoweUSSTreeNode extends IZoweTreeNode { * @interface export interface IZoweJobTreeNode extends IZoweTreeNode { */ export interface IZoweJobTreeNode extends IZoweTreeNode { + /** + * Use Job-specific tree node for children. + */ + children?: IZoweJobTreeNode[]; /** * Standard job response document * Represents the attributes and status of a z/OS batch job diff --git a/src/job/ZosJobsProvider.ts b/src/job/ZosJobsProvider.ts index d13c04d23a..3e0a0b99c6 100644 --- a/src/job/ZosJobsProvider.ts +++ b/src/job/ZosJobsProvider.ts @@ -293,6 +293,7 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree Date: Mon, 24 Aug 2020 17:53:56 -0400 Subject: [PATCH 07/26] Update Job Node getChildren for new favorites labeling Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- src/job/ZoweJobNode.ts | 4 +--- src/job/actions.ts | 7 +------ 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/job/ZoweJobNode.ts b/src/job/ZoweJobNode.ts index 9125b9e55a..4ab1054b9a 100644 --- a/src/job/ZoweJobNode.ts +++ b/src/job/ZoweJobNode.ts @@ -83,9 +83,7 @@ export class Job extends ZoweTreeNode implements IZoweJobTreeNode { if (prefix === undefined) { prefix = spool.procstep; } - const sessionName = contextually.isFavorite(this) ? - this.label.substring(1, this.label.lastIndexOf("]")).trim() : - this.getProfileName(); + const sessionName = this.getProfileName(); const spoolNode = new Spool(`${spool.stepname}:${spool.ddname}(${spool.id})`, vscode.TreeItemCollapsibleState.None, this, this.session, spool, this.job, this); const icon = getIconByNode(spoolNode); diff --git a/src/job/actions.ts b/src/job/actions.ts index fc37062beb..635046e010 100644 --- a/src/job/actions.ts +++ b/src/job/actions.ts @@ -101,12 +101,6 @@ export async function getSpoolContent(jobsProvider: IZoweTree, * @param jobsProvider The tree to which the refreshed node belongs */ export async function refreshJobsServer(node: IZoweJobTreeNode, jobsProvider: IZoweTree) { - let sesNamePrompt: string; - if (node.contextValue.endsWith(globals.FAV_SUFFIX)) { - sesNamePrompt = node.label.substring(1, node.label.indexOf("]")); - } else { - sesNamePrompt = node.label; - } jobsProvider.checkCurrentProfile(node); if (Profiles.getInstance().validProfile === ValidProfileEnum.VALID) { await jobsProvider.refreshElement(node); @@ -165,6 +159,7 @@ export async function stopCommand(job: Job) { * @param job The job to set the owner of * @param jobsProvider The tree to which the updated node belongs */ +// Is this redundant with the setter in the Job class (ZoweJobNode.ts)? export async function setOwner(job: IZoweJobTreeNode, jobsProvider: IZoweTree) { const newOwner = await vscode.window.showInputBox({ prompt: localize("setOwner.newOwner.prompt.owner", "Owner") }); job.owner = newOwner; From 78f7de51abb03ec9842fa3d697dbf340266513ee Mon Sep 17 00:00:00 2001 From: Lauren Li <45975633+lauren-li@users.noreply.github.com> Date: Tue, 25 Aug 2020 03:03:00 -0400 Subject: [PATCH 08/26] Fix syncing of Jobs deleteSession with favorites Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- src/abstract/ZoweTreeProvider.ts | 3 --- src/job/ZosJobsProvider.ts | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/abstract/ZoweTreeProvider.ts b/src/abstract/ZoweTreeProvider.ts index 3e3aab2fdf..a12a592221 100644 --- a/src/abstract/ZoweTreeProvider.ts +++ b/src/abstract/ZoweTreeProvider.ts @@ -214,9 +214,6 @@ export class ZoweTreeProvider { } protected deleteSessionByLabel(revisedLabel: string) { - if (revisedLabel.includes("[")) { - revisedLabel = revisedLabel.substring(0, revisedLabel.indexOf(" [")); - } this.mHistory.removeSession(revisedLabel); this.refresh(); } diff --git a/src/job/ZosJobsProvider.ts b/src/job/ZosJobsProvider.ts index 3e0a0b99c6..8ee6ce60db 100644 --- a/src/job/ZosJobsProvider.ts +++ b/src/job/ZosJobsProvider.ts @@ -550,6 +550,7 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree tempNode.label.trim() !== node.label.trim()); + this.mFavorites = this.mFavorites.filter((tempNode) => tempNode.label.trim() !== node.label.trim()); this.deleteSessionByLabel(node.getLabel()); } From 8c92cc9d008a8adcf41a377e19402267519770b2 Mon Sep 17 00:00:00 2001 From: Lauren Li <45975633+lauren-li@users.noreply.github.com> Date: Tue, 25 Aug 2020 03:49:30 -0400 Subject: [PATCH 09/26] Fix unit tests for Jobs addFavorite and removeFavorite Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- __tests__/__unit__/job/ZoweJobNode.unit.test.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/__tests__/__unit__/job/ZoweJobNode.unit.test.ts b/__tests__/__unit__/job/ZoweJobNode.unit.test.ts index 6796be39ba..24e99a1064 100644 --- a/__tests__/__unit__/job/ZoweJobNode.unit.test.ts +++ b/__tests__/__unit__/job/ZoweJobNode.unit.test.ts @@ -22,6 +22,7 @@ import { Job } from "../../../src/job/ZoweJobNode"; import { Profiles, ValidProfileEnum } from "../../../src/Profiles"; import { createIProfile, createISession, createInstanceOfProfile, createISessionWithoutCredentials, createQuickPickContent } from "../../../__mocks__/mockCreators/shared"; import { ZoweExplorerApiRegister } from "../../../src/api/ZoweExplorerApiRegister"; +import { IZoweJobTreeNode } from "../../../src/api/IZoweTreeNode"; async function createGlobalMocks() { const globalMocks = { @@ -300,8 +301,14 @@ describe("ZoweJobNode unit tests - Function addFavorite", () => { await globalMocks.testJobsProvider.addFavorite(blockMocks.testJobNode); + const profileNodeInFavs: IZoweJobTreeNode = globalMocks.testJobsProvider.mFavorites[0]; + const favoritedNode = profileNodeInFavs.children[0]; + expect(globalMocks.testJobsProvider.mFavorites.length).toEqual(1); - expect(globalMocks.testJobsProvider.mFavorites[0].label).toEqual("[sestest]: MYHLQ(JOB1283)"); + expect(profileNodeInFavs.label).toEqual("sestest"); + expect(profileNodeInFavs.children.length).toEqual(1); + expect(favoritedNode.label).toEqual("MYHLQ(JOB1283)"); + }); }); @@ -322,12 +329,14 @@ describe("ZoweJobNode unit tests - Function removeFavorite", () => { globalMocks.testJobsProvider.mFavorites = []; await globalMocks.testJobsProvider.addFavorite(blockMocks.testJobNode); + const profileNodeInFavs: IZoweJobTreeNode = globalMocks.testJobsProvider.mFavorites[0]; + const favoritedNode = profileNodeInFavs.children[0]; - expect(globalMocks.testJobsProvider.mFavorites.length).toEqual(1); + expect(profileNodeInFavs.children.length).toEqual(1); - await globalMocks.testJobsProvider.removeFavorite(globalMocks.testJobsProvider.mFavorites[0]); + await globalMocks.testJobsProvider.removeFavorite(favoritedNode); - expect(globalMocks.testJobsProvider.mFavorites.length).toEqual(0); + expect(profileNodeInFavs.children.length).toEqual(0); }); }); From d16e23bc77809368e2f2e21b52a4d581a235aa59 Mon Sep 17 00:00:00 2001 From: Lauren Li <45975633+lauren-li@users.noreply.github.com> Date: Tue, 25 Aug 2020 05:09:13 -0400 Subject: [PATCH 10/26] Add unit test for adding favorite search Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- .../__unit__/job/ZoweJobNode.unit.test.ts | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/__tests__/__unit__/job/ZoweJobNode.unit.test.ts b/__tests__/__unit__/job/ZoweJobNode.unit.test.ts index 24e99a1064..e13b016053 100644 --- a/__tests__/__unit__/job/ZoweJobNode.unit.test.ts +++ b/__tests__/__unit__/job/ZoweJobNode.unit.test.ts @@ -296,7 +296,6 @@ describe("ZoweJobNode unit tests - Function addFavorite", () => { it("Tests that addFavorite successfully favorites a job", async () => { const globalMocks = await createGlobalMocks(); const blockMocks = await createBlockMocks(globalMocks); - globalMocks.testJobsProvider.mFavorites = []; await globalMocks.testJobsProvider.addFavorite(blockMocks.testJobNode); @@ -308,7 +307,19 @@ describe("ZoweJobNode unit tests - Function addFavorite", () => { expect(profileNodeInFavs.label).toEqual("sestest"); expect(profileNodeInFavs.children.length).toEqual(1); expect(favoritedNode.label).toEqual("MYHLQ(JOB1283)"); + }); + it("Tests that addFavorite successfully favorites a search", async () => { + const globalMocks = await createGlobalMocks(); + await createBlockMocks(globalMocks); + globalMocks.testJobsProvider.mFavorites = []; + globalMocks.testJobsProvider.mSessionNodes[1].owner = "myHLQ"; + globalMocks.testJobsProvider.mSessionNodes[1].prefix = "*"; + + await globalMocks.testJobsProvider.addFavorite(globalMocks.testJobsProvider.mSessionNodes[1]); + const profileNodeInFavs: IZoweJobTreeNode = globalMocks.testJobsProvider.mFavorites[0]; + expect(profileNodeInFavs.children.length).toEqual(1); + expect(profileNodeInFavs.children[0].label).toEqual("Owner:myHLQ Prefix:*"); }); }); @@ -342,9 +353,11 @@ describe("ZoweJobNode unit tests - Function removeFavorite", () => { describe("ZoweJobNode unit tests - Function saveSearch", () => { async function createBlockMocks(globalMocks) { + const testSession = globalMocks.testJobsProvider.mSessionNodes[1].getSession(); const newMocks = { + testSession, testJobNode: new Job("MYHLQ(JOB1283) - Input", vscode.TreeItemCollapsibleState.Collapsed, globalMocks.testJobsProvider.mSessionNodes[1], - globalMocks.testJobsProvider.mSessionNodes[1].getSession(), globalMocks.testIJob, globalMocks.testProfile) + testSession, globalMocks.testIJob, globalMocks.testProfile) }; globalMocks.testJobsProvider.mFavorites = []; @@ -364,15 +377,21 @@ describe("ZoweJobNode unit tests - Function saveSearch", () => { it("Tests that saveSearch is executed successfully when owner is set", async () => { const globalMocks = await createGlobalMocks(); - await createBlockMocks(globalMocks); + const blockMocks = await createBlockMocks(globalMocks); globalMocks.testJobsProvider.mSessionNodes[1].owner = "myHLQ"; globalMocks.testJobsProvider.mSessionNodes[1].prefix = "*"; - await globalMocks.testJobsProvider.saveSearch(globalMocks.testJobsProvider.mSessionNodes[1]); - - expect(globalMocks.testJobsProvider.mFavorites.length).toEqual(1); - expect(globalMocks.testJobsProvider.mFavorites[0].label).toEqual("[sestest]: Owner:myHLQ Prefix:*"); + const favJob = await globalMocks.testJobsProvider.saveSearch(globalMocks.testJobsProvider.mSessionNodes[1]); + const profileNodeInFavs: IZoweJobTreeNode = globalMocks.testJobsProvider.mFavorites[0]; + const expectedJob = new Job("Owner:myHLQ Prefix:*", vscode.TreeItemCollapsibleState.None, profileNodeInFavs, + blockMocks.testSession, globalMocks.testIJob, globalMocks.testProfile); + favJob.contextValue = globals.JOBS_SESSION_CONTEXT + globals.FAV_SUFFIX; + favJob.command = { command: "zowe.jobs.search", title: "", arguments: [favJob] }; + + expect(favJob).toEqual(expectedJob); + // expect(profileNodeInFavs.children.length).toEqual(1); + // expect(profileNodeInFavs.children[0].label).toEqual("Owner:myHLQ Prefix:*"); }); it("Tests that saveSearch is executed successfully when prefix is set", async () => { From e505028c17d2e6a9825c09556d6ac1393b460fca Mon Sep 17 00:00:00 2001 From: Lauren Li <45975633+lauren-li@users.noreply.github.com> Date: Tue, 25 Aug 2020 09:27:32 -0400 Subject: [PATCH 11/26] Correct mParent when adding job/search favorites Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- src/job/ZosJobsProvider.ts | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/job/ZosJobsProvider.ts b/src/job/ZosJobsProvider.ts index 8ee6ce60db..fe47e2b583 100644 --- a/src/job/ZosJobsProvider.ts +++ b/src/job/ZosJobsProvider.ts @@ -89,16 +89,12 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree Date: Tue, 25 Aug 2020 13:42:40 -0400 Subject: [PATCH 12/26] Update Jobs saveSearch and related unit tests Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- .../__unit__/job/ZoweJobNode.unit.test.ts | 57 +++---------------- src/job/ZosJobsProvider.ts | 5 +- 2 files changed, 11 insertions(+), 51 deletions(-) diff --git a/__tests__/__unit__/job/ZoweJobNode.unit.test.ts b/__tests__/__unit__/job/ZoweJobNode.unit.test.ts index e13b016053..ed783d3d14 100644 --- a/__tests__/__unit__/job/ZoweJobNode.unit.test.ts +++ b/__tests__/__unit__/job/ZoweJobNode.unit.test.ts @@ -362,63 +362,24 @@ describe("ZoweJobNode unit tests - Function saveSearch", () => { globalMocks.testJobsProvider.mFavorites = []; globalMocks.testJobNode.label = "MYHLQ(JOB1283) - Input"; - globalMocks.getConfiguration.mockReturnValue({ - get: (setting: string) => [ - "[sestest]: Owner:stonecc Prefix:*{server}", - "[sestest]: USER1(JOB30148){job}", - ], - update: jest.fn(()=>{ - return {}; - }) - }); return newMocks; } - it("Tests that saveSearch is executed successfully when owner is set", async () => { + it("Tests that saveSearch is executed successfully", async () => { const globalMocks = await createGlobalMocks(); const blockMocks = await createBlockMocks(globalMocks); + const favJob = blockMocks.testJobNode; + favJob.owner = "myHLQ"; + favJob.prefix = "*"; + favJob.contextValue = globals.JOBS_SESSION_CONTEXT; - globalMocks.testJobsProvider.mSessionNodes[1].owner = "myHLQ"; - globalMocks.testJobsProvider.mSessionNodes[1].prefix = "*"; - - const favJob = await globalMocks.testJobsProvider.saveSearch(globalMocks.testJobsProvider.mSessionNodes[1]); - const profileNodeInFavs: IZoweJobTreeNode = globalMocks.testJobsProvider.mFavorites[0]; - const expectedJob = new Job("Owner:myHLQ Prefix:*", vscode.TreeItemCollapsibleState.None, profileNodeInFavs, - blockMocks.testSession, globalMocks.testIJob, globalMocks.testProfile); - favJob.contextValue = globals.JOBS_SESSION_CONTEXT + globals.FAV_SUFFIX; - favJob.command = { command: "zowe.jobs.search", title: "", arguments: [favJob] }; - - expect(favJob).toEqual(expectedJob); - // expect(profileNodeInFavs.children.length).toEqual(1); - // expect(profileNodeInFavs.children[0].label).toEqual("Owner:myHLQ Prefix:*"); - }); - - it("Tests that saveSearch is executed successfully when prefix is set", async () => { - const globalMocks = await createGlobalMocks(); - await createBlockMocks(globalMocks); - - globalMocks.testJobsProvider.mSessionNodes[1].owner = "*"; - globalMocks.testJobsProvider.mSessionNodes[1].prefix = "aH*"; + const expectedJob = favJob; + expectedJob.contextValue = globals.JOBS_SESSION_CONTEXT + globals.FAV_SUFFIX; - await globalMocks.testJobsProvider.saveSearch(globalMocks.testJobsProvider.mSessionNodes[1]); + const savedFavJob = await globalMocks.testJobsProvider.saveSearch(favJob); - expect(globalMocks.testJobsProvider.mFavorites.length).toEqual(1); - expect(globalMocks.testJobsProvider.mFavorites[0].label).toEqual("[sestest]: Owner:* Prefix:aH*"); - }); - - it("Tests that saveSearch is executed successfully when searchId is set", async () => { - const globalMocks = await createGlobalMocks(); - await createBlockMocks(globalMocks); - - globalMocks.testJobsProvider.mSessionNodes[1].owner = "*"; - globalMocks.testJobsProvider.mSessionNodes[1].prefix = "*"; - globalMocks.testJobsProvider.mSessionNodes[1].searchId = "JOB1234"; - - await globalMocks.testJobsProvider.saveSearch(globalMocks.testJobsProvider.mSessionNodes[1]); - - expect(globalMocks.testJobsProvider.mFavorites.length).toEqual(1); - expect(globalMocks.testJobsProvider.mFavorites[0].label).toEqual("[sestest]: JobId:JOB1234"); + expect(savedFavJob).toEqual(expectedJob); }); }); diff --git a/src/job/ZosJobsProvider.ts b/src/job/ZosJobsProvider.ts index fe47e2b583..f8110c8230 100644 --- a/src/job/ZosJobsProvider.ts +++ b/src/job/ZosJobsProvider.ts @@ -90,9 +90,6 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree Date: Wed, 26 Aug 2020 12:22:26 -0400 Subject: [PATCH 13/26] Add unit tests for Jobs Tree getChildren Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- __mocks__/mockCreators/jobs.ts | 15 ++ .../__unit__/job/ZosJobsProvider.unit.test.ts | 222 ++++++++++++++++++ 2 files changed, 237 insertions(+) create mode 100644 __tests__/__unit__/job/ZosJobsProvider.unit.test.ts diff --git a/__mocks__/mockCreators/jobs.ts b/__mocks__/mockCreators/jobs.ts index 213e41053a..eaf649e897 100644 --- a/__mocks__/mockCreators/jobs.ts +++ b/__mocks__/mockCreators/jobs.ts @@ -95,3 +95,18 @@ export function createJobsTree(session: imperative.Session, iJob: zowe.IJob, pro return testJobsTree; } + +export function createJobSessionNode(session: imperative.Session, profile: imperative.IProfileLoaded) { + const jobSessionNode = new Job("sestest", vscode.TreeItemCollapsibleState.Collapsed, + null, session, null, profile); + jobSessionNode.contextValue = globals.JOBS_SESSION_CONTEXT; + + return jobSessionNode; +} + +export function createJobFavoritesNode() { + const jobFavoritesNode = new Job("Favorites", vscode.TreeItemCollapsibleState.Collapsed, null, null, null, null); + jobFavoritesNode.contextValue = globals.FAVORITE_CONTEXT; + + return jobFavoritesNode; +} diff --git a/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts b/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts new file mode 100644 index 0000000000..65fd22f00e --- /dev/null +++ b/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts @@ -0,0 +1,222 @@ +/* +* This program and the accompanying materials are made available under the terms of the * +* Eclipse Public License v2.0 which accompanies this distribution, and is available at * +* https://www.eclipse.org/legal/epl-v20.html * +* * +* SPDX-License-Identifier: EPL-2.0 * +* * +* Copyright Contributors to the Zowe Project. * +* * +*/ + +jest.mock("@zowe/cli"); +jest.mock("@zowe/imperative"); +import { createJobsTree, ZosJobsProvider } from "../../../src/job/ZosJobsProvider"; +import * as vscode from "vscode"; +import * as zowe from "@zowe/cli"; +import * as globals from "../../../src/globals"; +import * as utils from "../../../src/utils"; +import { Logger } from "@zowe/imperative"; +import { createIJobFile, createIJobObject, createJobFavoritesNode, createJobSessionNode } from "../../../__mocks__/mockCreators/jobs"; +import { Job } from "../../../src/job/ZoweJobNode"; +import { Profiles, ValidProfileEnum } from "../../../src/Profiles"; +import { createIProfile, createISession, createInstanceOfProfile, createISessionWithoutCredentials, createQuickPickContent, createTreeView } from "../../../__mocks__/mockCreators/shared"; +import { ZoweExplorerApiRegister } from "../../../src/api/ZoweExplorerApiRegister"; +import { getIconByNode } from "../../../src/generators/icons"; + +async function createGlobalMocks() { + const globalMocks = { + mockGetConfiguration: jest.fn(), + mockGetJobs: jest.fn(), + mockGetJob: jest.fn(), + mockRefresh: jest.fn(), + mockAffectsConfig: jest.fn(), + createTreeView: jest.fn(), + mockCreateBasicZosmfSession: jest.fn(), + mockGetSpoolFiles: jest.fn(), + mockDeleteJobs: jest.fn(), + mockShowInputBox: jest.fn(), + mockDeleteJob: jest.fn(), + mockGetJobsByOwnerAndPrefix: jest.fn(), + mockShowInformationMessage: jest.fn(), + mockLoadNamedProfile: jest.fn(), + mockCreateQuickPick: jest.fn(), + mockLoadDefaultProfile: jest.fn(), + mockGetJesApi: jest.fn(), + mockShowQuickPick: jest.fn(), + testJobsProvider: null, + jesApi: null, + testSession: createISession(), + testSessionNoCred: createISessionWithoutCredentials(), + testProfile: createIProfile(), + testIJob: createIJobObject(), + testIJobComplete: createIJobObject(), + testJobNode: null, + testSessionNode: null, + mockIJobFile: createIJobFile(), + mockProfileInstance: null, + withProgress: jest.fn().mockImplementation((progLocation, callback) => { + return callback(); + }), + ProgressLocation: jest.fn().mockImplementation(() => { + return { + Notification: 15 + }; + }), + enums: jest.fn().mockImplementation(() => { + return { + Global: 1, + Workspace: 2, + WorkspaceFolder: 3 + }; + }) + }; + + Object.defineProperty(vscode, "ProgressLocation", { value: globalMocks.ProgressLocation, configurable: true }); + Object.defineProperty(vscode.window, "withProgress", { value: globalMocks.withProgress, configurable: true }); + Object.defineProperty(zowe, "GetJobs", { value: globalMocks.mockGetJobs, configurable: true }); + Object.defineProperty(vscode.window, "showInformationMessage", { value: globalMocks.mockShowInformationMessage, configurable: true }); + Object.defineProperty(globalMocks.mockGetJobs, "getJob", { value: globalMocks.mockGetJob, configurable: true }); + Object.defineProperty(globalMocks.mockGetJobs, "getJobsByOwnerAndPrefix", { value: globalMocks.mockGetJobsByOwnerAndPrefix, configurable: true }); + Object.defineProperty(zowe.ZosmfSession, "createBasicZosmfSession", { value: globalMocks.mockCreateBasicZosmfSession, configurable: true }); + Object.defineProperty(globalMocks.mockGetJobs, "getSpoolFiles", { value: globalMocks.mockGetSpoolFiles, configurable: true }); + Object.defineProperty(vscode.window, "createTreeView", { value: globalMocks.createTreeView, configurable: true }); + Object.defineProperty(vscode.window, "showQuickPick", { value: globalMocks.mockShowQuickPick, configurable: true }); + Object.defineProperty(vscode, "ConfigurationTarget", { value: globalMocks.enums, configurable: true }); + Object.defineProperty(vscode.window, "showInputBox", { value: globalMocks.mockShowInputBox, configurable: true }); + Object.defineProperty(vscode.workspace, "getConfiguration", { value: globalMocks.mockGetConfiguration, configurable: true }); + Object.defineProperty(Profiles, "getInstance", { value: jest.fn(() => globalMocks.mockProfileInstance), configurable: true }); + Object.defineProperty(zowe, "DeleteJobs", { value: globalMocks.mockDeleteJobs, configurable: true }); + Object.defineProperty(vscode.window, "createQuickPick", { value: globalMocks.mockCreateQuickPick, configurable: true }); + Object.defineProperty(globalMocks.mockDeleteJobs, "deleteJob", { value: globalMocks.mockDeleteJob, configurable: true }); + + // Profile instance mocks + globalMocks.mockProfileInstance = createInstanceOfProfile(globalMocks.testProfile); + globalMocks.mockGetSpoolFiles.mockReturnValue([globalMocks.mockIJobFile]); + globalMocks.mockLoadNamedProfile.mockReturnValue(globalMocks.testProfile); + globalMocks.mockProfileInstance.loadNamedProfile = globalMocks.mockLoadNamedProfile; + globalMocks.mockLoadDefaultProfile.mockReturnValue(globalMocks.testProfile); + globalMocks.mockProfileInstance.getDefaultProfile = globalMocks.mockLoadDefaultProfile; + + // Jes API mocks + globalMocks.jesApi = ZoweExplorerApiRegister.getJesApi(globalMocks.testProfile); + globalMocks.mockGetJesApi.mockReturnValue(globalMocks.jesApi); + ZoweExplorerApiRegister.getJesApi = globalMocks.mockGetJesApi.bind(ZoweExplorerApiRegister); + + globalMocks.mockCreateBasicZosmfSession.mockReturnValue(globalMocks.testSession); + globalMocks.createTreeView.mockReturnValue("testTreeView"); + globalMocks.mockGetJob.mockReturnValue(globalMocks.testIJob); + globalMocks.mockGetJobsByOwnerAndPrefix.mockReturnValue([globalMocks.testIJob, globalMocks.testIJobComplete]); + globalMocks.mockProfileInstance.editSession = jest.fn(() => globalMocks.testProfile); + globalMocks.testJobNode = new Job("jobtest", vscode.TreeItemCollapsibleState.Expanded, + null, globalMocks.testSession, globalMocks.testIJob, globalMocks.testProfile); + globalMocks.testJobNode.contextValue = "job"; + globalMocks.testJobNode.dirty = true; + globalMocks.testIJobComplete.jobid = "JOB1235"; + globalMocks.testIJobComplete.retcode = "0"; + globalMocks.testSessionNode = new Job("sestest", vscode.TreeItemCollapsibleState.Collapsed, + null, globalMocks.testSession, null, globalMocks.testProfile); + globalMocks.testSessionNode.contextValue = globals.JOBS_SESSION_CONTEXT; + globalMocks.mockGetConfiguration.mockReturnValue({ + persistence: true, + get: (setting: string) => [], + // tslint:disable-next-line: no-empty + update: jest.fn(()=>{ {} }) + }); + globalMocks.testJobsProvider = await createJobsTree(Logger.getAppLogger()); + Object.defineProperty(globalMocks.testJobsProvider, "refresh", { value: globalMocks.mockRefresh, configurable: true }); + + return globalMocks; +} + +// Idea is borrowed from: https://github.com/kulshekhar/ts-jest/blob/master/src/util/testing.ts +const mocked = any>(fn: T): jest.Mock> => fn as any; + +describe("ZosJobsProvider unit tests - Function getChildren", () => { + function createBlockMocks() { + const imperativeProfile = createIProfile(); + const profile = createInstanceOfProfile(imperativeProfile); + const session = createISession(); + const jobSessionNode = createJobSessionNode(session, imperativeProfile); + const jobFavoritesNode = createJobFavoritesNode(); + const treeView = createTreeView(); + const testIJob = createIJobObject(); + + return { + profile, + session, + jobSessionNode, + jobFavoritesNode, + treeView, + testIJob + }; + } + + it("Tests that getChildren returns the Favorites and sessions when called at the root node", async () => { + createGlobalMocks(); + const blockMocks = createBlockMocks(); + mocked(vscode.window.createTreeView).mockReturnValueOnce(blockMocks.treeView); + const testTree = new ZosJobsProvider(); + testTree.mSessionNodes.push(blockMocks.jobSessionNode); + const targetIcon = getIconByNode(blockMocks.jobFavoritesNode); + if (targetIcon) { + blockMocks.jobFavoritesNode.iconPath = targetIcon.path; + } + + const children = await testTree.getChildren(); + + expect(blockMocks.jobFavoritesNode).toMatchObject(children[0]); + expect(blockMocks.jobSessionNode).toMatchObject(children[1]); + + }); + it("Tests that getChildren returns favorites profile node when called on Favorites", async () => { + createGlobalMocks(); + const blockMocks = createBlockMocks(); + mocked(vscode.window.createTreeView).mockReturnValueOnce(blockMocks.treeView); + + const testTree = new ZosJobsProvider(); + const favoriteSessionNode = blockMocks.jobFavoritesNode; + const favProfileNode = new Job("sestest", vscode.TreeItemCollapsibleState.Collapsed, + favoriteSessionNode, null, null, null); + favProfileNode.contextValue = globals.FAV_PROFILE_CONTEXT; + testTree.mFavorites.push(favProfileNode); + + const children = await testTree.getChildren(favoriteSessionNode); + + expect(children).toEqual([favProfileNode]); + }); + it("Tests that getChildren gets profile-loaded favorites for profile node in Favorites section ", async () => { + createGlobalMocks(); + const blockMocks = createBlockMocks(); + mocked(vscode.window.createTreeView).mockReturnValueOnce(blockMocks.treeView); + + const testTree = new ZosJobsProvider(); + const log = Logger.getAppLogger(); + const favProfileNode = new Job("sestest", vscode.TreeItemCollapsibleState.Collapsed, + blockMocks.jobFavoritesNode, null, null, null); + favProfileNode.contextValue = globals.FAV_PROFILE_CONTEXT; + testTree.mFavorites.push(favProfileNode); + + const loadProfilesForFavoritesSpy= jest.spyOn(testTree, "loadProfilesForFavorites"); + + await testTree.getChildren(favProfileNode); + + expect(loadProfilesForFavoritesSpy).toHaveBeenCalledWith(log, favProfileNode); + }); + it("Tests that getChildren gets children of a session element", async () => { + createGlobalMocks(); + const blockMocks = createBlockMocks(); + mocked(Profiles.getInstance).mockReturnValue(blockMocks.profile); + mocked(vscode.window.createTreeView).mockReturnValueOnce(blockMocks.treeView); + + const testTree = new ZosJobsProvider(); + testTree.mSessionNodes.push(blockMocks.jobSessionNode); + testTree.mSessionNodes[1].dirty = true; + const sessionElement = testTree.mSessionNodes[1]; + const elementGetChildrenSpy = jest.spyOn(sessionElement, "getChildren"); + + await testTree.getChildren(testTree.mSessionNodes[1]); + + expect(elementGetChildrenSpy).toHaveBeenCalledTimes(1); + }); +}); From dfb87f344c3156bdb74cb43e699eec023b3e2fae Mon Sep 17 00:00:00 2001 From: Lauren Li <45975633+lauren-li@users.noreply.github.com> Date: Wed, 26 Aug 2020 13:38:14 -0400 Subject: [PATCH 14/26] Add unit tests for Jobs initializeFavChildNodeForProfile Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- __mocks__/mockCreators/jobs.ts | 23 +++++++ .../__unit__/job/ZosJobsProvider.unit.test.ts | 62 ++++++++++++++++++- 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/__mocks__/mockCreators/jobs.ts b/__mocks__/mockCreators/jobs.ts index eaf649e897..6ab962ca95 100644 --- a/__mocks__/mockCreators/jobs.ts +++ b/__mocks__/mockCreators/jobs.ts @@ -110,3 +110,26 @@ export function createJobFavoritesNode() { return jobFavoritesNode; } + +// Because the JobDetail class in ZosJobsProvider.ts is not exported: +export class MockJobDetail implements zowe.IJob { + public jobid: string; + public jobname: string; + public subsystem: string; + public owner: string; + public status: string; + public type: string; + public class: string; + public retcode: string; + public url: string; + public "files-url": string; + public "job-correlator": string; + public phase: number; + public "phase-name": string; + public "reason-not-running"?: string; + + constructor(combined: string) { + this.jobname = combined.substring(0, combined.indexOf("(")); + this.jobid = combined.substring(combined.indexOf("(") + 1, combined.indexOf(")")); + } +} diff --git a/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts b/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts index 65fd22f00e..4662d92a5a 100644 --- a/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts +++ b/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts @@ -17,7 +17,7 @@ import * as zowe from "@zowe/cli"; import * as globals from "../../../src/globals"; import * as utils from "../../../src/utils"; import { Logger } from "@zowe/imperative"; -import { createIJobFile, createIJobObject, createJobFavoritesNode, createJobSessionNode } from "../../../__mocks__/mockCreators/jobs"; +import { createIJobFile, createIJobObject, createJobFavoritesNode, createJobSessionNode, MockJobDetail } from "../../../__mocks__/mockCreators/jobs"; import { Job } from "../../../src/job/ZoweJobNode"; import { Profiles, ValidProfileEnum } from "../../../src/Profiles"; import { createIProfile, createISession, createInstanceOfProfile, createISessionWithoutCredentials, createQuickPickContent, createTreeView } from "../../../__mocks__/mockCreators/shared"; @@ -220,3 +220,63 @@ describe("ZosJobsProvider unit tests - Function getChildren", () => { expect(elementGetChildrenSpy).toHaveBeenCalledTimes(1); }); }); + +describe("ZosJobsProvider unit tests - Function initializeFavChildNodeForProfile", () => { + function createBlockMocks() { + const session = createISession(); + const imperativeProfile = createIProfile(); + const jobSessionNode = createJobSessionNode(session, imperativeProfile); + const jobFavoritesNode = createJobFavoritesNode(); + + return { + imperativeProfile, + session, + jobSessionNode, + jobFavoritesNode + }; + } + it("Checks that profile-less node is initiated for favorited Job", async () => { + createGlobalMocks(); + const blockMocks = createBlockMocks(); + const testTree = new ZosJobsProvider(); + + const favProfileNode = new Job("testProfile", vscode.TreeItemCollapsibleState.Collapsed, + blockMocks.jobFavoritesNode, null, null, null); + favProfileNode.contextValue = globals.FAV_PROFILE_CONTEXT; + const node = new Job("testJob(JOB123)", vscode.TreeItemCollapsibleState.Collapsed, + favProfileNode, null, new MockJobDetail("testJob(JOB123)"), null); + node.contextValue = globals.JOBS_JOB_CONTEXT + globals.FAV_SUFFIX; + node.command = {command: "zowe.zosJobsSelectjob", title: "", arguments: [node]}; + const targetIcon = getIconByNode(node); + if (targetIcon) { + node.iconPath = targetIcon.path; + } + + const favChildNodeForProfile = await testTree.initializeFavChildNodeForProfile("testJob(JOB123)", globals.JOBS_JOB_CONTEXT, favProfileNode); + + expect(favChildNodeForProfile).toEqual(node); + }); + it("Checks that profile-less node is initiated for favorited search", async () => { + createGlobalMocks(); + const blockMocks = createBlockMocks(); + const testTree = new ZosJobsProvider(); + + const favProfileNode = new Job("testProfile", vscode.TreeItemCollapsibleState.Collapsed, + blockMocks.jobFavoritesNode, null, null, null); + favProfileNode.contextValue = globals.FAV_PROFILE_CONTEXT; + const node = new Job("Owner:USER Prefix:*", vscode.TreeItemCollapsibleState.None, + testTree.mFavoriteSession, null, null, null); + node.command = {command: "zowe.jobs.search", title: "", arguments: [node]}; + node.contextValue = globals.JOBS_SESSION_CONTEXT + globals.FAV_SUFFIX; + const targetIcon = getIconByNode(node); + if (targetIcon) { + node.iconPath = targetIcon.path; + } + + const favChildNodeForProfile = await testTree.initializeFavChildNodeForProfile( + "Owner:USER Prefix:*", globals.JOBS_SESSION_CONTEXT, favProfileNode + ); + + expect(favChildNodeForProfile).toEqual(node); + }); +}); From df0a033c2b68df3f3c9e5caf1fc12ea46033768f Mon Sep 17 00:00:00 2001 From: Lauren Li <45975633+lauren-li@users.noreply.github.com> Date: Wed, 26 Aug 2020 13:42:26 -0400 Subject: [PATCH 15/26] Correct parent node for saved Jobs search in initializeFavChildNodeForProfile Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- __tests__/__unit__/job/ZosJobsProvider.unit.test.ts | 2 +- src/job/ZosJobsProvider.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts b/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts index 4662d92a5a..4ba615fa82 100644 --- a/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts +++ b/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts @@ -265,7 +265,7 @@ describe("ZosJobsProvider unit tests - Function initializeFavChildNodeForProfile blockMocks.jobFavoritesNode, null, null, null); favProfileNode.contextValue = globals.FAV_PROFILE_CONTEXT; const node = new Job("Owner:USER Prefix:*", vscode.TreeItemCollapsibleState.None, - testTree.mFavoriteSession, null, null, null); + favProfileNode, null, null, null); node.command = {command: "zowe.jobs.search", title: "", arguments: [node]}; node.contextValue = globals.JOBS_SESSION_CONTEXT + globals.FAV_SUFFIX; const targetIcon = getIconByNode(node); diff --git a/src/job/ZosJobsProvider.ts b/src/job/ZosJobsProvider.ts index f8110c8230..10049ec0dc 100644 --- a/src/job/ZosJobsProvider.ts +++ b/src/job/ZosJobsProvider.ts @@ -256,7 +256,7 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree Date: Wed, 26 Aug 2020 15:29:21 -0400 Subject: [PATCH 16/26] Add unit tests for Jobs loadProfilesForFavorites Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- .../__unit__/job/ZosJobsProvider.unit.test.ts | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts b/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts index 4ba615fa82..62ad77c455 100644 --- a/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts +++ b/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts @@ -23,6 +23,7 @@ import { Profiles, ValidProfileEnum } from "../../../src/Profiles"; import { createIProfile, createISession, createInstanceOfProfile, createISessionWithoutCredentials, createQuickPickContent, createTreeView } from "../../../__mocks__/mockCreators/shared"; import { ZoweExplorerApiRegister } from "../../../src/api/ZoweExplorerApiRegister"; import { getIconByNode } from "../../../src/generators/icons"; +import { createJesApi } from "../../../__mocks__/mockCreators/api"; async function createGlobalMocks() { const globalMocks = { @@ -280,3 +281,123 @@ describe("ZosJobsProvider unit tests - Function initializeFavChildNodeForProfile expect(favChildNodeForProfile).toEqual(node); }); }); + +describe("ZosJobsProvider unit tests - Function loadProfilesForFavorites", () => { + function createBlockMocks() { + const log = Logger.getAppLogger(); + const imperativeProfile = createIProfile(); + const session = createISession(); + const jobFavoritesNode = createJobFavoritesNode(); + const jesApi = createJesApi(imperativeProfile); + + return { + log, + imperativeProfile, + session, + jobFavoritesNode, + jesApi + }; + } + + it("Checks that loaded profile and session values are added to the profile grouping node in Favorites", async () => { + createGlobalMocks(); + const blockMocks = createBlockMocks(); + const favProfileNode = new Job("testProfile", vscode.TreeItemCollapsibleState.Collapsed, + blockMocks.jobFavoritesNode, null, null, null); + favProfileNode.contextValue = globals.FAV_PROFILE_CONTEXT; + const testTree = new ZosJobsProvider(); + testTree.mFavorites.push(favProfileNode); + const expectedFavProfileNode = new Job("testProfile", vscode.TreeItemCollapsibleState.Collapsed, + blockMocks.jobFavoritesNode, blockMocks.session, null, blockMocks.imperativeProfile); + expectedFavProfileNode.contextValue = globals.FAV_PROFILE_CONTEXT; + + // Mock successful loading of profile/session + Object.defineProperty(Profiles, "getInstance", { + value: jest.fn(() => { + return { + loadNamedProfile: jest.fn(() => { + return blockMocks.imperativeProfile; + }), + }; + }) + }); + Object.defineProperty(blockMocks.jesApi, "getSession", { + value: jest.fn(() => { + return blockMocks.session; + }) + }); + + await testTree.loadProfilesForFavorites(blockMocks.log, favProfileNode); + const resultFavProfileNode = testTree.mFavorites[0]; + + expect(resultFavProfileNode).toEqual(expectedFavProfileNode); + }); + it("Checks that the error is handled if profile fails to load", async () => { + createGlobalMocks(); + const blockMocks = createBlockMocks(); + const testTree = new ZosJobsProvider(); + const favProfileNode = new Job("badTestProfile", vscode.TreeItemCollapsibleState.Collapsed, + blockMocks.jobFavoritesNode, null, null, null); + favProfileNode.contextValue = globals.FAV_PROFILE_CONTEXT; + testTree.mFavorites.push(favProfileNode); + const errorHandlingSpy = jest.spyOn(utils, "errorHandling"); + + Object.defineProperty(Profiles, "getInstance", { + value: jest.fn(() => { + return { + loadNamedProfile: jest.fn(() => { + throw new Error(); + }), + }; + }) + }); + + await testTree.loadProfilesForFavorites(blockMocks.log, favProfileNode); + + expect(errorHandlingSpy).toBeCalledTimes(1); + }); + it("Checks that favorite nodes with pre-existing profile/session values continue using those values", async () => { + createGlobalMocks(); + const blockMocks = createBlockMocks(); + const favProfileNode = new Job("testProfile", vscode.TreeItemCollapsibleState.Collapsed, + blockMocks.jobFavoritesNode, blockMocks.session, null, blockMocks.imperativeProfile); + favProfileNode.contextValue = globals.FAV_PROFILE_CONTEXT; + const favJobNode = new Job("JOBTEST(JOB1234)", vscode.TreeItemCollapsibleState.Collapsed, + favProfileNode, blockMocks.session, null, blockMocks.imperativeProfile); + favJobNode.contextValue = globals.JOBS_JOB_CONTEXT + globals.FAV_SUFFIX; + const testTree = new ZosJobsProvider(); + favProfileNode.children.push(favJobNode); + testTree.mFavorites.push(favProfileNode); + + const expectedFavJobNode = new Job("JOBTEST(JOB1234)", vscode.TreeItemCollapsibleState.Collapsed, + favProfileNode, blockMocks.session, null, blockMocks.imperativeProfile); + expectedFavJobNode.contextValue = globals.JOBS_JOB_CONTEXT + globals.FAV_SUFFIX; + + await testTree.loadProfilesForFavorites(blockMocks.log, favProfileNode); + const resultFavJobNode = testTree.mFavorites[0].children[0]; + + expect(resultFavJobNode).toEqual(expectedFavJobNode); + }); + it("Checks that profile, session, and owner from profile node in Favorites get passed to child favorites without those values", async () => { + createGlobalMocks(); + const blockMocks = createBlockMocks(); + const favProfileNode = new Job("testProfile", vscode.TreeItemCollapsibleState.Collapsed, + blockMocks.jobFavoritesNode, blockMocks.session, null, blockMocks.imperativeProfile); + favProfileNode.contextValue = globals.FAV_PROFILE_CONTEXT; + // Leave mParent parameter undefined for favJobNode and expectedFavPdsNode to test undefined profile/session condition + const favJobNode = new Job("JOBTEST(JOB1234)", vscode.TreeItemCollapsibleState.Collapsed, + null, null, null, null); + favJobNode.contextValue = globals.JOBS_JOB_CONTEXT + globals.FAV_SUFFIX; + const testTree = new ZosJobsProvider(); + favProfileNode.children.push(favJobNode); + testTree.mFavorites.push(favProfileNode); + const expectedFavJobNode = new Job("JOBTEST(JOB1234)", vscode.TreeItemCollapsibleState.Collapsed, + null, blockMocks.session, null, blockMocks.imperativeProfile); + expectedFavJobNode.contextValue = globals.JOBS_JOB_CONTEXT + globals.FAV_SUFFIX; + + await testTree.loadProfilesForFavorites(blockMocks.log, favProfileNode); + const resultFavJobNode = testTree.mFavorites[0].children[0]; + + expect(resultFavJobNode).toEqual(expectedFavJobNode); + }); +}); From 55a0763a21a1fd01ccc8f4acd1049b1cdc3f0ab2 Mon Sep 17 00:00:00 2001 From: Lauren Li <45975633+lauren-li@users.noreply.github.com> Date: Thu, 27 Aug 2020 02:08:38 -0400 Subject: [PATCH 17/26] Refactor Jobs updateFavorites to reuse function from PersistentFilters Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- src/job/ZosJobsProvider.ts | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/job/ZosJobsProvider.ts b/src/job/ZosJobsProvider.ts index 10049ec0dc..46c949421c 100644 --- a/src/job/ZosJobsProvider.ts +++ b/src/job/ZosJobsProvider.ts @@ -383,20 +383,16 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree { - profileNode.children.forEach((fav) => { - const favoriteEntry = "[" + profileNode.label.trim() + "]: " + fav.label + "{" + (contextually.isFavoriteJob(fav) ? - globals.JOBS_JOB_CONTEXT : - globals.JOBS_SESSION_CONTEXT) + "}"; - settings.favorites.push(favoriteEntry); - } - ); + const favoritesArray = []; + this.mFavorites.forEach((profileNode) => { + profileNode.children.forEach((fav) => { + const favoriteEntry = "[" + profileNode.label.trim() + "]: " + fav.label + "{" + (contextually.isFavoriteJob(fav) ? + globals.JOBS_JOB_CONTEXT : + globals.JOBS_SESSION_CONTEXT) + "}"; + favoritesArray.push(favoriteEntry); }); - await vscode.workspace.getConfiguration().update(ZosJobsProvider.persistenceSchema, settings, vscode.ConfigurationTarget.Global); - } + }); + this.mHistory.updateFavorites(favoritesArray); } /** From f2a2bbc2d703c47695b5ddf41e2422936ff3b45e Mon Sep 17 00:00:00 2001 From: Lauren Li <45975633+lauren-li@users.noreply.github.com> Date: Thu, 27 Aug 2020 02:33:32 -0400 Subject: [PATCH 18/26] Add context value checking to Jobs addFavorite unit tests Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- __tests__/__unit__/job/ZoweJobNode.unit.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/__tests__/__unit__/job/ZoweJobNode.unit.test.ts b/__tests__/__unit__/job/ZoweJobNode.unit.test.ts index ed783d3d14..f749d8608c 100644 --- a/__tests__/__unit__/job/ZoweJobNode.unit.test.ts +++ b/__tests__/__unit__/job/ZoweJobNode.unit.test.ts @@ -297,6 +297,7 @@ describe("ZoweJobNode unit tests - Function addFavorite", () => { const globalMocks = await createGlobalMocks(); const blockMocks = await createBlockMocks(globalMocks); globalMocks.testJobsProvider.mFavorites = []; + blockMocks.testJobNode.contextValue = globals.JOBS_JOB_CONTEXT; await globalMocks.testJobsProvider.addFavorite(blockMocks.testJobNode); @@ -307,6 +308,7 @@ describe("ZoweJobNode unit tests - Function addFavorite", () => { expect(profileNodeInFavs.label).toEqual("sestest"); expect(profileNodeInFavs.children.length).toEqual(1); expect(favoritedNode.label).toEqual("MYHLQ(JOB1283)"); + expect(favoritedNode.contextValue).toEqual(globals.JOBS_JOB_CONTEXT + globals.FAV_SUFFIX); }); it("Tests that addFavorite successfully favorites a search", async () => { const globalMocks = await createGlobalMocks(); @@ -314,12 +316,14 @@ describe("ZoweJobNode unit tests - Function addFavorite", () => { globalMocks.testJobsProvider.mFavorites = []; globalMocks.testJobsProvider.mSessionNodes[1].owner = "myHLQ"; globalMocks.testJobsProvider.mSessionNodes[1].prefix = "*"; + globalMocks.testJobsProvider.mSessionNodes[1].contextValue = globals.JOBS_SESSION_CONTEXT; await globalMocks.testJobsProvider.addFavorite(globalMocks.testJobsProvider.mSessionNodes[1]); const profileNodeInFavs: IZoweJobTreeNode = globalMocks.testJobsProvider.mFavorites[0]; expect(profileNodeInFavs.children.length).toEqual(1); expect(profileNodeInFavs.children[0].label).toEqual("Owner:myHLQ Prefix:*"); + expect(profileNodeInFavs.children[0].contextValue).toEqual(globals.JOBS_SESSION_CONTEXT + globals.FAV_SUFFIX); }); }); From 73851c07b909a8ce706adc695cee76110f3a1edb Mon Sep 17 00:00:00 2001 From: Lauren Li <45975633+lauren-li@users.noreply.github.com> Date: Thu, 27 Aug 2020 03:31:30 -0400 Subject: [PATCH 19/26] Add error handling case for delete Job unit test Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- __tests__/__unit__/job/ZoweJobNode.unit.test.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/__tests__/__unit__/job/ZoweJobNode.unit.test.ts b/__tests__/__unit__/job/ZoweJobNode.unit.test.ts index f749d8608c..38f45509ab 100644 --- a/__tests__/__unit__/job/ZoweJobNode.unit.test.ts +++ b/__tests__/__unit__/job/ZoweJobNode.unit.test.ts @@ -177,6 +177,16 @@ describe("ZoweJobNode unit tests - Function delete", () => { `Job ${globalMocks.testJobNode.job.jobname}(${globalMocks.testJobNode.job.jobid}) deleted` ); }); + it("Tests that delete handles an error thrown during job deletion", async () => { + const globalMocks = await createGlobalMocks(); + const badJobNode = new Job("badJobNode",vscode.TreeItemCollapsibleState.Collapsed, null, + globalMocks.testSession, null, globalMocks.testProfile); + const errorHandlingSpy = jest.spyOn(utils, "errorHandling"); + + await globalMocks.testJobsProvider.delete(badJobNode); + + expect(errorHandlingSpy).toBeCalledTimes(1); + }); }); describe("ZoweJobNode unit tests - Function onDidConfiguration", () => { From 36a08472f4c6384f1fb74ba86e81bc27ee40951f Mon Sep 17 00:00:00 2001 From: Lauren Li <45975633+lauren-li@users.noreply.github.com> Date: Thu, 27 Aug 2020 05:38:42 -0400 Subject: [PATCH 20/26] Add unit test for Jobs searchPrompt with favorited search Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- .../__unit__/job/ZosJobsProvider.unit.test.ts | 18 ++++------------ .../__unit__/job/ZoweJobNode.unit.test.ts | 21 +++++++++++++++++-- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts b/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts index 62ad77c455..156dfcfd34 100644 --- a/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts +++ b/__tests__/__unit__/job/ZosJobsProvider.unit.test.ts @@ -33,7 +33,6 @@ async function createGlobalMocks() { mockRefresh: jest.fn(), mockAffectsConfig: jest.fn(), createTreeView: jest.fn(), - mockCreateBasicZosmfSession: jest.fn(), mockGetSpoolFiles: jest.fn(), mockDeleteJobs: jest.fn(), mockShowInputBox: jest.fn(), @@ -79,7 +78,6 @@ async function createGlobalMocks() { Object.defineProperty(vscode.window, "showInformationMessage", { value: globalMocks.mockShowInformationMessage, configurable: true }); Object.defineProperty(globalMocks.mockGetJobs, "getJob", { value: globalMocks.mockGetJob, configurable: true }); Object.defineProperty(globalMocks.mockGetJobs, "getJobsByOwnerAndPrefix", { value: globalMocks.mockGetJobsByOwnerAndPrefix, configurable: true }); - Object.defineProperty(zowe.ZosmfSession, "createBasicZosmfSession", { value: globalMocks.mockCreateBasicZosmfSession, configurable: true }); Object.defineProperty(globalMocks.mockGetJobs, "getSpoolFiles", { value: globalMocks.mockGetSpoolFiles, configurable: true }); Object.defineProperty(vscode.window, "createTreeView", { value: globalMocks.createTreeView, configurable: true }); Object.defineProperty(vscode.window, "showQuickPick", { value: globalMocks.mockShowQuickPick, configurable: true }); @@ -104,25 +102,17 @@ async function createGlobalMocks() { globalMocks.mockGetJesApi.mockReturnValue(globalMocks.jesApi); ZoweExplorerApiRegister.getJesApi = globalMocks.mockGetJesApi.bind(ZoweExplorerApiRegister); - globalMocks.mockCreateBasicZosmfSession.mockReturnValue(globalMocks.testSession); globalMocks.createTreeView.mockReturnValue("testTreeView"); globalMocks.mockGetJob.mockReturnValue(globalMocks.testIJob); globalMocks.mockGetJobsByOwnerAndPrefix.mockReturnValue([globalMocks.testIJob, globalMocks.testIJobComplete]); globalMocks.mockProfileInstance.editSession = jest.fn(() => globalMocks.testProfile); - globalMocks.testJobNode = new Job("jobtest", vscode.TreeItemCollapsibleState.Expanded, - null, globalMocks.testSession, globalMocks.testIJob, globalMocks.testProfile); - globalMocks.testJobNode.contextValue = "job"; - globalMocks.testJobNode.dirty = true; - globalMocks.testIJobComplete.jobid = "JOB1235"; - globalMocks.testIJobComplete.retcode = "0"; - globalMocks.testSessionNode = new Job("sestest", vscode.TreeItemCollapsibleState.Collapsed, - null, globalMocks.testSession, null, globalMocks.testProfile); - globalMocks.testSessionNode.contextValue = globals.JOBS_SESSION_CONTEXT; + globalMocks.mockGetConfiguration.mockReturnValue({ persistence: true, get: (setting: string) => [], - // tslint:disable-next-line: no-empty - update: jest.fn(()=>{ {} }) + update: jest.fn(() => { + return {}; + }) }); globalMocks.testJobsProvider = await createJobsTree(Logger.getAppLogger()); Object.defineProperty(globalMocks.testJobsProvider, "refresh", { value: globalMocks.mockRefresh, configurable: true }); diff --git a/__tests__/__unit__/job/ZoweJobNode.unit.test.ts b/__tests__/__unit__/job/ZoweJobNode.unit.test.ts index 38f45509ab..b97ad83fd5 100644 --- a/__tests__/__unit__/job/ZoweJobNode.unit.test.ts +++ b/__tests__/__unit__/job/ZoweJobNode.unit.test.ts @@ -564,8 +564,8 @@ describe("ZoweJobNode unit tests - Function searchPrompt", () => { const globalMocks = await createGlobalMocks(); await createBlockMocks(globalMocks); - globalMocks.testJobNode.label = "[sestest]: Owner:stonecc Prefix:*"; - globalMocks.testJobNode.contextValue = globals.DS_SESSION_CONTEXT + globals.FAV_SUFFIX; + globalMocks.testJobNode.label = "Owner:stonecc Prefix:*"; + globalMocks.testJobNode.contextValue = globals.JOBS_SESSION_CONTEXT + globals.FAV_SUFFIX; const checkSession = jest.spyOn(globalMocks.testJobsProvider, "addSession"); expect(checkSession).not.toHaveBeenCalled(); @@ -575,6 +575,23 @@ describe("ZoweJobNode unit tests - Function searchPrompt", () => { expect(checkSession).toHaveBeenLastCalledWith("sestest"); }); + it("Testing that searchPrompt from favorited search can pass session values into node in Sessions", async () => { + const globalMocks = await createGlobalMocks(); + await createBlockMocks(globalMocks); + globalMocks.testJobNode.label = "Owner:stonecc Prefix:*"; + globalMocks.testJobNode.contextValue = globals.JOBS_SESSION_CONTEXT + globals.FAV_SUFFIX; + + const sessionNoCreds = createISessionWithoutCredentials(); + globalMocks.testJobsProvider.mSessionNodes[1].session = sessionNoCreds; + const sessNodeNoCreds = globalMocks.testJobsProvider.mSessionNodes[1]; + + await globalMocks.testJobsProvider.searchPrompt(globalMocks.testJobNode); + + expect(sessNodeNoCreds.session.ISession.user).toEqual(globalMocks.testJobNode.session.ISession.user); + expect(sessNodeNoCreds.session.ISession.password).toEqual(globalMocks.testJobNode.session.ISession.password); + expect(sessNodeNoCreds.session.ISession.base64EncodedAuth).toEqual(globalMocks.testJobNode.session.ISession.base64EncodedAuth); + }); + it("Testing that searchPrompt is successfully executed when searching by owner, Theia route", async () => { const globalMocks = await createGlobalMocks(); const blockMocks = await createBlockMocks(globalMocks); From 158732eec66272aead0ebbe380041fcba8e37539 Mon Sep 17 00:00:00 2001 From: Lauren Li <45975633+lauren-li@users.noreply.github.com> Date: Thu, 27 Aug 2020 06:16:56 -0400 Subject: [PATCH 21/26] Update i18n Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- i18n/sample/src/job/ZosJobsProvider.i18n.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/i18n/sample/src/job/ZosJobsProvider.i18n.json b/i18n/sample/src/job/ZosJobsProvider.i18n.json index 8f2e64e936..bc960337e3 100644 --- a/i18n/sample/src/job/ZosJobsProvider.i18n.json +++ b/i18n/sample/src/job/ZosJobsProvider.i18n.json @@ -2,7 +2,9 @@ "Favorites": "Favorites", "deleteJob.job": "Job ", "deleteJob.delete": " deleted", - "initializeFavorites.log.debug": "initializing favorites", + "initializeJobsTree.log.debug": "Initializing profiles with jobs favorites.", + "initializeJobsTree.no.favorites": "No jobs favorites found.", + "loadProfilesForFavorites.log.debug": "Loading profile: {0} for jobs favorites", "initializeJobsFavorites.error.profile1": "Error: You have Jobs favorites that refer to a non-existent CLI profile named: ", "initializeJobsFavorites.error.profile2": ". To resolve this, you can create a profile with this name, ", "initializeJobsFavorites.error.profile3": "or remove the favorites with this profile name from the Zowe-Jobs-Persistent setting, which can be found in your ", From ff308718363aa644004b9e9cb98c25d18710fc6a Mon Sep 17 00:00:00 2001 From: Lauren Li <45975633+lauren-li@users.noreply.github.com> Date: Thu, 27 Aug 2020 07:42:56 -0400 Subject: [PATCH 22/26] Minor JSDoc edit Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- src/job/ZosJobsProvider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/job/ZosJobsProvider.ts b/src/job/ZosJobsProvider.ts index 46c949421c..3ea5e992b0 100644 --- a/src/job/ZosJobsProvider.ts +++ b/src/job/ZosJobsProvider.ts @@ -245,7 +245,7 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree Date: Fri, 28 Aug 2020 15:27:08 -0400 Subject: [PATCH 23/26] Fix deleting profile node in Favorites when profile is deleted Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- __tests__/__unit__/Profiles.unit.test.ts | 17 ++++++++++++----- src/Profiles.ts | 4 ++-- src/job/ZosJobsProvider.ts | 1 - 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/__tests__/__unit__/Profiles.unit.test.ts b/__tests__/__unit__/Profiles.unit.test.ts index ebe3de2aa1..a9987d5bf7 100644 --- a/__tests__/__unit__/Profiles.unit.test.ts +++ b/__tests__/__unit__/Profiles.unit.test.ts @@ -1159,16 +1159,23 @@ describe("Profiles Unit Tests - Function deleteProfile", () => { const startLength = blockMocks.testJobTree.mSessionNodes.length; const favoriteLength = blockMocks.testJobTree.mFavorites.length; - const jobNode = new Job( - "testNode", vscode.TreeItemCollapsibleState.Expanded, null, blockMocks.session, blockMocks.iJob, blockMocks.imperativeProfile); - const jobNodeAsFavorite = new Job(`[${blockMocks.datasetSessionNode.label.trim()}]: testNode`, vscode.TreeItemCollapsibleState.Expanded, - null, blockMocks.session, blockMocks.iJob, blockMocks.imperativeProfile); + // Set up job node + const jobNode = new Job("sestest", vscode.TreeItemCollapsibleState.Expanded, null, + blockMocks.session, blockMocks.iJob, blockMocks.imperativeProfile); jobNode.contextValue = globals.JOBS_SESSION_CONTEXT; blockMocks.testJobTree.mSessionNodes.push(jobNode); - blockMocks.testJobTree.addFavorite(jobNodeAsFavorite); + // Set up jobNode in Favorites + const favedJobNode = jobNode; + favedJobNode.contextValue = jobNode.contextValue + globals.FAV_SUFFIX; + const jobProfileNodeInFavs = new Job(`sestest`, vscode.TreeItemCollapsibleState.Expanded, blockMocks.testJobTree.mFavoriteSession, + blockMocks.session, null, blockMocks.imperativeProfile); + jobProfileNodeInFavs.contextValue = globals.FAV_PROFILE_CONTEXT; + jobProfileNodeInFavs.children.push(favedJobNode); + blockMocks.testJobTree.mFavorites.push(jobProfileNodeInFavs); globalMocks.mockShowQuickPick.mockResolvedValueOnce("Delete"); await blockMocks.profiles.deleteProfile(blockMocks.testDatasetTree, blockMocks.testUSSTree, blockMocks.testJobTree, jobNode); + expect(globalMocks.mockShowInformationMessage.mock.calls.length).toBe(1); expect(globalMocks.mockShowInformationMessage.mock.calls[0][0]).toBe("Profile sestest was deleted."); expect(blockMocks.testJobTree.mSessionNodes.length).toEqual(startLength); diff --git a/src/Profiles.ts b/src/Profiles.ts index 34bb26d3be..f8521ac01f 100644 --- a/src/Profiles.ts +++ b/src/Profiles.ts @@ -791,9 +791,9 @@ export class Profiles { // Delete from Jobs Favorites jobsProvider.mFavorites.forEach((ses) => { - const findNode = ses.label.substring(1, ses.label.indexOf("]")).trim(); + const findNode = ses.label.trim(); if (findNode === deleteLabel) { - jobsProvider.removeFavorite(ses); + jobsProvider.mFavorites = jobsProvider.mFavorites.filter((tempNode) => tempNode.label.trim() !== findNode); ses.dirty = true; jobsProvider.refresh(); } diff --git a/src/job/ZosJobsProvider.ts b/src/job/ZosJobsProvider.ts index 46c949421c..108744a8b0 100644 --- a/src/job/ZosJobsProvider.ts +++ b/src/job/ZosJobsProvider.ts @@ -549,7 +549,6 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree tempNode.label.trim() !== node.label.trim()); - this.mFavorites = this.mFavorites.filter((tempNode) => tempNode.label.trim() !== node.label.trim()); this.deleteSessionByLabel(node.getLabel()); } From 9cf141a4eb5ba438d93052a391d3b5965abb1195 Mon Sep 17 00:00:00 2001 From: Lauren Li <45975633+lauren-li@users.noreply.github.com> Date: Fri, 28 Aug 2020 15:35:40 -0400 Subject: [PATCH 24/26] Localize deleteProfile success message Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- i18n/sample/src/Profiles.i18n.json | 1 + src/Profiles.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/i18n/sample/src/Profiles.i18n.json b/i18n/sample/src/Profiles.i18n.json index f25a9e470e..889faf7dcf 100644 --- a/i18n/sample/src/Profiles.i18n.json +++ b/i18n/sample/src/Profiles.i18n.json @@ -37,6 +37,7 @@ "deleteProfile.showQuickPick.cancel": "Cancel", "deleteProfile.showQuickPick.log.debug": "User picked Cancel. Cancelling delete of profile", "deleteProfile.delete.log.error": "Error encountered when deleting profile! ", + "deleteProfile.success.info": "Profile {0} was deleted.", "createNewConnection.option.prompt.url.placeholder": "https://url:port", "createNewConnection.option.prompt.url": "Enter a z/OS URL in the format 'https://url:port'.", "createNewConnection.option.prompt.port.placeholder": "Port Number", diff --git a/src/Profiles.ts b/src/Profiles.ts index f8521ac01f..59b6636147 100644 --- a/src/Profiles.ts +++ b/src/Profiles.ts @@ -994,7 +994,7 @@ export class Profiles { throw error; } - vscode.window.showInformationMessage("Profile " + profileName + " was deleted."); + vscode.window.showInformationMessage(localize("deleteProfile.success.info", "Profile {0} was deleted.", profileName)); return profileName; } From 57e9fe9d6d56e77b9a63cb7ff9df88c04baf4051 Mon Sep 17 00:00:00 2001 From: Lauren Li <45975633+lauren-li@users.noreply.github.com> Date: Thu, 10 Sep 2020 10:29:35 -0400 Subject: [PATCH 25/26] Sort profile nodes in Jobs favorites Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- src/job/ZosJobsProvider.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/job/ZosJobsProvider.ts b/src/job/ZosJobsProvider.ts index d37d90227a..d76783473c 100644 --- a/src/job/ZosJobsProvider.ts +++ b/src/job/ZosJobsProvider.ts @@ -359,6 +359,7 @@ export class ZosJobsProvider extends ZoweTreeProvider implements IZoweTree tempNode.label === favJob.label)) { profileNodeInFavorites.children.push(favJob); sortTreeItems(profileNodeInFavorites.children, globals.JOBS_SESSION_CONTEXT + globals.FAV_SUFFIX); + sortTreeItems(this.mFavorites, globals.FAV_PROFILE_CONTEXT); await this.updateFavorites(); this.refreshElement(this.mFavoriteSession); } From 663c2981d5029c69d8a655072ad36e842fde24f1 Mon Sep 17 00:00:00 2001 From: Lauren Li <45975633+lauren-li@users.noreply.github.com> Date: Thu, 10 Sep 2020 10:50:57 -0400 Subject: [PATCH 26/26] Sort profile nodes in DS favorites Signed-off-by: Lauren Li <45975633+lauren-li@users.noreply.github.com> --- src/dataset/DatasetTree.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dataset/DatasetTree.ts b/src/dataset/DatasetTree.ts index 7ff7aace56..02d1fd2f54 100644 --- a/src/dataset/DatasetTree.ts +++ b/src/dataset/DatasetTree.ts @@ -417,6 +417,7 @@ export class DatasetTree extends ZoweTreeProvider implements IZoweTree