Skip to content

Commit

Permalink
ZE Webview Localization (#3162)
Browse files Browse the repository at this point in the history
* Webview Loc

Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com>

* Add unit tests and changelog

Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com>

* Update tests

Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com>

* Add more test suites

Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com>

* Address issue seen with edit history

Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com>

* Edit Attributes permissions localization

Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com>

* Address table-view No items selected and Page Size localization

Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com>

* Add changelog

Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com>

* run package; nls

Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com>

* Add code coverage

Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com>

---------

Signed-off-by: likhithanimma1 <142219673+likhithanimma1@users.noreply.github.com>
Signed-off-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com>
Co-authored-by: Fernando Rijo Cedeno <37381190+zFernand0@users.noreply.github.com>
Co-authored-by: Billie Simmons <49491949+JillieBeanSim@users.noreply.github.com>
  • Loading branch information
3 people committed Oct 17, 2024
1 parent da18679 commit 1c574a5
Show file tree
Hide file tree
Showing 31 changed files with 529 additions and 103 deletions.
1 change: 1 addition & 0 deletions packages/zowe-explorer-api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ All notable changes to the "zowe-explorer-api" extension will be documented in t
### New features and enhancements

- Zowe Explorer now includes support for the [VS Code display languages](https://code.visualstudio.com/docs/getstarted/locales) French, German, Japanese, Portuguese, and Spanish.
- Localization of strings within the webviews. [#2983](https://github.com/zowe/zowe-explorer-vscode/issues/2983)

### Bug fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import { Table, TableBuilder, WebView } from "../../../../src";
import { env, EventEmitter, Uri, window } from "vscode";
import * as crypto from "crypto";
import { diff } from "deep-object-diff";
import * as fs from "fs";

jest.mock("fs");
function createGlobalMocks() {
const mockPanel = {
dispose: jest.fn(),
Expand All @@ -23,6 +25,10 @@ function createGlobalMocks() {
};
// Mock `vscode.window.createWebviewPanel` to return a usable panel object
const createWebviewPanelMock = jest.spyOn(window, "createWebviewPanel").mockReturnValueOnce(mockPanel as any);
const spyReadFile = jest.fn((path, encoding, callback) => {
callback(null, "file contents");
});
Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true });

return {
createWebviewPanelMock,
Expand Down Expand Up @@ -273,6 +279,18 @@ describe("Table.View", () => {
globalMocks.updateWebviewMock.mockRestore();
});

it("should handle the case where 'GET_LOCALIZATION' is the command sent", async () => {
const globalMocks = await createGlobalMocks();
const view = new Table.View(globalMocks.context as any, false, { title: "Table" } as any);
const postMessageSpy = jest.spyOn(view.panel.webview, "postMessage");
await view.onMessageReceived({ command: "GET_LOCALIZATION" });
expect(postMessageSpy).toHaveBeenCalledWith({
command: "GET_LOCALIZATION",
contents: "file contents",
});
globalMocks.updateWebviewMock.mockRestore();
});

it("calls vscode.env.clipboard.writeText when handling the 'copy' command", async () => {
const globalMocks = createGlobalMocks();
const view = new Table.View(globalMocks.context as any, { title: "Table w/ copy" } as any);
Expand Down
17 changes: 16 additions & 1 deletion packages/zowe-explorer-api/src/vscode/ui/TableView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import { Event, EventEmitter, ExtensionContext, env } from "vscode";
import { randomUUID } from "crypto";
import { diff } from "deep-object-diff";
import { TableMediator } from "./utils/TableMediator";

import * as vscode from "vscode";
import * as fs from "fs";
export namespace Table {
/* The types of supported content for the table and how they are represented in callback functions. */
export type ContentTypes = string | number | boolean | string[];
Expand Down Expand Up @@ -360,6 +361,20 @@ export namespace Table {
case "copy-cell":
await env.clipboard.writeText(message.data.cell);
return;
case "GET_LOCALIZATION": {
const filePath = vscode.l10n.uri?.fsPath + "";
fs.readFile(filePath, "utf8", (err, data) => {
if (err) {
// File doesn't exist, fallback to English strings
return;

Check warning on line 369 in packages/zowe-explorer-api/src/vscode/ui/TableView.ts

View check run for this annotation

Codecov / codecov/patch

packages/zowe-explorer-api/src/vscode/ui/TableView.ts#L369

Added line #L369 was not covered by tests
}
(this.panel ?? this.view).webview.postMessage({
command: "GET_LOCALIZATION",
contents: data,
});
});
return;
}
default:
break;
}
Expand Down
1 change: 1 addition & 0 deletions packages/zowe-explorer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen
### New features and enhancements

- Zowe Explorer now includes support for the [VS Code display languages](https://code.visualstudio.com/docs/getstarted/locales) French, German, Japanese, Portuguese, and Spanish. Download the respective language pack and switch.
- Localization of strings within the webviews. [#2983](https://github.com/zowe/zowe-explorer-vscode/issues/2983)

### Bug fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ import { Gui } from "@zowe/zowe-explorer-api";
import { Profiles } from "../../../../src/configuration/Profiles";
import { ZoweLocalStorage } from "../../../../src/tools/ZoweLocalStorage";
import { UssFSProvider } from "../../../../src/trees/uss/UssFSProvider";
import * as fs from "fs";

jest.mock("fs");
async function initializeHistoryViewMock(blockMocks: any, globalMocks: any): Promise<SharedHistoryView> {
return new SharedHistoryView(
{
Expand Down Expand Up @@ -67,7 +69,10 @@ function createGlobalMocks(): any {
},
configurable: true,
});

const spyReadFile = jest.fn((path, encoding, callback) => {
callback(null, "file contents");
});
Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true });
return globalMocks;
}

Expand Down Expand Up @@ -278,6 +283,39 @@ describe("HistoryView Unit Tests", () => {
expect(historyView["currentSelection"]).toEqual({ ds: "search", jobs: "search", uss: "search" });
expect(resetEncodingHistorySpy).toHaveBeenCalledTimes(2);
});

it("should handle the case where 'GET_LOCALIZATION' is the command sent", async () => {
const globalMocks = await createGlobalMocks();
const blockMocks = createBlockMocks(globalMocks);
const historyView = await initializeHistoryViewMock(blockMocks, globalMocks);
const postMessageSpy = jest.spyOn(historyView.panel.webview, "postMessage");
await historyView["onDidReceiveMessage"]({ command: "GET_LOCALIZATION" });
expect(postMessageSpy).toHaveBeenCalledWith({
command: "GET_LOCALIZATION",
contents: "file contents",
});
});

it("if this.panel doesn't exist in GET_LOCALIZATION", async () => {
const globalMocks = await createGlobalMocks();
const blockMocks = createBlockMocks(globalMocks);
const historyView = await initializeHistoryViewMock(blockMocks, globalMocks);
historyView.panel = undefined as any;
await historyView["onDidReceiveMessage"]({ command: "GET_LOCALIZATION" });
expect(historyView.panel).toBeUndefined();
});

it("if read file throwing an error in GET_LOCALIZATION", async () => {
const globalMocks = await createGlobalMocks();
const blockMocks = createBlockMocks(globalMocks);
const spyReadFile = jest.fn((path, encoding, callback) => {
callback("error", "file contents");
});
Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true });
const historyView = await initializeHistoryViewMock(blockMocks, globalMocks);
await historyView["onDidReceiveMessage"]({ command: "GET_LOCALIZATION" });
expect(spyReadFile).toHaveBeenCalledTimes(1);
});
});

describe("getHistoryData", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ import { ZoweUSSNode } from "../../../../src/trees/uss/ZoweUSSNode";
import { ZoweExplorerApiRegister } from "../../../../src/extending/ZoweExplorerApiRegister";
import { MainframeInteraction } from "../../../../../zowe-explorer-api/src/extend";
import { SharedContext } from "../../../../src/trees/shared/SharedContext";
import * as fs from "fs";

jest.mock("fs");
describe("AttributeView unit tests", () => {
let view: USSAttributeView;
const context = { extensionPath: "some/fake/ext/path" } as unknown as vscode.ExtensionContext;
Expand Down Expand Up @@ -125,4 +127,35 @@ describe("AttributeView unit tests", () => {
updated: false,
});
});

it("handles GET_LOCALIZATION command", async () => {
const spyReadFile = jest.fn((path, encoding, callback) => {
callback(null, "file contents");
});
Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true });
await (view as any).onDidReceiveMessage({ command: "GET_LOCALIZATION" });
expect(view.panel.webview.postMessage).toHaveBeenCalledWith({
command: "GET_LOCALIZATION",
contents: "file contents",
});
});

it("if this.panel doesn't exist in GET_LOCALIZATION", async () => {
const spyReadFile = jest.fn((path, encoding, callback) => {
callback(null, "file contents");
});
Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true });
view.panel = undefined as any;
await (view as any).onDidReceiveMessage({ command: "GET_LOCALIZATION" });
expect(view.panel).toBeUndefined();
});

