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

feat: Introduce integrated terminal #3079

Draft
wants to merge 51 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
0f14050
chore: remove code duplication in preparation to handling integrated …
zFernand0 Aug 27, 2024
73f5814
chore: done consolidating, fixing unit test before continuing :yum:
zFernand0 Aug 28, 2024
ee95d66
tests: fix unit tests and address any missing checks :yum:
zFernand0 Aug 28, 2024
48abeef
tests: fix the rest of the unit tests :yum:
zFernand0 Aug 29, 2024
43d6863
l10n: update strings :yum:
zFernand0 Aug 29, 2024
beba0c4
chore: Add zoweTerminal :yum:
zFernand0 Aug 29, 2024
d3b5975
chore: finalize ZoweTerminal implementation :yum:
zFernand0 Aug 30, 2024
4f7dd21
chore: add actual z/os behavior :yum:
zFernand0 Aug 30, 2024
451c49b
chore: add missing license header
zFernand0 Oct 9, 2024
978ff99
tests: fix unit tests assuming we are not using integrated terminals
zFernand0 Oct 9, 2024
8b2d310
feat: initial addition of zowe commands to edit History webview
zFernand0 Oct 9, 2024
ee12695
fix: done with core terminal issues
zFernand0 Oct 9, 2024
859807c
tests: fix unit tests for now :yum:
zFernand0 Oct 10, 2024
6d49d02
fix remainig unit tests
zFernand0 Oct 21, 2024
65c8e24
Merge branch 'main' of https://github.com/zowe/zowe-explorer-vscode i…
zFernand0 Oct 21, 2024
04927a3
fix: remove circular references
zFernand0 Oct 21, 2024
96a8d25
test: add small unit test :yum:
zFernand0 Oct 21, 2024
257254b
test: add more unit testws to bump patch coverage
zFernand0 Oct 22, 2024
819e742
chore: more unit tests
zFernand0 Oct 22, 2024
3898c54
Merge branch 'main' into feat/int-term
zFernand0 Oct 22, 2024
ef41fcf
fix: edge case when processing double-byte characters
zFernand0 Oct 23, 2024
93b6c30
fix handle unicode characters
zFernand0 Oct 23, 2024
52eb208
fix: error handling for failing responses from the server
zFernand0 Oct 23, 2024
062327f
Merge branch 'main' into feat/int-term
zFernand0 Oct 29, 2024
20c313a
Update packages/zowe-explorer/src/commands/UnixCommandHandler.ts
zFernand0 Oct 29, 2024
7f1375e
test: update test to reflect less operation cancelled notifications :…
zFernand0 Oct 29, 2024
54c2f89
review: updates based on feedback :yum:
zFernand0 Oct 29, 2024
612473d
Merge branch 'main' of https://github.com/zowe/zowe-explorer-vscode i…
zFernand0 Oct 30, 2024
6df816c
review: localize strings in package.json
zFernand0 Oct 30, 2024
b6170fa
Merge branch 'main' into feat/int-term
JillieBeanSim Oct 31, 2024
75d1386
fix: profile selection cached between commands via the palette
zFernand0 Oct 31, 2024
882db9a
fix: iTerm setting not working from the workspace scope :yum:
zFernand0 Oct 31, 2024
1ba492a
Merge branch 'main' of https://github.com/zowe/zowe-explorer-vscode i…
zFernand0 Oct 31, 2024
7833f74
fix: make profile validation consistent amonogst all cmdTypes
zFernand0 Oct 31, 2024
88e064b
review: add validation of SSH porfiles:
zFernand0 Oct 31, 2024
33294c9
chore: multiple fixes (see below)
zFernand0 Nov 1, 2024
986fbaf
feat: separated commands history :yum:
zFernand0 Nov 1, 2024
e181481
fix: Greyout entry text in iTerms
zFernand0 Nov 1, 2024
e618b14
review: fix unit test after adding validation
zFernand0 Nov 2, 2024
75a6d03
chore: update changelog
zFernand0 Nov 2, 2024
7f18310
review: updated sdk and removed ssh2 lazy-loading
zFernand0 Nov 6, 2024
85696d1
chore: update unit tests for new APIs
zFernand0 Nov 6, 2024
931ed3f
chore: update dependencies across the board
zFernand0 Nov 6, 2024
3311857
Merge branch 'main' of https://github.com/zowe/zowe-explorer-vscode i…
zFernand0 Nov 6, 2024
133276e
Merge branch 'main' of https://github.com/zowe/zowe-explorer-vscode i…
zFernand0 Nov 6, 2024
ccc9f48
chore: fix lint issues and update changelogs
zFernand0 Nov 6, 2024
a18f7f6
review: fis unit tests
zFernand0 Nov 6, 2024
230e933
chore: cleanup ssh profile validation logic
zFernand0 Nov 6, 2024
172cfe5
review: update changelog
zFernand0 Nov 12, 2024
f578724
review: add italic to :clear command
zFernand0 Nov 25, 2024
dc3d748
Merge branch 'main' of https://github.com/zowe/zowe-explorer-vscode i…
zFernand0 Nov 25, 2024
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/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen

