diff --git a/packages/cli/__tests__/__unit__/enable/Enable.definition.unit.test.ts b/packages/cli/__tests__/__unit__/enable/Enable.definition.unit.test.ts index 98cc1966..ccd5717b 100644 --- a/packages/cli/__tests__/__unit__/enable/Enable.definition.unit.test.ts +++ b/packages/cli/__tests__/__unit__/enable/Enable.definition.unit.test.ts @@ -12,7 +12,7 @@ import { ICommandDefinition } from "@zowe/imperative"; describe("cics enable urimap", () => { - const ENABLE_RESOURCES = 2; + const ENABLE_RESOURCES = 3; it("should not have changed", () => { const definition: ICommandDefinition = require("../../../src/enable/Enable.definition"); diff --git a/packages/cli/__tests__/__unit__/enable/program/Program.definition.unit.test.ts b/packages/cli/__tests__/__unit__/enable/program/Program.definition.unit.test.ts new file mode 100644 index 00000000..30df5783 --- /dev/null +++ b/packages/cli/__tests__/__unit__/enable/program/Program.definition.unit.test.ts @@ -0,0 +1,21 @@ +/** + * 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. + * + */ + +import { ICommandDefinition } from "@zowe/imperative"; + +describe("cics enable program", () => { + it("should not have changed", () => { + const definition: ICommandDefinition = require("../../../../src/enable/program/Program.definition").ProgramDefinition; + expect(definition).toBeDefined(); + delete definition.handler; + expect(definition).toMatchSnapshot(); + }); +}); diff --git a/packages/cli/__tests__/__unit__/enable/program/Program.handler.unit.test.ts b/packages/cli/__tests__/__unit__/enable/program/Program.handler.unit.test.ts new file mode 100644 index 00000000..44bca60c --- /dev/null +++ b/packages/cli/__tests__/__unit__/enable/program/Program.handler.unit.test.ts @@ -0,0 +1,102 @@ +/** + * 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. + * + */ + +import { mockHandlerParameters } from "@zowe/cli-test-utils"; +import { CommandProfiles, IHandlerParameters, IProfile, Session } from "@zowe/imperative"; +import { ICMCIApiResponse } from "../../../../src"; +import { ProgramDefinition } from "../../../../src/enable/program/Program.definition"; +import ProgramHandler from "../../../../src/enable/program/Program.handler"; + +jest.mock("@zowe/cics-for-zowe-sdk"); +const Enable = require("@zowe/cics-for-zowe-sdk"); + +const host = "somewhere.com"; +const port = "43443"; +const user = "someone"; +const password = "somesecret"; +const protocol = "http"; +const rejectUnauthorized = false; + +const PROFILE_MAP = new Map(); +PROFILE_MAP.set("cics", [ + { + name: "cics", + type: "cics", + host, + port, + user, + password, + protocol, + rejectUnauthorized, + }, +]); +const PROFILES: CommandProfiles = new CommandProfiles(PROFILE_MAP); +const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ + positionals: ["cics", "enable", "program"], + definition: ProgramDefinition, + profiles: PROFILES, +}); + +describe("enableProgramHandler", () => { + const programName = "testProgram"; + const regionName = "testRegion"; + + const defaultReturn: ICMCIApiResponse = { + response: { + resultsummary: { api_response1: "1024", api_response2: "0", recordcount: "0", displayed_recordcount: "0" }, + records: "testing", + }, + }; + + const functionSpy = jest.spyOn(Enable, "enableProgram"); + + beforeEach(() => { + functionSpy.mockClear(); + functionSpy.mockImplementation(async () => defaultReturn); + }); + + it("should call the enableProgram api", async () => { + const handler = new ProgramHandler(); + + const commandParameters = { ...DEFAULT_PARAMETERS }; + commandParameters.arguments = { + ...commandParameters.arguments, + name: programName, + regionName, + host, + port, + user, + password, + protocol, + rejectUnauthorized, + }; + + await handler.process(commandParameters); + + expect(functionSpy).toHaveBeenCalledTimes(1); + const testProfile = PROFILE_MAP.get("cics")[0]; + expect(functionSpy).toHaveBeenCalledWith( + new Session({ + type: "basic", + hostname: testProfile.host, + port: testProfile.port, + user: testProfile.user, + password: testProfile.password, + rejectUnauthorized, + protocol, + }), + { + name: programName, + regionName, + } + ); + }); +}); diff --git a/packages/cli/__tests__/__unit__/enable/program/__snapshots__/Program.definition.unit.test.ts.snap b/packages/cli/__tests__/__unit__/enable/program/__snapshots__/Program.definition.unit.test.ts.snap new file mode 100644 index 00000000..28aa3f1e --- /dev/null +++ b/packages/cli/__tests__/__unit__/enable/program/__snapshots__/Program.definition.unit.test.ts.snap @@ -0,0 +1,85 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`cics enable program should not have changed 1`] = ` +{ + "aliases": [ + "prog", + ], + "description": "Enable a program from CICS.", + "examples": [ + { + "description": "Enable a program named PROGRAM1 from the region named MYREGION", + "options": "PROGRAM1 --region-name MYREGION", + }, + ], + "name": "program", + "options": [ + { + "description": "The CICS region name in which to enable the program", + "name": "region-name", + "type": "string", + }, + { + "description": "The name of the CICSPlex to which to enable the program", + "name": "cics-plex", + "type": "string", + }, + ], + "positionals": [ + { + "description": "The name of the program to enable. The maximum length is eight characters.", + "name": "name", + "required": true, + "type": "string", + }, + ], + "profile": { + "optional": [ + "cics", + ], + }, + "type": "command", +} +`; + +exports[`cics enable urimap should not have changed 1`] = ` +{ + "aliases": [ + "prog", + ], + "description": "Enable a program from CICS.", + "examples": [ + { + "description": "Enable a program named PROGRAM1 from the region named MYREGION", + "options": "PROGRAM1 --region-name MYREGION", + }, + ], + "name": "program", + "options": [ + { + "description": "The CICS region name in which to enable the program", + "name": "region-name", + "type": "string", + }, + { + "description": "The name of the CICSPlex to which to enable the program", + "name": "cics-plex", + "type": "string", + }, + ], + "positionals": [ + { + "description": "The name of the program to enable. The maximum length is eight characters.", + "name": "name", + "required": true, + "type": "string", + }, + ], + "profile": { + "optional": [ + "cics", + ], + }, + "type": "command", +} +`; diff --git a/packages/cli/__tests__/__unit__/enable/program/__snapshots__/Program.handler.unit.test.ts.snap b/packages/cli/__tests__/__unit__/enable/program/__snapshots__/Program.handler.unit.test.ts.snap new file mode 100644 index 00000000..4c23811d --- /dev/null +++ b/packages/cli/__tests__/__unit__/enable/program/__snapshots__/Program.handler.unit.test.ts.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`enableProgramHandler should call the enableProgram api 1`] = `"The program '%s' was enabled successfully."`; + +exports[`enableProgramHandler should call the enableProgram api 2`] = ` +{ + "response": { + "records": "testing", + "resultsummary": { + "api_response1": "1024", + "api_response2": "0", + "displayed_recordcount": "0", + "recordcount": "0", + }, + }, +} +`; diff --git a/packages/cli/__tests__/__unit__/enable/transaction/Transaction.definition.unit.test.ts b/packages/cli/__tests__/__unit__/enable/transaction/Transaction.definition.unit.test.ts index 025977df..9ba44301 100644 --- a/packages/cli/__tests__/__unit__/enable/transaction/Transaction.definition.unit.test.ts +++ b/packages/cli/__tests__/__unit__/enable/transaction/Transaction.definition.unit.test.ts @@ -11,7 +11,7 @@ import { ICommandDefinition } from "@zowe/imperative"; -describe("cics enable urimap", () => { +describe("cics enable transaction", () => { it("should not have changed", () => { const definition: ICommandDefinition = require("../../../../src/enable/transaction/Transaction.definition").TransactionDefinition; expect(definition).toBeDefined(); diff --git a/packages/cli/__tests__/__unit__/enable/transaction/__snapshots__/Transaction.definition.unit.test.ts.snap b/packages/cli/__tests__/__unit__/enable/transaction/__snapshots__/Transaction.definition.unit.test.ts.snap index b1791f1b..b58e4a9d 100644 --- a/packages/cli/__tests__/__unit__/enable/transaction/__snapshots__/Transaction.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/__unit__/enable/transaction/__snapshots__/Transaction.definition.unit.test.ts.snap @@ -1,5 +1,47 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`cics enable transaction should not have changed 1`] = ` +{ + "aliases": [ + "tran", + ], + "description": "Enable a transaction from CICS.", + "examples": [ + { + "description": "Enable a transaction named TRN1 from the region named MYREGION", + "options": "TRN1 --region-name MYREGION", + }, + ], + "name": "transaction", + "options": [ + { + "description": "The CICS region name in which to enable the transaction", + "name": "region-name", + "type": "string", + }, + { + "description": "The name of the CICSPlex to which to enable the transaction", + "name": "cics-plex", + "type": "string", + }, + ], + "positionals": [ + { + "description": "The name of the transaction to enable. The maximum length is four characters.", + "name": "name", + "required": true, + "type": "string", + }, + ], + "profile": { + "optional": [ + "cics", + ], + }, + "type": "command", +} +`; + exports[`cics enable urimap should not have changed 1`] = ` { "aliases": [ diff --git a/packages/cli/src/-strings-/en.ts b/packages/cli/src/-strings-/en.ts index b0ac1139..320fe560 100644 --- a/packages/cli/src/-strings-/en.ts +++ b/packages/cli/src/-strings-/en.ts @@ -321,6 +321,22 @@ export default { SUMMARY: "Enable resources from CICS", DESCRIPTION: "Enable resources from CICS through IBM CMCI.", RESOURCES: { + PROGRAM: { + DESCRIPTION: "Enable a program from CICS.", + POSITIONALS: { + NAME: "The name of the program to enable. The maximum length is eight characters.", + }, + OPTIONS: { + REGIONNAME: "The CICS region name in which to enable the program", + CICSPLEX: "The name of the CICSPlex to which to enable the program", + }, + MESSAGES: { + SUCCESS: "The program '%s' was enabled successfully.", + }, + EXAMPLES: { + EX1: "Enable a program named PROGRAM1 from the region named MYREGION", + }, + }, TRANSACTION: { DESCRIPTION: "Enable a transaction from CICS.", POSITIONALS: { diff --git a/packages/cli/src/enable/Enable.definition.ts b/packages/cli/src/enable/Enable.definition.ts index 8b72f658..7edad098 100644 --- a/packages/cli/src/enable/Enable.definition.ts +++ b/packages/cli/src/enable/Enable.definition.ts @@ -15,6 +15,7 @@ import { UrimapDefinition } from "./urimap/Urimap.definition"; import i18nTypings from "../-strings-/en"; import { CicsSession } from "../CicsSession"; import { TransactionDefinition } from "./transaction/Transaction.definition"; +import { ProgramDefinition } from "./program/Program.definition"; // Does not use the import in anticipation of some internationalization work to be done later. const strings = (require("../-strings-/en").default as typeof i18nTypings).ENABLE; @@ -28,7 +29,7 @@ const definition: ICommandDefinition = { summary: strings.SUMMARY, description: strings.DESCRIPTION, type: "group", - children: [TransactionDefinition, UrimapDefinition], + children: [ProgramDefinition, TransactionDefinition, UrimapDefinition], passOn: [ { property: "options", diff --git a/packages/cli/src/enable/program/Program.definition.ts b/packages/cli/src/enable/program/Program.definition.ts new file mode 100644 index 00000000..d3a501b7 --- /dev/null +++ b/packages/cli/src/enable/program/Program.definition.ts @@ -0,0 +1,52 @@ +/** + * 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. + * + */ + +import { ICommandDefinition } from "@zowe/imperative"; + +import i18nTypings from "../../-strings-/en"; + +// Does not use the import in anticipation of some internationalization work to be done later. +const strings = (require("../../-strings-/en").default as typeof i18nTypings).ENABLE.RESOURCES.PROGRAM; + +export const ProgramDefinition: ICommandDefinition = { + name: "program", + aliases: ["prog"], + description: strings.DESCRIPTION, + handler: __dirname + "/Program.handler", + type: "command", + positionals: [ + { + name: "name", + description: strings.POSITIONALS.NAME, + type: "string", + required: true, + }, + ], + options: [ + { + name: "region-name", + description: strings.OPTIONS.REGIONNAME, + type: "string", + }, + { + name: "cics-plex", + description: strings.OPTIONS.CICSPLEX, + type: "string", + }, + ], + profile: { optional: ["cics"] }, + examples: [ + { + description: strings.EXAMPLES.EX1, + options: "PROGRAM1 --region-name MYREGION", + }, + ], +}; diff --git a/packages/cli/src/enable/program/Program.handler.ts b/packages/cli/src/enable/program/Program.handler.ts new file mode 100644 index 00000000..43b413cd --- /dev/null +++ b/packages/cli/src/enable/program/Program.handler.ts @@ -0,0 +1,45 @@ +/** + * 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. + * + */ + +import { AbstractSession, IHandlerParameters, ITaskWithStatus, TaskStage } from "@zowe/imperative"; +import { ICMCIApiResponse, enableProgram } from "@zowe/cics-for-zowe-sdk"; +import { CicsBaseHandler } from "../../CicsBaseHandler"; + +import i18nTypings from "../../-strings-/en"; + +// Does not use the import in anticipation of some internationalization work to be done later. +const strings = (require("../../-strings-/en").default as typeof i18nTypings).ENABLE.RESOURCES.PROGRAM; + +/** + * Command handler for enabling CICS Programs via CMCI + * @export + * @class ProgramHandler + * @implements {ICommandHandler} + */ +export default class ProgramHandler extends CicsBaseHandler { + public async processWithSession(params: IHandlerParameters, session: AbstractSession): Promise { + const status: ITaskWithStatus = { + statusMessage: "Enabling Program from CICS", + percentComplete: 0, + stageName: TaskStage.IN_PROGRESS, + }; + params.response.progress.startBar({ task: status }); + + const response = await enableProgram(session, { + name: params.arguments.name, + regionName: params.arguments.regionName, + cicsPlex: params.arguments.cicsPlex, + }); + + params.response.console.log(strings.MESSAGES.SUCCESS, params.arguments.name); + return response; + } +} diff --git a/packages/sdk/__tests__/__unit__/enable/Enable.program.unit.test.ts b/packages/sdk/__tests__/__unit__/enable/Enable.program.unit.test.ts new file mode 100644 index 00000000..8f340f37 --- /dev/null +++ b/packages/sdk/__tests__/__unit__/enable/Enable.program.unit.test.ts @@ -0,0 +1,106 @@ +/** + * 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. + * + */ + +import { Session } from "@zowe/imperative"; +import { CicsCmciConstants, CicsCmciRestClient, enableProgram, ICMCIApiResponse, IBaseParms } from "../../../src"; + +describe("CMCI - enable program", () => { + const program = "program"; + const region = "region"; + const content = "ThisIsATest" as unknown as ICMCIApiResponse; + + const enableParms: IBaseParms = { + regionName: region, + name: program, + }; + + const dummySession = new Session({ + user: "fake", + password: "fake", + hostname: "fake", + port: 1490, + }); + + let error: any; + let response: any; + let endPoint: any; + let requestBody: any; + + describe("validation", () => { + beforeEach(() => { + response = undefined; + error = undefined; + enableParms.regionName = region; + enableParms.name = program; + }); + + it("should throw an error if no region name is specified", async () => { + enableParms.regionName = undefined as any; + try { + response = await enableProgram(dummySession, enableParms); + } catch (err) { + error = err; + } + expect(response).toBeUndefined(); + expect(error).toBeDefined(); + expect(error.message).toContain("CICS region name is required"); + }); + + it("should throw an error if no program name is specified", async () => { + enableParms.name = undefined as any; + try { + response = await enableProgram(dummySession, enableParms); + } catch (err) { + error = err; + } + expect(response).toBeUndefined(); + expect(error).toBeDefined(); + expect(error.message).toContain("CICS Program name is required"); + }); + }); + + describe("success scenarios", () => { + const enableSpy = jest.spyOn(CicsCmciRestClient, "putExpectParsedXml").mockResolvedValue(content); + + beforeEach(() => { + response = undefined; + error = undefined; + enableSpy.mockClear(); + enableSpy.mockResolvedValue(content); + enableParms.regionName = region; + enableParms.name = program; + }); + + it("should be able to enable a program", async () => { + endPoint = + "/" + + CicsCmciConstants.CICS_SYSTEM_MANAGEMENT + + "/" + + CicsCmciConstants.CICS_PROGRAM_RESOURCE + + "/" + + region + + `?CRITERIA=(PROGRAM=${enableParms.name})`; + requestBody = { + request: { + action: { + $: { + name: "ENABLE", + }, + }, + }, + }; + + response = await enableProgram(dummySession, enableParms); + expect(response).toContain(content); + expect(enableSpy).toHaveBeenCalledWith(dummySession, endPoint, [], requestBody); + }); + }); +}); diff --git a/packages/sdk/__tests__/__unit__/enable/Enable.transaction.unit.test.ts b/packages/sdk/__tests__/__unit__/enable/Enable.transaction.unit.test.ts index d13bfa26..e942ccd2 100644 --- a/packages/sdk/__tests__/__unit__/enable/Enable.transaction.unit.test.ts +++ b/packages/sdk/__tests__/__unit__/enable/Enable.transaction.unit.test.ts @@ -43,7 +43,7 @@ describe("CMCI - enable transaction", () => { }); it("should throw an error if no region name is specified", async () => { - enableParms.regionName = undefined; + enableParms.regionName = undefined as any; try { response = await enableTransaction(dummySession, enableParms); } catch (err) { @@ -55,7 +55,7 @@ describe("CMCI - enable transaction", () => { }); it("should throw an error if no transaction name is specified", async () => { - enableParms.name = undefined; + enableParms.name = undefined as any; try { response = await enableTransaction(dummySession, enableParms); } catch (err) { diff --git a/packages/sdk/src/methods/enable/Enable.ts b/packages/sdk/src/methods/enable/Enable.ts index 6cbd459a..3a13e01d 100644 --- a/packages/sdk/src/methods/enable/Enable.ts +++ b/packages/sdk/src/methods/enable/Enable.ts @@ -12,7 +12,7 @@ import { AbstractSession, ImperativeExpect, Logger } from "@zowe/imperative"; import { CicsCmciRestClient } from "../../rest"; import { CicsCmciConstants } from "../../constants"; -import { IBaseParms, ICMCIApiResponse, IURIMapParms } from "../../doc"; +import { IBaseParms, ICMCIApiResponse, IProgramParms, IURIMapParms } from "../../doc"; /** * Enable a URIMap installed in CICS through CMCI REST API @@ -91,3 +91,42 @@ export async function enableTransaction(session: AbstractSession, parms: IBasePa return await CicsCmciRestClient.putExpectParsedXml(session, cmciResource, [], requestBody); } + +/** + * Enable a program installed in CICS through CMCI REST API + * @param {AbstractSession} session - the session to connect to CMCI with + * @param {IURIMapParms} parms - parameters for enabling your program + * @returns {Promise} promise that resolves to the response (XML parsed into a javascript object) + * when the request is complete + * @throws {ImperativeError} CICS Program name not defined or blank + * @throws {ImperativeError} CICS Region name not defined or blank + * @throws {ImperativeError} CicsCmciRestClient request fails + */ +export async function enableProgram(session: AbstractSession, parms: IProgramParms): Promise { + ImperativeExpect.toBeDefinedAndNonBlank(parms.name, "CICS Program name", "CICS Program name is required"); + ImperativeExpect.toBeDefinedAndNonBlank(parms.regionName, "CICS Region name", "CICS region name is required"); + const requestBody: any = { + request: { + action: { + $: { + name: "ENABLE", + }, + }, + }, + }; + + const cicsPlex = parms.cicsPlex == null ? "" : parms.cicsPlex + "/"; + const cmciResource = + "/" + + CicsCmciConstants.CICS_SYSTEM_MANAGEMENT + + "/" + + CicsCmciConstants.CICS_PROGRAM_RESOURCE + + "/" + + cicsPlex + + parms.regionName + + "?CRITERIA=(PROGRAM=" + + parms.name + + ")"; + + return await CicsCmciRestClient.putExpectParsedXml(session, cmciResource, [], requestBody); +} diff --git a/packages/vsce/src/commands/enableCommands/enableProgramCommand.ts b/packages/vsce/src/commands/enableCommands/enableProgramCommand.ts index 26940508..8b9a3b3d 100644 --- a/packages/vsce/src/commands/enableCommands/enableProgramCommand.ts +++ b/packages/vsce/src/commands/enableCommands/enableProgramCommand.ts @@ -9,8 +9,6 @@ * */ -import { CicsCmciConstants, CicsCmciRestClient, ICMCIApiResponse } from "@zowe/cics-for-zowe-sdk"; -import { imperative } from "@zowe/zowe-explorer-api"; import { commands, ProgressLocation, TreeView, window } from "vscode"; import { CICSRegionTree } from "../../trees/CICSRegionTree"; import { CICSTree } from "../../trees/CICSTree"; @@ -19,6 +17,7 @@ import { CICSRegionsContainer } from "../../trees/CICSRegionsContainer"; import { CICSProgramTreeItem } from "../../trees/treeItems/CICSProgramTreeItem"; import { findSelectedNodes } from "../../utils/commandUtils"; import { CICSCombinedProgramTree } from "../../trees/CICSCombinedTrees/CICSCombinedProgramTree"; +import { enableProgram } from "@zowe/cics-for-zowe-sdk"; /** * Performs enable on selected CICSProgram nodes. @@ -103,33 +102,3 @@ export function getEnableProgramCommand(tree: CICSTree, treeview: TreeView) ); }); } - -async function enableProgram( - session: imperative.AbstractSession, - parms: { name: string; regionName: string; cicsPlex: string } -): Promise { - const requestBody: any = { - request: { - action: { - $: { - name: "ENABLE", - }, - }, - }, - }; - - const cicsPlex = parms.cicsPlex === undefined ? "" : parms.cicsPlex + "/"; - const cmciResource = - "/" + - CicsCmciConstants.CICS_SYSTEM_MANAGEMENT + - "/" + - CicsCmciConstants.CICS_PROGRAM_RESOURCE + - "/" + - cicsPlex + - parms.regionName + - "?CRITERIA=(PROGRAM=" + - parms.name + - ")"; - - return await CicsCmciRestClient.putExpectParsedXml(session, cmciResource, [], requestBody); -}