Skip to content

Commit

Permalink
Merge branch 'main' into fix/ftp/create-member
Browse files Browse the repository at this point in the history
  • Loading branch information
traeok authored Sep 12, 2023
2 parents 98cf361 + 6c5d66d commit 9982386
Show file tree
Hide file tree
Showing 29 changed files with 488 additions and 260 deletions.
5 changes: 5 additions & 0 deletions packages/zowe-explorer-api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ All notable changes to the "zowe-explorer-api" extension will be documented in t

### New features and enhancements

- Added optional `pendingActions` record to `IZoweTreeNode` to allow nodes to track pending promises.
- Added optional `wasDoubleClicked` variable to `IZoweTreeNode` to track whether a node was double-clicked during an action.

### Bug fixes

- Bump `@zowe/secrets-for-zowe-sdk` to 7.18.4 to handle install errors gracefully and to allow running without MSVC redistributables.

## `2.10.0`

### New features and enhancements
Expand Down
2 changes: 2 additions & 0 deletions packages/zowe-explorer-api/__mocks__/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
*/

const fs = jest.genMockFromModule("fs") as any;
const origExistsSync = jest.requireActual("fs").existsSync;
const origReadFileSync = jest.requireActual("fs").readFileSync;
const mockReadFileSync = fs.readFileSync;