- Update Zowe SDKs to `8.2.0` to get the latest enhancements from Imperative.
- Added expired JSON web token detection for profiles in each tree view (Data Sets, USS, Jobs). When a user performs a search on a profile, they are prompted to log in if their token expired. [#3175](https://github.com/zowe/zowe-explorer-vscode/issues/3175)
- Added integrated terminals for z/OS Unix, TSO, and MVS commands which can be enabled via the `Zowe › Commands: Use Integrated Terminals` setting. [#3079](https://github.com/zowe/zowe-explorer-vscode/pull/3079)

### Bug fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { ProfileManagement } from "../../../src/management/ProfileManagement";
import { FilterDescriptor, FilterItem } from "../../../src/management/FilterManagement";
import { ZoweLogger } from "../../../src/tools/ZoweLogger";
import { MvsCommandHandler } from "../../../src/commands/MvsCommandHandler";
import { SettingsConfig } from "../../../src/configuration/SettingsConfig";

jest.mock("Session");

Expand All @@ -28,6 +29,7 @@ describe("mvsCommandActions unit testing", () => {
const showInformationMessage = jest.fn();
const showQuickPick = jest.fn();
const createQuickPick = jest.fn();
const createTerminal = jest.fn();
const getConfiguration = jest.fn();
const createOutputChannel = jest.fn();

Expand Down Expand Up @@ -94,10 +96,7 @@ describe("mvsCommandActions unit testing", () => {
});

const withProgress = jest.fn().mockImplementation((progLocation, callback) => {
return {
success: true,
commandResponse: callback(),
};
return callback();
});

const session = new imperative.Session({
Expand Down Expand Up @@ -129,6 +128,7 @@ describe("mvsCommandActions unit testing", () => {
Object.defineProperty(vscode.window, "showInformationMessage", { value: showInformationMessage });
Object.defineProperty(vscode.window, "showQuickPick", { value: showQuickPick });
Object.defineProperty(vscode.window, "createQuickPick", { value: createQuickPick });
Object.defineProperty(vscode.window, "createTerminal", { value: createTerminal });
Object.defineProperty(vscode.window, "createOutputChannel", { value: createOutputChannel });
Object.defineProperty(vscode, "ProgressLocation", { value: ProgressLocation });
Object.defineProperty(vscode.window, "withProgress", { value: withProgress });
Expand All @@ -141,13 +141,20 @@ describe("mvsCommandActions unit testing", () => {
}),
});

beforeEach(() => {
jest.spyOn(SettingsConfig, "getDirectValue").mockReturnValue(false);
});

afterEach(() => {
(MvsCommandHandler as any).instance = undefined;
jest.clearAllMocks();
});

const apiRegisterInstance = ZoweExplorerApiRegister.getInstance();
const mvsActions = MvsCommandHandler.getInstance();
const profilesForValidation = { status: "active", name: "fake" };
const getMvsActions = () => {
return MvsCommandHandler.getInstance();
};

it("tests the issueMvsCommand function", async () => {
Object.defineProperty(profileLoader.Profiles, "getInstance", {
Expand Down Expand Up @@ -180,16 +187,16 @@ describe("mvsCommandActions unit testing", () => {

showInputBox.mockReturnValueOnce("/d iplinfo1");
jest.spyOn(Gui, "resolveQuickPick").mockImplementation(() => Promise.resolve(qpItem));
jest.spyOn(mockCommandApi, "issueMvsCommand").mockReturnValue("iplinfo1" as any);
jest.spyOn(mockCommandApi, "issueMvsCommand").mockReturnValue({ commandResponse: "iplinfo1" } as any);

await mvsActions.issueMvsCommand();
await getMvsActions().issueMvsCommand();

expect(showQuickPick.mock.calls.length).toBe(1);
expect(showQuickPick.mock.calls[0][0]).toEqual(["firstName", "secondName"]);
expect(showQuickPick.mock.calls[0][1]).toEqual({
canPickMany: false,
ignoreFocusOut: true,
placeHolder: "Select the Profile to use to submit the command",
placeHolder: "Select an MVS profile for this command",
});
expect(showInputBox.mock.calls.length).toBe(1);
expect(appendLine.mock.calls.length).toBe(2);
Expand Down Expand Up @@ -223,16 +230,19 @@ describe("mvsCommandActions unit testing", () => {
apiRegisterInstance.getCommandApi = getCommandApiMock.bind(apiRegisterInstance);

jest.spyOn(Gui, "resolveQuickPick").mockImplementation(() => Promise.resolve(qpItem2));
jest.spyOn(mockCommandApi, "issueMvsCommand").mockReturnValue("iplinfo0" as any);
jest.spyOn(mockCommandApi, "issueMvsCommand").mockReturnValue({ commandResponse: "iplinfo0" } as any);

const actions = getMvsActions();
(actions.history as any).mSearchHistory = [qpItem2.label];

await mvsActions.issueMvsCommand();
await actions.issueMvsCommand();

expect(showQuickPick.mock.calls.length).toBe(1);
expect(showQuickPick.mock.calls[0][0]).toEqual(["firstName", "secondName"]);
expect(showQuickPick.mock.calls[0][1]).toEqual({
canPickMany: false,
ignoreFocusOut: true,
placeHolder: "Select the Profile to use to submit the command",
placeHolder: "Select an MVS profile for this command",
});
expect(showInputBox.mock.calls.length).toBe(0);
expect(appendLine.mock.calls.length).toBe(2);
Expand Down Expand Up @@ -267,16 +277,16 @@ describe("mvsCommandActions unit testing", () => {
getCommandApiMock.mockReturnValue(mockCommandApi);
apiRegisterInstance.getCommandApi = getCommandApiMock.bind(apiRegisterInstance);
jest.spyOn(Gui, "resolveQuickPick").mockImplementation(() => Promise.resolve(qpItem));
jest.spyOn(mockCommandApi, "issueMvsCommand").mockReturnValue("iplinfo3" as any);
jest.spyOn(mockCommandApi, "issueMvsCommand").mockReturnValue({ commandResponse: "iplinfo3" } as any);

await mvsActions.issueMvsCommand();
await getMvsActions().issueMvsCommand();

expect(showQuickPick.mock.calls.length).toBe(1);
expect(showQuickPick.mock.calls[0][0]).toEqual(["firstName", "secondName"]);
expect(showQuickPick.mock.calls[0][1]).toEqual({
canPickMany: false,
ignoreFocusOut: true,
placeHolder: "Select the Profile to use to submit the command",
placeHolder: "Select an MVS profile for this command",
});
expect(showInputBox.mock.calls.length).toBe(1);
expect(showErrorMessage.mock.calls.length).toBe(1);
Expand Down Expand Up @@ -309,18 +319,21 @@ describe("mvsCommandActions unit testing", () => {

jest.spyOn(Gui, "resolveQuickPick").mockImplementation(() => Promise.resolve(undefined));

await mvsActions.issueMvsCommand();
const actions = getMvsActions();
(actions.history as any).mSearchHistory = [qpItem2.label];

await actions.issueMvsCommand();

expect(showQuickPick.mock.calls.length).toBe(1);
expect(showInputBox.mock.calls.length).toBe(0);
expect(showQuickPick.mock.calls[0][0]).toEqual(["firstName", "secondName"]);
expect(showQuickPick.mock.calls[0][1]).toEqual({
canPickMany: false,
ignoreFocusOut: true,
placeHolder: "Select the Profile to use to submit the command",
placeHolder: "Select an MVS profile for this command",
});
expect(showInformationMessage.mock.calls.length).toBe(1);
expect(showInformationMessage.mock.calls[0][0]).toEqual("No selection made. Operation cancelled.");
expect(showInformationMessage.mock.calls[0][0]).toEqual("Operation cancelled");
});

it("tests the issueMvsCommand function user escapes the command box", async () => {
Expand Down Expand Up @@ -349,18 +362,18 @@ describe("mvsCommandActions unit testing", () => {

jest.spyOn(Gui, "resolveQuickPick").mockImplementation(() => Promise.resolve(qpItem));

await mvsActions.issueMvsCommand();
await getMvsActions().issueMvsCommand();

expect(showQuickPick.mock.calls.length).toBe(1);
expect(showQuickPick.mock.calls[0][0]).toEqual(["firstName", "secondName"]);
expect(showQuickPick.mock.calls[0][1]).toEqual({
canPickMany: false,
ignoreFocusOut: true,
placeHolder: "Select the Profile to use to submit the command",
placeHolder: "Select an MVS profile for this command",
});
expect(showInputBox.mock.calls.length).toBe(1);
expect(showInformationMessage.mock.calls.length).toBe(1);
expect(showInformationMessage.mock.calls[0][0]).toEqual("No command entered.");
expect(showInformationMessage.mock.calls[0][0]).toEqual("Operation cancelled");
});

it("tests the issueMvsCommand function user starts typing a value in quick pick", async () => {
Expand Down Expand Up @@ -406,14 +419,17 @@ describe("mvsCommandActions unit testing", () => {

jest.spyOn(Gui, "resolveQuickPick").mockImplementation(() => Promise.resolve(qpItem));

await mvsActions.issueMvsCommand();
const actions = getMvsActions();
(actions.history as any).mSearchHistory = [qpItem2.label];

await actions.issueMvsCommand();

expect(showQuickPick.mock.calls.length).toBe(1);
expect(showQuickPick.mock.calls[0][0]).toEqual(["firstName", "secondName"]);
expect(showQuickPick.mock.calls[0][1]).toEqual({
canPickMany: false,
ignoreFocusOut: true,
placeHolder: "Select the Profile to use to submit the command",
placeHolder: "Select an MVS profile for this command",
});
expect(showInputBox.mock.calls.length).toBe(0);
});
Expand Down Expand Up @@ -450,14 +466,14 @@ describe("mvsCommandActions unit testing", () => {
jest.spyOn(Gui, "resolveQuickPick").mockImplementation(() => Promise.resolve(qpItem));
jest.spyOn(mockCommandApi, "issueMvsCommand").mockReturnValueOnce({ commandResponse: "fake response" } as any);

await mvsActions.issueMvsCommand();
await getMvsActions().issueMvsCommand();

expect(showQuickPick.mock.calls.length).toBe(1);
expect(showQuickPick.mock.calls[0][0]).toEqual(["firstName", "secondName"]);
expect(showQuickPick.mock.calls[0][1]).toEqual({
canPickMany: false,
ignoreFocusOut: true,
placeHolder: "Select the Profile to use to submit the command",
placeHolder: "Select an MVS profile for this command",
});
expect(showInputBox.mock.calls.length).toBe(1);
});
Expand Down Expand Up @@ -492,14 +508,14 @@ describe("mvsCommandActions unit testing", () => {
jest.spyOn(Gui, "resolveQuickPick").mockImplementation(() => Promise.resolve(qpItem));
jest.spyOn(mockCommandApi, "issueMvsCommand").mockReturnValueOnce({ commandResponse: "fake response" } as any);

await mvsActions.issueMvsCommand();
await getMvsActions().issueMvsCommand();

expect(showQuickPick.mock.calls.length).toBe(1);
expect(showQuickPick.mock.calls[0][0]).toEqual(["firstName", "secondName"]);
expect(showQuickPick.mock.calls[0][1]).toEqual({
canPickMany: false,
ignoreFocusOut: true,
placeHolder: "Select the Profile to use to submit the command",
placeHolder: "Select an MVS profile for this command",
});
expect(showInputBox.mock.calls.length).toBe(1);
});
Expand All @@ -523,7 +539,7 @@ describe("mvsCommandActions unit testing", () => {
showQuickPick.mockReturnValueOnce("firstName");
showInputBox.mockReturnValueOnce("fake");

await mvsActions.issueMvsCommand();
await getMvsActions().issueMvsCommand();

expect(showErrorMessage.mock.calls.length).toBe(1);
});
Expand All @@ -544,10 +560,10 @@ describe("mvsCommandActions unit testing", () => {

showQuickPick.mockReturnValueOnce(undefined);

await mvsActions.issueMvsCommand();
await getMvsActions().issueMvsCommand();

expect(showInformationMessage.mock.calls.length).toBe(1);
expect(showInformationMessage.mock.calls[0][0]).toEqual("Operation Cancelled");
expect(showInformationMessage.mock.calls[0][0]).toEqual("Operation cancelled");
});

it("tests the issueMvsCommand function from a session", async () => {
Expand All @@ -564,7 +580,7 @@ describe("mvsCommandActions unit testing", () => {
}),
});

jest.spyOn(mvsActions, "checkCurrentProfile").mockReturnValue(undefined as any);
jest.spyOn(getMvsActions(), "checkCurrentProfile").mockReturnValue(undefined as any);

const mockCommandApi = await apiRegisterInstance.getCommandApi(profileOne);
const getCommandApiMock = jest.fn();
Expand All @@ -574,7 +590,7 @@ describe("mvsCommandActions unit testing", () => {
showInputBox.mockReturnValueOnce("/d iplinfo1");
jest.spyOn(mockCommandApi, "issueMvsCommand").mockReturnValueOnce({ commandResponse: "fake response" } as any);

await mvsActions.issueMvsCommand(session, null as any, testNode);
await getMvsActions().issueMvsCommand(session, null as any, testNode);

expect(showInputBox.mock.calls.length).toBe(1);
expect(showInformationMessage.mock.calls.length).toBe(0);
Expand Down Expand Up @@ -608,14 +624,14 @@ describe("mvsCommandActions unit testing", () => {
throw testError;
});

await mvsActions.issueMvsCommand();
await getMvsActions().issueMvsCommand();

expect(showQuickPick.mock.calls.length).toBe(1);
expect(showQuickPick.mock.calls[0][0]).toEqual(["firstName", "secondName"]);
expect(showQuickPick.mock.calls[0][1]).toEqual({
canPickMany: false,
ignoreFocusOut: true,
placeHolder: "Select the Profile to use to submit the command",
placeHolder: "Select an MVS profile for this command",
});
expect(showInputBox.mock.calls.length).toBe(0);
expect(showErrorMessage.mock.calls.length).toBe(1);
Expand All @@ -641,7 +657,7 @@ describe("mvsCommandActions unit testing", () => {
value: jest.fn().mockReturnValue([]),
configurable: true,
});
await mvsActions.issueMvsCommand();
await getMvsActions().issueMvsCommand();
expect(showInformationMessage.mock.calls[0][0]).toEqual("No profiles available");
});
});
Loading