diff --git a/package-lock.json b/package-lock.json index b6183f9..615c53a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,7 @@ "app": "bin/run" }, "devDependencies": { - "@oclif/test": "^4.0.3", + "@oclif/test": "^2.5.6", "@types/adm-zip": "^0.5.5", "@types/chai": "^4.3.11", "@types/lodash": "^4.17.4", @@ -1938,36 +1938,64 @@ } }, "node_modules/@oclif/test": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@oclif/test/-/test-4.0.3.tgz", - "integrity": "sha512-LxcRYVFTUHoOW2Koo1lmbEwl/4HRFIdNWXuUY1/PHEawjwLvp3xwVe2rOWGqYD+vlHr+TYUw2QDQc8e2vUTDrw==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@oclif/test/-/test-2.5.6.tgz", + "integrity": "sha512-AcusFApdU6/akXaofhBDrY4IM9uYzlOD9bYCCM0NwUXOv1m6320hSp2DT/wkj9H1gsvKbJXZHqgtXsNGZTWLFg==", "dev": true, "dependencies": { - "ansis": "^3.2.0", - "debug": "^4.3.5" + "@oclif/core": "^2.15.0", + "fancy-test": "^2.0.42" }, "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@oclif/core": ">= 3.0.0" + "node": ">=12.0.0" } }, - "node_modules/@oclif/test/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "node_modules/@oclif/test/node_modules/@oclif/core": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/@oclif/core/-/core-2.16.0.tgz", + "integrity": "sha512-dL6atBH0zCZl1A1IXCKJgLPrM/wR7K+Wi401E/IvqsK8m2iCHW+0TEOGrans/cuN3oTW+uxIyJFHJ8Im0k4qBw==", "dev": true, "dependencies": { - "ms": "2.1.2" + "@types/cli-progress": "^3.11.0", + "ansi-escapes": "^4.3.2", + "ansi-styles": "^4.3.0", + "cardinal": "^2.1.1", + "chalk": "^4.1.2", + "clean-stack": "^3.0.1", + "cli-progress": "^3.12.0", + "debug": "^4.3.4", + "ejs": "^3.1.8", + "get-package-type": "^0.1.0", + "globby": "^11.1.0", + "hyperlinker": "^1.0.0", + "indent-string": "^4.0.0", + "is-wsl": "^2.2.0", + "js-yaml": "^3.14.1", + "natural-orderby": "^2.0.3", + "object-treeify": "^1.1.33", + "password-prompt": "^1.1.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "supports-color": "^8.1.1", + "supports-hyperlinks": "^2.2.0", + "ts-node": "^10.9.1", + "tslib": "^2.5.0", + "widest-line": "^3.1.0", + "wordwrap": "^1.0.0", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">=14.0.0" + } + }, + "node_modules/@oclif/test/node_modules/object-treeify": { + "version": "1.1.33", + "resolved": "https://registry.npmjs.org/object-treeify/-/object-treeify-1.1.33.tgz", + "integrity": "sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==", + "dev": true, + "engines": { + "node": ">= 10" } }, "node_modules/@octokit/auth-token": { @@ -2974,6 +3002,21 @@ "@types/node": "*" } }, + "node_modules/@types/sinon": { + "version": "17.0.3", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.3.tgz", + "integrity": "sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw==", + "dev": true, + "dependencies": { + "@types/sinonjs__fake-timers": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", + "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", + "dev": true + }, "node_modules/@types/tmp": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.6.tgz", @@ -6508,6 +6551,26 @@ "node": ">=0.6.0" } }, + "node_modules/fancy-test": { + "version": "2.0.42", + "resolved": "https://registry.npmjs.org/fancy-test/-/fancy-test-2.0.42.tgz", + "integrity": "sha512-TX8YTALYAmExny+f+G24MFxWry3Pk09+9uykwRjfwjibRxJ9ZjJzrnHYVBZK46XQdyli7d+rQc5U/KK7V6uLsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "dependencies": { + "@types/chai": "*", + "@types/lodash": "*", + "@types/node": "*", + "@types/sinon": "*", + "lodash": "^4.17.13", + "mock-stdin": "^1.0.0", + "nock": "^13.3.3", + "stdout-stderr": "^0.1.9" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -9004,6 +9067,12 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -9832,6 +9901,12 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "node_modules/mock-stdin": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mock-stdin/-/mock-stdin-1.0.0.tgz", + "integrity": "sha512-tukRdb9Beu27t6dN+XztSRHq9J0B/CoAOySGzHfn8UTfmqipA5yNT/sDUEyYdAV3Hpka6Wx6kOMxuObdOex60Q==", + "dev": true + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -9907,6 +9982,20 @@ "node": ">= 0.6" } }, + "node_modules/nock": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.4.tgz", + "integrity": "sha512-yAyTfdeNJGGBFxWdzSKCBYxs5FxLbCg5X5Q4ets974hcQzG1+qCxvIyOo4j2Ry6MUlhWVMX4OoYDefAIIwupjw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "propagate": "^2.0.0" + }, + "engines": { + "node": ">= 10.13" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -13953,6 +14042,15 @@ "react-is": "^16.13.1" } }, + "node_modules/propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -15683,6 +15781,19 @@ "node": ">= 0.8" } }, + "node_modules/stdout-stderr": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/stdout-stderr/-/stdout-stderr-0.1.13.tgz", + "integrity": "sha512-Xnt9/HHHYfjZ7NeQLvuQDyL1LnbsbddgMFKCuaQKwGCdJm8LnstZIXop+uOY36UR1UXXoHXfMbC1KlVdVd2JLA==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/stop-iteration-iterator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", diff --git a/package.json b/package.json index d870985..948e954 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "winston": "^3.11.0" }, "devDependencies": { - "@oclif/test": "^4.0.3", + "@oclif/test": "^2.5.6", "@types/adm-zip": "^0.5.5", "@types/chai": "^4.3.11", "@types/lodash": "^4.17.4", diff --git a/test/unit/commands/app/deploy.test.ts b/test/unit/commands/app/deploy.test.ts new file mode 100644 index 0000000..4e4637f --- /dev/null +++ b/test/unit/commands/app/deploy.test.ts @@ -0,0 +1,145 @@ +import { ux, cliux, configHandler } from "@contentstack/cli-utilities"; +import { expect, test } from "@oclif/test"; + +import * as mock from "../../mock/common.mock.json"; + +import messages, { $t } from "../../../../src/messages"; +import { getDeveloperHubUrl } from "../../../../src/util/inquirer"; +// import { join } from "path"; + +const region: { cma: string; cda: string; name: string } = + configHandler.get("region"); +const developerHubBaseUrl = getDeveloperHubUrl(); + +describe("app:deploy", () => { + describe("Deploy an app with custom hosting", () => { + test + .stdout({ print: process.env.PRINT === "true" || false }) + .stub(ux.action, "stop", () => {}) + .stub(ux.action, "start", () => {}) + .stub(cliux, "inquire", async (...args: any) => { + const [prompt]: any = args; + const cases = { + App: mock.apps[1].name, + Organization: mock.organizations[0].name, + "hosting types": "Custom Hosting", + appUrl: "https://example.com", + }; + return (cases as Record)[prompt.name]; + }) + .nock(region.cma, (api) => + api + .get("/v3/organizations?limit=100&asc=name&include_count=true&skip=0") + .reply(200, { organizations: mock.organizations }) + ) + .nock(`https://${developerHubBaseUrl}`, (api) => + api + .get("/manifests?limit=50&asc=name&include_count=true&skip=0") + .reply(200, { + data: mock.apps2, + }) + ) + .nock(`https://${developerHubBaseUrl}`, (api) => + api.put(`/manifests/${mock.apps2[1].uid}`).reply(200, mock.deploy_custom_host) + ) + .command(["app:deploy"]) + .do(({ stdout }) => { + expect(stdout).to.contain( + $t(messages.APP_DEPLOYED, { app: mock.apps[1].name }) + ); + }) + .it("should deploy the app with custom hosting"); + }); + + describe("Deploy an app with custom hosting using flags in command", () => { + test + .stdout({ print: process.env.PRINT === "true" || false }) + .stub(ux.action, "stop", () => {}) + .stub(ux.action, "start", () => {}) + .stub(cliux, "inquire", async (...args: any) => { + const [prompt]: any = args; + const cases = { + App: mock.apps[1].name, + Organization: mock.organizations[0].name, + "hosting types": "Custom Hosting", + appUrl: "https://example.com", + }; + return (cases as Record)[prompt.name]; + }) + .nock(region.cma, (api) => + api + .get("/v3/organizations?limit=100&asc=name&include_count=true&skip=0") + .reply(200, { organizations: mock.organizations }) + ) + .nock(`https://${developerHubBaseUrl}`, (api) => + api + .get(`/manifests/${mock.apps2[1].uid}`) + .reply(200, { + data: mock.apps2[1], + }) + ) + .nock(`https://${developerHubBaseUrl}`, (api) => + api.put(`/manifests/${mock.apps2[1].uid}`).reply(200, mock.deploy_custom_host) + ) + .command([ + "app:deploy", + "--org", + mock.organizations[0].uid, + "--app-uid", + mock.apps[1].uid, + "--hosting-type", + "Custom Hosting", + "--app-url", + "https://example.com", + ]) + .do(({ stdout }) => { + expect(stdout).to.contain( + $t(messages.APP_DEPLOYED, { app: mock.apps[1].name }) + ); + }) + .it("should deploy the app with custom hosting using flags in command"); + }); + + describe("Deploy an app with Hosting with Launch with existing project", () => { + test + .stdout({ print: process.env.PRINT === "true" || false }) + .stub(ux.action, "stop", () => {}) + .stub(ux.action, "start", () => {}) + .stub(cliux, "inquire", async (...args: any) => { + const [prompt]: any = args; + const cases = { + App: mock.apps2[1].name, + Organization: mock.organizations[0].name, + "hosting types": "Hosting with Launch", + "provider": "launch", + "selected_launch_project":"existing", + "deployment_url": "https://example.com", + "environment_uid": "environment_uid", + "project_uid": "project_uid", + }; + return (cases as Record)[prompt.name]; + }) + .nock(region.cma, (api) => + api + .get("/v3/organizations?limit=100&asc=name&include_count=true&skip=0") + .reply(200, { organizations: mock.organizations }) + ) + .nock(`https://${developerHubBaseUrl}`, (api) => + api + .get("/manifests?limit=50&asc=name&include_count=true&skip=0") + .reply(200, { + data: mock.apps2, + }) + ) + .nock(`https://${developerHubBaseUrl}`, (api) => + api.put(`/manifests/${mock.apps2[1].uid}`).reply(200, mock.deploy_launch_host) + ) + .command(["app:deploy"]) + .do(({ stdout }) => { + expect(stdout).to.contain( + $t(messages.APP_DEPLOYED, { app: mock.apps2[1].name }) + ); + }) + .it("should deploy the app with Hosting with Launch with existing project"); + }); +}); diff --git a/test/unit/mock/common.mock.json b/test/unit/mock/common.mock.json index 989d13e..8b22927 100644 --- a/test/unit/mock/common.mock.json +++ b/test/unit/mock/common.mock.json @@ -42,5 +42,113 @@ "uid": "test-installation-uid-2", "target": { "uid": "stack_api_key_2" } } + ], + "deploy_custom_host": { + "group": "user", + "framework_version": "1.0", + "version": 13, + "icon": "", + "description": "", + "hosting": { + "provider": "external", + "deployment_url": "https://example.com" + }, + "target_type": "stack", + "name": "App 1", + "ui_location": { + "signed": false, + "base_url": "https://example.com", + "locations": [] + }, + "visibility": "private", + "created_by": { + "uid": "uid", + "first_name": "first_name", + "last_name": "last_name" + }, + "updated_by": { + "uid": "uid", + "first_name": "first_name", + "last_name": "last_name" + }, + "organization_uid": "test-uid-1", + "created_at": "2024-05-28T11:20:12.405Z", + "updated_at": "2024-06-25T06:24:31.864Z", + "uid": "app-uid-1" + }, + "deploy_launch_host": { + "group": "user", + "framework_version": "1.0", + "version": 13, + "icon": "", + "description": "", + "hosting": { + "provider": "external", + "deployment_url": "https://example.com" + }, + "target_type": "stack", + "name": "App 1", + "ui_location": { + "signed": false, + "base_url": "https://example.com", + "locations": [] + }, + "visibility": "private", + "created_by": { + "uid": "uid", + "first_name": "first_name", + "last_name": "last_name" + }, + "updated_by": { + "uid": "uid", + "first_name": "first_name", + "last_name": "last_name" + }, + "organization_uid": "test-uid-1", + "created_at": "2024-05-28T11:20:12.405Z", + "updated_at": "2024-06-25T06:24:31.864Z", + "uid": "app-uid-1" + }, + "apps2": [ + { + "uid": "app-uid-1", + "name": "App 1", + "target_type": "organization" + }, + { + "uid": "app-uid-2", + "name": "App 2", + "group": "user", + "framework_version": "1.0", + "version": 24, + "icon": "", + "description": "", + "hosting": { + "provider": "launch", + "deployment_url": "https://example.com", + "environment_uid": "environment_uid", + "project_uid": "project_uid" + }, + "target_type": "stack", + "ui_location": { + "signed": false, + "base_url": "https://example.com", + "locations": [] + }, + "visibility": "private", + "created_by": { + "uid": "uid", + "first_name": "first_name", + "last_name": "last_name" + }, + "updated_by": { + "uid": "uid", + "first_name": "first_name", + "last_name": "last_name" + }, + "organization_uid": "test-uid-1", + "created_at": "2024-05-28T11:20:12.405Z", + "updated_at": "2024-06-25T10:50:52.071Z" + } ] }