it("if read file throwing an error in GET_LOCALIZATION", async () => {
const spyReadFile = jest.fn((path, encoding, callback) => {
callback("error", "file contents");
});
Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true });
await (view as any).onDidReceiveMessage({ command: "GET_LOCALIZATION" });
expect(spyReadFile).toHaveBeenCalledTimes(1);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@
*/

import { Gui } from "@zowe/zowe-explorer-api";
import * as fs from "fs";
import { CertificateWizard } from "../../../src/utils/CertificateWizard";
import { ExtensionContext, Uri } from "vscode";
import { ZoweLogger } from "../../../src/tools/ZoweLogger";

jest.mock("fs");
describe("CertificateWizard", () => {
const context = { extensionPath: "some/fake/ext/path" } as unknown as ExtensionContext;

it("handles the promptCert message", async () => {
const certWizard = new CertificateWizard(context, {
cert: "/a/b/cert.pem",
Expand Down Expand Up @@ -103,4 +104,52 @@ describe("CertificateWizard", () => {
});
expect(traceMock).toHaveBeenCalledWith("User dismissed the certificate wizard.");
});

it("handles the get_localization message", async () => {
const spyReadFile = jest.fn((path, encoding, callback) => {
callback(null, "file contents");
});
Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true });
const certWizard = new CertificateWizard(context, {
cert: "/a/b/cert.pem",
certKey: "/a/b/cert.key.pem",
});
const postMessageMock = jest.spyOn(certWizard.panel.webview, "postMessage").mockImplementation();
(certWizard as any).onDidReceiveMessage({
command: "GET_LOCALIZATION",
});
(certWizard as any).data = "file contents";
expect(postMessageMock).toHaveBeenCalledWith({ command: "GET_LOCALIZATION", contents: (certWizard as any).data });
});

it("if this.panel doesn't exist in GET_LOCALIZATION", async () => {
const spyReadFile = jest.fn((path, encoding, callback) => {
callback(null, "file contents");
});
Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true });
const certWizard = new CertificateWizard(context, {
cert: "/a/b/cert.pem",
certKey: "/a/b/cert.key.pem",
});
certWizard.panel = undefined as any;
(certWizard as any).onDidReceiveMessage({
command: "GET_LOCALIZATION",
});
expect(certWizard.panel).toBeUndefined();
});

