Skip to content

Commit

Permalink
fix(v2): prompt optimizations for create file/dir; address case of sk…
Browse files Browse the repository at this point in the history
…ipping prompt (#3192)

* fix: handle trailing slashes and dismissing prompt

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

* chore: update changelog

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

* refactor: remove isTopLevel param, update test cases

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

* chore: update ZE changelog

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

* chore: update changelog w/ v2-specific change

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

* refactor(createUSSNode): remove optional chaining in if block

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

---------

Signed-off-by: Trae Yelovich <[email protected]>
  • Loading branch information
traeok authored Oct 7, 2024
1 parent d090118 commit 29d09ff
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 15 deletions.
3 changes: 3 additions & 0 deletions packages/zowe-explorer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen

- Fix issue where the Zowe Explorer VS Code command `Refresh Zowe Explorer` failed catastrophically. [#3100](https://github.com/zowe/zowe-explorer-vscode/issues/3100)
- Fixed an issue where the `ProfilesUtils.getProfileInfo` function returned a new `ProfileInfo` instance that did not respect the `ZOWE_CLI_HOME` environment variable and workspace paths. [#3168](https://github.com/zowe/zowe-explorer-vscode/issues/3168)
- Fixed an issue where the location prompt for the `Create Directory` and `Create File` USS features would appear even when a path is already set for the profile or parent folder. [#3183](https://github.com/zowe/zowe-explorer-vscode/pull/3183)
- Fixed an issue where the `Create Directory` and `Create File` features would continue processing when the first prompt was dismissed, causing an incorrect path to be generated. [#3183](https://github.com/zowe/zowe-explorer-vscode/pull/3183)
- Fixed an issue where the `Create Directory` and `Create File` features would incorrectly handle user-specified locations with trailing slashes. [#3183](https://github.com/zowe/zowe-explorer-vscode/pull/3183)

## `2.18.0`

Expand Down
62 changes: 55 additions & 7 deletions packages/zowe-explorer/__tests__/__unit__/uss/actions.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,14 +197,64 @@ describe("USS Action Unit Tests - Function createUSSNode", () => {

globalMocks.mockShowInputBox.mockReturnValue("USSFolder");
jest.spyOn(blockMocks.ussNode, "getChildren").mockResolvedValueOnce([]);
const isTopLevel = false;
jest.spyOn(refreshActions, "refreshAll");
mocked(refreshActions.refreshAll).mockClear();

await ussNodeActions.createUSSNode(blockMocks.ussNode, blockMocks.testUSSTree, "folder", isTopLevel);
await ussNodeActions.createUSSNode(blockMocks.ussNode, blockMocks.testUSSTree, "folder");
expect(blockMocks.testUSSTree.refreshElement).toHaveBeenCalled();
expect(refreshActions.refreshAll).not.toHaveBeenCalled();
});

it("should prompt the user for a location if one is not set on the node", async () => {
const globalMocks = createGlobalMocks();
const blockMocks = await createBlockMocks(globalMocks);

globalMocks.mockShowInputBox.mockReturnValue("USSFolder");
jest.spyOn(blockMocks.ussNode, "getChildren").mockResolvedValueOnce([]);
globalMocks.mockShowInputBox.mockResolvedValueOnce("/u/myuser/");
globalMocks.mockShowInputBox.mockResolvedValueOnce("folderName");
const createApiMock = jest.spyOn(blockMocks.ussApi, "create").mockImplementation();
const refreshAllMock = jest.spyOn(refreshActions, "refreshAll").mockImplementation();
blockMocks.ussNode.getParent().fullPath = "";

await ussNodeActions.createUSSNode(blockMocks.ussNode.getParent(), blockMocks.testUSSTree, "folder");
expect(globalMocks.mockShowInputBox).toHaveBeenCalledTimes(2);
expect(refreshAllMock).toHaveBeenCalled();
createApiMock.mockRestore();
refreshAllMock.mockRestore();
});

it("returns early if a location was never provided", async () => {
const globalMocks = createGlobalMocks();
const blockMocks = await createBlockMocks(globalMocks);

globalMocks.mockShowInputBox.mockResolvedValueOnce(undefined);
const createApiMock = jest.spyOn(blockMocks.ussApi, "create").mockImplementation();
createApiMock.mockClear();
blockMocks.ussNode.getParent().fullPath = "";

await ussNodeActions.createUSSNode(blockMocks.ussNode.getParent(), blockMocks.testUSSTree, "directory");
expect(createApiMock).not.toHaveBeenCalled();
createApiMock.mockRestore();
});

it("handles trailing slashes in the location", async () => {
const globalMocks = createGlobalMocks();
const blockMocks = await createBlockMocks(globalMocks);

globalMocks.mockShowInputBox.mockResolvedValueOnce("/u/myuser/aDir/");
globalMocks.mockShowInputBox.mockResolvedValueOnce("testFile.txt");
const createApiMock = jest.spyOn(blockMocks.ussApi, "create").mockImplementation();
const refreshAllMock = jest.spyOn(refreshActions, "refreshAll").mockImplementation();
blockMocks.ussNode.getParent().fullPath = "";

await ussNodeActions.createUSSNode(blockMocks.ussNode.getParent(), blockMocks.testUSSTree, "file");
expect(createApiMock).toHaveBeenCalledWith("/u/myuser/aDir/testFile.txt", "file");
expect(refreshAllMock).toHaveBeenCalled();
createApiMock.mockRestore();
refreshAllMock.mockRestore();
});

it("Tests that createUSSNode does not execute if node name was not entered", async () => {
const globalMocks = createGlobalMocks();
const blockMocks = await createBlockMocks(globalMocks);
Expand Down Expand Up @@ -262,11 +312,10 @@ describe("USS Action Unit Tests - Function createUSSNode", () => {
const blockMocks = await createBlockMocks(globalMocks);

globalMocks.mockShowInputBox.mockReturnValueOnce("USSFolder");
jest.spyOn(blockMocks.ussNode, "getChildren").mockResolvedValueOnce([]);
const isTopLevel = false;
jest.spyOn(refreshActions, "refreshAll");
mocked(refreshActions.refreshAll).mockClear();

await ussNodeActions.createUSSNode(blockMocks.ussNode, blockMocks.testUSSTree, "folder", isTopLevel);
await ussNodeActions.createUSSNode(blockMocks.ussNode, blockMocks.testUSSTree, "folder");
expect(blockMocks.testUSSTree.refreshElement).toHaveBeenCalled();
expect(refreshActions.refreshAll).not.toHaveBeenCalled();
});
Expand All @@ -275,7 +324,6 @@ describe("USS Action Unit Tests - Function createUSSNode", () => {
const globalMocks = createGlobalMocks();
const blockMocks = await createBlockMocks(globalMocks);
globalMocks.mockShowInputBox.mockReturnValueOnce("USSFolder");
const isTopLevel = false;
const errorHandlingSpy = jest.spyOn(utils, "errorHandling");

// Simulate unsuccessful api call
Expand All @@ -285,7 +333,7 @@ describe("USS Action Unit Tests - Function createUSSNode", () => {
}),
});

await expect(ussNodeActions.createUSSNode(blockMocks.ussNode, blockMocks.testUSSTree, "folder", isTopLevel)).rejects.toThrow();
await expect(ussNodeActions.createUSSNode(blockMocks.ussNode, blockMocks.testUSSTree, "folder")).rejects.toThrow();
expect(errorHandlingSpy).toHaveBeenCalledTimes(1);
});
});
Expand Down
17 changes: 9 additions & 8 deletions packages/zowe-explorer/src/uss/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,12 @@ const localize: nls.LocalizeFunc = nls.loadMessageBundle();
* @param {ussTree} ussFileProvider - Current ussTree used to populate the TreeView
* @returns {Promise<void>}
*/
export async function createUSSNode(
node: IZoweUSSTreeNode,
ussFileProvider: IZoweTree<IZoweUSSTreeNode>,
nodeType: string,
isTopLevel?: boolean
): Promise<void> {
export async function createUSSNode(node: IZoweUSSTreeNode, ussFileProvider: IZoweTree<IZoweUSSTreeNode>, nodeType: string): Promise<void> {
ZoweLogger.trace("uss.actions.createUSSNode called.");
await ussFileProvider.checkCurrentProfile(node);
let filePath = "";
if (contextually.isSession(node)) {
const isTopLevel = contextually.isSession(node);
if (isTopLevel && node.fullPath?.length === 0) {
const filePathOptions: vscode.InputBoxOptions = {
placeHolder: localize("createUSSNode.inputBox.placeholder", "{0} location", nodeType),
prompt: localize("createUSSNode.inputBox.prompt", "Choose a location to create the {0}", nodeType),
Expand All @@ -64,13 +60,18 @@ export async function createUSSNode(
} else {
filePath = node.fullPath;
}

if (filePath == null || filePath.length === 0) {
return;
}

const nameOptions: vscode.InputBoxOptions = {
placeHolder: localize("createUSSNode.name", "Name of file or directory"),
};
const name = await Gui.showInputBox(nameOptions);
if (name && filePath) {
try {
filePath = `${filePath}/${name}`;
filePath = path.posix.join(filePath, name);
await ZoweExplorerApiRegister.getUssApi(node.getProfile()).create(filePath, nodeType);
if (isTopLevel) {
await refreshAll(ussFileProvider);
Expand Down

0 comments on commit 29d09ff

Please sign in to comment.