Skip to content

Commit

Permalink
Merge pull request zowe#1 from kristinochka/uss-explorer-create-delete
Browse files Browse the repository at this point in the history
Create and delete Nodes in USS Explorer
  • Loading branch information
kristinochka authored Apr 18, 2019
2 parents 094ef09 + c216ce0 commit dc8fa12
Show file tree
Hide file tree
Showing 7 changed files with 240 additions and 9 deletions.
4 changes: 2 additions & 2 deletions __tests__/extension.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ describe("Extension Unit Tests", async () => {
getChildren: mockGetUSSChildren,
}
});
expect(registerCommand.mock.calls.length).toBe(24);
expect(registerCommand.mock.calls.length).toBe(27);
expect(registerCommand.mock.calls[0][0]).toBe("zowe.addSession");
expect(registerCommand.mock.calls[0][1]).toBeInstanceOf(Function);
expect(registerCommand.mock.calls[1][0]).toBe("zowe.addFavorite");
Expand Down Expand Up @@ -1193,7 +1193,7 @@ describe("Extension Unit Tests", async () => {
showInputBox.mockReset();

const node = new ZoweUSSNode("node", vscode.TreeItemCollapsibleState.None, ussNode, null, null);
node.fullPath = "/u/test";
node.fullPath = "//u/test";
node.contextValue = "uss_session";

showInputBox.mockReturnValueOnce("/u/test");
Expand Down
8 changes: 3 additions & 5 deletions __tests__/integrationTests/extension.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -499,14 +499,12 @@ describe("Extension Integration Tests - USS", () => {
});

describe("Enter USS Pattern", () => {
it("should output path that match the user-provided path", async () => {
it("should output path that match the user-provided and starts with 2 double slashes", async () => {
const inputBoxStub = sandbox.stub(vscode.window, "showInputBox");
inputBoxStub.returns(fullUSSPath);

await extension.enterUSSPattern(ussSessionNode, ussTestTree);

expect(ussTestTree.mSessionNodes[0].fullPath).to.equal(fullUSSPath);
expect(ussTestTree.mSessionNodes[0].tooltip).to.equal(fullUSSPath);
expect(ussTestTree.mSessionNodes[0].fullPath).to.equal(`/${fullUSSPath}`);
expect(ussTestTree.mSessionNodes[0].tooltip).to.equal(`/${fullUSSPath}`);
expect(ussTestTree.mSessionNodes[0].collapsibleState).to.equal(vscode.TreeItemCollapsibleState.Expanded);

// const ussTestTreeView = vscode.window.createTreeView("zowe.uss.explorer", {treeDataProvider: ussTestTree});
Expand Down
121 changes: 121 additions & 0 deletions __tests__/uss/ussNodeActions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* This program and the accompanying materials are made available under the terms of the *
* Eclipse Public License v2.0 which accompanies this distribution, and is available at *
* https://www.eclipse.org/legal/epl-v20.html *
* *
* SPDX-License-Identifier: EPL-2.0 *
* *
* Copyright Contributors to the Zowe Project. *
* *
*/

import * as vscode from "vscode";
import { ZoweUSSNode } from "../../src/ZoweUSSNode";
import * as brtimperative from "@brightside/imperative";
import * as brightside from "@brightside/core";
import { createUSSNode, deleteUSSNode, parseUSSPath } from "../../src/uss/ussNodeActions";

const Create = jest.fn();
const Delete = jest.fn();
const uss = jest.fn();
const ussFile = jest.fn();
const mockAddUSSSession = jest.fn();
const mockUSSRefresh = jest.fn();
const mockGetUSSChildren = jest.fn();
const showInputBox = jest.fn();
const showErrorMessage = jest.fn();
const showQuickPick = jest.fn();

function getUSSNode() {
const ussNode = new ZoweUSSNode("usstest", vscode.TreeItemCollapsibleState.Expanded, null, session, null);
ussNode.contextValue = "uss_session";
ussNode.fullPath = "/u/myuser";
return ussNode;
}

function getUSSTree() {
const ussNode = getUSSNode();
const USSTree = jest.fn().mockImplementation(() => {
return {
mSessionNodes: [],
addSession: mockAddUSSSession,
refresh: mockUSSRefresh,
getChildren: mockGetUSSChildren,
};
});
const testUSSTree = USSTree();
testUSSTree.mSessionNodes = [];
testUSSTree.mSessionNodes.push(ussNode);
return testUSSTree;
}

const session = new brtimperative.Session({
user: "fake",
password: "fake",
hostname: "fake",
protocol: "https",
type: "basic",
});

const ussNode = getUSSNode();
const testUSSTree = getUSSTree();

Object.defineProperty(brightside, "Create", {value: Create});
Object.defineProperty(brightside, "Delete", {value: Delete});
Object.defineProperty(Create, "uss", { value: uss });
Object.defineProperty(Delete, "ussFile", { value: ussFile });
Object.defineProperty(vscode.window, "showInputBox", {value: showInputBox});
Object.defineProperty(vscode.window, "showErrorMessage", {value: showErrorMessage});
Object.defineProperty(vscode.window, "showQuickPick", {value: showQuickPick});

describe("ussNodeActions", async () => {
beforeEach(() => {
showErrorMessage.mockReset();
testUSSTree.refresh.mockReset();
showQuickPick.mockReset();
});
describe("createUSSNode", () => {
it("createUSSNode is executed successfully", async () => {
showInputBox.mockReset();
showInputBox.mockReturnValueOnce("USSFolder");
await createUSSNode(ussNode, testUSSTree, "file");
expect(testUSSTree.refresh).toHaveBeenCalled();
expect(showErrorMessage.mock.calls.length).toBe(0);
});
it("createUSSNode does not execute if node name was not entered", async () => {
showInputBox.mockReset();
showInputBox.mockReturnValueOnce("");
await createUSSNode(ussNode, testUSSTree, "file");
expect(testUSSTree.refresh).not.toHaveBeenCalled();
expect(showErrorMessage.mock.calls.length).toBe(0);
});
})
describe("deleteUSSNode", () => {
it("deleteUSSNode is executed successfully", async () => {
showQuickPick.mockResolvedValueOnce("Yes");
await deleteUSSNode(ussNode, testUSSTree, "");
expect(testUSSTree.refresh).toHaveBeenCalled();
});
it("should not delete node if user did not verify", async () => {
showQuickPick.mockResolvedValueOnce("No");
await deleteUSSNode(ussNode, testUSSTree, "");
expect(testUSSTree.refresh).not.toHaveBeenCalled();
});
});
describe("parseUSSPath", () => {
it("should append slash", () => {
expect(parseUSSPath("/u/user")).toEqual("//u/user");
expect(parseUSSPath("/test")).toEqual("//test");
expect(parseUSSPath("/u/kri/dir/dir2")).toEqual("//u/kri/dir/dir2");
});
it("should not append slash", () => {
expect(parseUSSPath("//u/user")).toEqual("//u/user");
expect(parseUSSPath("//")).toEqual("//");
expect(parseUSSPath("///")).toEqual("///");
expect(parseUSSPath("/")).toEqual("/");
expect(parseUSSPath("")).toEqual("");
expect(parseUSSPath(undefined)).toEqual(undefined);
expect(parseUSSPath("//u/kri/dir/dir2")).toEqual("//u/kri/dir/dir2");
});
});
});
30 changes: 29 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@
]
},
"commands": [
{
"command": "zowe.uss.createFile",
"title": "Create file"
},
{
"command": "zowe.uss.createFolder",
"title": "Create directory"
},
{
"command": "zowe.uss.deleteNode",
"title": "Delete"
},
{
"command": "zowe.addFavorite",
"title": "Add Favorite"
Expand Down Expand Up @@ -204,6 +216,21 @@
}
],
"view/item/context": [
{
"when": "view == zowe.uss.explorer && viewItem == directory",
"command": "zowe.uss.createFile",
"group": "navigation"
},
{
"when": "view == zowe.uss.explorer && viewItem == directory",
"command": "zowe.uss.createFolder",
"group": "navigation"
},
{
"when": "view == zowe.uss.explorer",
"command": "zowe.uss.deleteNode",
"group": "navigation"
},
{
"when": "viewItem == member",
"command": "zowe.refreshNode",
Expand Down Expand Up @@ -527,7 +554,8 @@
}
},
"testMatch": [
"**/__tests__/*test.+(ts|tsx)"
"**/__tests__/*test.+(ts|tsx)",
"**/__tests__/*/*test.+(ts|tsx)"
],
"modulePathIgnorePatterns": [
"__tests__/integrationTests/"
Expand Down
2 changes: 1 addition & 1 deletion resources/testProfileData.example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const profile: IProfile = {
host: "",
port: 0,
user: "",
pass: "",
password: "",
rejectUnauthorized: false,
name: "" // @NOTE: This profile name must match an existing zowe profile in the ~/.zowe/profiles/zosmf folder
};
Expand Down
5 changes: 5 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { CliProfileManager, Logger } from "@brightside/imperative";
import { DatasetTree } from "./DatasetTree";
import { USSTree } from "./USSTree";
import { ZoweUSSNode } from "./ZoweUSSNode";
import * as ussActions from "./uss/ussNodeActions";

// Globals
export const BRIGHTTEMPFOLDER = path.join(__dirname, "..", "..", "resources", "temp");
Expand Down Expand Up @@ -111,6 +112,9 @@ export async function activate(context: vscode.ExtensionContext) {
vscode.commands.registerCommand("zowe.uss.fullPath", (node) => enterUSSPattern(node, ussFileProvider));
vscode.commands.registerCommand("zowe.uss.ZoweUSSNode.open", (node) => openUSS(node));
vscode.commands.registerCommand("zowe.uss.removeSession", async (node) => ussFileProvider.deleteSession(node));
vscode.commands.registerCommand("zowe.uss.createFile", async (node) => ussActions.createUSSNode(node, ussFileProvider, "file"));
vscode.commands.registerCommand("zowe.uss.createFolder", async (node) => ussActions.createUSSNode(node, ussFileProvider, "directory"));
vscode.commands.registerCommand("zowe.uss.deleteNode", async (node) => ussActions.deleteUSSNode(node, ussFileProvider, getUSSDocumentFilePath(node)));
}

/**
Expand Down Expand Up @@ -538,6 +542,7 @@ export async function enterUSSPattern(node: ZoweUSSNode, ussFileProvider: USSTre
};
// get user input
remotepath = await vscode.window.showInputBox(options);
remotepath = ussActions.parseUSSPath(remotepath);
if (!remotepath) {
vscode.window.showInformationMessage("You must enter a path.");
return;
Expand Down
79 changes: 79 additions & 0 deletions src/uss/ussNodeActions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* This program and the accompanying materials are made available under the terms of the *
* Eclipse Public License v2.0 which accompanies this distribution, and is available at *
* https://www.eclipse.org/legal/epl-v20.html *
* *
* SPDX-License-Identifier: EPL-2.0 *
* *
* Copyright Contributors to the Zowe Project. *
* *
*/

import { USSTree } from "../USSTree";
import { ZoweUSSNode } from "../ZoweUSSNode";
import * as vscode from "vscode";
import * as zowe from "@brightside/core";
import * as fs from "fs";

/**
* Prompts the user for a path, and populates the [TreeView]{@link vscode.TreeView} based on the path
*
* @param {ZoweUSSNode} node - The session node
* @param {ussTree} ussFileProvider - Current ussTree used to populate the TreeView
* @returns {Promise<void>}
*/
export async function createUSSNode(node: ZoweUSSNode, ussFileProvider: USSTree, nodeType: string) {
const name = await vscode.window.showInputBox({placeHolder: "Name of Member"});
if (name) {
try {
const filePath = `${node.fullPath}/${name}`;
await zowe.Create.uss(node.getSession(), filePath, nodeType);
ussFileProvider.refresh();
} catch (err) {
vscode.window.showErrorMessage(`Unable to create node: ${err.message}`);
throw (err);
}
}
}

export async function deleteUSSNode(node: ZoweUSSNode, ussFileProvider: USSTree, filePath: string) {
const nodePath = node.fullPath;
const quickPickOptions: vscode.QuickPickOptions = {
placeHolder: `Are you sure you want to delete ${node.label}`,
ignoreFocusOut: true,
canPickMany: false
};
if (await vscode.window.showQuickPick(["Yes", "No"], quickPickOptions) === "No") {
return;
}
try {
const isRecursive = node.contextValue === "directory" ? true : false;
await zowe.Delete.ussFile(node.getSession(), nodePath, isRecursive);
ussFileProvider.refresh();
deleteFromDisk(node, filePath);
} catch (err) {
vscode.window.showErrorMessage(`Unable to delete node: ${err.message}`);
throw (err);
}
}

export function parseUSSPath(path: string) {
if (path && path.match('^\/[^\/]')) {
return `/${path}`;
}
return path;
}

/**
* Marks file as deleted from disk
*
* @param {ZoweUSSNode} node
*/
export async function deleteFromDisk(node: ZoweUSSNode, filePath: string) {
try {
if (fs.existsSync(filePath)) {
fs.unlinkSync(filePath);
}
}
catch (err) {}
}

0 comments on commit dc8fa12

Please sign in to comment.