Skip to content

Commit

Permalink
Merge pull request #2615 from zowe/feat/cfg/update-schema
Browse files Browse the repository at this point in the history
feat(cfg): Allow extenders to contribute to Zowe schema during activation
  • Loading branch information
JillieBeanSim authored Feb 20, 2024
2 parents cddfa38 + 8a539ef commit 6c900e7
Show file tree
Hide file tree
Showing 27 changed files with 276 additions and 124 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"vscode": "^1.53.2"
},
"dependencies": {
"@zowe/cli": "7.23.2",
"@zowe/cli": "7.23.3",
"vscode-nls": "4.1.2"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/zowe-explorer-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
},
"dependencies": {
"@types/vscode": "^1.53.2",
"@zowe/cli": "7.23.2",
"@zowe/cli": "7.23.3",
"@zowe/secrets-for-zowe-sdk": "7.18.6",
"handlebars": "^4.7.7",
"semver": "^7.5.3"
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

- Implemented sorting of PDS members by date created [#2707](https://github.com/zowe/vscode-extension-for-zowe/pull/2707)
- Added the capability for extenders to contribute new profile types to the Zowe schema during extender activation. [#2508](https://github.com/zowe/vscode-extension-for-zowe/issues/2508)

### Bug fixes

Expand Down
15 changes: 15 additions & 0 deletions packages/zowe-explorer/__mocks__/@zowe/imperative.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,17 @@ export class ProfileInfo {
public readProfilesFromDisk(teamCfgOpts?: IConfigOpts) {
return;
}

public addProfileTypeToSchema(
profileType: string,
typeInfo: {
sourceApp: string;
schema: any;
version?: string;
}
): any {
return;
}
}

export class ImperativeError extends Error {
Expand Down Expand Up @@ -279,6 +290,10 @@ export class ConfigSchema {
public static buildSchema() {
return {};
}

public static loadSchema() {
return [];
}
}

export class CredentialManagerOverride {
Expand Down
6 changes: 6 additions & 0 deletions packages/zowe-explorer/__mocks__/mockCreators/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import { FilterDescriptor } from "../../src/utils/ProfilesUtils";
import { imperative, ZosmfSession } from "@zowe/cli";
import { SettingsConfig } from "../../src/utils/SettingsConfig";
import * as globals from "../../src/globals";
import { Profiles } from "../../src/Profiles";

const MOCK_PROFILES = [];

export function createPersistentConfig() {
return {
Expand Down Expand Up @@ -310,6 +313,7 @@ export function createTextDocument(name: string, sessionNode?: ZoweDatasetNode |

export function createInstanceOfProfile(profile: imperative.IProfileLoaded) {
return {
addToConfigArray: Profiles.prototype.addToConfigArray,
allProfiles: [{ name: "sestest" }, { name: "profile1" }, { name: "profile2" }],
defaultProfile: { name: "sestest" },
getDefaultProfile: jest.fn(),
Expand All @@ -321,6 +325,8 @@ export function createInstanceOfProfile(profile: imperative.IProfileLoaded) {
return { status: "active", name: "sestest" };
}),
profilesForValidation: [{ status: "active", name: "sestest" }],
profileTypeConfigurations: MOCK_PROFILES,
getConfigArray: () => MOCK_PROFILES,
validateProfiles: jest.fn(),
getBaseProfile: jest.fn(),
enableValidationContext: jest.fn(),
Expand Down
13 changes: 13 additions & 0 deletions packages/zowe-explorer/__mocks__/mockUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* 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.
*
*/

// Idea is borrowed from: https://github.com/kulshekhar/ts-jest/blob/master/src/util/testing.ts
export const mocked = <T extends (..._args: any[]) => any>(fn: T): jest.Mock<ReturnType<T>> => fn as any;
4 changes: 4 additions & 0 deletions packages/zowe-explorer/__mocks__/path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,7 @@ export function extname(file: string): string {
export function parse(file: string) {
return { name: file };
}

export function basename(path: string) {
return jest.requireActual("path")["basename"](path);
}
12 changes: 12 additions & 0 deletions packages/zowe-explorer/__mocks__/vscode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,18 @@ export namespace window {
return Promise.resolve("");
}

/**
* Show a warning message to users. Optionally provide an array of items which will be presented as
* clickable buttons.
*
* @param message The message to show.
* @param items A set of items that will be rendered as actions in the message.
* @return A thenable that resolves to the selected item or `undefined` when being dismissed.
*/
export function showWarningMessage(message: string, ...items: string[]): Thenable<string> {
return Promise.resolve("");
}

export function showTextDocument(document: TextDocument, column?: ViewColumn, preserveFocus?: boolean): any {
return undefined;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ import { ZoweExplorerExtender } from "../../src/ZoweExplorerExtender";
import { Profiles } from "../../src/Profiles";
import * as path from "path";
import * as fs from "fs";
import { getZoweDir, Gui } from "@zowe/zowe-explorer-api";
import * as profUtils from "../../src/utils/ProfilesUtils";
import { getZoweDir, Gui, ProfilesCache } from "@zowe/zowe-explorer-api";
import { ProfilesUtils } from "../../src/utils/ProfilesUtils";
import { ZoweLogger } from "../../src/utils/LoggerUtils";
import { SettingsConfig } from "../../src/utils/SettingsConfig";
jest.mock("fs");

describe("ZoweExplorerExtender unit tests", () => {
Expand All @@ -35,7 +36,7 @@ describe("ZoweExplorerExtender unit tests", () => {
altTypeProfile: createAltTypeIProfile(),
treeView: createTreeView(),
instTest: ZoweExplorerExtender.getInstance(),
profiles: null,
profiles: {},
mockGetConfiguration: jest.fn(),
mockErrorMessage: jest.fn(),
mockExistsSync: jest.fn(),
Expand All @@ -44,15 +45,7 @@ describe("ZoweExplorerExtender unit tests", () => {

Object.defineProperty(fs, "existsSync", { value: newMocks.mockExistsSync, configurable: true });
newMocks.profiles = createInstanceOfProfile(newMocks.imperativeProfile);
Object.defineProperty(Profiles, "getInstance", {
value: jest
.fn(() => {
return {
refresh: jest.fn(),
};
})
.mockReturnValue(newMocks.profiles),
});
jest.spyOn(Profiles, "getInstance").mockReturnValue(newMocks.profiles as any);
Object.defineProperty(vscode.window, "createTreeView", {
value: jest.fn().mockReturnValue({ onDidCollapseElement: jest.fn() }),
configurable: true,
Expand Down Expand Up @@ -81,10 +74,6 @@ describe("ZoweExplorerExtender unit tests", () => {
value: jest.fn(),
configurable: true,
});
Object.defineProperty(Profiles.getInstance(), "addToConfigArray", {
value: jest.fn(),
configurable: true,
});
return newMocks;
}

Expand Down Expand Up @@ -217,11 +206,57 @@ describe("ZoweExplorerExtender unit tests", () => {

const readProfilesFromDiskSpy = jest.fn();
const refreshProfilesQueueAddSpy = jest.spyOn((ZoweExplorerExtender as any).refreshProfilesQueue, "add");
jest.spyOn(profUtils.ProfilesUtils, "getProfileInfo").mockReturnValue({
jest.spyOn(ProfilesUtils, "getProfileInfo").mockReturnValueOnce({
readProfilesFromDisk: readProfilesFromDiskSpy,
} as any);
await expect(blockMocks.instTest.initForZowe("USS", ["" as any])).resolves.not.toThrow();
expect(readProfilesFromDiskSpy).toBeCalledTimes(1);
expect(refreshProfilesQueueAddSpy).toHaveBeenCalledTimes(1);
});

describe("Add to Schema functionality", () => {
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const updateSchema = async (
addProfileTypeToSchemaMock: (
profileType: string,
typeInfo: { sourceApp: string; schema: any; version?: string | undefined }
) => any = jest.fn()
) => {
const blockMocks = await createBlockMocks();
// bypass "if (hasSecureCredentialManagerEnabled)" check for sake of testing
jest.spyOn(SettingsConfig, "getDirectValue").mockReturnValueOnce(false);
jest.spyOn(ZoweLogger, "trace").mockImplementation();
jest.spyOn(ZoweLogger, "info").mockImplementation();
const profInfo = new imperative.ProfileInfo("zowe", {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
credMgrOverride: imperative.ProfileCredentials.defaultCredMgrWithKeytar(ProfilesCache.requireKeyring),
});
const addProfTypeToSchema = jest
.spyOn(imperative.ProfileInfo.prototype, "addProfileTypeToSchema")
.mockImplementation(addProfileTypeToSchemaMock as unknown as any);
await (blockMocks.instTest as any).updateSchema(profInfo, [
{
type: "test-type",
schema: {} as any,
} as any,
]);
expect(addProfTypeToSchema).toHaveBeenCalled();
};

it("should update the schema when an extender calls initForZowe", async () => {
await updateSchema();
});

it("should throw an error if the schema is read-only", async () => {
const errorMessageSpy = jest.spyOn(Gui, "errorMessage");
await updateSchema((_filepath, _contents) => {
const err = new Error("test error");
Object.defineProperty(err, "code", {
value: "EACCES",
});
throw err;
});
expect(errorMessageSpy).toHaveBeenCalledWith("Failed to update Zowe schema: insufficient permissions or read-only file. test error");
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { ZoweLogger } from "../../../src/utils/LoggerUtils";

describe("TsoCommandHandler extended testing", () => {
// Idea is borrowed from: https://github.com/kulshekhar/ts-jest/blob/master/src/util/testing.ts
const mocked = <T extends (...args: any[]) => any>(fn: T): jest.Mock<ReturnType<T>> => fn as any;
const newMocks = {
imperativeProfile: createIProfile(),
profileInstance: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import * as sharedActions from "../../../src/shared/actions";
import { ZoweLogger } from "../../../src/utils/LoggerUtils";
import { TreeProviders } from "../../../src/shared/TreeProviders";
import { join } from "path";
import { mocked } from "../../../__mocks__/mockUtils";
import * as sharedUtils from "../../../src/shared/utils";

jest.mock("fs");
Expand Down Expand Up @@ -171,9 +172,6 @@ function createGlobalMocks() {
return globalMocks;
}

// Idea is borrowed from: https://github.com/kulshekhar/ts-jest/blob/eadf408f90ca2007b85f5a61c6c0b74b4e431943/src/utils/testing.ts
const mocked = <T extends (...args: any[]) => any>(fn: T): jest.Mock<ReturnType<T>> => fn as any;

describe("Dataset Tree Unit Tests - Initialisation", () => {
function createBlockMocks() {
const session = createISession();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { Profiles } from "../../../src/Profiles";
import * as utils from "../../../src/utils/ProfilesUtils";
import { getNodeLabels } from "../../../src/dataset/utils";
import { ZoweLogger } from "../../../src/utils/LoggerUtils";
import { mocked } from "../../../__mocks__/mockUtils";

// Missing the definition of path module, because I need the original logic for tests
jest.mock("fs");
Expand Down Expand Up @@ -130,9 +131,6 @@ function createGlobalMocks() {
return newMocks;
}

// Idea is borrowed from: https://github.com/kulshekhar/ts-jest/blob/master/src/util/testing.ts
const mocked = <T extends (...args: any[]) => any>(fn: T): jest.Mock<ReturnType<T>> => fn as any;

const createBlockMocksShared = () => {
const session = createISession();
const imperativeProfile = createIProfile();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { jobStringValidator } from "../../../src/shared/utils";
import { ZoweLogger } from "../../../src/utils/LoggerUtils";
import { Poller } from "@zowe/zowe-explorer-api/src/utils";
import { SettingsConfig } from "../../../src/utils/SettingsConfig";
import { mocked } from "../../../__mocks__/mockUtils";
import { TreeProviders } from "../../../src/shared/TreeProviders";

jest.mock("vscode");
Expand Down Expand Up @@ -240,9 +241,6 @@ async function createGlobalMocks() {
return globalMocks;
}

// Idea is borrowed from: https://github.com/kulshekhar/ts-jest/blob/master/src/util/testing.ts
const mocked = <T extends (...args: any[]) => any>(fn: T): jest.Mock<ReturnType<T>> => fn as any;

describe("ZosJobsProvider unit tests - Function getChildren", () => {
function createBlockMocks(globalMocks) {
const newMocks = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import { SpoolFile } from "../../../src/SpoolProvider";
import { ZosJobsProvider } from "../../../src/job/ZosJobsProvider";
import { ProfileManagement } from "../../../src/utils/ProfileManagement";
import { TreeProviders } from "../../../src/shared/TreeProviders";
import { mocked } from "../../../__mocks__/mockUtils";

const activeTextEditorDocument = jest.fn();

Expand Down Expand Up @@ -141,9 +142,6 @@ function createGlobalMocks() {
return newMocks;
}

// Idea is borrowed from: https://github.com/kulshekhar/ts-jest/blob/master/src/util/testing.ts
const mocked = <T extends (...args: any[]) => any>(fn: T): jest.Mock<ReturnType<T>> => fn as any;

afterEach(() => {
jest.clearAllMocks();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { ZoweUSSNode } from "../../../src/uss/ZoweUSSNode";
import { getIconById, IconId, getIconByNode } from "../../../src/generators/icons";
import * as zowe from "@zowe/cli";
import { ZoweLogger } from "../../../src/utils/LoggerUtils";
import { mocked } from "../../../__mocks__/mockUtils";

async function createGlobalMocks() {
const globalMocks = {
Expand Down Expand Up @@ -110,9 +111,6 @@ async function createGlobalMocks() {
return globalMocks;
}

// Idea is borrowed from: https://github.com/kulshekhar/ts-jest/blob/master/src/util/testing.ts
const mocked = <T extends (...args: any[]) => any>(fn: T): jest.Mock<ReturnType<T>> => fn as any;

describe("Shared Actions Unit Tests - Function searchInAllLoadedItems", () => {
function createBlockMocks(globalMocks) {
const newMocks = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ import { Gui, IZoweTreeNode, ProfilesCache, ZosEncoding } from "@zowe/zowe-explo
import { ZoweLogger } from "../../../src/utils/LoggerUtils";
import { ZoweLocalStorage } from "../../../src/utils/ZoweLocalStorage";

jest.mock("path");

async function createGlobalMocks() {
const newMocks = {
session: createISession(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { ZoweLogger } from "../../../src/utils/LoggerUtils";
import { TreeProviders } from "../../../src/shared/TreeProviders";
import { join } from "path";
import * as sharedUtils from "../../../src/shared/utils";
import { mocked } from "../../../__mocks__/mockUtils";

async function createGlobalMocks() {
const globalMocks = {
Expand Down Expand Up @@ -1378,8 +1379,6 @@ describe("USSTree Unit Tests - Function getChildren", () => {
expect(loadProfilesForFavoritesSpy).toHaveBeenCalledWith(log, favProfileNode);
});
});
// Idea is borrowed from: https://github.com/kulshekhar/ts-jest/blob/master/src/util/testing.ts
const mocked = <T extends (...args: any[]) => any>(fn: T): jest.Mock<ReturnType<T>> => fn as any;

describe("USSTree Unit Tests - Function loadProfilesForFavorites", () => {
function createBlockMocks(globalMocks) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ async function createGlobalMocks() {
Object.defineProperty(workspaceUtils, "closeOpenedTextFile", { value: jest.fn(), configurable: true });
Object.defineProperty(globalMocks.Download, "ussFile", { value: globalMocks.ussFile, configurable: true });
Object.defineProperty(zowe, "Delete", { value: globalMocks.Delete, configurable: true });
Object.defineProperty(fs, "existsSync", { value: globalMocks.existsSync, configurable: true });
jest.spyOn(fs, "existsSync").mockImplementation(globalMocks.existsSync);
Object.defineProperty(globalMocks.Delete, "ussFile", { value: globalMocks.ussFile, configurable: true });
Object.defineProperty(Profiles, "createInstance", {
value: jest.fn(() => globalMocks.profileOps),
Expand All @@ -173,7 +173,7 @@ async function createGlobalMocks() {
configurable: true,
});
Object.defineProperty(vscode.env.clipboard, "readText", { value: globalMocks.readText, configurable: true });
Object.defineProperty(path, "basename", { value: globalMocks.basePath, configurable: true });
jest.spyOn(path, "basename").mockImplementation(globalMocks.basePath);
Object.defineProperty(ZoweLogger, "error", { value: jest.fn(), configurable: true });
Object.defineProperty(ZoweLogger, "debug", { value: jest.fn(), configurable: true });
Object.defineProperty(ZoweLogger, "warn", { value: jest.fn(), configurable: true });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { createUssApi, bindUssApi } from "../../../__mocks__/mockCreators/api";
import * as refreshActions from "../../../src/shared/refresh";
import { ZoweLogger } from "../../../src/utils/LoggerUtils";
import { AttributeView } from "../../../src/uss/AttributeView";
import { mocked } from "../../../__mocks__/mockUtils";

function createGlobalMocks() {
const globalMocks = {
Expand Down Expand Up @@ -166,8 +167,6 @@ function createGlobalMocks() {

return globalMocks;
}
// Idea is borrowed from: https://github.com/kulshekhar/ts-jest/blob/master/src/util/testing.ts
const mocked = <T extends (...args: any[]) => any>(fn: T): jest.Mock<ReturnType<T>> => fn as any;

describe("USS Action Unit Tests - Function createUSSNodeDialog", () => {
async function createBlockMocks(globalMocks) {
Expand Down
Loading

0 comments on commit 6c900e7

Please sign in to comment.