Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VSC Compare function, not working with Favorites from Zowe Explorer #2549

Merged
merged 14 commits into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/zowe-explorer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen
- Fixed submitting local JCL using command pallet option `Zowe Explorer: Submit as JCL` by adding a check for chosen profile returned to continue the action. [#1625](https://github.com/zowe/vscode-extension-for-zowe/issues/1625)
- Fixed conflict resolution being skipped if local and remote file have different contents but are the same size. [#2496](https://github.com/zowe/vscode-extension-for-zowe/issues/2496)
- Fixed issue with token based auth for unsecure profiles in Zowe Explorer. [#2518](https://github.com/zowe/vscode-extension-for-zowe/issues/2518)
- Fixed VSC Compare function, not working with Favorites from Zowe Explorer. [#2549](https://github.com/zowe/vscode-extension-for-zowe/pull/2549)

## `2.11.2`

Expand Down
263 changes: 124 additions & 139 deletions packages/zowe-explorer/__tests__/__unit__/dataset/actions.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,100 @@ describe("Dataset Actions Unit Tests - Function saveFile", () => {

afterAll(() => jest.restoreAllMocks());

it("To check Compare Function is getting triggered from Favorites", async () => {
globals.defineGlobals("");
const globalMocks = createGlobalMocks();
const blockMocks = createBlockMocks();

// Create nodes for Session section
const node = new ZoweDatasetNode(
"HLQ.TEST.AFILE",
vscode.TreeItemCollapsibleState.None,
blockMocks.datasetSessionNode,
null,
undefined,
undefined,
blockMocks.imperativeProfile
);
node.contextValue = globals.DS_PDS_CONTEXT;
const childNode = new ZoweDatasetNode(
"MEM",
vscode.TreeItemCollapsibleState.None,
node,
null,
undefined,
undefined,
blockMocks.imperativeProfile
);

// Create nodes for Favorites section
const favProfileNode = new ZoweDatasetNode(
"sestest",
vscode.TreeItemCollapsibleState.Expanded,
blockMocks.datasetFavoritesNode,
null,
globals.FAV_PROFILE_CONTEXT
);
const favoriteNode = new ZoweDatasetNode(
"HLQ.TEST.AFILE",
vscode.TreeItemCollapsibleState.Expanded,
favProfileNode,
null,
undefined,
undefined,
blockMocks.imperativeProfile
);
favoriteNode.contextValue = globals.DS_PDS_CONTEXT + globals.FAV_SUFFIX;
const favoriteChildNode = new ZoweDatasetNode(
"MEM",
vscode.TreeItemCollapsibleState.None,
favoriteNode,
null,
undefined,
undefined,
blockMocks.imperativeProfile
);

// Push nodes into respective Session or Favorites sections
node.children.push(childNode);
blockMocks.testDatasetTree.mSessionNodes.find((child) => child.label.toString().trim() === "sestest").children.push(node);
favoriteNode.children.push(favoriteChildNode);
blockMocks.testDatasetTree.mFavorites.push(favProfileNode);
blockMocks.testDatasetTree.mFavorites[0].children.push(favoriteNode);

mocked(sharedUtils.concatChildNodes).mockReturnValueOnce([favoriteNode, favoriteChildNode]);
blockMocks.testDatasetTree.getChildren.mockReturnValueOnce(blockMocks.testDatasetTree.mSessionNodes);
mocked(zowe.List.dataSet).mockResolvedValue({
success: true,
commandResponse: "",
apiResponse: {
items: [{ dsname: "HLQ.TEST.AFILE" }, { dsname: "HLQ.TEST.AFILE(MEM)" }],
},
});
mocked(zowe.Upload.pathToDataSet).mockResolvedValueOnce({
success: true,
commandResponse: "success",
apiResponse: [
{
etag: "123",
},
],
});
mocked(vscode.window.withProgress).mockImplementation((progLocation, callback) => {
return callback();
});
blockMocks.profileInstance.loadNamedProfile.mockReturnValueOnce(blockMocks.imperativeProfile);
mocked(Profiles.getInstance).mockReturnValue(blockMocks.profileInstance);
const testDocument = createTextDocument("HLQ.TEST.AFILE(MEM)", blockMocks.datasetSessionNode);
jest.spyOn(favoriteChildNode, "getEtag").mockImplementation(() => "123");
(testDocument as any).fileName = path.join(globals.DS_DIR, blockMocks.imperativeProfile.name, testDocument.fileName);
await dsActions.saveFile(testDocument, blockMocks.testDatasetTree);

expect(mocked(sharedUtils.concatChildNodes)).toBeCalled();
expect(mocked(globalMocks.statusBarMsgSpy)).toBeCalledWith("success", globals.STATUS_BAR_TIMEOUT_MS);
expect(blockMocks.profileInstance.loadNamedProfile).toBeCalledWith(blockMocks.imperativeProfile.name);
});

it("Checking common dataset saving action when no session is defined", async () => {
globals.defineGlobals("");
createGlobalMocks();
Expand Down Expand Up @@ -1391,137 +1485,6 @@ describe("Dataset Actions Unit Tests - Function saveFile", () => {
expect(mocked(sharedUtils.concatChildNodes)).toBeCalled();
expect(mocked(Gui.setStatusBarMessage)).toBeCalledWith("success", globals.STATUS_BAR_TIMEOUT_MS);
});
it("Checking common dataset saving failed due to conflict with server version", async () => {
globals.defineGlobals("");
createGlobalMocks();
const blockMocks = createBlockMocks();
const node = new ZoweDatasetNode(
"HLQ.TEST.AFILE",
vscode.TreeItemCollapsibleState.None,
blockMocks.datasetSessionNode,
null,
undefined,
undefined,
blockMocks.imperativeProfile
);
blockMocks.datasetSessionNode.children.push(node);

mocked(sharedUtils.concatChildNodes).mockReturnValueOnce([node]);
blockMocks.testDatasetTree.getChildren.mockReturnValueOnce([blockMocks.datasetSessionNode]);
mocked(zowe.List.dataSet).mockResolvedValue({
success: true,
commandResponse: "",
apiResponse: {
items: [{ dsname: "HLQ.TEST.AFILE" }],
},
});
mocked(zowe.Upload.pathToDataSet).mockResolvedValueOnce({
success: false,
commandResponse: "Rest API failure with HTTP(S) status 412",
apiResponse: [],
});

mocked(vscode.window.withProgress).mockImplementation((progLocation, callback) => {
return callback();
});
const profile = blockMocks.imperativeProfile;
profile.profile.encoding = 1047;
blockMocks.profileInstance.loadNamedProfile.mockReturnValueOnce(blockMocks.imperativeProfile);
mocked(Profiles.getInstance).mockReturnValue(blockMocks.profileInstance);
Object.defineProperty(wsUtils, "markDocumentUnsaved", {
value: jest.fn(),
configurable: true,
});
Object.defineProperty(context, "isTypeUssTreeNode", {
value: jest.fn().mockReturnValueOnce(false),
configurable: true,
});
Object.defineProperty(ZoweExplorerApiRegister.getMvsApi, "getContents", {
value: jest.fn(),
configurable: true,
});

const testDocument = createTextDocument("HLQ.TEST.AFILE", blockMocks.datasetSessionNode);
(testDocument as any).fileName = path.join(globals.DS_DIR, testDocument.fileName);
const logSpy = jest.spyOn(ZoweLogger, "warn");
const commandSpy = jest.spyOn(vscode.commands, "executeCommand");

await dsActions.saveFile(testDocument, blockMocks.testDatasetTree);

expect(logSpy).toBeCalledWith("Remote file has changed. Presenting with way to resolve file.");
expect(mocked(sharedUtils.concatChildNodes)).toBeCalled();
expect(commandSpy).toBeCalledWith("workbench.files.action.compareWithSaved");
logSpy.mockClear();
commandSpy.mockClear();
});

it("Checking common dataset saving failed due to conflict with server version when file size has not changed", async () => {
globals.defineGlobals("");
createGlobalMocks();
const blockMocks = createBlockMocks();
const node = new ZoweDatasetNode(
"HLQ.TEST.AFILE",
vscode.TreeItemCollapsibleState.None,
blockMocks.datasetSessionNode,
null,
undefined,
undefined,
blockMocks.imperativeProfile
);
blockMocks.datasetSessionNode.children.push(node);

mocked(sharedUtils.concatChildNodes).mockReturnValueOnce([node]);
blockMocks.testDatasetTree.getChildren.mockReturnValueOnce([blockMocks.datasetSessionNode]);
mocked(zowe.List.dataSet).mockResolvedValue({
success: true,
commandResponse: "",
apiResponse: {
items: [{ dsname: "HLQ.TEST.AFILE" }],
},
});
mocked(zowe.Upload.pathToDataSet).mockResolvedValueOnce({
success: false,
commandResponse: "Rest API failure with HTTP(S) status 412",
apiResponse: [],
});

mocked(vscode.window.withProgress).mockImplementation((progLocation, callback) => {
return callback();
});
const profile = blockMocks.imperativeProfile;
profile.profile.encoding = 1047;
blockMocks.profileInstance.loadNamedProfile.mockReturnValueOnce(blockMocks.imperativeProfile);
mocked(Profiles.getInstance).mockReturnValue(blockMocks.profileInstance);
Object.defineProperty(wsUtils, "markDocumentUnsaved", {
value: jest.fn(),
configurable: true,
});
Object.defineProperty(context, "isTypeUssTreeNode", {
value: jest.fn().mockReturnValueOnce(false),
configurable: true,
});
Object.defineProperty(ZoweExplorerApiRegister.getMvsApi, "getContents", {
value: jest.fn(),
configurable: true,
});

const testDocument = createTextDocument("HLQ.TEST.AFILE", blockMocks.datasetSessionNode);
(testDocument as any).fileName = path.join(globals.DS_DIR, testDocument.fileName);
const logSpy = jest.spyOn(ZoweLogger, "warn");
const commandSpy = jest.spyOn(vscode.commands, "executeCommand");
const applyEditSpy = jest.spyOn(vscode.workspace, "applyEdit");
jest.spyOn(fs, "statSync").mockReturnValueOnce({ size: 0 } as any);

await dsActions.saveFile(testDocument, blockMocks.testDatasetTree);

expect(logSpy).toBeCalledWith("Remote file has changed. Presenting with way to resolve file.");
expect(mocked(sharedUtils.concatChildNodes)).toBeCalled();
expect(commandSpy).toBeCalledWith("workbench.files.action.compareWithSaved");
expect(applyEditSpy).toHaveBeenCalledTimes(2);
logSpy.mockClear();
commandSpy.mockClear();
applyEditSpy.mockClear();
});
});

describe("Dataset Actions Unit Tests - Function showAttributes", () => {
Expand Down Expand Up @@ -3455,6 +3418,28 @@ describe("Dataset Actions Unit Tests - Function openPS", () => {
expect(mocked(vscode.workspace.openTextDocument)).toBeCalledWith(sharedUtils.getDocumentFilePath(node.label.toString(), node));
});

it("Checking of opening for common dataset without supporting ongoing actions", async () => {
globals.defineGlobals("");
createGlobalMocks();
const blockMocks = createBlockMocks();

mocked(blockMocks.mvsApi.getContents).mockResolvedValueOnce({
success: true,
commandResponse: "",
apiResponse: {
etag: "123",
},
});
mocked(Profiles.getInstance).mockReturnValue(blockMocks.profileInstance);
const node = new ZoweDatasetNode("node", vscode.TreeItemCollapsibleState.None, blockMocks.datasetSessionNode, null);
node.ongoingActions = undefined as any;

await dsActions.openPS(node, true, blockMocks.testDatasetTree);

expect(mocked(fs.existsSync)).toBeCalledWith(path.join(globals.DS_DIR, node.getSessionNode().label.toString(), node.label.toString()));
expect(mocked(vscode.workspace.openTextDocument)).toBeCalledWith(sharedUtils.getDocumentFilePath(node.label.toString(), node));
});

it("Checking of failed attempt to open dataset", async () => {
globals.defineGlobals("");
const globalMocks = createGlobalMocks();
Expand All @@ -3472,20 +3457,20 @@ 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 () => {
it("Check for invalid/null response when contents are already fetched", async () => {
globals.defineGlobals("");
const globalMocks = createGlobalMocks();
const blockMocks = createBlockMocks();
globalMocks.getContentsSpy.mockResolvedValueOnce(null);
globalMocks.getContentsSpy.mockClear();
mocked(fs.existsSync).mockReturnValueOnce(true);
mocked(Profiles.getInstance).mockReturnValue(blockMocks.profileInstance);
const node = new ZoweDatasetNode("node", vscode.TreeItemCollapsibleState.None, blockMocks.datasetSessionNode, null);
const node = new ZoweDatasetNode("node", vscode.TreeItemCollapsibleState.None, blockMocks.datasetSessionNode, null, null, "abc");
node.ongoingActions = undefined as any;

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

expect(globalMocks.getContentsSpy).not.toHaveBeenCalled();
expect(node.getEtag()).toBe("abc");
});

it("Checking of opening for PDS Member", async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ describe("Test force upload", () => {
ussNode: new ZoweUSSNode(null, null, null, null, null),
showInformationMessage: jest.fn(),
showWarningMessage: jest.fn(),
showErrorMessage: jest.fn(),
getMvsApi: jest.fn(),
getUssApi: jest.fn(),
withProgress: jest.fn(),
Expand All @@ -297,6 +298,10 @@ describe("Test force upload", () => {
value: newVariables.showWarningMessage,
configurable: true,
});
Object.defineProperty(vscode.window, "showErrorMessage", {
value: newVariables.showErrorMessage,
configurable: true,
});
Object.defineProperty(ZoweExplorerApiRegister, "getMvsApi", {
value: newVariables.getMvsApi,
configurable: true,
Expand Down Expand Up @@ -336,6 +341,7 @@ describe("Test force upload", () => {
},
expect.any(Function)
);
expect(blockMocks.showInformationMessage.mock.calls[1][0]).toBe(blockMocks.fileResponse.commandResponse);
});

it("should successfully call upload for a data set if user clicks 'Yes'", async () => {
Expand All @@ -350,6 +356,7 @@ describe("Test force upload", () => {
},
expect.any(Function)
);
expect(blockMocks.showInformationMessage.mock.calls[1][0]).toBe(blockMocks.fileResponse.commandResponse);
});

it("should cancel upload if user clicks 'No'", async () => {
Expand All @@ -368,6 +375,37 @@ describe("Test force upload", () => {
"A merge conflict has been detected. Since you are running inside Theia editor, a merge conflict resolution is not available yet."
);
});

it("should show error message if file fails to upload", async () => {
const blockMocks = await createBlockMocks();
blockMocks.showInformationMessage.mockResolvedValueOnce("Yes");
blockMocks.withProgress.mockResolvedValueOnce({ ...blockMocks.fileResponse, success: false });
await sharedUtils.willForceUpload(blockMocks.ussNode, blockMocks.mockDoc, null);
expect(blockMocks.withProgress).toBeCalledWith(
{
location: vscode.ProgressLocation.Notification,
title: "Saving file...",
},
expect.any(Function)
);
expect(blockMocks.showErrorMessage.mock.calls[0][0]).toBe(blockMocks.fileResponse.commandResponse);
});

it("should show error message if upload throws an error", async () => {
const blockMocks = await createBlockMocks();
blockMocks.showInformationMessage.mockResolvedValueOnce("Yes");
const testError = new Error("Task failed successfully");
blockMocks.withProgress.mockRejectedValueOnce(testError);
await sharedUtils.willForceUpload(blockMocks.ussNode, blockMocks.mockDoc, null, { name: "fakeProfile" } as any);
expect(blockMocks.withProgress).toBeCalledWith(
{
location: vscode.ProgressLocation.Notification,
title: "Saving file...",
},
expect.any(Function)
);
expect(blockMocks.showErrorMessage.mock.calls[0][0]).toBe(`Error: ${testError.message}`);
});
});

describe("Shared Utils Unit Tests - Function filterTreeByString", () => {
Expand Down
Loading
Loading