Skip to content

Commit 123206b

Browse files
authored
Merge pull request #4144 from NativeScript/kddimitrov/handle-plugin-create-fail
Kddimitrov/handle plugin create fail
2 parents 1afcdc3 + 57b1631 commit 123206b

File tree

2 files changed

+80
-8
lines changed

2 files changed

+80
-8
lines changed

lib/commands/plugin/create-plugin.ts

+16-7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export class CreatePluginCommand implements ICommand {
55
public allowedParameters: ICommandParameter[] = [];
66
public userMessage = "What is your GitHub username?\n(will be used to update the Github URLs in the plugin's package.json)";
77
public nameMessage = "What will be the name of your plugin?\n(use lowercase characters and dashes only)";
8+
public pathAlreadyExistsMessageTemplate = "Path already exists and is not empty %s";
89
constructor(private $options: IOptions,
910
private $errors: IErrors,
1011
private $terminalSpinnerService: ITerminalSpinnerService,
@@ -22,8 +23,17 @@ export class CreatePluginCommand implements ICommand {
2223
const selectedPath = path.resolve(pathToProject || ".");
2324
const projectDir = path.join(selectedPath, pluginRepoName);
2425

25-
await this.downloadPackage(selectedTemplate, projectDir);
26-
await this.setupSeed(projectDir, pluginRepoName);
26+
// Must be out of try catch block, because will throw error if folder alredy exists and we don't want to delete it.
27+
this.ensurePackageDir(projectDir);
28+
29+
try {
30+
await this.downloadPackage(selectedTemplate, projectDir);
31+
await this.setupSeed(projectDir, pluginRepoName);
32+
} catch (err) {
33+
// The call to this.ensurePackageDir() above will throw error if folder alredy exists, so it is safe to delete here.
34+
this.$fs.deleteDirectory(projectDir);
35+
throw err;
36+
}
2737

2838
this.$logger.printMarkdown("Solution for `%s` was successfully created.", pluginRepoName);
2939
}
@@ -66,13 +76,15 @@ export class CreatePluginCommand implements ICommand {
6676
}
6777
}
6878

69-
private async downloadPackage(selectedTemplate: string, projectDir: string): Promise<void> {
79+
private ensurePackageDir(projectDir: string): void {
7080
this.$fs.createDirectory(projectDir);
7181

7282
if (this.$fs.exists(projectDir) && !this.$fs.isEmptyDir(projectDir)) {
73-
this.$errors.fail("Path already exists and is not empty %s", projectDir);
83+
this.$errors.fail(this.pathAlreadyExistsMessageTemplate, projectDir);
7484
}
85+
}
7586

87+
private async downloadPackage(selectedTemplate: string, projectDir: string): Promise<void> {
7688
if (selectedTemplate) {
7789
this.$logger.printMarkdown("Make sure your custom template is compatible with the Plugin Seed at https://github.com/NativeScript/nativescript-plugin-seed/");
7890
} else {
@@ -84,9 +96,6 @@ export class CreatePluginCommand implements ICommand {
8496
try {
8597
spinner.start();
8698
await this.$pacoteService.extractPackage(packageToInstall, projectDir);
87-
} catch (err) {
88-
this.$fs.deleteDirectory(projectDir);
89-
throw err;
9099
} finally {
91100
spinner.stop();
92101
}

test/plugin-create.ts

+64-1
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,20 @@ import * as stubs from "./stubs";
33
import { CreatePluginCommand } from "../lib/commands/plugin/create-plugin";
44
import { assert } from "chai";
55
import helpers = require("../lib/common/helpers");
6+
import * as sinon from "sinon";
7+
import temp = require("temp");
8+
import * as path from "path";
9+
import * as util from "util";
10+
temp.track();
611

712
interface IPacoteOutput {
813
packageName: string;
914
destinationDirectory: string;
1015
}
1116

1217
const originalIsInteractive = helpers.isInteractive;
13-
const dummyArgs = ["dummyProjectName"];
18+
const dummyProjectName = "dummyProjectName";
19+
const dummyArgs = [dummyProjectName];
1420
const dummyUser = "devUsername";
1521
const dummyName = "devPlugin";
1622
const dummyPacote: IPacoteOutput = { packageName: "", destinationDirectory: "" };
@@ -142,5 +148,62 @@ describe("Plugin create command tests", () => {
142148
options.pluginName = dummyName;
143149
await createPluginCommand.execute(dummyArgs);
144150
});
151+
152+
describe("when fails", () => {
153+
let sandbox: sinon.SinonSandbox;
154+
let fsSpy: sinon.SinonSpy;
155+
let projectPath: string;
156+
157+
beforeEach(() => {
158+
sandbox = sinon.sandbox.create();
159+
const workingPath = temp.mkdirSync("test_plugin");
160+
options.path = workingPath;
161+
projectPath = path.join(workingPath, dummyProjectName);
162+
const fsService = testInjector.resolve("fs");
163+
fsSpy = sandbox.spy(fsService, "deleteDirectory");
164+
});
165+
166+
afterEach(() => {
167+
sandbox.restore();
168+
});
169+
170+
it("downloadPackage, should remove projectDir", async () => {
171+
const errorMessage = "Test fail";
172+
const pacoteService = testInjector.resolve("pacoteService");
173+
sandbox.stub(pacoteService, "extractPackage").callsFake(() => {
174+
return Promise.reject(new Error(errorMessage));
175+
});
176+
177+
const executePromise = createPluginCommand.execute(dummyArgs);
178+
179+
await assert.isRejected(executePromise, errorMessage);
180+
assert(fsSpy.calledWith(projectPath));
181+
});
182+
183+
it("setupSeed, should remove projectDir", async () => {
184+
const errorMessage = "Test fail";
185+
const npmService = testInjector.resolve("npm");
186+
sandbox.stub(npmService, "install").callsFake(() => {
187+
return Promise.reject(new Error(errorMessage));
188+
});
189+
190+
const executePromise = createPluginCommand.execute(dummyArgs);
191+
192+
await assert.isRejected(executePromise, errorMessage);
193+
assert(fsSpy.calledWith(projectPath));
194+
});
195+
196+
it("ensurePachageDir should not remove projectDir", async () => {
197+
const fsService = testInjector.resolve("fs");
198+
sandbox.stub(fsService, "isEmptyDir").callsFake(() => {
199+
return false;
200+
});
201+
202+
const executePromise = createPluginCommand.execute(dummyArgs);
203+
204+
await assert.isRejected(executePromise, util.format(createPluginCommand.pathAlreadyExistsMessageTemplate, projectPath));
205+
assert(fsSpy.notCalled);
206+
});
207+
});
145208
});
146209
});

0 commit comments

Comments
 (0)