it("if read file throwing an error in GET_LOCALIZATION", async () => {
const spyReadFile = jest.fn((path, encoding, callback) => {
callback("error", "file contents");
});
Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true });
const certWizard = new CertificateWizard(context, {
cert: "/a/b/cert.pem",
certKey: "/a/b/cert.key.pem",
});
(certWizard as any).onDidReceiveMessage({
command: "GET_LOCALIZATION",
});
expect(spyReadFile).toHaveBeenCalledTimes(1);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import { createInstanceOfProfile, createIProfile } from "../../__mocks__/mockCre
import { ZosConsoleViewProvider } from "../../../src/zosconsole/ZosConsolePanel";
import { Profiles } from "../../../src/configuration/Profiles";
import * as vscode from "vscode";
import * as fs from "fs";

jest.mock("fs");
jest.mock("@zowe/zowe-explorer-api", () => ({
...jest.requireActual("@zowe/zowe-explorer-api"),
HTMLTemplate: jest.requireActual("../../../../zowe-explorer-api/src/vscode/ui/utils/HTMLTemplate"),
Expand All @@ -39,7 +41,10 @@ describe("ZosConsoleViewProvider", () => {
configurable: true,
});
Object.defineProperty(vscode.Uri, "joinPath", { value: jest.fn(), configurable: true });

const spyReadFile = jest.fn((path, encoding, callback) => {
callback(null, "file contents");
});
Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true });
return newMocks;
}
describe("resolveWebviewView", () => {
Expand All @@ -49,5 +54,34 @@ describe("ZosConsoleViewProvider", () => {
myconsole.resolveWebviewView(globalMocks.testWebView, {} as any, { isCancellationRequested: false } as any);
expect(globalMocks.testWebView.webview.onDidReceiveMessage).toHaveBeenCalled();
});
it("handles the get_localization message", async () => {
const globalMocks = createGlobalMocks();
const myconsole = new ZosConsoleViewProvider({} as any);
const postMessageMock = jest.spyOn(globalMocks.testWebView.webview, "postMessage").mockImplementation();
const onDidReceiveMessageCallback = jest
.spyOn(globalMocks.testWebView.webview, "onDidReceiveMessage")
.mockImplementation((callback: any) => {
callback({ command: "GET_LOCALIZATION" });
});
(myconsole as any).data = "file contents";
myconsole.resolveWebviewView(globalMocks.testWebView, {} as any, { isCancellationRequested: false } as any);
expect(onDidReceiveMessageCallback).toHaveBeenCalled();
expect(postMessageMock).toHaveBeenCalledWith({ type: "GET_LOCALIZATION", contents: (myconsole as any).data });
});
it("handles the get_localization message", async () => {
const globalMocks = createGlobalMocks();
const spyReadFile = jest.fn((path, encoding, callback) => {
callback("error", "file contents");
});
Object.defineProperty(fs, "readFile", { value: spyReadFile, configurable: true });
const myconsole = new ZosConsoleViewProvider({} as any);
const onDidReceiveMessageCallback = jest
.spyOn(globalMocks.testWebView.webview, "onDidReceiveMessage")
.mockImplementation((callback: any) => {
callback({ command: "GET_LOCALIZATION" });
});
myconsole.resolveWebviewView(globalMocks.testWebView, {} as any, { isCancellationRequested: false } as any);
expect(onDidReceiveMessageCallback).toHaveBeenCalled();
});
});
});
Loading

0 comments on commit 1c574a5

Please sign in to comment.