Skip to content

Commit

Permalink
address #3069 by using chokidar fs events (#4038)
Browse files Browse the repository at this point in the history
* address #3069 by using chokidar fs events

* use chokidar directly for watching specs and add tests

the watchers lib watches for file contents changing and doesn’t watch for files being added or removed
  • Loading branch information
pauledwin authored and chrisbreiding committed May 7, 2019
1 parent 6d5963b commit f34471c
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 14 deletions.
37 changes: 27 additions & 10 deletions packages/server/lib/open_project.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ _ = require("lodash")
la = require("lazy-ass")
debug = require("debug")("cypress:server:openproject")
Promise = require("bluebird")
path = require("path")
chokidar = require("chokidar")
files = require("./controllers/files")
config = require("./config")
Project = require("./project")
Expand All @@ -11,8 +13,8 @@ preprocessor = require("./plugins/preprocessor")

create = ->
openProject = null
specIntervalId = null
relaunchBrowser = null
specsWatcher = null

reset = ->
openProject = null
Expand Down Expand Up @@ -126,17 +128,34 @@ create = ->
currentSpecs = specs
options.onChange(specs)

checkForSpecUpdates = =>
checkForSpecUpdates = _.debounce =>
if not openProject
return @clearSpecInterval()
return @stopSpecsWatcher()

debug("check for spec updates")

get()
.then(sendIfChanged)
.catch(options.onError)
, 250, { leading: true }

createSpecsWatcher = (cfg) ->
return if specsWatcher

debug("watch test files: %s in %s", cfg.testFiles, cfg.integrationFolder)

specsWatcher = chokidar.watch(cfg.testFiles, {
cwd: cfg.integrationFolder
ignored: cfg.ignoreTestFiles
ignoreInitial: true
})
specsWatcher.on("add", checkForSpecUpdates)
specsWatcher.on("unlink", checkForSpecUpdates)

get = ->
openProject.getConfig()
.then (cfg) ->
createSpecsWatcher(cfg)
specsUtil.find(cfg)
.then (specs = []) ->
## TODO: put back 'integration' property
Expand All @@ -145,15 +164,13 @@ create = ->
integration: specs
}

specIntervalId = setInterval(checkForSpecUpdates, 2500)

## immediately check the first time around
checkForSpecUpdates()

clearSpecInterval: ->
if specIntervalId
clearInterval(specIntervalId)
specIntervalId = null
stopSpecsWatcher: ->
debug("stop spec watcher")
Promise.try ->
specsWatcher?.close()

closeBrowser: ->
browsers.close()
Expand All @@ -171,7 +188,7 @@ create = ->
close: ->
debug("closing opened project")

@clearSpecInterval()
@stopSpecsWatcher()
@closeOpenProjectAndBrowsers()

create: (path, args = {}, options = {}) ->
Expand Down
4 changes: 1 addition & 3 deletions packages/server/lib/watchers.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ class Watchers

watch: (filePath, options = {}) ->
_.defaults options,
interval: 250
usePolling: true
useFsEvents: false
useFsEvents: true
ignored: null
onChange: null
onReady: null
Expand Down
44 changes: 43 additions & 1 deletion packages/server/test/unit/open_project_spec.coffee
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require("../spec_helper")

chokidar = require("chokidar")
browsers = require("#{root}lib/browsers")
Project = require("#{root}lib/project")
openProject = require("#{root}lib/open_project")
Expand All @@ -11,13 +12,18 @@ describe "lib/open_project", ->
reset: sinon.stub()
use: sinon.stub()
}
@config = {
integrationFolder: "/user/foo/cypress/integration"
testFiles: "**/*.*"
ignoreTestFiles: "**/*.nope"
}

sinon.stub(browsers, "get").resolves()
sinon.stub(browsers, "open")
sinon.stub(Project.prototype, "open").resolves()
sinon.stub(Project.prototype, "reset").resolves()
sinon.stub(Project.prototype, "getSpecUrl").resolves()
sinon.stub(Project.prototype, "getConfig").resolves({})
sinon.stub(Project.prototype, "getConfig").resolves(@config)
sinon.stub(Project.prototype, "getAutomation").returns(@automation)
sinon.stub(preprocessor, "removeFile")

Expand Down Expand Up @@ -64,3 +70,39 @@ describe "lib/open_project", ->
.then =>
expect(@browser.isHeaded).to.be.true
expect(@browser.isHeadless).to.be.false

context "#getSpecChanges", ->
beforeEach ->
@watcherStub = {
on: sinon.stub()
}
sinon.stub(chokidar, "watch").returns(@watcherStub)

it "watches spec files", ->
openProject.getSpecChanges({}).then =>
expect(chokidar.watch).to.be.calledWith(@config.testFiles, {
cwd: @config.integrationFolder
ignored: @config.ignoreTestFiles
ignoreInitial: true
})

it "calls onChange callback when file is added", ->
onChange = sinon.spy()
@watcherStub.on.withArgs("add").yields()
openProject.getSpecChanges({ onChange }).then =>
expect(onChange).to.be.called

it "calls onChange callback when file is removed", ->
onChange = sinon.spy()
@watcherStub.on.withArgs("unlink").yields()
openProject.getSpecChanges({ onChange }).then =>
expect(onChange).to.be.called

it "only calls onChange once if there are multiple changes in a row", ->
onChange = sinon.spy()
@watcherStub.on.withArgs("unlink").yields()
@watcherStub.on.withArgs("add").yields()
@watcherStub.on.withArgs("unlink").yields()
@watcherStub.on.withArgs("add").yields()
openProject.getSpecChanges({ onChange }).then =>
expect(onChange).to.be.calledOnce

0 comments on commit f34471c

Please sign in to comment.