Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix: Handle error when running init without npm (#9169)
Modify fetchPeerDependencies() function in npm-util to retun null if the
npm process exited with an ENOENT error.
Modify installSyncSaveDev() function in npm-util to log an error message  if the
npm process exited with an ENOENT error.
Write new tests for fetchPeerDependencies() and installSyncSaveDev() to
cover these scenarios.
Modify the sync stub in other installSyncSaveDev() tests to return an object
more similar to the child_process object specified in the node.js docs,
to avoid undefined field errors.
  • Loading branch information
GAumala authored and not-an-aardvark committed Aug 30, 2017
1 parent 4b94c6c commit af4ad60
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 7 deletions.
4 changes: 3 additions & 1 deletion lib/config/config-initializer.js
Expand Up @@ -65,6 +65,7 @@ function writeFile(config, format) {
* @param {string} moduleName The module name to get.
* @returns {Object} The peer dependencies of the given module.
* This object is the object of `peerDependencies` field of `package.json`.
* Returns null if npm was not found.
*/
function getPeerDependencies(moduleName) {
let result = getPeerDependencies.cache.get(moduleName);
Expand Down Expand Up @@ -356,7 +357,8 @@ function hasESLintVersionConflict(answers) {
// Get the required range of ESLint version.
const configName = getStyleGuideName(answers);
const moduleName = `eslint-config-${configName}@latest`;
const requiredESLintVersionRange = getPeerDependencies(moduleName).eslint;
const peerDependencies = getPeerDependencies(moduleName) || {};
const requiredESLintVersionRange = peerDependencies.eslint;

if (!requiredESLintVersionRange) {
return false;
Expand Down
25 changes: 21 additions & 4 deletions lib/util/npm-util.js
Expand Up @@ -53,22 +53,39 @@ function installSyncSaveDev(packages) {
if (!Array.isArray(packages)) {
packages = [packages];
}
spawn.sync("npm", ["i", "--save-dev"].concat(packages), { stdio: "inherit" });
const npmProcess = spawn.sync("npm", ["i", "--save-dev"].concat(packages),
{ stdio: "inherit" });
const error = npmProcess.error;

if (error && error.code === "ENOENT") {
const pluralS = packages.length > 1 ? "s" : "";

log.error(`Could not execute npm. Please install the following package${pluralS} with your package manager of choice: ${packages.join(", ")}`);
}
}

/**
* Fetch `peerDependencies` of the given package by `npm show` command.
* @param {string} packageName The package name to fetch peerDependencies.
* @returns {Object} Gotten peerDependencies.
* @returns {Object} Gotten peerDependencies. Returns null if npm was not found.
*/
function fetchPeerDependencies(packageName) {
const fetchedText = spawn.sync(
const npmProcess = spawn.sync(
"npm",
["show", "--json", packageName, "peerDependencies"],
{ encoding: "utf8" }
).stdout.trim();
);

const error = npmProcess.error;

if (error && error.code === "ENOENT") {
return null;
}
const fetchedText = npmProcess.stdout.trim();

return JSON.parse(fetchedText || "{}");


}

/**
Expand Down
26 changes: 24 additions & 2 deletions tests/lib/util/npm-util.js
Expand Up @@ -170,7 +170,7 @@ describe("npmUtil", () => {

describe("installSyncSaveDev()", () => {
it("should invoke npm to install a single desired package", () => {
const stub = sandbox.stub(spawn, "sync");
const stub = sandbox.stub(spawn, "sync").returns({ stdout: "" });

npmUtil.installSyncSaveDev("desired-package");
assert(stub.calledOnce);
Expand All @@ -180,14 +180,26 @@ describe("npmUtil", () => {
});

it("should accept an array of packages to install", () => {
const stub = sandbox.stub(spawn, "sync");
const stub = sandbox.stub(spawn, "sync").returns({ stdout: "" });

npmUtil.installSyncSaveDev(["first-package", "second-package"]);
assert(stub.calledOnce);
assert.equal(stub.firstCall.args[0], "npm");
assert.deepEqual(stub.firstCall.args[1], ["i", "--save-dev", "first-package", "second-package"]);
stub.restore();
});

it("should log an error message if npm throws ENOENT error", () => {
const logErrorStub = sandbox.stub(log, "error");
const npmUtilStub = sandbox.stub(spawn, "sync").returns({ error: { code: "ENOENT" } });

npmUtil.installSyncSaveDev("some-package");

assert(logErrorStub.calledOnce);

logErrorStub.restore();
npmUtilStub.restore();
});
});

describe("fetchPeerDependencies()", () => {
Expand All @@ -200,5 +212,15 @@ describe("npmUtil", () => {
assert.deepEqual(stub.firstCall.args[1], ["show", "--json", "desired-package", "peerDependencies"]);
stub.restore();
});

it("should return null if npm throws ENOENT error", () => {
const stub = sandbox.stub(spawn, "sync").returns({ error: { code: "ENOENT" } });

const peerDependencies = npmUtil.fetchPeerDependencies("desired-package");

assert.isNull(peerDependencies);

stub.restore();
});
});
});

0 comments on commit af4ad60

Please sign in to comment.