Skip to content

Commit

Permalink
Watcher should track newly created files
Browse files Browse the repository at this point in the history
Currently newly created are added to the graph but not added the
watcher.

Fixes sass#1891
  • Loading branch information
xzyfer committed Mar 29, 2017
1 parent ae4f935 commit bd25e96
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 95 deletions.
41 changes: 24 additions & 17 deletions bin/node-sass
Original file line number Diff line number Diff line change
Expand Up @@ -245,23 +245,11 @@ function watch(options, emitter) {
return graph;
};

var watch = [];
var graph = buildGraph(options);

// Add all files to watch list
for (var i in graph.index) {
watch.push(i);
}

var gaze = new Gaze();
gaze.add(watch);
gaze.on('error', emitter.emit.bind(emitter, 'error'));

gaze.on('changed', function(file) {
var updateWatcher = function(file) {
var graph = buildGraph(options);
var files = [file];

// descendents may be added, so we need a new graph
graph = buildGraph(options);
graph.visitAncestors(file, function(parent) {
files.push(parent);
});
Expand All @@ -278,15 +266,34 @@ function watch(options, emitter) {
renderFile(file, options, emitter);
}
});
});
};

gaze.on('added', function() {
graph = buildGraph(options);
var watch = [];
var graph = buildGraph(options);

// Add all files to watch list
for (var i in graph.index) {
watch.push(i);
}

var gaze = new Gaze();
gaze.add(watch);
gaze.on('error', emitter.emit.bind(emitter, 'error'));

gaze.on('changed', function(file) {
updateWatcher(file);
});
gaze.on('added', function(file) {
updateWatcher(file);
});

gaze.on('deleted', function() {
graph = buildGraph(options);
});

if (!options.quiet) {
console.log('Watching', options.directory || options.src);
}
}

/**
Expand Down
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

{
"name": "node-sass",
"version": "4.5.2",
Expand Down Expand Up @@ -31,7 +32,7 @@
"install": "node scripts/install.js",
"postinstall": "node scripts/build.js",
"lint": "node_modules/.bin/eslint bin/node-sass lib scripts test",
"test": "node_modules/.bin/mocha test/{*,**/**}.js",
"test": "node_modules/.bin/mocha test/cli.js",
"build": "node scripts/build.js --force",
"prepublish": "not-in-install && node scripts/prepublish.js || in-install"
},
Expand Down Expand Up @@ -76,11 +77,14 @@
"coveralls": "^2.11.8",
"eslint": "^3.4.0",
"istanbul": "^0.4.2",
"lodash.once": "^4.1.1",
"mocha": "^3.1.2",
"mocha-lcov-reporter": "^1.2.0",
"object-merge": "^2.5.1",
"read-yaml": "^1.0.0",
"rimraf": "^2.5.2",
"sass-spec": "3.5.0-1"
"sass-spec": "3.5.0-1",
"touch": "^1.0.0",
"unique-temp-dir": "^1.0.0"
}
}
186 changes: 110 additions & 76 deletions test/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ var assert = require('assert'),
glob = require('glob'),
rimraf = require('rimraf'),
stream = require('stream'),
once = require('lodash.once'),
spawn = require('cross-spawn'),
cli = path.join(__dirname, '..', 'bin', 'node-sass'),
touch = require('touch'),
tmpDir = require('unique-temp-dir'),
fixture = path.join.bind(null, __dirname, 'fixtures');

describe('cli', function() {
Expand Down Expand Up @@ -226,165 +229,196 @@ describe('cli', function() {
}, 100);
});

it.skip('should emit `warn` on file change when using --watch option', function(done) {
var src = fixture('simple/tmp.scss');

fs.writeFileSync(src, '');
it('should emit `warn` on file change when using --watch option', function(done) {
var src = fixture('watching-dir-01/index.scss');

var bin = spawn(cli, ['--watch', src]);

bin.stderr.setEncoding('utf8');
bin.stderr.once('data', function(data) {
assert.strictEqual(data.trim(), '=> changed: ' + src);
fs.unlinkSync(src);
bin.kill();
});
bin.on('error', function(err) {
assert.fail(err);
done();
});
bin.on('exit', done);

setTimeout(function() {
fs.appendFileSync(src, 'body {}');
touch.sync(src);
}, 500);
});
}).timeout(5000);

it.skip('should emit nothing on file change when using --watch and --quiet options', function(done) {
var src = fixture('simple/tmp.scss');
var didEmit = false;
fs.writeFileSync(src, '');
it('should emit nothing on file change when using --watch and --quiet options', function(done) {
var src = fixture('watching-dir-01/index.scss');

var bin = spawn(cli, ['--watch', '--quiet', src]);

bin.stderr.setEncoding('utf8');
bin.stderr.once('data', function() {
didEmit = true;
assert.fail('should not emit console output with --quiet flag');
});
bin.on('error', function(err) {
assert.fail(err);
done();
});
bin.on('exit', done);

setTimeout(function() {
fs.appendFileSync(src, 'body {}');
setTimeout(function() {
assert.equal(didEmit, false);
bin.kill();
done();
fs.unlinkSync(src);
}, 200);
touch(src, {}, function(err) {
if (err) {
assert.fail(err);
}

setTimeout(function() {
bin.kill();
}, 1000);
});
}, 500);
});
}).timeout(5000);

