Skip to content

Commit

Permalink
Merge pull request #2210 from zowe/update-next
Browse files Browse the repository at this point in the history
Update next with changes from master
  • Loading branch information
t1m0thyj authored Jul 26, 2024
2 parents b554743 + 743182b commit dd14d3f
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 12 deletions.
8 changes: 8 additions & 0 deletions __tests__/__packages__/cli-test-utils/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

All notable changes to the Zowe CLI test utils package will be documented in this file.

## Recent Changes

- Update: See `7.28.2` for details

## `8.0.0-next.202407021516`

- BugFix: Updated dependencies for technical currency [#2188](https://github.com/zowe/zowe-cli/pull/2188)
Expand All @@ -14,6 +18,10 @@ All notable changes to the Zowe CLI test utils package will be documented in thi

- Major: First major version bump for V3

## `7.28.2`

- BugFix: Improved the error message shown on Windows when `runCliScript` method cannot find `sh` executable on PATH. [#2208](https://github.com/zowe/zowe-cli/issues/2208)

## `7.18.11`

- BugFix: Fix types error from an incorrect jstree type during compilation
Expand Down
13 changes: 9 additions & 4 deletions __tests__/__packages__/cli-test-utils/src/TestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*/

import * as fs from "fs";
import { spawnSync, SpawnSyncReturns } from "child_process";
import { spawnSync, SpawnSyncReturns, ExecFileException } from "child_process";
import { ITestEnvironment } from "./environment/doc/response/ITestEnvironment";
import { CommandProfiles, ICommandDefinition, IHandlerParameters } from "@zowe/imperative";

Expand All @@ -37,11 +37,16 @@ export function runCliScript(scriptPath: string, testEnvironment: ITestEnvironme

if (process.platform === "win32") {
// Execute the command synchronously
return spawnSync("sh", [`${scriptPath}`].concat(args), {
const response = spawnSync("sh", [scriptPath].concat(args), {
cwd: testEnvironment.workingDir,
env: childEnv,
encoding: "buffer"
encoding: "buffer",
env: childEnv
});
if ((response.error as ExecFileException)?.code === "ENOENT") {
throw new Error(`"sh" is missing from your PATH. Check that Git Bash is installed with the option to ` +
`"Use Git and Unix Tools from Windows Command Prompt".`);
}
return response;
}

// Check to see if the file is executable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ function mockConfigApi(properties: IConfig | undefined): any {
},
profiles: {
getProfilePathFromName: (name: string) => `profiles.${name}`,
get: jest.fn().mockReturnValue({})
get: jest.fn().mockReturnValue(properties.profiles.base?.properties)
},
secure: {
securePropsForProfile: jest.fn().mockReturnValue([])
securePropsForProfile: jest.fn().mockReturnValue(properties.profiles.base?.secure)
}
},
exists: true,
Expand Down Expand Up @@ -200,21 +200,97 @@ describe("ApimlAutoInitHandler", () => {
expect(response.profiles[baseProfName].properties.tokenValue).toEqual("fakeToken");
});

it("should not have changed - secure fields with existing non-default base profile", async () => {
// NOTE: Token type and token value will be stored, but user and password will still be present in the base profile
const mockCreateZosmfSession = jest.fn();
const mockGetPluginApimlConfigs = jest.fn().mockReturnValue([]);
const mockGetServicesByConfig = jest.fn().mockResolvedValue([]);
jest.spyOn(ConfigUtils, "getActiveProfileName").mockReturnValueOnce("base");
const mockConfigValue: any = {
defaults: {},
profiles: {
"base": {
properties: {
host: "fake",
port: 12345,
user: "fake",
password: "fake"
},
secure: [
"host",
"user",
"password"
],
profiles: {}
}
},
plugins: []
};
const mockConvertApimlProfileInfoToProfileConfig = jest.fn().mockReturnValue(mockConfigValue);
const mockLogin = jest.fn().mockResolvedValue("fakeToken");
jest.spyOn(ImperativeConfig.instance, "config", "get").mockReturnValue(mockConfigApi(mockConfigValue));

ZosmfSession.createSessCfgFromArgs = mockCreateZosmfSession;
Services.getPluginApimlConfigs = mockGetPluginApimlConfigs;
Services.getServicesByConfig = mockGetServicesByConfig;
Services.convertApimlProfileInfoToProfileConfig = mockConvertApimlProfileInfoToProfileConfig;
Login.apimlLogin = mockLogin;

const handler: any = new ApimlAutoInitHandler();
expect(handler.mProfileType).toBe("base");

handler.createSessCfgFromArgs();
expect(mockCreateZosmfSession).toHaveBeenCalledTimes(1);

const response = await handler.doAutoInit(
{
ISession: {
hostname: "fake",
port: 1234,
user: "fake",
password: "fake",
type: SessConstants.AUTH_TYPE_BASIC,
tokenType: undefined
}
}, {
arguments: {
$0: "fake",
_: ["fake"],
"base-profile": "base"
}
});
expect(mockGetPluginApimlConfigs).toHaveBeenCalledTimes(1);
expect(mockGetServicesByConfig).toHaveBeenCalledTimes(1);
expect(mockConvertApimlProfileInfoToProfileConfig).toHaveBeenCalledTimes(1);
expect(mockLogin).toHaveBeenCalledTimes(1);
expect(response.profiles.base.secure).toEqual(["host", "tokenValue"]);
expect(response.profiles.base.properties.tokenType).toBeDefined();
expect(response.profiles.base.properties.tokenValue).toBeDefined();
expect(response.profiles.base.properties.user).toBeUndefined();
expect(response.profiles.base.properties.password).toBeUndefined();
expect(response.defaults.base).toBe("base");
});

it("should not have changed - user & password with existing base profile", async () => {
// NOTE: Token type and token value will be stored, but user and password will still be present in the base profile
const mockCreateZosmfSession = jest.fn();
const mockGetPluginApimlConfigs = jest.fn().mockReturnValue([]);
const mockGetServicesByConfig = jest.fn().mockResolvedValue([]);
jest.spyOn(ConfigUtils, "getActiveProfileName").mockReturnValueOnce("base");
const mockConfigValue: any = {
defaults: { base: "base"},
defaults: { base: "base" },
profiles: {
"base": {
properties: {
host: "fake",
port: 12345
port: 12345,
user: "fake",
password: "fake"
},
secure: [],
secure: [
"user",
"password"
],
profiles: {}
}
},
Expand Down Expand Up @@ -259,6 +335,9 @@ describe("ApimlAutoInitHandler", () => {
expect(response.profiles.base.secure).toContain("tokenValue");
expect(response.profiles.base.properties.tokenType).toBeDefined();
expect(response.profiles.base.properties.tokenValue).toBeDefined();
expect(response.profiles.base.properties.user).toBeUndefined();
expect(response.profiles.base.properties.password).toBeUndefined();
expect(response.defaults.base).toBe("base");
});

it("should not have changed - rejectUnauthorized flag true", async () => {
Expand Down
8 changes: 8 additions & 0 deletions packages/imperative/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

All notable changes to the Imperative package will be documented in this file.

## Recent Changes

- Update: See `5.26.1` for details

## `8.0.0-next.202407232256`

- Enhancement: Allowed boolean value (`false`) to be provided to the Credential Manager related function. [zowe-explorer-vscode#2622](https://github.com/zowe/zowe-explorer-vscode/issues/2622)
Expand Down Expand Up @@ -422,6 +426,10 @@ All notable changes to the Imperative package will be documented in this file.

- Major: First major version bump for V3

## `5.26.1`

- BugFix: Fixed missing export for `Proxy` class in Imperative package. [#2205](https://github.com/zowe/zowe-cli/pull/2205)

## `5.26.0`

- Enhancement: Updated `ProfileInfo.updateProperty` function to support updating properties in typeless profiles. [#2196](https://github.com/zowe/zowe-cli/issues/2196)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import { ImperativeConfig } from "../../utilities/src/ImperativeConfig";
import { setupConfigToLoad } from "../../../__tests__/src/TestUtil";
import { EnvFileUtils } from "../../utilities";
import { join } from "path";
import { Config } from "../../config";
import { LoggerUtils } from "../../logger/src/LoggerUtils";

jest.mock("../src/syntax/SyntaxValidator");
jest.mock("../src/utils/SharedOptions");
Expand Down Expand Up @@ -1479,7 +1481,7 @@ describe("Command Processor", () => {
rootCommandName: SAMPLE_ROOT_COMMAND,
commandLine: "",
promptPhrase: "dummydummy",
config: ImperativeConfig.instance.config
config: ImperativeConfig.instance.config
});

// Mock the profile loader
Expand All @@ -1506,7 +1508,8 @@ describe("Command Processor", () => {
expect(commandResponse.data.optionalProfiles[0]).toBe(`banana`);
expect(commandResponse.data.requiredProfiles).toBeUndefined();
});
it("should mask input value for a secure parm when --show-inputs-only flag is set", async () => {

it("should mask input value for a default secure parm when --show-inputs-only flag is set", async () => {

// values to test
const secretParmKey = `brownSpots`;
Expand Down Expand Up @@ -1589,7 +1592,7 @@ describe("Command Processor", () => {
rootCommandName: SAMPLE_ROOT_COMMAND,
commandLine: "",
promptPhrase: "dummydummy",
config: ImperativeConfig.instance.config
config: ImperativeConfig.instance.config
});

// Mock the profile loader
Expand Down Expand Up @@ -1619,6 +1622,80 @@ describe("Command Processor", () => {
expect(commandResponse.data.requiredProfiles).toBeUndefined();
});

it.each(LoggerUtils.SECURE_PROMPT_OPTIONS)("should mask input value for secure parm %s when --show-inputs-only flag is set", async (propName) => {

// values to test
const parm1Key = CliUtils.getOptionFormat(propName).kebabCase;
const parm1Value = `secret`;
const secure = `(secure value)`;
jest.spyOn(ImperativeConfig, "instance", "get").mockReturnValue({
config: {
api: {
secure: {
securePropsForProfile: jest.fn(() => [propName])
}
},
layers: [{ exists: true, path: "zowe.config.json" }],
properties: Config.empty()
}
} as any);

// Allocate the command processor
const processor: CommandProcessor = new CommandProcessor({
envVariablePrefix: ENV_VAR_PREFIX,
fullDefinition: SAMPLE_COMPLEX_COMMAND, // `group action`
definition: { // `object`
name: "banana",
description: "The banana command",
type: "command",
handler: __dirname + "/__model__/TestCmdHandler",
options: [
{
name: parm1Key,
type: "string",
description: "The first parameter",
}
],
profile: {
optional: ["fruit"]
}
},
helpGenerator: FAKE_HELP_GENERATOR,
rootCommandName: SAMPLE_ROOT_COMMAND,
commandLine: "",
promptPhrase: "dummydummy",
config: ImperativeConfig.instance.config
});

// Mock the profile loader
(CommandProfileLoader.loader as any) = jest.fn((args) => {
return {
loadProfiles: (profArgs: any) => {
return;
}
};
});

// return the "fake" args object with values from profile
CliUtils.getOptValueFromProfiles = jest.fn((cmdProfiles, profileDef, allOpts) => {
return {};
});

const parms: any = {
arguments: {
_: ["check", "for", "banana"],
$0: "",
[parm1Key]: parm1Value,
valid: true,
showInputsOnly: true,
},
silent: true
};
const commandResponse: ICommandResponse = await processor.invoke(parms);
expect(commandResponse.data.commandValues[parm1Key]).toBe(secure);
expect(commandResponse.stderr.toString()).toContain(`Some inputs are not displayed`);
});

it("should not mask input value for a secure parm when --show-inputs-only flag is set with env setting", async () => {

// values to test
Expand Down
1 change: 1 addition & 0 deletions packages/imperative/src/rest/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export * from "./src/client/doc/IRestClientError";
export * from "./src/client/doc/IRestClientResponse";
export * from "./src/client/doc/IRestOptions";
export * from "./src/client/Headers";
export * from "./src/client/Proxy";
export * from "./src/client/AbstractRestClient";
// export * from "./src/client/CompressionUtils";
export * from "./src/client/RestClient";
Expand Down

0 comments on commit dd14d3f

Please sign in to comment.