Skip to content

Commit 95ff7cc

Browse files
Merge pull request #407 from contentstack/enhancement/DX-3409
added negative test cases and improved overall coverage
2 parents 208724f + 86cdf7b commit 95ff7cc

File tree

6 files changed

+502
-5
lines changed

6 files changed

+502
-5
lines changed

.github/workflows/unit-test.yml

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
name: Run Unit Tests
1+
name: Unit Test & Reports
22

33
on:
44
pull_request:
55
types: [opened, synchronize, reopened]
66

77
jobs:
8-
run-tests:
8+
build-test:
9+
name: Build & Test
910
runs-on: ubuntu-latest
1011
steps:
1112
- name: Checkout code
@@ -24,5 +25,18 @@ jobs:
2425
- name: Configure Region
2526
run: csdx config:set:region AWS-NA
2627

27-
- name: Run tests
28-
run: npm run test
28+
- name: Run tests with coverage
29+
run: npm run test:unit:report:json
30+
31+
- name: Test Report
32+
uses: dorny/test-reporter@v1
33+
if: success() || failure()
34+
with:
35+
name: Mocha Unit Test
36+
path: report.json
37+
reporter: mocha-json
38+
39+
- name: Coverage Report
40+
uses: lucassabreu/comment-coverage-clover@main
41+
with:
42+
file: coverage/clover.xml

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@
8484
"test": "mocha --forbid-only \"test/**/*.test.ts\"",
8585
"version": "oclif readme && git add README.md",
8686
"clean": "rm -rf ./lib tsconfig.tsbuildinfo oclif.manifest.json",
87-
"test:unit:report": "nyc --extension .ts mocha --forbid-only \"test/unit/**/*.test.ts\""
87+
"test:unit:report": "nyc --extension .ts mocha --forbid-only \"test/unit/**/*.test.ts\"",
88+
"test:unit:report:json": "mocha --reporter json --reporter-options output=report.json --forbid-only \"test/unit/**/*.test.ts\" && nyc --reporter=clover --extension .ts mocha --forbid-only \"test/unit/**/*.test.ts\""
8889
},
8990
"engines": {
9091
"node": ">=16"

test/unit/commands/app/create.test.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,4 +397,77 @@ describe("app:create", () => {
397397
expect(result.stdout).to.contain("App could not be registered");
398398
});
399399
});
400+
401+
describe("App creation with duplicate app name", () => {
402+
beforeEach(() => {
403+
nock(`https://${developerHubBaseUrl}`)
404+
.post("/manifests", (body) => {
405+
return body.name === "test-app" && body.target_type === "stack";
406+
})
407+
.reply(409, {
408+
errorMessage: "App with this name already exists.",
409+
});
410+
411+
sandbox.stub(cliux, "loader").callsFake(() => {});
412+
sandbox.stub(fs, "writeFileSync").callsFake(() => {});
413+
sandbox.stub(cliux, "inquire").callsFake((prompt: any) => {
414+
const cases: Record<string, any> = {
415+
appName: "test-app",
416+
cloneBoilerplate: true,
417+
Organization: "test org 1",
418+
};
419+
return Promise.resolve(cases[prompt.name]);
420+
});
421+
});
422+
423+
it("should fail when app name already exists", async () => {
424+
const result = await runCommand([
425+
"app:create",
426+
"--name",
427+
"test-app",
428+
"--data-dir",
429+
process.cwd(),
430+
]);
431+
expect(result.stdout).to.contain("already exists");
432+
});
433+
});
434+
435+
describe("App creation with organization UID instead of app UID", () => {
436+
beforeEach(() => {
437+
nock(region.cma)
438+
.get("/v3/organizations?limit=100&asc=name&include_count=true&skip=0")
439+
.reply(200, { organizations: mock.organizations });
440+
441+
nock(`https://${developerHubBaseUrl}`)
442+
.post("/manifests", (body) => {
443+
return body.name === "test-app" && body.target_type === "stack";
444+
})
445+
.reply(400, {
446+
errorMessage:
447+
"Invalid app configuration. Organization UID provided instead of app data.",
448+
});
449+
450+
sandbox.stub(cliux, "loader").callsFake(() => {});
451+
sandbox.stub(fs, "writeFileSync").callsFake(() => {});
452+
sandbox.stub(cliux, "inquire").callsFake((prompt: any) => {
453+
const cases: Record<string, any> = {
454+
appName: "test-app",
455+
cloneBoilerplate: true,
456+
Organization: "test org 1",
457+
};
458+
return Promise.resolve(cases[prompt.name]);
459+
});
460+
});
461+
462+
it("should fail when organization UID is used instead of app data", async () => {
463+
const result = await runCommand([
464+
"app:create",
465+
"--name",
466+
"test-app",
467+
"--data-dir",
468+
process.cwd(),
469+
]);
470+
expect(result.stdout).to.contain("App could not be registered");
471+
});
472+
});
400473
});

