Skip to content

Commit

Permalink
feat(server): Add public API to force a file refresh
Browse files Browse the repository at this point in the history
Adds a public API similar to `server.refreshFiles()` that allows to refresh a specific file.
This is useful for preprocessors that process files with dependencies (sass, js modules, postcss), so they can trigger an update on a file when a change is detected on a dependency.
Contrary to `server.refreshFiles()` it allows to refresh only the file that need to be processed again.
  • Loading branch information
pvdlg authored and lusarz committed Oct 11, 2018
1 parent 871a1c9 commit dab8a82
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 3 deletions.
8 changes: 8 additions & 0 deletions docs/dev/04-public-api.md
Expand Up @@ -33,6 +33,14 @@ Trigger a file list refresh. Returns a promise.
server.refreshFiles()
```

### **server.refreshFile(path)**

Trigger a file refresh. Returns a promise.

```javascript
server.refreshFile('src/js/module-dep.js')
```

### Events

The `server` object is an [`EventEmitter`](https://nodejs.org/docs/latest/api/events.html#events_class_events_eventemitter). You can simply listen to events like this:
Expand Down
6 changes: 3 additions & 3 deletions lib/file-list.js
Expand Up @@ -213,7 +213,7 @@ class FileList {
})
}

changeFile (path) {
changeFile (path, force) {
const pattern = this._findIncluded(path)
const file = this._findFile(path, pattern)

Expand All @@ -226,14 +226,14 @@ class FileList {
fs.statAsync(path),
this._refreshing
]).spread((stat) => {
if (stat.mtime <= file.mtime) throw new Promise.CancellationError()
if (!force && stat.mtime <= file.mtime) throw new Promise.CancellationError()

file.mtime = stat.mtime
return this._preprocess(file)
})
.then(() => {
log.info('Changed file "%s".', path)
this._emitModified()
this._emitModified(force)
return this.files
})
.catch(Promise.CancellationError, () => this.files)
Expand Down
4 changes: 4 additions & 0 deletions lib/server.js
Expand Up @@ -133,6 +133,10 @@ class Server extends KarmaEventEmitter {
return this._fileList ? this._fileList.refresh() : Promise.resolve()
}

refreshFile (path) {
return this._fileList ? this._fileList.changeFile(path) : Promise.resolve()
}

_start (config, launcher, preprocess, fileList, capturedBrowsers, executor, done) {
if (config.detached) {
this._detach(config, done)
Expand Down
17 changes: 17 additions & 0 deletions test/unit/file-list.spec.js
Expand Up @@ -632,6 +632,23 @@ describe('FileList', () => {
})
})

it('fire "file_list_modified" if force is true even if mtime has not changed', () => {
// MATCH: /some/a.js, /some/b.js, /a.txt
list = new List(patterns('/some/*.js', '/a.*'), [], emitter, preprocess)

var modified = sinon.stub()
emitter.on('file_list_modified', modified)

return list.refresh().then((files) => {
// not touching the file, stat will return still the same
modified.reset()

return list.changeFile('/some/b.js', true).then(() => {
expect(modified).to.have.been.calledOnce
})
})
})

it('does not fire "file_list_modified" if mtime has not changed', () => {
// chokidar on fucking windows sometimes fires event multiple times
// MATCH: /some/a.js, /some/b.js, /a.txt
Expand Down

0 comments on commit dab8a82

Please sign in to comment.