Skip to content

Commit

Permalink
ds: Show error for unsaved dataset rename; use mtime in ms for DS ent…
Browse files Browse the repository at this point in the history
…ries (#3326)

* fix(ds): update rename to match FS sample; check editor before rename

Signed-off-by: Trae Yelovich <[email protected]>

* chore: update changelog

Signed-off-by: Trae Yelovich <[email protected]>

* refactor: create common fn TreeViewUtils.promptedForUnsavedResource

Signed-off-by: Trae Yelovich <[email protected]>

* tests: resolve failing tests, add cases for promptedForUnsavedResource

Signed-off-by: Trae Yelovich <[email protected]>

* tests: patch coverage for DatasetTree, USSTree

Signed-off-by: Trae Yelovich <[email protected]>

* test: mtime update in USS provider

Signed-off-by: Trae Yelovich <[email protected]>

* refactor: shorten logic in promptedForUnsavedResource

Signed-off-by: Trae Yelovich <[email protected]>

* remove changes to DatasetFS rename

Signed-off-by: Trae Yelovich <[email protected]>

* chore: add PR number to changelog

Signed-off-by: Trae Yelovich <[email protected]>

* rename to errorForUnsavedResource, update tests & l10n

Signed-off-by: Trae Yelovich <[email protected]>

* refactor: use checkCurrentProfile in tree rename fns

Signed-off-by: Trae Yelovich <[email protected]>

* chore: address changelog feedback

Signed-off-by: Trae Yelovich <[email protected]>

* refactor: log error in errorForUnsavedResource

Signed-off-by: Trae Yelovich <[email protected]>

---------

Signed-off-by: Trae Yelovich <[email protected]>
  • Loading branch information
traeok authored Nov 22, 2024
1 parent 66f4592 commit 07232b7
Show file tree
Hide file tree
Showing 15 changed files with 366 additions and 90 deletions.
3 changes: 2 additions & 1 deletion packages/zowe-explorer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen

### New features and enhancements

- Updated Zowe SDKs to `8.8.2` for technical currency. [#3296](https://github.com/zowe/zowe-explorer-vscode/pull/3296)
- Added expired JSON web token detection for profiles in each tree view (Data Sets, USS, Jobs). When a user performs a search on a profile, they are prompted to log in if their token expired. [#3175](https://github.com/zowe/zowe-explorer-vscode/issues/3175)
- Add a data set or USS resource to a virtual workspace with the new "Add to Workspace" context menu option. [#3265](https://github.com/zowe/zowe-explorer-vscode/issues/3265)
- Power users and developers can now build links to efficiently open mainframe resources in Zowe Explorer. Use the **Copy External Link** option in the context menu to get the URL for a data set or USS resource, or create a link in the format `vscode://Zowe.vscode-extension-for-zowe?<ZoweResourceUri>`. For more information on building resource URIs, see the [FileSystemProvider wiki article](https://github.com/zowe/zowe-explorer-vscode/wiki/FileSystemProvider#file-paths-vs-uris). [#3271](https://github.com/zowe/zowe-explorer-vscode/pull/3271)
- Implemented more user-friendly error messages for API or network errors within Zowe Explorer. [#3243](https://github.com/zowe/zowe-explorer-vscode/pull/3243)
- Use the "Troubleshoot" option for certain errors to obtain additional context, tips, and resources for how to resolve the errors. [#3243](https://github.com/zowe/zowe-explorer-vscode/pull/3243)
- Updated Zowe SDKs to `8.8.2` for technical currency. [#3296](https://github.com/zowe/zowe-explorer-vscode/pull/3296)
- Allow extenders to add context menu actions to a top level node, i.e. data sets, USS, Jobs, by encoding the profile type in the context value. [#3309](https://github.com/zowe/zowe-explorer-vscode/pull/3309)
- You can now add multiple partitioned data sets or USS directories to your workspace at once using the "Add to Workspace" feature. [#3324](https://github.com/zowe/zowe-explorer-vscode/issues/3324)
- Exposed read and write access to local storage keys for Zowe Explorer extenders. [#3180](https://github.com/zowe/zowe-explorer-vscode/issues/3180)
Expand All @@ -22,6 +22,7 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen
- Fixed an issue where editing a team config file or updating secrets in the OS credential vault could trigger multiple events for a single action. [#3296](https://github.com/zowe/zowe-explorer-vscode/pull/3296)
- 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 persistent settings defined at the workspace level were migrated into global storage rather than workspace-specific storage. [#3180](https://github.com/zowe/zowe-explorer-vscode/issues/3180)
- Fixed an issue where renaming a data set with unsaved changes did not cancel the rename operation. Now, when renaming a data set with unsaved changes, you are prompted to resolve them before continuing. [#3326](https://github.com/zowe/zowe-explorer-vscode/pull/3326)

## `3.0.3`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ export function createUSSSessionNode(session: imperative.Session, profile: imper
collapsibleState: vscode.TreeItemCollapsibleState.Collapsed,
session,
profile,
parentPath: "/",
});
zoweUSSNode.fullPath = "/test";
zoweUSSNode.contextValue = Constants.USS_SESSION_CONTEXT;
Expand Down
3 changes: 1 addition & 2 deletions packages/zowe-explorer/__tests__/__mocks__/vscode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -918,7 +918,7 @@ export namespace l10n {
return options;
}
options.args?.forEach((arg: string, i: number) => {
options.message = options.message.replace(`{${i}}`, arg);
options.message = options.message.replaceAll(`{${i}}`, arg);
});
return options.message;
}
Expand Down Expand Up @@ -1312,7 +1312,6 @@ export enum FileSystemProviderErrorCode {
* a file or folder doesn't exist, use them like so: `throw vscode.FileSystemError.FileNotFound(someUri);`
*/
export const { FileSystemError } = require("jest-mock-vscode").createVSCodeMock(jest);

/**
* Namespace for dealing with the current workspace. A workspace is the representation
* of the folder that has been opened. There is no workspace when just a file but not a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ describe("stat", () => {
expect(lookupMock).toHaveBeenCalledWith(testUris.pdsMember, false);
expect(lookupParentDirMock).toHaveBeenCalledWith(testUris.pdsMember);
expect(allMembersMock).toHaveBeenCalledWith("USER.DATA.PDS", { attributes: true });
expect(res).toStrictEqual({ ...fakePdsMember, mtime: dayjs("2024-08-08 12:30").unix() });
expect(res).toStrictEqual({ ...fakePdsMember, mtime: dayjs("2024-08-08 12:30").valueOf() });
expect(fakePdsMember.wasAccessed).toBe(false);
lookupMock.mockRestore();
lookupParentDirMock.mockRestore();
Expand Down Expand Up @@ -1126,6 +1126,7 @@ describe("rename", () => {
.mockImplementation((uri): DirEntry | FileEntry => ((uri as Uri).path.includes("USER.DATA.PS2") ? (null as any) : oldPs));
const _lookupParentDirectoryMock = jest
.spyOn(DatasetFSProvider.instance as any, "_lookupParentDirectory")
.mockReturnValueOnce({ ...testEntries.session })
.mockReturnValueOnce({ ...testEntries.session });
await DatasetFSProvider.instance.rename(testUris.ps, testUris.ps.with({ path: "/USER.DATA.PS2" }), { overwrite: true });
expect(mockMvsApi.renameDataSet).toHaveBeenCalledWith("USER.DATA.PS", "USER.DATA.PS2");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import { Sorting } from "../../../../../zowe-explorer-api/src/tree";
import { IconUtils } from "../../../../src/icons/IconUtils";
import { SharedContext } from "../../../../src/trees/shared/SharedContext";
import { ZoweTreeProvider } from "../../../../src/trees/ZoweTreeProvider";
import { TreeViewUtils } from "../../../../src/utils/TreeViewUtils";

jest.mock("fs");
jest.mock("util");
Expand Down Expand Up @@ -2280,6 +2281,31 @@ describe("Dataset Tree Unit Tests - Function rename", () => {
};
}

it("returns early if errorForUnsavedResource was true", async () => {
createGlobalMocks();
const blockMocks = createBlockMocks();
mocked(Profiles.getInstance).mockReturnValue(blockMocks.profileInstance);
mocked(vscode.window.createTreeView).mockReturnValueOnce(blockMocks.treeView);
const testTree = new DatasetTree();
testTree.mSessionNodes.push(blockMocks.datasetSessionNode);
const node = new ZoweDatasetNode({
label: "HLQ.TEST.RENAME.NODE",
collapsibleState: vscode.TreeItemCollapsibleState.None,
parentNode: testTree.mSessionNodes[1],
session: blockMocks.session,
profile: testTree.mSessionNodes[1].getProfile(),
});
blockMocks.rename.mockClear();
const errorForUnsavedResource = jest.spyOn(TreeViewUtils, "errorForUnsavedResource").mockResolvedValueOnce(true);
await testTree.rename(node);
expect(errorForUnsavedResource).toHaveBeenCalled();
expect(blockMocks.rename).not.toHaveBeenLastCalledWith(
{ path: "/sestest/HLQ.TEST.RENAME.NODE", scheme: ZoweScheme.DS },
{ path: "/sestest/HLQ.TEST.RENAME.NODE.NEW", scheme: ZoweScheme.DS },
{ overwrite: false }
);
});

it("Tests that rename() renames a node", async () => {
createGlobalMocks();
const blockMocks = createBlockMocks();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ import { FilterDescriptor } from "../../../../src/management/FilterManagement";
import { AuthUtils } from "../../../../src/utils/AuthUtils";
import { Icon } from "../../../../src/icons/Icon";
import { ZoweTreeProvider } from "../../../../src/trees/ZoweTreeProvider";
import { TreeViewUtils } from "../../../../src/utils/TreeViewUtils";
import { SharedContext } from "../../../../src/trees/shared/SharedContext";

function createGlobalMocks() {
const globalMocks = {
Expand Down Expand Up @@ -934,6 +936,7 @@ describe("USSTree Unit Tests - Function rename", () => {
globalMocks.FileSystemProvider.rename.mockClear();

const newMocks = {
errorForUnsavedResource: jest.spyOn(TreeViewUtils, "errorForUnsavedResource").mockResolvedValueOnce(false),
ussFavNode,
ussFavNodeParent,
setAttributes: jest.spyOn(ZoweUSSNode.prototype, "setAttributes").mockImplementation(),
Expand All @@ -948,6 +951,23 @@ describe("USSTree Unit Tests - Function rename", () => {
getEncodingForFileMock.mockRestore();
});

it("returns early if errorForUnsavedResource was true", async () => {
const globalMocks = createGlobalMocks();
const blockMocks = createBlockMocks(globalMocks);
blockMocks.errorForUnsavedResource.mockReset();
blockMocks.errorForUnsavedResource.mockResolvedValueOnce(true);
const testUSSDir = new ZoweUSSNode({
label: "test",
collapsibleState: vscode.TreeItemCollapsibleState.Expanded,
session: globalMocks.testSession,
profile: globalMocks.testProfile,
parentPath: "/",
});
const isFolderMock = jest.spyOn(SharedContext, "isFolder");
await globalMocks.testTree.rename(testUSSDir);
expect(isFolderMock).not.toHaveBeenCalled();
});

it("Tests that USSTree.rename() shows no error if an open dirty file's fullpath includes that of the node being renamed", async () => {
// Open dirty file defined by globalMocks.mockTextDocumentDirty, with filepath including "sestest/test/node"
const globalMocks = createGlobalMocks();
Expand Down Expand Up @@ -1233,7 +1253,6 @@ describe("USSTree Unit Tests - Function getChildren", () => {
contextOverride: Constants.USS_SESSION_CONTEXT,
session: globalMocks.testSession,
profile: globalMocks.testProfile,
parentPath: "/",
}),
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,26 @@ describe("stat", () => {
expect(listFilesMock).toHaveBeenCalled();
listFilesMock.mockRestore();
});

it("updates a file entry with new modification time and resets wasAccessed flag", async () => {
const fakeFile = Object.assign(Object.create(Object.getPrototypeOf(testEntries.file)), testEntries.file);
lookupMock.mockReturnValueOnce(fakeFile);
const newMtime = Date.now();
const listFilesMock = jest.spyOn(UssFSProvider.instance, "listFiles").mockResolvedValueOnce({
success: true,
apiResponse: {
items: [{ name: fakeFile.name, mtime: newMtime }],
},
commandResponse: "",
});
await expect(UssFSProvider.instance.stat(testUris.file)).resolves.toStrictEqual(fakeFile);
expect(lookupMock).toHaveBeenCalledWith(testUris.file, false);
expect(fakeFile.mtime).toBe(newMtime);
expect(fakeFile.wasAccessed).toBe(false);
expect(listFilesMock).toHaveBeenCalled();
listFilesMock.mockRestore();
});

it("returns a file as 'read-only' when query has conflict parameter", async () => {
lookupMock.mockReturnValueOnce(testEntries.file);
await expect(UssFSProvider.instance.stat(testUris.conflictFile)).resolves.toStrictEqual({
Expand Down
Loading

0 comments on commit 07232b7

Please sign in to comment.