Skip to content

Commit

Permalink
Merge branch 'main' into fix/misc-profile-issues
Browse files Browse the repository at this point in the history
  • Loading branch information
t1m0thyj committed Nov 14, 2024
2 parents f54b4c1 + fc799e3 commit 2399989
Show file tree
Hide file tree
Showing 30 changed files with 623 additions and 275 deletions.
1 change: 1 addition & 0 deletions packages/zowe-explorer-api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ All notable changes to the "zowe-explorer-api" extension will be documented in t

- Fixed an issue to review inconsistent capitalization across translation strings. [#2935](https://github.com/zowe/zowe-explorer-vscode/issues/2935)
- Fixed an issue where the `responseTimeout` profile property was ignored for z/OSMF MVS and USS API calls. [#3225](https://github.com/zowe/zowe-explorer-vscode/issues/3225)
- Fixed an issue where the assignment of the `profile` property in `ZoweTreeNode.setProfileToChoice` caused references to that object to break elsewhere. [#3289](https://github.com/zowe/zowe-explorer-vscode/issues/3289)

## `3.0.2`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,17 @@ import * as vscode from "vscode";
import { ZoweTreeNode } from "../../../src/tree/ZoweTreeNode";
import { IZoweTreeNode } from "../../../src/tree/IZoweTreeNode";
import * as imperative from "@zowe/imperative";
import { BaseProvider } from "../../../src";

describe("ZoweTreeNode", () => {
const innerProfile = { user: "apple", password: "banana" };
const fakeProfile: imperative.IProfileLoaded = {
name: "amazingProfile",
profile: innerProfile,
message: "",
type: "zosmf",
failNotFound: true,
};

const makeNode = (
name: string,
collapseState: vscode.TreeItemCollapsibleState,
Expand Down Expand Up @@ -48,8 +56,8 @@ describe("ZoweTreeNode", () => {

it("getProfile should return profile of current node", () => {
const node = makeNode("test", vscode.TreeItemCollapsibleState.None, undefined);
node.setProfileToChoice("myProfile" as unknown as imperative.IProfileLoaded);
expect(node.getProfile()).toBe("myProfile");
node.setProfileToChoice(fakeProfile);
expect(node.getProfile().name).toBe("amazingProfile");
});

it("getProfile should return profile of parent node", () => {
Expand Down Expand Up @@ -83,49 +91,43 @@ describe("ZoweTreeNode", () => {

it("setProfileToChoice should update properties on existing profile object", () => {
const node = makeNode("test", vscode.TreeItemCollapsibleState.None, undefined, undefined, {
name: "oldProfile",
profile: { host: "example.com" },
...fakeProfile,
});
node.setProfileToChoice({ name: "newProfile", profile: { host: "example.com", port: 443 } } as unknown as imperative.IProfileLoaded);
// Profile name should not change but properties should
expect(node.getProfileName()).toBe("oldProfile");
node.setProfileToChoice({ ...fakeProfile, profile: { host: "example.com", port: 443 } });
expect(node.getProfile().profile?.port).toBeDefined();
});

it("setProfileToChoice should update profile for associated FSProvider entry", () => {
const node = makeNode("test", vscode.TreeItemCollapsibleState.None, undefined);
node.resourceUri = vscode.Uri.file(__dirname);
const prof = { ...fakeProfile, profile: { ...innerProfile } };
const fsEntry = {
metadata: {
profile: { name: "oldProfile" },
profile: prof,
},
};
node.setProfileToChoice(
{ name: "newProfile" } as unknown as imperative.IProfileLoaded,
{
lookup: jest.fn().mockReturnValue(fsEntry),
} as unknown as BaseProvider
);
expect(node.getProfileName()).toBe("newProfile");
expect(fsEntry.metadata.profile.name).toBe("newProfile");
prof.profile.user = "banana";
prof.profile.password = "apple";
node.setProfileToChoice(prof);
expect(node.getProfile().profile?.user).toBe("banana");
expect(node.getProfile().profile?.password).toBe("apple");
expect(fsEntry.metadata.profile.profile?.user).toBe("banana");
expect(fsEntry.metadata.profile.profile?.password).toBe("apple");
});

it("setProfileToChoice should update child nodes with the new profile", () => {
const node = makeNode("test", vscode.TreeItemCollapsibleState.Expanded, undefined);
node.setProfileToChoice({ ...fakeProfile, profile: { ...fakeProfile.profile, user: "banana" } });
const nodeChild = makeNode("child", vscode.TreeItemCollapsibleState.None, undefined);
nodeChild.setProfileToChoice(node.getProfile());
node.children = [nodeChild as any];
const setProfileToChoiceChildMock = jest.spyOn(nodeChild, "setProfileToChoice").mockImplementation();
const fsEntry = {
metadata: {
profile: { name: "oldProfile" },
profile: node.getProfile(),
},
};
const mockNewProfile = { name: "newProfile" } as unknown as imperative.IProfileLoaded;
const mockProvider = {
lookup: jest.fn().mockReturnValue(fsEntry),
} as unknown as BaseProvider;
node.setProfileToChoice(mockNewProfile, mockProvider);
expect(node.getProfileName()).toBe("newProfile");
expect(setProfileToChoiceChildMock).toHaveBeenCalledWith(mockNewProfile, mockProvider);
expect(node.getProfile().profile?.user).toBe("banana");
expect(nodeChild.getProfile().profile?.user).toBe("banana");
expect(fsEntry.metadata.profile.profile?.user).toBe("banana");
});
});
2 changes: 1 addition & 1 deletion packages/zowe-explorer-api/src/fs/BaseProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ export class BaseProvider {
})
.then(async ({ userResponse }) => {
if (userResponse === "Retry" && opts?.retry?.fn != null) {
await opts.retry.fn(...(opts?.retry.args ?? []));
await opts.retry.fn(...(opts.retry.args ?? []));
}
})
.catch(() => {
Expand Down
17 changes: 2 additions & 15 deletions packages/zowe-explorer-api/src/tree/ZoweTreeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,21 +101,8 @@ export class ZoweTreeNode extends vscode.TreeItem {
* @param {imperative.IProfileLoaded} The profile you will set the node to use
*/
public setProfileToChoice(aProfile: imperative.IProfileLoaded, fsProvider?: BaseProvider): void {
if (this.profile == null) {
this.profile = aProfile;
} else {
// Don't reassign profile, we want to keep object reference shared across nodes
this.profile.profile = aProfile.profile;
}
if (this.resourceUri != null) {
const fsEntry = fsProvider?.lookup(this.resourceUri, true);
if (fsEntry != null) {
fsEntry.metadata.profile = aProfile;
}
}
for (const child of this.children) {
(child as unknown as ZoweTreeNode).setProfileToChoice(aProfile, fsProvider);
}
// Don't reassign profile if its already defined, as we want to keep the reference valid for other nodes and filesystems
this.profile = Object.assign(this.profile ?? {}, aProfile);
}
/**
* Sets the session for this node to the one chosen in parameters.
Expand Down
3 changes: 3 additions & 0 deletions packages/zowe-explorer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen
- Reduced the number of MVS API calls performed by `vscode.workspace.fs.readFile` when fetching the contents of a data set entry. [#3278](https://github.com/zowe/zowe-explorer-vscode/issues/3278)
- Fixed an issue to review inconsistent capitalization across translation strings. [#2935](https://github.com/zowe/zowe-explorer-vscode/issues/2935)
- Updated the test for the default credential manager for better compatibility with Cloud-based platforms such as Eclipse Che and Red Hat OpenShift Dev Spaces. [#3297](https://github.com/zowe/zowe-explorer-vscode/pull/3297)
- Fixed an issue where opening a PDS member after renaming an expanded PDS resulted in an error. [#3314](https://github.com/zowe/zowe-explorer-vscode/issues/3314)
- Fixed issue where users were not prompted to enter credentials if a 401 error was encountered when opening files, data sets or spools in the editor. [#3197](https://github.com/zowe/zowe-explorer-vscode/issues/3197)
- Fixed issue where profile credential updates or token changes were not reflected within the filesystem. [#3289](https://github.com/zowe/zowe-explorer-vscode/issues/3289)
- Fixed an issue where editing a team config file or updating credentials in OS vault could trigger multiple events for a single action. [#3296](https://github.com/zowe/zowe-explorer-vscode/pull/3296)
- Updated Zowe SDKs to `8.2.2` for technical currency. [#3296](https://github.com/zowe/zowe-explorer-vscode/pull/3296)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,22 @@ When("a user opens Zowe Explorer", async function () {

Then("the Show Config dialog should appear", async function () {
this.workbench = await browser.getWorkbench();
let notification: Notification;
const notificationCenter = await (this.workbench as Workbench).openNotificationsCenter();
await notificationCenter.wait(60000);

let configNotification: Notification;
await browser.waitUntil(async () => {
const notifications: Notification[] = await notificationCenter.getNotifications("error" as any);
const notifications = await (this.workbench as Workbench).getNotifications();
for (const n of notifications) {
if ((await n.getMessage()).startsWith("Error encountered when loading your Zowe config.")) {
notification = n;
const msg = await n.getMessage();
if (msg.startsWith("Error encountered when loading your Zowe config.")) {
configNotification = n;
return true;
}
}

return false;
});
await expect(notification).toBeDefined();
this.configErrorDialog = notification;

await expect(configNotification).toBeDefined();
this.configErrorDialog = configNotification;
await (this.configErrorDialog as Notification).wait();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ When("a user clicks search button for the profile", async function () {

// Locate and select the search button on the profile node
const searchButton = actionButtons[actionButtons.length - 1];
await searchButton.wait();
await expect(searchButton.elem).toBeDefined();
await searchButton.elem.click();
});
Expand All @@ -86,7 +87,6 @@ Then(/the user will be prompted for (.*) credentials/, async function (authType:
await browser.keys(Key.Escape);
});
Then("the profile node icon will be marked as inactive", async function () {
await browser.waitUntil((): Promise<boolean> => this.profileNode.isExpanded());
const iconElement = await this.profileNode.elem.$(".custom-view-tree-node-item-icon");
const iconPath = (await iconElement.getCSSProperty("background-image")).value;
await expect(iconPath).toContain("folder-root-disconnected-closed.svg");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ export function createTreeView(selection?): vscode.TreeView<ZoweTreeProvider<any
onDidChangeVisibility: jest.fn(),
dispose: jest.fn(),
addSingleSession: jest.fn(),
setStatusForSession: jest.fn(),
} as unknown as vscode.TreeView<ZoweTreeProvider<any>>;
}

Expand Down Expand Up @@ -367,6 +368,7 @@ export function createInstanceOfProfile(profile: imperative.IProfileLoaded) {
convertV1ProfToConfig: jest.fn(),
getLoadedProfConfig: jest.fn(),
getSecurePropsForProfile: jest.fn(),
showProfileInactiveMsg: jest.fn(),
} as any;
}

Expand Down Expand Up @@ -616,6 +618,7 @@ export function createTreeProviders() {
removeSession: jest.fn(),
refresh: jest.fn(),
addSingleSession: jest.fn(),
setStatusForSession: jest.fn(),
refreshElement: jest.fn(),
} as any,
uss: {
Expand All @@ -627,6 +630,7 @@ export function createTreeProviders() {
removeSession: jest.fn(),
refresh: jest.fn(),
addSingleSession: jest.fn(),
setStatusForSession: jest.fn(),
refreshElement: jest.fn(),
addEncodingHistory: jest.fn(),
getEncodingHistory: jest.fn(),
Expand All @@ -640,6 +644,7 @@ export function createTreeProviders() {
deleteSession: jest.fn(),
refresh: jest.fn(),
addSingleSession: jest.fn(),
setStatusForSession: jest.fn(),
} as any,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,8 @@ describe("ZoweCommandProvider Unit Tests - function checkCurrentProfile", () =>
});
const profileStatus = { name: "test", status: "inactive" };
jest.spyOn(Profiles.getInstance(), "checkCurrentProfile").mockResolvedValue(profileStatus);
const errorHandlingSpy = jest.spyOn(AuthUtils, "errorHandling").mockImplementation();
const showProfileInactiveMsg = jest.spyOn(Profiles.getInstance(), "showProfileInactiveMsg").mockImplementation();
await expect(ZoweCommandProvider.prototype.checkCurrentProfile(testNode)).resolves.toEqual(profileStatus);
expect(errorHandlingSpy).toHaveBeenCalledWith(
"Profile Name " +
globalMocks.testProfile.name +
" is inactive. Please check if your Zowe server is active or if the URL and port in your profile is correct.",
{ apiType: ZoweExplorerApiType.Command, profile: globalMocks.testProfile }
);
expect(showProfileInactiveMsg).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -1049,7 +1049,7 @@ describe("Profiles Unit Tests - function checkCurrentProfile", () => {
jest.spyOn(AuthUtils, "isUsingTokenAuth").mockResolvedValueOnce(true);
environmentSetup(globalMocks);
setupProfilesCheck(globalMocks);
const ssoLoginSpy = jest.spyOn(Profiles.getInstance(), "ssoLogin").mockResolvedValueOnce();
const ssoLoginSpy = jest.spyOn(Profiles.getInstance(), "ssoLogin").mockResolvedValueOnce(true);
jest.spyOn(Profiles.getInstance(), "loadNamedProfile").mockReturnValueOnce(globalMocks.testProfile);
await expect(Profiles.getInstance().checkCurrentProfile(globalMocks.testProfile)).resolves.toEqual({ name: "sestest", status: "active" });
expect(ssoLoginSpy).toHaveBeenCalledTimes(1);
Expand Down Expand Up @@ -2448,3 +2448,20 @@ describe("Profiles Unit Tests - function tokenAuthClearSecureArray", () => {
getProfileFromConfigMock.mockRestore();
});
});

describe("Profiles unit tests - function showProfilesInactiveMsg", () => {
it("should call ZoweLogger.error to log the error", () => {
const errorSpy = jest.spyOn(ZoweLogger, "error");
Profiles.getInstance().showProfileInactiveMsg("profName");
expect(errorSpy).toHaveBeenCalledWith(
"Profile profName is inactive. Please check if your Zowe server is active or if the URL and port in your profile is correct."
);
});
it("should call Gui.errorMessage to display the message", () => {
const errorMsgSpy = jest.spyOn(Gui, "errorMessage");
Profiles.getInstance().showProfileInactiveMsg("profName");
expect(errorMsgSpy).toHaveBeenCalledWith(
"Profile profName is inactive. Please check if your Zowe server is active or if the URL and port in your profile is correct."
);
});
});
Loading

0 comments on commit 2399989

Please sign in to comment.