Expand All @@ -28,5 +29,6 @@ function realpathSync(path: string): string {
fs.readFileSync = readFileSync;
fs.realpathSync = realpathSync;
fs.realpathSync.native = realpathSync;
fs.existsSync = origExistsSync;

module.exports = fs;
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ describe("ProfilesCache", () => {
});

it("getProfileInfo should initialize ProfileInfo API", async () => {
const existsSync = jest.spyOn(fs, "existsSync").mockImplementation();
const profInfo = await new ProfilesCache(fakeLogger as unknown as zowe.imperative.Logger, __dirname).getProfileInfo();
expect(readProfilesFromDiskSpy).toHaveBeenCalledTimes(1);
expect(defaultCredMgrWithKeytarSpy).toHaveBeenCalledTimes(1);
Expand All @@ -143,6 +144,7 @@ describe("ProfilesCache", () => {
path.join(fakeZoweDir, teamConfig.userConfigName),
path.join(fakeZoweDir, teamConfig.configName),
]);
existsSync.mockRestore();
});

it("requireKeyring returns keyring module from Secrets SDK", async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/zowe-explorer-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"dependencies": {
"@types/vscode": "^1.53.2",
"@zowe/cli": "^7.18.0",
"@zowe/secrets-for-zowe-sdk": "7.18.1",
"@zowe/secrets-for-zowe-sdk": "7.18.4",
"handlebars": "^4.7.7",
"semver": "^7.5.3"
},
Expand Down
13 changes: 12 additions & 1 deletion packages/zowe-explorer-api/src/tree/IZoweTreeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import { FileAttributes } from "../utils/files";

export type IZoweNodeType = IZoweDatasetTreeNode | IZoweUSSTreeNode | IZoweJobTreeNode;

export enum NodeAction {
Download = "download",
}

/**
* The base interface for Zowe tree nodes that are implemented by vscode.TreeItem.
*
Expand Down Expand Up @@ -66,6 +70,14 @@ export interface IZoweTreeNode {
* This will show action `extension.deleteFolder` only for items with `contextValue` is `folder`.
*/
contextValue?: string;
/**
* Any ongoing actions that must be awaited before continuing
*/
ongoingActions?: Record<NodeAction | string, Promise<any>>;
/**
* whether the node was double-clicked
*/
wasDoubleClicked?: boolean;
/**
* Retrieves the node label
*/
Expand Down Expand Up @@ -123,7 +135,6 @@ export interface IZoweDatasetTreeNode extends IZoweTreeNode {
* Search criteria for a Dataset member search
*/
memberPattern?: string;

/**
* Retrieves child nodes of this IZoweDatasetTreeNode
*
Expand Down
5 changes: 5 additions & 0 deletions packages/zowe-explorer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen

### Bug fixes

- Fixed issue with favorited Job filter search. [#2440](https://github.com/zowe/vscode-extension-for-zowe/issues/2440)
- Remove the 'Show Attributes' context menu action for migrated datasets. [#2033](https://github.com/zowe/vscode-extension-for-zowe/issues/2033)
- Fixed issue with endless credential prompt loop when logging out. [#2262](https://github.com/zowe/vscode-extension-for-zowe/issues/2262)
- Bump `@zowe/secrets-for-zowe-sdk` to 7.18.4 to handle install errors gracefully and to allow running without MSVC redistributables.
- Fixed issue where data set content does not always appear as soon as the editor is opened. [#2427](https://github.com/zowe/vscode-extension-for-zowe/issues/2427)
- Adjust scope of "Security: Secure Credentials Enabled" setting to `machine-overridable` so it appears again in certain cloud IDEs.

## `2.10.0`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1303,7 +1303,7 @@ describe("Profiles Unit Tests - function deleteProfile", () => {
});

describe("Profiles Unit Tests - function checkCurrentProfile", () => {
const environmentSetup = (globalMocks) => {
const environmentSetup = (globalMocks): void => {
globalMocks.testProfile.profile.password = null;
globalMocks.testProfile.profile.tokenType = "";
Object.defineProperty(Profiles.getInstance(), "profilesForValidation", {
Expand All @@ -1329,23 +1329,57 @@ describe("Profiles Unit Tests - function checkCurrentProfile", () => {
});
};

const setupProfilesCheck = (globalMocks): void => {
jest.spyOn(Profiles.getInstance(), "getDefaultProfile").mockReturnValue({ name: "base" } as any);
jest.spyOn(Profiles.getInstance(), "getProfileInfo").mockResolvedValue({
getTeamConfig: () => ({
properties: {
profiles: {
sestest: { ...globalMocks.testProfile.profile, secure: [] },
base: {
type: "base",
host: "test",
port: 1443,
rejectUnauthorized: false,
name: "base",
tokenType: "",
secure: [],
},
},
},
}),
} as any);
jest.spyOn(Profiles.getInstance(), "getLoadedProfConfig").mockResolvedValue(globalMocks.testProfile);
jest.spyOn(Profiles.getInstance(), "getSecurePropsForProfile").mockResolvedValue([]);
};

it("should show as active in status of profile", async () => {
const globalMocks = await createGlobalMocks();
environmentSetup(globalMocks);
setupProfilesCheck(globalMocks);
jest.spyOn(Profiles.getInstance(), "validateProfiles").mockReturnValue({ status: "active", name: "sestest" } as any);
jest.spyOn(Profiles.getInstance(), "promptCredentials").mockResolvedValue(["sestest", "12345", "base64Auth"]);
await expect(Profiles.getInstance().checkCurrentProfile(globalMocks.testProfile)).resolves.toEqual({ name: "sestest", status: "active" });
});
it("should show as unverified in status of profile", async () => {
const globalMocks = await createGlobalMocks();
environmentSetup(globalMocks);
setupProfilesCheck(globalMocks);
jest.spyOn(Profiles.getInstance(), "promptCredentials").mockResolvedValue(undefined);
await expect(Profiles.getInstance().checkCurrentProfile(globalMocks.testProfile)).resolves.toEqual({ name: "sestest", status: "unverified" });
});
it("should show as inactive in status of profile", async () => {
const globalMocks = await createGlobalMocks();
setupProfilesCheck(globalMocks);
await expect(Profiles.getInstance().checkCurrentProfile(globalMocks.testProfile)).resolves.toEqual({ name: "sestest", status: "inactive" });
});
it("should throw an error if using token auth and is logged out or has expired token", async () => {
const globalMocks = await createGlobalMocks();
jest.spyOn(utils, "errorHandling").mockImplementation();
jest.spyOn(utils, "isUsingTokenAuth").mockResolvedValue(true);
setupProfilesCheck(globalMocks);
await expect(Profiles.getInstance().checkCurrentProfile(globalMocks.testProfile)).resolves.toEqual({ name: "sestest", status: "unverified" });
});
});

describe("Profiles Unit Tests - function editSession", () => {
Expand Down Expand Up @@ -1582,6 +1616,47 @@ describe("Profiles Unit Tests - function ssoLogin", () => {
});
});

describe("Profiles Unit Tests - function ssoLogout", () => {
let testNode;
let globalMocks;
beforeEach(async () => {
globalMocks = await createGlobalMocks();
testNode = new (ZoweTreeNode as any)(
"fake",
vscode.TreeItemCollapsibleState.None,
undefined,
globalMocks.testSession,
globalMocks.testProfile
);
testNode.profile.profile.password = undefined;
testNode.profile.profile.user = "fake";
Object.defineProperty(Profiles.getInstance(), "allProfiles", {
value: [
{
name: "fake",
},
],
configurable: true,
});
jest.spyOn(Gui, "showMessage").mockImplementation();
});
it("should logout successfully and refresh zowe explorer", async () => {
const getTokenTypeNameMock = jest.fn();
const logoutMock = jest.fn();
jest.spyOn(ZoweExplorerApiRegister.getInstance(), "getCommonApi").mockImplementation(() => ({
logout: logoutMock,
getSession: jest.fn(),
getProfileTypeName: jest.fn(),
getTokenTypeName: getTokenTypeNameMock,
}));
const updateBaseProfileFileLogoutSpy = jest.spyOn(Profiles.getInstance() as any, "updateBaseProfileFileLogout").mockImplementation();
await expect(Profiles.getInstance().ssoLogout(testNode)).resolves.not.toThrow();
expect(getTokenTypeNameMock).toBeCalledTimes(1);
expect(logoutMock).toBeCalledTimes(1);
expect(updateBaseProfileFileLogoutSpy).toBeCalledTimes(1);
});
});

describe("Profiles Unit Tests - function updateBaseProfileFileLogin", () => {
it("should update the property of mProfileInfo", async () => {
const privateProfile = Profiles.getInstance() as any;
Expand Down Expand Up @@ -1701,3 +1776,26 @@ describe("Profiles Unit Tests - function loginCredentialPrompt", () => {
expect(showMessageSpy).toBeCalledTimes(1);
});
});

describe("Profiles Unit Tests - function getSecurePropsForProfile", () => {
afterEach(() => {
jest.clearAllMocks();
jest.resetAllMocks();
});
it("should retrieve the secure properties of a profile", async () => {
const globalMocks = await createGlobalMocks();
jest.spyOn(Profiles.getInstance(), "getProfileInfo").mockResolvedValue({
mergeArgsForProfile: () => ({
knownArgs: [
{
argName: "tokenValue",
secure: true,
} as any,
],
missingArgs: [],
}),
getAllProfiles: () => [],
} as any);
await expect(Profiles.getInstance().getSecurePropsForProfile(globalMocks.testProfile.name ?? "")).resolves.toEqual(["tokenValue"]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ describe("ZoweJobNode unit tests - Function checkCurrentProfile", () => {
it("Tests that checkCurrentProfile is executed successfully with inactive status", async () => {
const globalMocks = await createGlobalMocks();
const blockMocks = await createBlockMocks(globalMocks);
blockMocks.jobNode.contextValue = "SERVER";
blockMocks.jobNode.contextValue = "session";
globalMocks.mockCheckCurrentProfile.mockReturnValueOnce({
name: globalMocks.testProfile.name,
status: "inactive",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,12 @@ function createGlobalMocks() {
}),
});
Object.defineProperty(zowe.Download, "dataSet", {
value: jest.fn(() => {
return {
success: true,
commandResponse: null,
apiResponse: {
etag: "123",
},
};
value: jest.fn().mockResolvedValue({
success: true,
commandResponse: null,
apiResponse: {
etag: "123",
},
}),
configurable: true,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3343,9 +3343,9 @@ describe("Dataset Actions Unit Tests - Function openPS", () => {
createGlobalMocks();
const blockMocks = createBlockMocks();

mocked(vscode.window.withProgress).mockResolvedValueOnce({
mocked(blockMocks.mvsApi.getContents).mockResolvedValueOnce({
success: true,
commandResponse: null,
commandResponse: "",
apiResponse: {
etag: "123",
},
Expand All @@ -3364,9 +3364,9 @@ describe("Dataset Actions Unit Tests - Function openPS", () => {
createGlobalMocks();
const blockMocks = createBlockMocks();

mocked(vscode.window.withProgress).mockResolvedValueOnce({
mocked(blockMocks.mvsApi.getContents).mockResolvedValueOnce({
success: true,
commandResponse: null,
commandResponse: "",
apiResponse: {
etag: "123",
},
Expand Down Expand Up @@ -3403,14 +3403,31 @@ describe("Dataset Actions Unit Tests - Function openPS", () => {

expect(mocked(Gui.errorMessage)).toBeCalledWith("Error: testError");
});

it("Check for invalid/null response without supporting ongoing actions", async () => {
globals.defineGlobals("");
const globalMocks = createGlobalMocks();
const blockMocks = createBlockMocks();
globalMocks.getContentsSpy.mockResolvedValueOnce(null);
mocked(Profiles.getInstance).mockReturnValue(blockMocks.profileInstance);
const node = new ZoweDatasetNode("node", vscode.TreeItemCollapsibleState.None, blockMocks.datasetSessionNode, null);
node.ongoingActions = undefined as any;

try {
await dsActions.openPS(node, true, blockMocks.testDatasetTree);
} catch (err) {
expect(err.message).toBe("Response was null or invalid.");
}
});

it("Checking of opening for PDS Member", async () => {
globals.defineGlobals("");
createGlobalMocks();
const blockMocks = createBlockMocks();

mocked(vscode.window.withProgress).mockResolvedValueOnce({
mocked(blockMocks.mvsApi.getContents).mockResolvedValueOnce({
success: true,
commandResponse: null,
commandResponse: "",
apiResponse: {
etag: "123",
},
Expand All @@ -3435,9 +3452,9 @@ describe("Dataset Actions Unit Tests - Function openPS", () => {
createGlobalMocks();
const blockMocks = createBlockMocks();

mocked(vscode.window.withProgress).mockResolvedValueOnce({
mocked(blockMocks.mvsApi.getContents).mockResolvedValueOnce({
success: true,
commandResponse: null,
commandResponse: "",
apiResponse: {
etag: "123",
},
Expand All @@ -3462,9 +3479,9 @@ describe("Dataset Actions Unit Tests - Function openPS", () => {
createGlobalMocks();
const blockMocks = createBlockMocks();

mocked(vscode.window.withProgress).mockResolvedValueOnce({
mocked(blockMocks.mvsApi.getContents).mockResolvedValueOnce({
success: true,
commandResponse: null,
commandResponse: "",
apiResponse: {
etag: "123",
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,17 @@ describe("ZosJobsProvider unit tests - Function getChildren", () => {

expect(elementGetChildrenSpy).toHaveBeenCalledTimes(1);
});
it("Tests that getChildren returns the empty array if status of profile is unverified", async () => {
const globalMocks = await createGlobalMocks();
jest.spyOn(Profiles.getInstance(), "checkCurrentProfile").mockResolvedValueOnce({ status: "unverified" } as any);
const blockMocks = createBlockMocks(globalMocks);
mocked(vscode.window.createTreeView).mockReturnValueOnce(blockMocks.treeView);
const testTree = new ZosJobsProvider();
testTree.mSessionNodes.push(blockMocks.jobSessionNode);
testTree.mSessionNodes[1].dirty = true;

await expect(testTree.getChildren(testTree.mSessionNodes[1])).resolves.toEqual([]);
});
});

describe("ZosJobsProvider unit tests - Function initializeFavChildNodeForProfile", () => {
Expand Down
Loading

0 comments on commit 9982386

Please sign in to comment.