test/unit/commands/app/deploy.test.ts

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,110 @@ describe("app:deploy", () => {
149149
);
150150
});
151151
});
152+
153+
describe("Deploy app error handling", () => {
154+
it("should fail with invalid hosting type", async () => {
155+
sandbox.restore();
156+
sandbox = sinon.createSandbox();
157+
stubAuthentication(sandbox);
158+
159+
sandbox.stub(cliux, "loader").callsFake(() => {});
160+
sandbox.stub(cliux, "inquire").callsFake((prompt: any) => {
161+
const cases: Record<string, any> = {
162+
App: mock.apps[1].name,
163+
Organization: mock.organizations[0].name,
164+
"hosting types": "invalid-hosting",
165+
};
166+
return Promise.resolve(cases[prompt.name]);
167+
});
168+
169+
sandbox
170+
.stub(require("../../../../src/util/common-utils"), "getProjects")
171+
.resolves([]);
172+
sandbox
173+
.stub(require("../../../../src/util/common-utils"), "updateApp")
174+
.resolves();
175+
176+
nock(region.cma)
177+
.get(
178+
"/v3/organizations?limit=100&asc=name&asc=name&include_count=true&skip=0"
179+
)
180+
.reply(200, { organizations: mock.organizations });
181+
182+
nock(`https://${developerHubBaseUrl}`)
183+
.get("/manifests?limit=50&asc=name&include_count=true&skip=0")
184+
.reply(200, { data: mock.apps2 });
185+
186+
const { stdout } = await runCommand(["app:deploy"], {
187+
root: process.cwd(),
188+
});
189+
expect(stdout).to.contain("Please provide a valid Hosting Type.");
190+
});
191+
192+
it("should handle new project creation with hosting-with-launch", async () => {
193+
sandbox.restore();
194+
sandbox = sinon.createSandbox();
195+
stubAuthentication(sandbox);
196+
197+
sandbox.stub(cliux, "loader").callsFake(() => {});
198+
sandbox.stub(cliux, "inquire").callsFake((prompt: any) => {
199+
const cases: Record<string, any> = {
200+
App: mock.apps[1].name,
201+
Organization: mock.organizations[0].name,
202+
"hosting types": "hosting-with-launch",
203+
"launch project": "new",
204+
};
205+
return Promise.resolve(cases[prompt.name]);
206+
});
207+
208+
sandbox
209+
.stub(require("../../../../src/util/common-utils"), "getProjects")
210+
.resolves([
211+
{
212+
name: "new-project",
213+
uid: "project-2",
214+
url: "https://new-project.com",
215+
environmentUid: "env-2",
216+
},
217+
]);
218+
sandbox
219+
.stub(require("../../../../src/util/common-utils"), "setupConfig")
220+
.returns({
221+
name: "new-project",
222+
type: "react",
223+
environment: "production",
224+
framework: "nextjs",
225+
});
226+
sandbox
227+
.stub(
228+
require("../../../../src/util/common-utils"),
229+
"handleProjectNameConflict"
230+
)
231+
.resolves("new-project");
232+
sandbox
233+
.stub(require("@contentstack/cli-launch").Launch, "run")
234+
.resolves();
235+
236+
nock(region.cma)
237+
.get(
238+
"/v3/organizations?limit=100&asc=name&asc=name&include_count=true&skip=0"
239+
)
240+
.reply(200, { organizations: mock.organizations });
241+
242+
nock(`https://${developerHubBaseUrl}`)
243+
.get("/manifests?limit=50&asc=name&include_count=true&skip=0")
244+
.reply(200, { data: mock.apps2 });
245+
246+
nock(`https://${developerHubBaseUrl}`)
247+
.put(`/manifests/${mock.apps2[1].uid}`)
248+
.reply(200, mock.deploy_launch_host);
249+
250+
const { stdout } = await runCommand(["app:deploy"], {
251+
root: process.cwd(),
252+
});
253+
expect(stdout).to.contain(
254+
$t(messages.APP_DEPLOYED, { app: mock.apps[1].name })
255+
);
256+
});
257+
});
152258
});

0 commit comments

Comments
 (0)