Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

less-cluster

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

less-cluster - npm Package Compare versions

Comparing version 0.4.6 to 0.4.7

.travis.yml

2

lib/cli.js

@@ -151,3 +151,3 @@ /**

// resolve onto directory
parsed._files = remain.map(function (file) {
parsed.files = remain.map(function (file) {
return path.resolve(parsed.directory, file);

@@ -154,0 +154,0 @@ });

@@ -6,3 +6,3 @@ /**

var fs = require('fs');
var fs = require('graceful-fs');
var glob = require('glob');

@@ -45,3 +45,3 @@ var path = require('path');

this._children = {};
this._fileData = {};
this._fileCache = {};
}

@@ -76,6 +76,9 @@

@method run
@chainable
**/
LessCluster.prototype.run = function () {
this.worker = require('./less-worker')(this.options);
this.worker = require('./less-worker')(this.options, this._fileCache);
this._attachEvents();
return this;
};

@@ -153,6 +156,3 @@

if (worker && fileName) {
worker.build({
dest: this._getDestinationPath(fileName),
file: fileName
});
worker.build(fileName, this._getDestinationPath(fileName));
}

@@ -167,14 +167,2 @@ };

/**
Convert absolute dirpath into relative fragment
@method _getRelativePath
@param {String} dir
@return {String}
@private
**/
LessCluster.prototype._getRelativePath = function (dir) {
return path.relative(process.cwd(), dir);
};
/**
Create pattern for glob

@@ -188,3 +176,2 @@

LessCluster.prototype._getGlobPattern = function (dir) {
// return path.join(this._getRelativePath(dir), this.options.match);
return path.join(dir, this.options.match);

@@ -239,10 +226,18 @@ };

fileList.on('error', function (err) {
fileList.on("abort", handleAbort);
fileList.on("error", handleError);
fileList.on("end", handleEnd);
function handleError(err) {
fileList.abort();
throw err;
});
cb(err);
}
fileList.on('end', function (matches) {
function handleEnd(matches) {
readFiles(matches, cb);
});
}
function handleAbort() {
fileList.removeListener("end", handleEnd);
}
};

@@ -332,6 +327,6 @@

var filesToRead = Object.keys(data);
var filesToProcess = this.options._files;
var filesToProcess = this.options.files;
// add data to cache
utils.mix(this._fileData, data);
utils.mix(this._fileCache, data);

@@ -377,3 +372,3 @@ // but only operate on added data, not entire cache

var imports = [];
var fileContents = this._fileData[fileName];
var fileContents = this._fileCache[fileName];
var rx = LessCluster.RX_IMPORT;

@@ -380,0 +375,0 @@

@@ -5,3 +5,3 @@ /**

var fs = require('fs');
var fs = require('graceful-fs');
var path = require('path');

@@ -15,3 +15,2 @@ var less = require('less');

var utils = require('./utils');
var readFiles = require('./read-files');
var Logger = require('./logger');

@@ -31,4 +30,5 @@

@param {Object} [options]
@param {Object} [fileCache] Hash of file contents, stored by reference, keyed on filename.
**/
function LessWorker(options) {
function LessWorker(options, fileCache) {
// factory constructor

@@ -43,3 +43,3 @@ if (!(this instanceof LessWorker)) {

this._fileData = {};
this._fileCache = fileCache || {};
this._pathCache = {};

@@ -60,4 +60,5 @@ this._pathRebase = {};

LessWorker.prototype.destroy = function () {
this._fileData = this._pathCache = this._pathRebase = null;
this._fileCache = this._pathCache = this._pathRebase = null;
less.Parser.importer = LessWorker._originalLessImporter;
this.emit('cleanup');
this.removeAllListeners();

@@ -71,3 +72,3 @@ };

LessWorker.prototype._bindImporter = function () {
// override static importer method to utilize _fileData cache
// override static importer method to utilize _fileCache
less.Parser.importer = this._importer.bind(this);

@@ -129,6 +130,4 @@ };

LessWorker.prototype.build = function (msg) {
var file = msg.file,
dest = msg.dest,
data = this._fileData[file],
LessWorker.prototype._build = function (file, dest) {
var data = this._fileCache[file],
parser = this._createParser(file, dest);

@@ -142,2 +141,6 @@

LessWorker.prototype.build = function (file, dest) {
this._build(file, dest);
};
LessWorker.prototype._createParseEnv = function (fileName, destFileName) {

@@ -160,3 +163,3 @@ // copy options to avoid munging between executions

// copying over cached data avoids repetitious disk seeks
options.contents = this._fileData;
options.contents = this._fileCache;

@@ -173,3 +176,3 @@ return new less.tree.parseEnv(options);

// Actually support --include-path args...
LessWorker.prototype._getChildPath = function (file, parentFilePath, envPaths) {
LessWorker.prototype.resolveChildPath = function (file, parentFilePath, envPaths) {
var i, len, importPaths,

@@ -237,3 +240,3 @@ childPath = this._pathCache[file];

// resolve child filename against parent filepath
childPath = this._getChildPath(file, parentFileInfo.filename, parentEnv.paths),
childPath = this.resolveChildPath(file, parentFileInfo.filename, parentEnv.paths),

@@ -244,3 +247,3 @@ // derive child dirname for currentDirectory

// retrieve cached file contents from instance hash
childData = this._fileData[childPath];
childData = this._fileCache[childPath];

@@ -279,22 +282,1 @@ // only the top importing parser visits imports

};
LessWorker.prototype._readFinished = function (err, data) {
if (err) {
this.emit('error', err);
return;
}
this.debug(this._logPrefix, 'finished reading');
// add data to cache
utils.mix(this._fileData, data);
// tell our master that we are ready
this.emit('ready');
};
LessWorker.prototype.start = function (msg) {
this.debug(this._logPrefix, 'started');
readFiles(msg.data, this._readFinished.bind(this));
};

@@ -5,3 +5,3 @@ /**

var fs = require('fs');
var fs = require('graceful-fs');

@@ -8,0 +8,0 @@ module.exports = readFiles;

@@ -7,2 +7,3 @@ /**

var LessWorker = require('./less-worker');
var utils = require('./utils');

@@ -36,4 +37,7 @@ module.exports = Worker;

Worker.readFiles = require('./read-files');
Worker.prototype._attachEvents = function () {
process.on('message', this.dispatchMessage.bind(this));
var boundDispatchMessage = this.dispatchMessage.bind(this);
process.on('message', boundDispatchMessage);

@@ -43,2 +47,6 @@ this.on('drain', function () { this.sendMaster('drain'); });

this.on('ready', function () { this.sendMaster('ready'); });
this.once('cleanup', function () {
process.removeListener('message', boundDispatchMessage);
});
};

@@ -68,2 +76,27 @@

Worker.prototype.build = function (msg) {
this._build(msg.file, msg.dest);
};
Worker.prototype._readFinished = function (err, data) {
if (err) {
this.emit('error', err);
return;
}
this.debug(this._logPrefix, 'finished reading');
// add data to cache
utils.mix(this._fileCache, data);
// tell our master that we are ready
this.emit('ready');
};
Worker.prototype.start = function (msg) {
this.debug(this._logPrefix, 'started');
Worker.readFiles(msg.data, this._readFinished.bind(this));
};
if (cluster.isWorker) {

@@ -70,0 +103,0 @@ /*jshint newcap: false */

{
"name": "less-cluster",
"version": "0.4.6",
"version": "0.4.7",
"description": "Parallel, directory-based execution of lessc.",

@@ -22,4 +22,4 @@ "main": "index.js",

"pretest": "jshint bin lib test",
"test": "istanbul test --print both ./node_modules/mocha/bin/_mocha",
"posttest": "istanbul check-coverage --statements 60 --functions 50 --branches 50 --lines 60"
"test": "istanbul cover --print both ./node_modules/mocha/bin/_mocha",
"posttest": "istanbul check-coverage --statements 90 --functions 90 --branches 90 --lines 90"
},

@@ -40,6 +40,7 @@ "repository": {

"devDependencies": {
"chai": "~1.8.0",
"istanbul": "~0.1.44",
"chai": "~1.8.1",
"istanbul": "~0.1.46",
"jshint": "~2.3.0",
"mocha": "~1.14.0",
"mocha": "~1.15.1",
"rimraf": "~2.2.4",
"sinon": "~1.7.3",

@@ -49,4 +50,5 @@ "sinon-chai": "~2.4.0"

"dependencies": {
"nopt": "~2.1.1",
"glob": "~3.2.1",
"nopt": "~2.1.2",
"glob": "~3.2.7",
"graceful-fs": "~2.0.1",
"less": "git://github.com/evocateur/less.js.git#normalize-urls",

@@ -53,0 +55,0 @@ "mkdirp": "~0.3.5"

# less-cluster
A utility to make lessc's CLI more performant for large directories of LESS files.
A utility to make [lessc](https://github.com/less/less.js)'s CLI more performant for large directories of LESS files.
[![Build Status](https://travis-ci.org/zillow/less-cluster.png)](https://travis-ci.org/zillow/less-cluster)
## Install

@@ -6,0 +8,0 @@

@@ -497,10 +497,10 @@ /*global describe, it, before, beforeEach, after, afterEach, chai, should, sinon */

it("should populate files array", function () {
topic._files.should.be.an('array');
topic.files.should.be.an('array');
});
it("with two members", function () {
topic._files.should.have.length(files.length);
topic.files.should.have.length(files.length);
});
it("resolved to directory", function () {
files.forEach(function (file, i) {
topic._files[i].should.equal(path.resolve(topic.directory, file));
topic.files[i].should.equal(path.resolve(topic.directory, file));
});

@@ -507,0 +507,0 @@ });

@@ -5,2 +5,3 @@ /*global describe, it, before, beforeEach, after, afterEach, chai, should, sinon */

**/
var fs = require('fs');
var path = require('path');

@@ -97,6 +98,45 @@

instance.should.have.ownProperty('_children', {});
instance.should.have.ownProperty('_fileData', {});
instance.should.have.ownProperty('_fileCache', {});
});
});
describe("run()", function () {
beforeEach(function () {
this.instance = new LessCluster().run();
});
afterEach(function () {
this.instance = null;
});
it("should instantiate a worker", function () {
this.instance.should.have.ownProperty("worker");
});
it("should hook worker events", function () {
this.instance.worker.listeners("drain").should.have.length(1);
});
});
describe("destroy()", function () {
beforeEach(function () {
this.instance = new LessCluster().run();
sinon.stub(this.instance, "removeAllListeners");
sinon.stub(this.instance.worker, "destroy");
this.instance.destroy();
});
afterEach(function () {
this.instance = null;
});
it("should unhook all events", function () {
this.instance.removeAllListeners.should.have.been.calledOnce;
});
it("should destroy worker", function () {
this.instance.worker.destroy.should.have.been.calledOnce;
});
});
describe("getNextFile()", function () {

@@ -129,2 +169,59 @@ beforeEach(function () {

describe("onDrain()", function () {
beforeEach(function () {
this.instance = new LessCluster();
sinon.stub(this.instance, "getNextFile");
});
afterEach(function () {
this.instance = null;
});
it("should pass next available file to buildFile()", function () {
sinon.stub(this.instance, "buildFile");
this.instance.getNextFile.returns("foo.less");
this.instance.onDrain();
this.instance.buildFile.should.have.been.calledWith("foo.less");
});
it("should emit 'finished' event when queue empty", function () {
sinon.stub(this.instance, "emit");
this.instance.getNextFile.returns();
this.instance.onDrain();
this.instance.emit.should.have.been.calledWith("finished");
});
});
describe("buildFile()", function () {
beforeEach(function () {
this.instance = new LessCluster().run();
sinon.stub(this.instance.worker, "build");
});
afterEach(function () {
this.instance.destroy();
this.instance = null;
});
it("should not error when worker missing", function () {
should.not.Throw(function () {
new LessCluster().buildFile("foo.less");
});
});
it("should not call worker.build() when fileName missing", function () {
this.instance.buildFile();
this.instance.worker.build.should.not.have.been.called;
});
it("should call worker.build() with correct options", function () {
var fileName = addImportsDir("base.less");
this.instance.buildFile(fileName);
this.instance.worker.build.should.have.been.calledWith(fileName, addImportsDir("base.css"));
});
});
describe("collect()", function () {

@@ -138,13 +235,2 @@ var instance;

it("_getDestinationPath()", function () {
var actually = instance._getDestinationPath(addImportsDir('base.less'));
var expected = addImportsDir('base.css');
actually.should.equal(expected);
});
it("_getRelativePath()", function () {
var actually = instance._getRelativePath(__dirname + '/fixtures');
var expected = 'test/fixtures';
actually.should.equal(expected);
});
it("_getGlobPattern()", function () {

@@ -184,3 +270,3 @@ var actually = instance._getGlobPattern('foo');

it("finds all files successfully", function () {
cb.data.should.have.keys([
cb.data.should.include.keys([
addImportsDir("_variables.less"),

@@ -197,2 +283,43 @@ addImportsDir("base.less"),

});
describe("variations", function () {
beforeEach(function () {
this.instance = new LessCluster({
"directory": importsDir
});
});
afterEach(function () {
this.instance = null;
});
it("should allow callback only", function (done) {
this.instance.collect(done);
});
it("should allow accept directory override", function (done) {
this.instance.collect(includeDir, function (err, data) {
should.exist(data);
data.should.have.property(path.join(includeDir, "a.less"));
data.should.have.property(path.join(includeDir, "b.less"));
done();
});
});
it("should allow call with no arguments", function (done) {
sinon.stub(this.instance, "_finishCollect", done);
this.instance.collect();
});
it("should abort glob if error emitted", function (done) {
sinon.stub(fs, "readdir");
// yieldsAsync() necessary to pass through internal process.nextTick
fs.readdir.yieldsAsync({ code: "WTF" });
this.instance.collect(function (err) {
fs.readdir.restore();
done();
});
});
});
});

@@ -206,2 +333,3 @@

"included/a.less",
"included/b.less",
"modules/child.less",

@@ -224,2 +352,3 @@ "modules/parent.less",

"included/a.less",
"included/b.less",
"modules/child.less",

@@ -238,2 +367,3 @@ "modules/parent.less",

"included/a.less",
"included/b.less",
"modules/child.less",

@@ -257,3 +387,2 @@ "modules/parent.less",

// "base.less",
// "included/a.less",
"modules/child.less",

@@ -316,10 +445,9 @@ "modules/parent.less",

var absolutized = expected.map(addImportsDir);
actually.should.eql(absolutized);
actually.should.include.members(absolutized);
});
expected.forEach(function (relativePath, i) {
expected.forEach(function (relativePath) {
it(relativePath, function () {
var actually = results[subtitle];
should.exist(actually[i]);
actually[i].should.equal(addImportsDir(relativePath));
actually.should.include(addImportsDir(relativePath));
});

@@ -344,3 +472,3 @@ });

if (relativePaths && relativePaths.length) {
instanceConfig._files = relativePaths.map(function (p) {
instanceConfig.files = relativePaths.map(function (p) {
return path.join(importsDir, p);

@@ -347,0 +475,0 @@ });

@@ -5,2 +5,6 @@ /*global describe, it, before, beforeEach, after, afterEach, chai, should, sinon */

**/
var fs = require('graceful-fs');
var path = require('path');
var less = require('less');
var rimraf = require('rimraf');
var LessWorker = require('../lib/less-worker');

@@ -19,2 +23,3 @@

});
describe("instance", function () {

@@ -26,29 +31,376 @@ var instance = new LessWorker();

});
it("should set _fileData property to an empty object", function () {
instance.should.have.property('_fileData')
.that.is.an('object')
.that.deep.equals({});
it("should create private caches as empty objects", function () {
instance.should.have.property('_fileCache').that.deep.equals({});
instance.should.have.property('_pathCache').that.deep.equals({});
instance.should.have.property('_pathRebase').that.deep.equals({});
});
it("should default options when missing", function () {
instance.options.should.deep.equal(LessWorker.defaults);
});
describe("destroy()", function () {
before(function () {
sinon.spy(instance, "emit");
sinon.spy(instance, "removeAllListeners");
instance.destroy();
});
it("should nullify private caches", function () {
instance.should.have.property('_fileCache').that.is.null;
instance.should.have.property('_pathCache').that.is.null;
instance.should.have.property('_pathRebase').that.is.null;
});
it("should emit 'cleanup' event", function () {
instance.emit.should.have.been.calledWith("cleanup");
});
it("should remove all listeners", function () {
instance.removeAllListeners.should.have.been.calledOnce;
});
it("should restore original less.Parser.importer");
// this is hard to assert that it actually happened...
});
describe("with options", function () {
var fileDataCache = {
"foo.less": "foo"
};
before(function () {
this.instance = new LessWorker({
lint: true
}, fileDataCache);
});
after(function () {
this.instance.destroy();
});
it("should override defaults when passed", function () {
this.instance.options.should.have.property('lint').that.is.true;
});
it("should update cache when fileData passed", function () {
this.instance.should.have.property("_fileCache").that.equals(fileDataCache);
// the object stored in _fileCache is literally the same object passed in
fileDataCache.bar = "bar";
this.instance._fileCache.should.equal(fileDataCache);
});
});
});
describe("methods", function () {
describe("_applyConfig()", function () {
var defaults = LessWorker.defaults;
var instance = new LessWorker();
it("defaults values when missing", function () {
instance._applyConfig();
instance.options.should.deep.equal(defaults);
describe("method", function () {
var fileName = "a.less";
var filePath = path.resolve(__dirname, "fixtures/imports/included", fileName);
var fileData = "foo"; // file is actually empty, but we never actually read it
var childImportName = "modules/parent.less";
var childImportPath = path.resolve(__dirname, "fixtures/imports", childImportName);
var parentFilePath = path.resolve(__dirname, "fixtures/imports/base.less");
var ohNoesError = "oh noes!";
var outputdir = path.resolve(__dirname, "output");
// simulating --include-path arguments
var envPaths = [path.dirname(filePath)];
beforeEach(function () {
this.instance = new LessWorker({
outputdir: outputdir
});
});
afterEach(function () {
this.instance.destroy();
this.instance = null;
});
it("overrides defaults when passed", function () {
instance._applyConfig({
'lint': true
describe("doneWrote()", function () {
beforeEach(function () {
sinon.stub(this.instance, "emit");
sinon.stub(this.instance, "log");
});
afterEach(function () {
this.instance.emit.restore();
this.instance.log.restore();
});
it("should emit an error if present", function () {
this.instance.doneWrote(filePath, ohNoesError);
this.instance.emit.should.have.been.calledWith("error", ohNoesError);
});
it("should emit drain when successful", function () {
this.instance.doneWrote(filePath);
this.instance.log.should.have.been.calledOnce;
this.instance.emit.should.have.been.calledWith("drain", filePath);
});
});
describe("inDir()", function () {
beforeEach(function () {
sinon.stub(this.instance, "emit");
sinon.stub(this.instance, "doneWrote");
sinon.stub(fs, "writeFile");
});
afterEach(function () {
this.instance.emit.restore();
this.instance.doneWrote.restore();
fs.writeFile.restore();
});
it("should emit an error if present", function () {
this.instance.inDir(filePath, fileData, ohNoesError);
this.instance.emit.should.have.been.calledWith("error", ohNoesError);
fs.writeFile.should.not.have.been.called;
});
it("should write data into filename", function () {
fs.writeFile.yields();
this.instance.inDir(filePath, fileData, null);
this.instance.doneWrote.should.have.been.calledOnce;
fs.writeFile.should.have.been.calledWith(filePath, fileData, "utf8", sinon.match.func);
});
});
describe("writeOutput()", function () {
beforeEach(function () {
sinon.stub(this.instance, "emit");
sinon.stub(this.instance, "warn");
sinon.stub(this.instance, "inDir");
// mkdirp calls fs.mkdir under the covers
sinon.stub(fs, "mkdir");
});
afterEach(function () {
this.instance.emit.restore();
this.instance.warn.restore();
this.instance.inDir.restore();
fs.mkdir.restore();
});
it("should skip writing if data empty, draining immediately", function () {
this.instance.writeOutput(filePath, "");
this.instance.warn.should.have.been.calledOnce;
this.instance.emit.should.have.been.calledWith("drain", filePath);
this.instance.inDir.should.not.have.been.called;
fs.mkdir.should.not.have.been.called;
});
it("should ensure directory exists before writing", function () {
fs.mkdir.yields(null); // success
this.instance.writeOutput(filePath, fileData);
fs.mkdir.should.have.been.calledWith(path.dirname(filePath));
this.instance.inDir.should.have.been.calledWith(filePath, fileData, null);
});
});
describe("resolveChildPath()", function () {
beforeEach(function () {
sinon.stub(fs, "existsSync");
});
afterEach(function () {
fs.existsSync.restore();
});
describe("when cache is hot", function () {
beforeEach(function () {
this.instance._pathCache[fileName] = filePath;
});
instance.options.should.have.property('lint').that.is.true;
it("should early return cached childPath", function () {
var result = this.instance.resolveChildPath(fileName, parentFilePath, []);
fs.existsSync.should.not.have.been.called;
result.should.equal(filePath);
});
});
describe("when cache is cold", function () {
beforeEach(function () {
fs.existsSync.withArgs(filePath).returns(true);
fs.existsSync.withArgs(childImportPath).returns(true);
});
it("should cache a successful lookup", function () {
this.instance
.resolveChildPath(childImportName, parentFilePath, envPaths)
.should.equal(childImportPath);
fs.existsSync.should.have.been.calledOnce;
this.instance._pathCache.should.have.property(childImportName, childImportPath);
});
it("should loop over all include paths when locating child", function () {
this.instance
.resolveChildPath(fileName, parentFilePath, envPaths)
.should.equal(filePath);
fs.existsSync.should.have.been.calledTwice;
});
it("should indicate if the resolved path has been rebased", function () {
this.instance.resolveChildPath(childImportName, parentFilePath, envPaths);
this.instance.resolveChildPath(fileName, parentFilePath, envPaths);
fs.existsSync.should.have.been.calledThrice;
this.instance._pathRebase.should.have.property(childImportName, false);
this.instance._pathRebase.should.have.property(fileName, true);
});
it("should throw error when lookup fails?");
});
});
describe("rebaseRootPath()", function () {
describe("when staying inside parent directory", function () {
it("should not rebase sibling rootpath", function () {
var childFileInfo = {
"currentDirectory" : __dirname + "/fixtures/imports/",
"entryPath" : __dirname + "/fixtures/imports/",
"filename" : __dirname + "/fixtures/imports/external.css",
"rootFilename" : __dirname + "/fixtures/imports/base.less",
"rootpath" : ""
};
this.instance.rebaseRootPath("external.css", parentFilePath, childFileInfo);
childFileInfo.rootpath.should.equal("");
});
it("should rebase relative from root file source path", function () {
var childFileInfo = {
"currentDirectory" : __dirname + "/fixtures/imports/modules/",
"entryPath" : __dirname + "/fixtures/imports/",
"filename" : __dirname + "/fixtures/imports/modules/parent.less",
"rootFilename" : __dirname + "/fixtures/imports/base.less",
"rootpath" : ""
};
this.instance.rebaseRootPath(childImportName, parentFilePath, childFileInfo);
childFileInfo.rootpath.should.equal("modules/");
});
});
describe("when traversing outside parent directory", function () {
beforeEach(function () {
this.instance._pathRebase[fileName] = true;
});
it("should rebase relative from destination path", function () {
var childFileInfo = {
"currentDirectory" : __dirname + "/fixtures/imports/included/",
"filename" : __dirname + "/fixtures/imports/included/a.less",
"entryPath" : __dirname + "/fixtures/imports/",
"rootFilename" : __dirname + "/fixtures/imports/base.less",
"destPath" : __dirname + "/fixtures/output",
"rootpath" : ""
};
this.instance.rebaseRootPath(fileName, parentFilePath, childFileInfo);
childFileInfo.rootpath.should.equal("../imports/included/");
});
});
});
describe("build()", function () {
it("TODO");
var expectedFilePath = path.resolve(__dirname, "fixtures", "output", "base.css");
var compiledFilePath = path.resolve(outputdir, "base.css");
before(function (done) {
// read file contents into context variables
var test = this;
rimraf(outputdir, function () {
fs.readFile(expectedFilePath, "utf8", function (err, data) {
test.expectedContent = data;
fs.readFile(parentFilePath, "utf8", function (err, data) {
test.parentContent = data;
done();
});
});
});
});
beforeEach(function () {
// populate instance file cache
this.instance._fileCache = {};
this.instance._fileCache[parentFilePath] = this.parentContent;
});
it("should pass arguments directly to utility method", function () {
sinon.stub(this.instance, "_build");
this.instance.build("foo.less", "foo.css");
this.instance._build.should.be.calledWith("foo.less", "foo.css");
});
describe("failure", function () {
beforeEach(function () {
sinon.stub(less, "writeError");
sinon.stub(console, "error");
});
afterEach(function () {
less.writeError.restore();
console.error.restore();
});
it("should emit error when imported file not found", function (done) {
this.instance.once("error", function (err) {
should.exist(err);
err.should.have.property("type", "Syntax");
err.should.have.property("message", "File not found: undefined");
less.writeError.should.have.been.calledWith(err, this.options);
done();
});
this.instance.build(parentFilePath, compiledFilePath);
});
it("should emit error when tree.toCSS fails", function (done) {
// provide correct import paths
this.instance.options.paths = envPaths;
// we can't effectively mock tree.toCSS, so let's pretend
sinon.stub(this.instance, "writeOutput").throws({ type: "Fake" });
this.instance.once("error", function (err) {
should.exist(err);
err.should.have.property("type", "Fake");
done();
});
this.instance.build(parentFilePath, compiledFilePath);
});
});
describe("success", function () {
beforeEach(function () {
// provide correct import paths
this.instance.options.paths = envPaths;
});
it("should match compiled output", function (done) {
var test = this;
sinon.stub(console, "log");
this.instance.once("error", done);
this.instance.once("drain", function (fileName) {
should.exist(fileName);
fileName.should.equal(compiledFilePath);
fs.readFile(fileName, "utf8", function (err, data) {
should.exist(data);
data.should.equal(test.expectedContent);
console.log.should.have.been.calledWith("compiled test/output/base.css");
console.log.restore();
done();
});
});
this.instance.build(parentFilePath, compiledFilePath);
});
});
});
});
});

@@ -149,3 +149,3 @@ /*global describe, it, before, beforeEach, after, afterEach, chai, should, sinon */

afterEach(function () {
cluster.workers = null;
cluster.workers = {};
});

@@ -197,3 +197,3 @@

cluster.workers = null;
cluster.workers = {};
});

@@ -261,3 +261,3 @@ });

afterEach(function () {
cluster.workers = null;
cluster.workers = {};
});

@@ -264,0 +264,0 @@

@@ -57,2 +57,3 @@ /*global describe, it, before, beforeEach, after, afterEach, chai, should, sinon */

});
it("should pass lifecycle events through to sendMaster", function () {

@@ -73,2 +74,16 @@ var consoleError = sinon.stub(console, "error");

});
describe("when destroyed", function () {
before(function () {
sinon.spy(process, "removeListener");
instance.destroy();
});
after(function () {
process.removeListener.restore();
});
it("should remove process.message listener", function () {
process.removeListener.should.have.been.calledWith("message", sinon.match.func);
});
});
});

@@ -100,5 +115,9 @@

it("should execute build command", function () {
var build = sinon.stub(instance, "build");
var build = sinon.spy(instance, "build");
var _build = sinon.stub(instance, "_build");
var msg = {
cmd: "build"
cmd: "build",
dest: "one.css",
file: "one.less"
};

@@ -110,2 +129,5 @@

build.restore();
_build.should.have.been.calledWith(msg.file, msg.dest);
_build.restore();
});

@@ -165,3 +187,39 @@ it("should execute start command", function () {

});
describe("start()", function () {
var message = { "cmd": "start", "data": ["foo.less"] };
beforeEach(function () {
this.instance = new ClusterWorker();
sinon.stub(this.instance, "emit");
sinon.stub(ClusterWorker, "readFiles");
});
afterEach(function () {
ClusterWorker.readFiles.restore();
this.instance.destroy();
this.instance = null;
});
it("should read all the files specified in message data", function () {
this.instance.start(message);
ClusterWorker.readFiles.should.have.been.calledWith(message.data, sinon.match.func);
});
it("should emit error event when encountered", function () {
var ohNoesError = "oh noes!";
ClusterWorker.readFiles.yields(ohNoesError);
this.instance.start(message);
this.instance.emit.should.have.been.calledWith("error", ohNoesError);
});
it("should emit ready event when successful", function () {
var data = {};
data["foo.less"] = "foo";
ClusterWorker.readFiles.yields(null, data);
this.instance.start(message);
this.instance.emit.should.have.been.calledWith("ready");
this.instance._fileCache.should.eql(data);
});
});
});
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc