Skip to content

Commit

Permalink
Merge pull request #3056 from zowe/fix/theia-console-panel
Browse files Browse the repository at this point in the history
fix(console): Fix codicons in Theia and improve error handling
  • Loading branch information
zFernand0 authored Aug 21, 2024
2 parents ea0b0b0 + fd7a3f6 commit 2de66d0
Show file tree
Hide file tree
Showing 9 changed files with 215 additions and 165 deletions.
1 change: 1 addition & 0 deletions packages/zowe-explorer-api/src/vscode/ui/WebView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export class WebView {
};

const builtHtml = Mustache.render(HTMLTemplate, {
cspSource: this.panel.webview.cspSource,
uris: this.uris,
nonce: this.nonce,
title: this.title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ const HTMLTemplate: string = /*html*/ `
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
http-equiv="Content-Security-Policy"
content="default-src 'none'; font-src data: https:; img-src data: vscode-resource: https:; script-src 'nonce-{{ nonce }}';
style-src vscode-resource: 'unsafe-inline' http: https: data:;"
content="default-src 'none'; font-src data: {{ cspSource }}; img-src data: vscode-resource: https:; script-src 'nonce-{{ nonce }}';
style-src {{ cspSource }} vscode-resource: 'unsafe-inline' http: https: data:;"
/>
<base href="{{ uris.resource.build }}">
{{{ style }}}
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -18,125 +18,125 @@ const SHORTSLEEPTIME = 2000;
const WAITTIME = 30000;
let driverFirefox: WebDriver;

export async function openBrowser(headless = true) {
export async function openBrowser(headless = true): Promise<WebDriver> {
const firefoxOptions = new firefox.Options();
if (headless) {
firefoxOptions.headless();
firefoxOptions.addArguments("--headless");
}
driverFirefox = new Builder().forBrowser("firefox").setFirefoxOptions(firefoxOptions).build();
driverFirefox = await new Builder().forBrowser("firefox").setFirefoxOptions(firefoxOptions).build();
return driverFirefox;
}

export async function takeScreenshot(filename: string) {
export async function takeScreenshot(filename: string): Promise<void> {
const image = await driverFirefox.takeScreenshot();
writeFileSync(filename, image, "base64");
}

export async function OpenTheiaInFirefox() {
export async function OpenTheiaInFirefox(): Promise<void> {
await driverFirefox.get(TheiaLocator.theiaUrl);
}

export async function clickOnZoweExplorer() {
driverFirefox.wait(until.elementLocated(By.id(TheiaLocator.zoweExplorerxId)), WAITTIME).click();
export async function clickOnZoweExplorer(): Promise<void> {
await driverFirefox.wait(until.elementLocated(By.id(TheiaLocator.zoweExplorerxId)), WAITTIME).click();
}

export async function clickOnDatasetsTab() {
export async function clickOnDatasetsTab(): Promise<void> {
await driverFirefox.findElement(By.id(DatasetsLocators.datasetTabId)).click();
await driverFirefox.findElement(By.xpath(DatasetsLocators.datasetTabXpath)).click();
}

export async function clickOnUssTab() {
export async function clickOnUssTab(): Promise<void> {
await driverFirefox.findElement(By.id(UssLocators.ussTabId)).click();
await driverFirefox.findElement(By.xpath(UssLocators.ussTabXpath)).click();
}

export async function clickOnJobsTab() {
export async function clickOnJobsTab(): Promise<void> {
await driverFirefox.findElement(By.id(JobsLocators.jobTabId)).click();
await driverFirefox.findElement(By.xpath(JobsLocators.jobTabXpath)).click();
}

export async function clickOnUssPanel() {
export async function clickOnUssPanel(): Promise<void> {
await driverFirefox.findElement(By.id(UssLocators.ussPanelId)).click();
}

export async function clickOnAddSessionInUss() {
export async function clickOnAddSessionInUss(): Promise<void> {
await driverFirefox.findElement(By.id(UssLocators.ussAddSessionId)).click();
}

export async function clickOnJobsPanel() {
export async function clickOnJobsPanel(): Promise<void> {
await driverFirefox.findElement(By.id(JobsLocators.jobsPanelId)).click();
}

export async function clickOnAddSessionInJobs() {
export async function clickOnAddSessionInJobs(): Promise<void> {
await driverFirefox.findElement(By.id(JobsLocators.jobsAddSessionId)).click();
}

export async function addProfileDetailsInUss(profileName: string) {
export async function addProfileDetailsInUss(profileName: string): Promise<void> {
const ussProfileName = await driverFirefox.findElement(By.xpath(UssLocators.emptyInputBoxXpath));
ussProfileName.sendKeys(profileName);
ussProfileName.sendKeys(Key.ENTER);
await ussProfileName.sendKeys(profileName);
await ussProfileName.sendKeys(Key.ENTER);
await driverFirefox.sleep(SHORTSLEEPTIME);
const addToAllTrees = await driverFirefox.findElement(By.xpath(JobsLocators.emptyInputBoxXpath));
addToAllTrees.sendKeys("No");
addToAllTrees.sendKeys(Key.ENTER);
await addToAllTrees.sendKeys("No");
await addToAllTrees.sendKeys(Key.ENTER);
}

export async function addProfileDetailsInJobs(profileName: string) {
export async function addProfileDetailsInJobs(profileName: string): Promise<void> {
const jobsProfileName = await driverFirefox.findElement(By.xpath(JobsLocators.emptyInputBoxXpath));
jobsProfileName.sendKeys(profileName);
jobsProfileName.sendKeys(Key.ENTER);
await jobsProfileName.sendKeys(profileName);
await jobsProfileName.sendKeys(Key.ENTER);
}

export async function getUssDefaultProfilename() {
export async function getUssDefaultProfilename(): Promise<string> {
const ussProfile = await driverFirefox.wait(until.elementLocated(By.xpath(UssLocators.defaultUssProfileXpath)), WAITTIME).getText();
return ussProfile;
}

export async function getJobsDefaultProfilename() {
export async function getJobsDefaultProfilename(): Promise<string> {
const jobsProfile = await driverFirefox.wait(until.elementLocated(By.xpath(JobsLocators.defaultJobsProfileXpath)), WAITTIME).getText();
return jobsProfile;
}

export async function getUssProfilename() {
export async function getUssProfilename(): Promise<string> {
const ussProfile = await driverFirefox.wait(until.elementLocated(By.xpath(UssLocators.secondUssProfileXpath)), WAITTIME).getText();
return ussProfile;
}

export async function getJobsProfilename() {
export async function getJobsProfilename(): Promise<string> {
const jobsProfile = await driverFirefox.wait(until.elementLocated(By.xpath(JobsLocators.secondJobsProfileXpath)), WAITTIME).getText();
return jobsProfile;
}

export async function getFavoritesNode() {
export async function getFavoritesNode(): Promise<string> {
const favoriteLink = await driverFirefox.wait(until.elementLocated(By.xpath(DatasetsLocators.favoriteTabXpath)), WAITTIME).getAttribute("title");
return favoriteLink;
}

export async function getDatasetNode() {
export async function getDatasetNode(): Promise<string> {
await driverFirefox.wait(until.elementLocated(By.id(DatasetsLocators.datasetTabId)), WAITTIME);
const datasetLink = await driverFirefox.wait(until.elementLocated(By.xpath(DatasetsLocators.datasetTabXpath)), WAITTIME).getText();
return datasetLink;
}

export async function getUssNode() {
export async function getUssNode(): Promise<string> {
await driverFirefox.wait(until.elementLocated(By.id(UssLocators.ussTabId)), WAITTIME);
const ussLink = await driverFirefox.wait(until.elementLocated(By.xpath(UssLocators.ussTabXpath)), WAITTIME).getText();
return ussLink;
}

export async function getJobsNode() {
export async function getJobsNode(): Promise<string> {
await driverFirefox.wait(until.elementLocated(By.id(JobsLocators.jobTabId)), WAITTIME);
const jobsLink = await driverFirefox.wait(until.elementLocated(By.xpath(JobsLocators.jobTabXpath)), WAITTIME).getText();
return jobsLink;
}

export async function sleepTime(sleeptime: number) {
export async function sleepTime(sleeptime: number): Promise<void> {
await driverFirefox.sleep(sleeptime);
}
export async function refreshBrowser() {
export async function refreshBrowser(): Promise<void> {
await driverFirefox.navigate().refresh();
}

export function closeBrowser() {
driverFirefox.close();
export async function closeBrowser(): Promise<void> {
await driverFirefox.close();
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ import { createInstanceOfProfile, createIProfile } from "../../../__mocks__/mock
import { ZosConsoleViewProvider } from "../../../src/zosconsole/ZosConsolePanel";
import { Profiles } from "../../../src/Profiles";
import * as vscode from "vscode";
import { ZoweExplorerApiRegister } from "../../../src/ZoweExplorerApiRegister";

describe("ZosConsoleViewProvider", () => {
function createGlobalMocks(): any {
const newMocks = {
imperativeProfile: createIProfile(),
profileInstance: null,
testWebView: {},
issueMvsCommand: jest.fn(),
};
newMocks.testWebView = {
webview: {
Expand All @@ -34,6 +36,9 @@ describe("ZosConsoleViewProvider", () => {
configurable: true,
});
Object.defineProperty(vscode.Uri, "joinPath", { value: jest.fn(), configurable: true });
jest.spyOn(ZoweExplorerApiRegister, "getCommandApi").mockReturnValue({
issueMvsCommand: newMocks.issueMvsCommand,
} as any);

return newMocks;
}
Expand All @@ -45,4 +50,36 @@ describe("ZosConsoleViewProvider", () => {
expect(globalMocks.testWebView.webview.onDidReceiveMessage).toBeCalled();
});
});

describe("runOperCmd", () => {
it("should successfully return command response", async () => {
const globalMocks = createGlobalMocks();
globalMocks.issueMvsCommand.mockResolvedValueOnce({ commandResponse: "hello" });
const myconsole = new ZosConsoleViewProvider({} as any);
(myconsole as any).profiles.set("fake", { type: "zosmf" });
const response = await (myconsole as any).runOperCmd("D T", "fake");
expect(globalMocks.issueMvsCommand).toBeCalled();
expect(response).toBe("hello");
});

it("should return error when profile not found", async () => {
const globalMocks = createGlobalMocks();
const myconsole = new ZosConsoleViewProvider({} as any);
const response = await (myconsole as any).runOperCmd("D T", "fake");
expect(globalMocks.issueMvsCommand).not.toBeCalled();
expect(response).toContain("No profile found");
});

it("should return error when MVS command fails", async () => {
const globalMocks = createGlobalMocks();
globalMocks.issueMvsCommand.mockImplementationOnce(() => {
throw new Error("Command failed");
});
const myconsole = new ZosConsoleViewProvider({} as any);
(myconsole as any).profiles.set("fake", { type: "zosmf" });
const response = await (myconsole as any).runOperCmd("D T", "fake");
expect(globalMocks.issueMvsCommand).toBeCalled();
expect(response).toContain("Command failed");
});
});
});
4 changes: 2 additions & 2 deletions packages/zowe-explorer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2097,7 +2097,7 @@
"@types/expect": "^1.20.3",
"@types/fs-extra": "^7.0.0",
"@types/promise-queue": "^2.2.0",
"@types/selenium-webdriver": "^3.0.4",
"@types/selenium-webdriver": "^4.1.25",
"chai": "^4.1.2",
"chai-as-promised": "^7.1.1",
"chalk": "^2.4.1",
Expand All @@ -2117,7 +2117,7 @@
"log4js": "^6.4.6",
"markdownlint-cli": "^0.33.0",
"run-sequence": "^2.2.1",
"selenium-webdriver": "^3.6.0",
"selenium-webdriver": "^4.23.0",
"sinon": "^6.1.0"
},
"dependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export function App() {
} else {
vscode.postMessage({
command: "opercmd",
profile: profileList.options[profileList.selectedIndex].text,
profile: profileList.options[profileList.selectedIndex]?.text,
text: consoleField.value,
});
}
Expand Down
4 changes: 4 additions & 0 deletions packages/zowe-explorer/src/zosconsole/ZosConsolePanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export class ZosConsoleViewProvider implements vscode.WebviewViewProvider {

// Tip: Install the es6-string-html VS Code extension to enable code highlighting below
return Mustache.render(HTMLTemplate.default, {
cspSource: webview.cspSource,
uris: { resource: { script: scriptUri } },
nonce,
style: /* html */ `
Expand Down Expand Up @@ -131,6 +132,9 @@ export class ZosConsoleViewProvider implements vscode.WebviewViewProvider {
private async runOperCmd(command: string, profile: string): Promise<string> {
try {
const theProfile: imperative.IProfileLoaded = this.profiles.get(profile);
if (theProfile == null) {
return "Error: No profile found to issue console commands\n";
}
const response = await ZoweExplorerApiRegister.getCommandApi(theProfile).issueMvsCommand(command, theProfile.profile?.consoleName);
return response.commandResponse;
} catch (e) {
Expand Down
Loading

0 comments on commit 2de66d0

Please sign in to comment.