Skip to content

Commit

Permalink
Fix UNIX attributes refresh button (#3462)
Browse files Browse the repository at this point in the history
* early stage fixes

Signed-off-by: Billie Simmons <[email protected]>

* save state

Signed-off-by: Billie Simmons <[email protected]>

* set fetched values

Signed-off-by: Billie Simmons <[email protected]>

* run prepublish

Signed-off-by: Billie Simmons <[email protected]>

* add CHANGELOG

Signed-off-by: Billie Simmons <[email protected]>

* ZE API changelog

Signed-off-by: Billie Simmons <[email protected]>

* clean up of comments

Signed-off-by: Billie Simmons <[email protected]>

* add code cov

Signed-off-by: Billie Simmons <[email protected]>

* address comments and add coverage for updated checks

Signed-off-by: Billie Simmons <[email protected]>

* remove un-needed import

Signed-off-by: Billie Simmons <[email protected]>

* fix tests order info

Signed-off-by: Billie Simmons <[email protected]>

* make new api fetchAttributes optional

Signed-off-by: Billie Simmons <[email protected]>

---------

Signed-off-by: Billie Simmons <[email protected]>
Signed-off-by: Billie Simmons <[email protected]>
Co-authored-by: Trae Yelovich <[email protected]>
Signed-off-by: Billie Simmons <[email protected]>
  • Loading branch information
JillieBeanSim and traeok committed Mar 4, 2025
1 parent 6f0fb13 commit 5665fad
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 13 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 @@ -6,6 +6,7 @@ All notable changes to the "zowe-explorer-api" extension will be documented in t

### New features and enhancements

- 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 optional `refreshFavorites` to IZoweTree interface. [#3470](https://github.com/zowe/zowe-explorer-vscode/issues/3470)

### 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 @@ -13,6 +13,7 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen
- Fixed missing z/OS Console icon when `Workbench > Panel: Show Labels` is set to false. [#3293](https://github.com/zowe/zowe-explorer-vscode/issues/3293)
- Fixed z/OS Console panel background colour to be in sync with the rest of the VS Code styling. [#3445](https://github.com/zowe/zowe-explorer-vscode/pull/3445)
- 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)
- Fixed an issue seen where extender favorites not showing in the tree views. [#3470](https://github.com/zowe/zowe-explorer-vscode/issues/3470)

## `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

0 comments on commit 5665fad

Please sign in to comment.