diff --git a/packages/zowe-explorer/__tests__/__unit__/commands/ZoweCommandProvider.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/commands/ZoweCommandProvider.unit.test.ts index 5cdc94051..98c1da9b6 100644 --- a/packages/zowe-explorer/__tests__/__unit__/commands/ZoweCommandProvider.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/commands/ZoweCommandProvider.unit.test.ts @@ -96,23 +96,34 @@ describe("ZoweCommandProvider Unit Tests", () => { }); describe("function issueCommand", () => { + const testError = new imperative.ImperativeError({ + msg: "test-msg", + causeErrors: "test-causeErrors", + additionalDetails: "test-additionalDetails", + }); + const mockCmdProvider: any = { + useIntegratedTerminals: true, + terminalName: "test-terminal", + pseudoTerminal: {}, + formatCommandLine: (cmd: string) => "test-" + cmd, + history: { getSearchHistory: () => ["old-cmd-01", "old-cmd-02"], addSearchHistory: jest.fn() }, + runCommand: jest.fn().mockRejectedValue(testError), + }; + const testProfile: any = { name: "test", profile: { user: "firstName", password: "12345" } }; + + it("should not create a terminal if the profile or the command is undefined", async () => { + const createTerminal = jest.fn().mockReturnValue({ show: jest.fn() }); + Object.defineProperty(vscode.window, "createTerminal", { value: createTerminal, configurable: true }); + await ZoweCommandProvider.prototype.issueCommand.call(mockCmdProvider, null, "test"); + await ZoweCommandProvider.prototype.issueCommand.call(mockCmdProvider, undefined, "test"); + await ZoweCommandProvider.prototype.issueCommand.call(mockCmdProvider, testProfile, null); + await ZoweCommandProvider.prototype.issueCommand.call(mockCmdProvider, testProfile, undefined); + expect(createTerminal).not.toHaveBeenCalled(); + }); + it("should create an integrated terminal", async () => { const createTerminal = jest.fn().mockReturnValue({ show: jest.fn() }); - Object.defineProperty(vscode.window, "createTerminal", { value: createTerminal }); - const testError = new imperative.ImperativeError({ - msg: "test-msg", - causeErrors: "test-causeErrors", - additionalDetails: "test-additionalDetails", - }); - const mockCmdProvider: any = { - useIntegratedTerminals: true, - terminalName: "test-terminal", - pseudoTerminal: {}, - formatCommandLine: (cmd: string) => "test-" + cmd, - history: { getSearchHistory: () => ["old-cmd-01", "old-cmd-02"], addSearchHistory: jest.fn() }, - runCommand: jest.fn().mockRejectedValue(testError), - }; - const testProfile: any = { name: "test", profile: { user: "firstName", password: "12345" } }; + Object.defineProperty(vscode.window, "createTerminal", { value: createTerminal, configurable: true }); await ZoweCommandProvider.prototype.issueCommand.call(mockCmdProvider, testProfile, "test"); expect(createTerminal).toHaveBeenCalled(); diff --git a/packages/zowe-explorer/__tests__/__unit__/tools/ZoweTerminal.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/tools/ZoweTerminal.unit.test.ts index f919ce2db..514b0e4c1 100644 --- a/packages/zowe-explorer/__tests__/__unit__/tools/ZoweTerminal.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/tools/ZoweTerminal.unit.test.ts @@ -16,6 +16,22 @@ describe("ZoweTerminal Unit Tests", () => { expect(ZoweTerminal.Keys).toMatchSnapshot(); }); + it("should handle ctrl_c to cancel a running command", async () => { + const spyCb = jest.fn().mockImplementation(async (cmd: string) => Promise.resolve("test-output")); + const signalSpy = jest.fn().mockImplementation((_event, cb) => cb()); + const iTerm = new ZoweTerminal("test", spyCb, { abort: jest.fn(), signal: { addEventListener: signalSpy } } as any, { history: ["old"] }); + (iTerm as any).command = "open"; + iTerm.open(); + + await iTerm.handleInput(ZoweTerminal.Keys.ENTER); + (iTerm as any).isCommandRunning = true; + await iTerm.handleInput(ZoweTerminal.Keys.CTRL_D); + expect(spyCb).toHaveBeenCalledWith("open"); + spyCb.mockClear(); + + expect((iTerm as any).mHistory as string[]).toEqual(["old", "open"]); + }); + it("should send the entered command to the callback function", async () => { const spyCb = jest.fn().mockImplementation(async (cmd: string) => Promise.resolve("test-output")); const iTerm = new ZoweTerminal("test", spyCb, { signal: { addEventListener: jest.fn() } } as any, { history: ["old"] }); @@ -26,6 +42,10 @@ describe("ZoweTerminal Unit Tests", () => { expect(spyCb).toHaveBeenCalledWith("testABC"); spyCb.mockClear(); + await iTerm.handleInput(ZoweTerminal.Keys.HOME); // |testABC + await iTerm.handleInput(ZoweTerminal.Keys.END); // testABC| + await iTerm.handleInput(ZoweTerminal.Keys.CMD_LEFT); // |testABC + await iTerm.handleInput(ZoweTerminal.Keys.CMD_RIGHT); // testABC| await iTerm.handleInput(ZoweTerminal.Keys.UP); // testABC| await iTerm.handleInput(ZoweTerminal.Keys.UP); // old| await iTerm.handleInput(ZoweTerminal.Keys.DOWN); // testABC| @@ -40,20 +60,29 @@ describe("ZoweTerminal Unit Tests", () => { // Handle double byte characters await iTerm.handleInput("🙏🙏"); // test1🙏🙏|C await iTerm.handleInput(ZoweTerminal.Keys.BACKSPACE); // test1🙏|C - // Handle unicode "hello" + // Handle unicode "Hello" await iTerm.handleInput("\u0048\u0065\u006C\u006C\u006F"); // test1🙏Hello|C + await iTerm.handleInput(ZoweTerminal.Keys.DEL); // test1🙏Hello| await iTerm.handleInput(ZoweTerminal.Keys.ENTER); - expect(spyCb).toHaveBeenCalledWith("test1🙏HelloC"); + expect(spyCb).toHaveBeenCalledWith("test1🙏Hello"); spyCb.mockClear(); (iTerm as any).command = ""; + await iTerm.handleInput(ZoweTerminal.Keys.INSERT); // do nothing + await iTerm.handleInput(ZoweTerminal.Keys.TAB); // do nothing + await iTerm.handleInput("\x1b[1;A"); // Shift+Up // do nothing + await iTerm.handleInput("\x1b[3;A"); // fn+option+shift+up // do nothing await iTerm.handleInput(ZoweTerminal.Keys.ENTER); - await iTerm.handleInput(ZoweTerminal.Keys.CTRL_C); + await iTerm.handleInput(ZoweTerminal.Keys.UP); // "test1🙏Hello" + await iTerm.handleInput(ZoweTerminal.Keys.CTRL_C); // Clear the terminal + await iTerm.handleInput(ZoweTerminal.Keys.CTRL_C); // Present the "(to exit ...)" message + await iTerm.handleInput(ZoweTerminal.Keys.CTRL_C); // close + await iTerm.handleInput(ZoweTerminal.Keys.CTRL_D); // close await iTerm.handleInput(":clear"); await iTerm.handleInput(ZoweTerminal.Keys.ENTER); await iTerm.handleInput(":exit"); await iTerm.handleInput(ZoweTerminal.Keys.ENTER); - expect((iTerm as any).mHistory as string[]).toEqual(["old", "testABC", "test1🙏HelloC", ":clear", ":exit"]); + expect((iTerm as any).mHistory as string[]).toEqual(["old", "testABC", "test1🙏Hello", ":clear", ":exit"]); }); }); diff --git a/packages/zowe-explorer/__tests__/__unit__/tools/__snapshots__/ZoweTerminal.unit.test.ts.snap b/packages/zowe-explorer/__tests__/__unit__/tools/__snapshots__/ZoweTerminal.unit.test.ts.snap index 76b26e001..af6e6bd61 100644 --- a/packages/zowe-explorer/__tests__/__unit__/tools/__snapshots__/ZoweTerminal.unit.test.ts.snap +++ b/packages/zowe-explorer/__tests__/__unit__/tools/__snapshots__/ZoweTerminal.unit.test.ts.snap @@ -25,6 +25,8 @@ exports[`ZoweTerminal Unit Tests should not change the keys 1`] = ` ", "OPT_BACKSPACE": "", "OPT_CMD_BACKSPACE": "", + "OPT_LEFT": "b", + "OPT_RIGHT": "f", "PAGE_DOWN": "[6~", "PAGE_UP": "[5~", "RIGHT": "", diff --git a/packages/zowe-explorer/src/tools/ZoweTerminal.ts b/packages/zowe-explorer/src/tools/ZoweTerminal.ts index 029650cfd..90a7ed2cf 100644 --- a/packages/zowe-explorer/src/tools/ZoweTerminal.ts +++ b/packages/zowe-explorer/src/tools/ZoweTerminal.ts @@ -37,6 +37,8 @@ export class ZoweTerminal implements vscode.Pseudoterminal { PAGE_DOWN: "\x1b[6~", ENTER: "\r", NEW_LINE: "\r\n", + OPT_LEFT: "\x1bb", + OPT_RIGHT: "\x1bf", UP: "\x1b[A", DOWN: "\x1b[B", RIGHT: "\x1b[C", @@ -225,7 +227,7 @@ export class ZoweTerminal implements vscode.Pseudoterminal { // Handle input from the terminal public async handleInput(data: string): Promise { - console.log("data", data, Buffer.from(data)); + // console.log("data", data, Buffer.from(data)); if (this.isCommandRunning) { if ([ZoweTerminal.Keys.CTRL_C, ZoweTerminal.Keys.CTRL_D].includes(data)) this.controller.abort(); if (data === ZoweTerminal.Keys.CTRL_D) this.close(); @@ -256,9 +258,11 @@ export class ZoweTerminal implements vscode.Pseudoterminal { this.navigateHistory(1); break; case ZoweTerminal.Keys.LEFT: + case ZoweTerminal.Keys.OPT_LEFT: this.moveCursor(-1); break; case ZoweTerminal.Keys.RIGHT: + case ZoweTerminal.Keys.OPT_RIGHT: this.moveCursor(1); break; case ZoweTerminal.Keys.HOME: