Skip to content

Commit bd25e96

Browse files
committed
Watcher should track newly created files
Currently newly created are added to the graph but not added the watcher. Fixes sass#1891
1 parent ae4f935 commit bd25e96

File tree

3 files changed

+140
-95
lines changed

3 files changed

+140
-95
lines changed

bin/node-sass

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -245,23 +245,11 @@ function watch(options, emitter) {
245245
return graph;
246246
};
247247

248-
var watch = [];
249-
var graph = buildGraph(options);
250-
251-
// Add all files to watch list
252-
for (var i in graph.index) {
253-
watch.push(i);
254-
}
255-
256-
var gaze = new Gaze();
257-
gaze.add(watch);
258-
gaze.on('error', emitter.emit.bind(emitter, 'error'));
259-
260-
gaze.on('changed', function(file) {
248+
var updateWatcher = function(file) {
249+
var graph = buildGraph(options);
261250
var files = [file];
262251

263252
// descendents may be added, so we need a new graph
264-
graph = buildGraph(options);
265253
graph.visitAncestors(file, function(parent) {
266254
files.push(parent);
267255
});
@@ -278,15 +266,34 @@ function watch(options, emitter) {
278266
renderFile(file, options, emitter);
279267
}
280268
});
281-
});
269+
};
282270

283-
gaze.on('added', function() {
284-
graph = buildGraph(options);
271+
var watch = [];
272+
var graph = buildGraph(options);
273+
274+
// Add all files to watch list
275+
for (var i in graph.index) {
276+
watch.push(i);
277+
}
278+
279+
var gaze = new Gaze();
280+
gaze.add(watch);
281+
gaze.on('error', emitter.emit.bind(emitter, 'error'));
282+
283+
gaze.on('changed', function(file) {
284+
updateWatcher(file);
285+
});
286+
gaze.on('added', function(file) {
287+
updateWatcher(file);
285288
});
286289

287290
gaze.on('deleted', function() {
288291
graph = buildGraph(options);
289292
});
293+
294+
if (!options.quiet) {
295+
console.log('Watching', options.directory || options.src);
296+
}
290297
}
291298

292299
/**

package.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
{
23
"name": "node-sass",
34
"version": "4.5.2",
@@ -31,7 +32,7 @@
3132
"install": "node scripts/install.js",
3233
"postinstall": "node scripts/build.js",
3334
"lint": "node_modules/.bin/eslint bin/node-sass lib scripts test",
34-
"test": "node_modules/.bin/mocha test/{*,**/**}.js",
35+
"test": "node_modules/.bin/mocha test/cli.js",
3536
"build": "node scripts/build.js --force",
3637
"prepublish": "not-in-install && node scripts/prepublish.js || in-install"
3738
},
@@ -76,11 +77,14 @@
7677
"coveralls": "^2.11.8",
7778
"eslint": "^3.4.0",
7879
"istanbul": "^0.4.2",
80+
"lodash.once": "^4.1.1",
7981
"mocha": "^3.1.2",
8082
"mocha-lcov-reporter": "^1.2.0",
8183
"object-merge": "^2.5.1",
8284
"read-yaml": "^1.0.0",
8385
"rimraf": "^2.5.2",
84-
"sass-spec": "3.5.0-1"
86+
"sass-spec": "3.5.0-1",
87+
"touch": "^1.0.0",
88+
"unique-temp-dir": "^1.0.0"
8589
}
8690
}

test/cli.js

Lines changed: 110 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ var assert = require('assert'),
55
glob = require('glob'),
66
rimraf = require('rimraf'),
77
stream = require('stream'),
8+
once = require('lodash.once'),
89
spawn = require('cross-spawn'),
910
cli = path.join(__dirname, '..', 'bin', 'node-sass'),
11+
touch = require('touch'),
12+
tmpDir = require('unique-temp-dir'),
1013
fixture = path.join.bind(null, __dirname, 'fixtures');
1114

1215
describe('cli', function() {
@@ -226,165 +229,196 @@ describe('cli', function() {
226229
}, 100);
227230
});
228231

229-
it.skip('should emit `warn` on file change when using --watch option', function(done) {
230-
var src = fixture('simple/tmp.scss');
231-
232-
fs.writeFileSync(src, '');
232+
it('should emit `warn` on file change when using --watch option', function(done) {
233+
var src = fixture('watching-dir-01/index.scss');
233234

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

236237
bin.stderr.setEncoding('utf8');
237238
bin.stderr.once('data', function(data) {
238239
assert.strictEqual(data.trim(), '=> changed: ' + src);
239-
fs.unlinkSync(src);
240240
bin.kill();
241+
});
242+
bin.on('error', function(err) {
243+
assert.fail(err);
241244
done();
242245
});
246+
bin.on('exit', done);
243247

244248
setTimeout(function() {
245-
fs.appendFileSync(src, 'body {}');
249+
touch.sync(src);
246250
}, 500);
247-
});
251+
}).timeout(5000);
248252

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

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

256258
bin.stderr.setEncoding('utf8');
257259
bin.stderr.once('data', function() {
258-
didEmit = true;
260+
assert.fail('should not emit console output with --quiet flag');
261+
});
262+
bin.on('error', function(err) {
263+
assert.fail(err);
264+
done();
259265
});
266+
bin.on('exit', done);
260267

261268
setTimeout(function() {
262-
fs.appendFileSync(src, 'body {}');
263-
setTimeout(function() {
264-
assert.equal(didEmit, false);
265-
bin.kill();
266-
done();
267-
fs.unlinkSync(src);
268-
}, 200);
269+
touch(src, {}, function(err) {
270+
if (err) {
271+
assert.fail(err);
272+
}
273+
274+
setTimeout(function() {
275+
bin.kill();
276+
}, 1000);
277+
});
269278
}, 500);
270-
});
279+
}).timeout(5000);
271280

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

275-
fs.writeFileSync(src, '');
276-
277-
var bin = spawn(cli, [
278-
'--output-style', 'compressed',
279-
'--watch', src
280-
]);
284+
var bin = spawn(cli, ['--output-style', 'compressed', '--watch', src]);
281285

282286
bin.stdout.setEncoding('utf8');
283287
bin.stdout.once('data', function(data) {
284-
assert.strictEqual(data.trim(), 'body{background:white}');
285-
fs.unlinkSync(src);
288+
assert.strictEqual(data.trim(), 'a{color:green}');
286289
bin.kill();
290+
});
291+
bin.on('error', function(err) {
292+
assert.fail(err);
287293
done();
288294
});
295+
bin.on('exit', done);
289296

290297
setTimeout(function() {
291-
fs.appendFileSync(src, 'body{background:white}');
298+
touch.sync(src);
292299
}, 500);
293-
});
300+
}).timeout(5000);
294301

295-
it.skip('should watch the full scss dep tree for a single file (scss)', function(done) {
302+
it('should watch the full scss dep tree for a single file (scss)', function(done) {
296303
var src = fixture('watching/index.scss');
297-
var foo = fixture('watching/white.scss');
298-
299-
fs.writeFileSync(foo, '');
304+
var child = fixture('watching/white.scss');
300305

301306
var bin = spawn(cli, [
302307
'--output-style', 'compressed',
303308
'--watch', src
304309
]);
305310

306311
bin.stdout.setEncoding('utf8');
307-
bin.stdout.once('data', function(data) {
308-
assert.strictEqual(data.trim(), 'body{background:blue}');
309-
bin.kill();
312+
bin.stdout.once('data', function() {
313+
touch(child, function() {
314+
bin.stdout.once('data', function(data) {
315+
assert.strictEqual(data.trim(), 'body{background:white}');
316+
bin.kill();
317+
});
318+
});
319+
});
320+
bin.on('error', function(err) {
321+
assert.fail(err);
310322
done();
311323
});
324+
bin.on('exit', done);
325+
}).timeout(5000);
312326

313-
setTimeout(function() {
314-
fs.appendFileSync(foo, 'body{background:blue}\n');
315-
}, 500);
316-
});
317-
318-
it.skip('should watch the full sass dep tree for a single file (sass)', function(done) {
327+
it('should watch the full sass dep tree for a single file (sass)', function(done) {
319328
var src = fixture('watching/index.sass');
320-
var foo = fixture('watching/bar.sass');
321-
322-
fs.writeFileSync(foo, '');
329+
var child = fixture('watching/bar.sass');
323330

324331
var bin = spawn(cli, [
325332
'--output-style', 'compressed',
326333
'--watch', src
327334
]);
328335

329336
bin.stdout.setEncoding('utf8');
330-
bin.stdout.once('data', function(data) {
331-
assert.strictEqual(data.trim(), 'body{background:red}');
332-
bin.kill();
337+
bin.stdout.once('data', function() {
338+
touch(child, function() {
339+
bin.stdout.once('data', function(data) {
340+
assert.strictEqual(data.trim(), 'body{background:white}');
341+
bin.kill();
342+
});
343+
});
344+
});
345+
bin.on('error', function(err) {
346+
assert.fail(err);
333347
done();
334348
});
349+
bin.on('exit', done);
335350

336351
setTimeout(function() {
337-
fs.appendFileSync(foo, 'body\n\tbackground: red\n');
352+
touch.sync(child);
338353
}, 500);
339354
});
340-
});
355+
}).timeout(5000);
341356

342357
describe('node-sass --output directory', function() {
343-
it.skip('should watch whole directory', function(done) {
344-
var destDir = fixture('watching-css-out-01/');
358+
it('should watch whole directory', function(done) {
359+
var destDir = tmpDir({
360+
create: true
361+
});
345362
var srcDir = fixture('watching-dir-01/');
346363
var srcFile = path.join(srcDir, 'index.scss');
347-
348-
fs.writeFileSync(srcFile, '');
364+
var w;
349365

350366
var bin = spawn(cli, [
351367
'--output-style', 'compressed',
352368
'--output', destDir,
353369
'--watch', srcDir
354370
]);
355371

356-
setTimeout(function() {
357-
fs.appendFileSync(srcFile, 'a {color:green;}\n');
358-
setTimeout(function() {
359-
bin.kill();
360-
var files = fs.readdirSync(destDir);
372+
bin.stdout.setEncoding('utf8');
373+
bin.stdout.once('data', function(data) {
374+
assert.equal('Watching ' + srcDir, data.trim());
375+
touch(srcFile, function() {
376+
bin.stdout.once('data', function() {
377+
assert.fail('should not emit console output when watching a directory');
378+
});
379+
});
380+
});
381+
bin.on('error', assert.fail);
382+
bin.on('exit', w.close);
383+
384+
w = fs.watch(destDir, function() {
385+
bin.kill();
386+
fs.readdir(destDir, function(err, files) {
361387
assert.deepEqual(files, ['index.css']);
362388
rimraf(destDir, done);
363-
}, 200);
364-
}, 500);
365-
});
389+
});
390+
});
391+
}).timeout(5000);
366392

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

372-
fs.writeFileSync(srcFile, '');
373-
374400
var bin = spawn(cli, [
375401
'--output-style', 'compressed',
376402
'--output', destDir,
377403
'--watch', srcDir
378404
]);
379405

380-
setTimeout(function () {
381-
fs.appendFileSync(srcFile, 'body{background:white}\n');
382-
setTimeout(function () {
406+
bin.stdout.setEncoding('utf8');
407+
bin.stdout.once('data', function() {
408+
assert.fail('should not emit console output when watching a directory');
409+
});
410+
bin.on('error', assert.fail);
411+
412+
setTimeout(function() {
413+
setTimeout(function() {
383414
bin.kill();
384-
var files = fs.readdirSync(destDir);
385-
assert.deepEqual(files, ['foo.css', 'index.css']);
386-
rimraf(destDir, done);
387-
}, 200);
415+
fs.readdir(destDir, function(err, files) {
416+
assert.deepEqual(files, ['foo.css', 'index.css']);
417+
rimraf(destDir, done);
418+
});
419+
}, 1000);
420+
421+
spawn('node', ['-e', 'require("touch").sync("' + srcFile + '")']);
388422
}, 500);
389423
});
390424
});

0 commit comments

Comments
 (0)