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

Fix UNIX attributes refresh button #3462

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
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-api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ All notable changes to the "zowe-explorer-api" extension will be documented in t
### New features and enhancements

- Added new `copyDataSetCrossLpar` API to provide ability to copy/paste data sets across LPARs. [#3012](https://github.com/zowe/zowe-explorer-vscode/issues/3012)
- Added new `fetchAttributes` API to `IZoweUSSTreeNode` to fetch latest attributes for UNIX files. [#3238](https://github.com/zowe/zowe-explorer-vscode/issues/3238)
- Added new `directConnectLogin` and `directConnectLogout` to the ZoweVsCodeExtension class. [#3346](https://github.com/zowe/zowe-explorer-vscode/issues/3346)

### Bug fixes
Expand Down
5 changes: 5 additions & 0 deletions packages/zowe-explorer-api/src/tree/IZoweTreeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,11 @@ export interface IZoweUSSTreeNode extends IZoweTreeNode {
*/
getAttributes(): Types.FileAttributes | PromiseLike<Types.FileAttributes>;

/**
* Fetches the attributes for the USS file/folder from host.
*/
fetchAttributes?(): Types.FileAttributes | PromiseLike<Types.FileAttributes>;

/**
* Sets the attributes for the USS file/folder.
*/
Expand Down
1 change: 1 addition & 0 deletions packages/zowe-explorer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen
- Fixed an issue seen with outdated profile information in the z/OS tree view data during upload and download of data set and USS files
[#3457](https://github.com/zowe/zowe-explorer-vscode/issues/3457)
- Fixed issue where deleting too many nodes at once would cause the confirmation prompt to be oversized. [#3254](https://github.com/zowe/zowe-explorer-vscode/issues/3254)
- Fixed an issue with UNIX file edit attributes refresh button not updating/reverting values correctly. [#3238](https://github.com/zowe/zowe-explorer-vscode/issues/3238)

## `3.1.1`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ describe("AttributeView unit tests", () => {
node.getParent = jest.fn().mockReturnValueOnce({ label: "parent node" } as IZoweUSSTreeNode);
await (view as any).onDidReceiveMessage({ command: "refresh" });
expect(treeProvider.refreshElement).toHaveBeenCalled();

expect(node.onUpdate).toHaveBeenCalledTimes(2);
});

it("dispatches node data to webview when 'ready' command is received", async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1410,6 +1410,74 @@ describe("ZoweUSSNode Unit Tests - Function node.getAttributes", () => {
});
});

describe("ZoweUSSNode Unit Tests - Function node.fetchAttributes", () => {
const attrs1 = { owner: "aUser", uid: 0, gid: 1000, group: "USERS", perms: "rwxrwxrwx" };
const attrs2 = { owner: "bUser", uid: 0, gid: 1000, group: "USERS", perms: "rwxrw-rw-" };
const fileAttrs = [
{
gid: attrs2.gid,
uid: attrs2.uid,
group: attrs2.group,
mode: attrs2.perms,
user: attrs2.owner,
},
];
it("fetches the attributes for a file from host", async () => {
const fileEntry = new UssFile("testFile");
fileEntry.attributes = attrs1;
const lookupMock = jest.spyOn(UssFSProvider.instance, "lookup").mockReturnValueOnce(fileEntry);
const node = new ZoweUSSNode({ label: "testFile", collapsibleState: vscode.TreeItemCollapsibleState.None });
jest.spyOn(UssFSProvider.instance, "listFiles").mockResolvedValueOnce({
success: true,
apiResponse: { items: fileAttrs },
commandResponse: "",
});
jest.spyOn(node, "setAttributes").mockImplementation();
expect(await node.fetchAttributes()).toStrictEqual(attrs2);
lookupMock.mockRestore();
});
it("returns undefined if no entry is found", async () => {
const lookupMock = jest.spyOn(UssFSProvider.instance, "lookup").mockReturnValueOnce(undefined);
const node = new ZoweUSSNode({ label: "testFile", collapsibleState: vscode.TreeItemCollapsibleState.None });
expect(await node.fetchAttributes()).toBeUndefined();
lookupMock.mockRestore();
});
it("returns undefined if API response success is false", async () => {
const fileEntry = new UssFile("testFile");
const lookupMock = jest.spyOn(UssFSProvider.instance, "lookup").mockReturnValueOnce(fileEntry);
const node = new ZoweUSSNode({ label: "testFile", collapsibleState: vscode.TreeItemCollapsibleState.None });
jest.spyOn(UssFSProvider.instance, "listFiles").mockResolvedValueOnce({
success: false,
apiResponse: { items: [] },
commandResponse: "",
});
expect(await node.fetchAttributes()).toBeUndefined();
lookupMock.mockRestore();
});
it("returns undefined if API response apiResponse is empty array", async () => {
const lookupMock = jest.spyOn(UssFSProvider.instance, "lookup").mockReturnValueOnce(undefined);
const node = new ZoweUSSNode({ label: "testFile", collapsibleState: vscode.TreeItemCollapsibleState.None });
jest.spyOn(UssFSProvider.instance, "listFiles").mockResolvedValueOnce({
success: true,
apiResponse: { items: [] },
commandResponse: "",
});
expect(await node.fetchAttributes()).toBeUndefined();
lookupMock.mockRestore();
});
it("returns undefined if API response apiResponse is more than 1 array/file attrs", async () => {
const lookupMock = jest.spyOn(UssFSProvider.instance, "lookup").mockReturnValueOnce(undefined);
const node = new ZoweUSSNode({ label: "testFile", collapsibleState: vscode.TreeItemCollapsibleState.None });
jest.spyOn(UssFSProvider.instance, "listFiles").mockResolvedValueOnce({
success: true,
apiResponse: { items: fileAttrs, fileAttrs },
commandResponse: "",
});
expect(await node.fetchAttributes()).toBeUndefined();
lookupMock.mockRestore();
});
});

describe("ZoweUSSNode Unit Tests - Function node.setAttributes", () => {
const attrs = { owner: "aUser", uid: 0, gid: 1000, group: "USERS", perms: "rwxrwxrwx" };
it("sets the attributes for a file", () => {
Expand Down
19 changes: 8 additions & 11 deletions packages/zowe-explorer/src/trees/uss/USSAttributeView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*/

import { Types, Gui, MainframeInteraction, IZoweUSSTreeNode, WebView } from "@zowe/zowe-explorer-api";
import { Disposable, ExtensionContext } from "vscode";
import { ExtensionContext } from "vscode";
import { ZoweExplorerApiRegister } from "../../extending/ZoweExplorerApiRegister";
import { SharedContext } from "../shared/SharedContext";
import * as vscode from "vscode";
Expand All @@ -22,8 +22,6 @@ export class USSAttributeView extends WebView {
private readonly ussApi: MainframeInteraction.IUss;
private readonly canUpdate: boolean;

private onUpdateDisposable: Disposable;

public constructor(context: ExtensionContext, treeProvider: Types.IZoweUSSTreeType, node: IZoweUSSTreeNode) {
const label = node.label ? `Edit Attributes: ${node.label as string}` : "Edit Attributes";
super(label, "edit-attributes", context, {
Expand All @@ -45,14 +43,13 @@ export class USSAttributeView extends WebView {
switch (message.command) {
case "refresh":
if (this.canUpdate) {
this.onUpdateDisposable = this.ussNode.onUpdate(async (node) => {
await this.attachTag(node);
await this.panel.webview.postMessage({
attributes: await this.ussNode.getAttributes(),
name: node.fullPath,
readonly: this.ussApi.updateAttributes == null,
});
this.onUpdateDisposable.dispose();
const attrs = await this.ussNode.fetchAttributes();
await this.ussNode.setAttributes(attrs);
await this.attachTag(this.ussNode);
await this.panel.webview.postMessage({
attributes: await this.ussNode.getAttributes(),
name: this.ussNode.fullPath,
allowUpdate: false,
});

if (this.ussNode.getParent()) {
Expand Down
21 changes: 21 additions & 0 deletions packages/zowe-explorer/src/trees/uss/ZoweUSSNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,27 @@ export class ZoweUSSNode extends ZoweTreeNode implements IZoweUSSTreeNode {
return ussEntry.attributes;
}

public async fetchAttributes(): Promise<Types.FileAttributes> {
const ussEntry = UssFSProvider.instance.lookup(this.resourceUri, true) as UssFile | UssDirectory;
if (ussEntry == null || FsAbstractUtils.isDirectoryEntry(ussEntry)) {
return undefined;
}
const response = await this.getUssFiles(this.profile);
if (response.success === false || response.apiResponse?.items.length === 0 || response.apiResponse?.items.length > 1) {
return undefined;
}
const item = response.apiResponse.items[0];
const attrs: Types.FileAttributes = {
gid: item.gid,
uid: item.uid,
group: item.group,
perms: item.mode,
owner: item.user,
};
this.setAttributes(attrs);
return attrs;
}

public setAttributes(attributes: Partial<Types.FileAttributes>): void {
const ussEntry = UssFSProvider.instance.lookup(this.resourceUri, true) as UssFile | UssDirectory;
if (ussEntry == null) {
Expand Down
Loading