it.skip('should render all watched files', function(done) {
var src = fixture('simple/bar.scss');
it('should render all watched files', function(done) {
var src = fixture('watching-dir-01/index.scss');

fs.writeFileSync(src, '');

var bin = spawn(cli, [
'--output-style', 'compressed',
'--watch', src
]);
var bin = spawn(cli, ['--output-style', 'compressed', '--watch', src]);

bin.stdout.setEncoding('utf8');
bin.stdout.once('data', function(data) {
assert.strictEqual(data.trim(), 'body{background:white}');
fs.unlinkSync(src);
assert.strictEqual(data.trim(), 'a{color:green}');
bin.kill();
});
bin.on('error', function(err) {
assert.fail(err);
done();
});
bin.on('exit', done);

setTimeout(function() {
fs.appendFileSync(src, 'body{background:white}');
touch.sync(src);
}, 500);
});
}).timeout(5000);

it.skip('should watch the full scss dep tree for a single file (scss)', function(done) {
it('should watch the full scss dep tree for a single file (scss)', function(done) {
var src = fixture('watching/index.scss');
var foo = fixture('watching/white.scss');

fs.writeFileSync(foo, '');
var child = fixture('watching/white.scss');

var bin = spawn(cli, [
'--output-style', 'compressed',
'--watch', src
]);

bin.stdout.setEncoding('utf8');
bin.stdout.once('data', function(data) {
assert.strictEqual(data.trim(), 'body{background:blue}');
bin.kill();
bin.stdout.once('data', function() {
touch(child, function() {
bin.stdout.once('data', function(data) {
assert.strictEqual(data.trim(), 'body{background:white}');
bin.kill();
});
});
});
bin.on('error', function(err) {
assert.fail(err);
done();
});
bin.on('exit', done);
}).timeout(5000);

setTimeout(function() {
fs.appendFileSync(foo, 'body{background:blue}\n');
}, 500);
});

it.skip('should watch the full sass dep tree for a single file (sass)', function(done) {
it('should watch the full sass dep tree for a single file (sass)', function(done) {
var src = fixture('watching/index.sass');
var foo = fixture('watching/bar.sass');

fs.writeFileSync(foo, '');
var child = fixture('watching/bar.sass');

var bin = spawn(cli, [
'--output-style', 'compressed',
'--watch', src
]);

bin.stdout.setEncoding('utf8');
bin.stdout.once('data', function(data) {
assert.strictEqual(data.trim(), 'body{background:red}');
bin.kill();
bin.stdout.once('data', function() {
touch(child, function() {
bin.stdout.once('data', function(data) {
assert.strictEqual(data.trim(), 'body{background:white}');
bin.kill();
});
});
});
bin.on('error', function(err) {
assert.fail(err);
done();
});
bin.on('exit', done);

setTimeout(function() {
fs.appendFileSync(foo, 'body\n\tbackground: red\n');
touch.sync(child);
}, 500);
});
});
}).timeout(5000);

describe('node-sass --output directory', function() {
it.skip('should watch whole directory', function(done) {
var destDir = fixture('watching-css-out-01/');
it('should watch whole directory', function(done) {
var destDir = tmpDir({
create: true
});
var srcDir = fixture('watching-dir-01/');
var srcFile = path.join(srcDir, 'index.scss');

fs.writeFileSync(srcFile, '');
var w;

var bin = spawn(cli, [
'--output-style', 'compressed',
'--output', destDir,
'--watch', srcDir
]);

setTimeout(function() {
fs.appendFileSync(srcFile, 'a {color:green;}\n');
setTimeout(function() {
bin.kill();
var files = fs.readdirSync(destDir);
bin.stdout.setEncoding('utf8');
bin.stdout.once('data', function(data) {
assert.equal('Watching ' + srcDir, data.trim());
touch(srcFile, function() {
bin.stdout.once('data', function() {
assert.fail('should not emit console output when watching a directory');
});
});
});
bin.on('error', assert.fail);
bin.on('exit', w.close);

w = fs.watch(destDir, function() {
bin.kill();
fs.readdir(destDir, function(err, files) {
assert.deepEqual(files, ['index.css']);
rimraf(destDir, done);
}, 200);
}, 500);
});
});
});
}).timeout(5000);

it.skip('should compile all changed files in watched directory', function(done) {
var destDir = fixture('watching-css-out-02/');
it('should compile all changed files in watched directory', function(done) {
var destDir = tmpDir({
create: true
});
var srcDir = fixture('watching-dir-02/');
var srcFile = path.join(srcDir, 'foo.scss');

fs.writeFileSync(srcFile, '');

var bin = spawn(cli, [
'--output-style', 'compressed',
'--output', destDir,
'--watch', srcDir
]);

setTimeout(function () {
fs.appendFileSync(srcFile, 'body{background:white}\n');
setTimeout(function () {
bin.stdout.setEncoding('utf8');
bin.stdout.once('data', function() {
assert.fail('should not emit console output when watching a directory');
});
bin.on('error', assert.fail);

setTimeout(function() {
setTimeout(function() {
bin.kill();
var files = fs.readdirSync(destDir);
assert.deepEqual(files, ['foo.css', 'index.css']);
rimraf(destDir, done);
}, 200);
fs.readdir(destDir, function(err, files) {
assert.deepEqual(files, ['foo.css', 'index.css']);
rimraf(destDir, done);
});
}, 1000);

spawn('node', ['-e', 'require("touch").sync("' + srcFile + '")']);
}, 500);
});
});
Expand Down

0 comments on commit bd25e96

Please sign in to comment.