mirror of
https://github.com/cypress-io/cypress.git
synced 2026-05-07 23:40:21 -05:00
Remove fs sync 373 (#376)
* remove fs.existsSync in unit test, close #373 * updating an integration test * remove unlinkSync from an integration spec * remove only * make saved_stage async * switched some tests to async state * server: fix more state tests * working on config to async * change config mergeDefaults to async * more .mergeDefaults tests updated * fix config unit tests * remove only in config unit tests * fix server unit test * fix two more tests * server: maybe all unit tests fixed * server: handle NPM 3 vs 4 in exit codes * fix server start * fix another server startup in test * server: messaging and promise.try
This commit is contained in:
@@ -85,7 +85,9 @@ module.exports = {
|
||||
}, resolve)
|
||||
|
||||
open: (browserName, url, options = {}, automation) ->
|
||||
savedState(options.projectPath).get()
|
||||
savedState(options.projectPath)
|
||||
.then (state) ->
|
||||
state.get()
|
||||
.then (state) =>
|
||||
@_render(url, state, options)
|
||||
.then (win) =>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
_ = require("lodash")
|
||||
path = require("path")
|
||||
Promise = require("bluebird")
|
||||
fs = require("fs")
|
||||
fs = require("fs-extra")
|
||||
errors = require("./errors")
|
||||
scaffold = require("./scaffold")
|
||||
errors = require("./errors")
|
||||
@@ -187,11 +187,8 @@ module.exports = {
|
||||
|
||||
config = @setParentTestsPaths(config)
|
||||
|
||||
config = @setSupportFileAndFolder(config)
|
||||
|
||||
config = @setScaffoldPaths(config)
|
||||
|
||||
return config
|
||||
@setSupportFileAndFolder(config)
|
||||
.then @setScaffoldPaths
|
||||
|
||||
setResolvedConfigValues: (config, defaults, resolved) ->
|
||||
obj = _.clone(config)
|
||||
@@ -235,18 +232,22 @@ module.exports = {
|
||||
|
||||
return obj
|
||||
|
||||
# async function
|
||||
setSupportFileAndFolder: (obj) ->
|
||||
return obj if not obj.supportFile
|
||||
return Promise.resolve(obj) if not obj.supportFile
|
||||
|
||||
obj = _.clone(obj)
|
||||
|
||||
## TODO move this logic to find support file into util/path_helpers
|
||||
|
||||
sf = obj.supportFile
|
||||
log "setting support file #{sf}"
|
||||
log "for project root #{obj.projectRoot}"
|
||||
try
|
||||
|
||||
Promise
|
||||
.try ->
|
||||
## resolve full path with extension
|
||||
obj.supportFile = require.resolve(sf)
|
||||
.then () ->
|
||||
if pathHelpers.checkIfResolveChangedRootFolder(obj.supportFile, sf)
|
||||
log("require.resolve switched support folder from %s to %s",
|
||||
sf, obj.supportFile)
|
||||
@@ -255,36 +256,38 @@ module.exports = {
|
||||
# which can confuse the rest of the code
|
||||
# switch it back to "normal" file
|
||||
obj.supportFile = path.join(sf, path.basename(obj.supportFile))
|
||||
if not fs.existsSync(obj.supportFile)
|
||||
errors.throw("SUPPORT_FILE_NOT_FOUND", obj.supportFile)
|
||||
log("switching to found file %s", obj.supportFile)
|
||||
catch err
|
||||
if err.code isnt "MODULE_NOT_FOUND"
|
||||
throw err
|
||||
|
||||
log("support file does not exist")
|
||||
return fs.pathExists(obj.supportFile)
|
||||
.then (found) ->
|
||||
if not found
|
||||
errors.throw("SUPPORT_FILE_NOT_FOUND", obj.supportFile)
|
||||
log("switching to found file %s", obj.supportFile)
|
||||
.catch({code: "MODULE_NOT_FOUND"}, ->
|
||||
log("support file %s does not exist", sf)
|
||||
## supportFile doesn't exist on disk
|
||||
if sf is path.resolve(obj.projectRoot, defaults.supportFile)
|
||||
log("support file is default, check if #{path.dirname(sf)} exists")
|
||||
if fs.existsSync(sf)
|
||||
log("support folder exists, set supportFile to false")
|
||||
## if the directory exists, set it to false so it's ignored
|
||||
obj.supportFile = false
|
||||
return fs.pathExists(sf)
|
||||
.then (found) ->
|
||||
if (found)
|
||||
log("support folder exists, set supportFile to false")
|
||||
## if the directory exists, set it to false so it's ignored
|
||||
obj.supportFile = false
|
||||
else
|
||||
log("support folder does not exist, set to default index.js")
|
||||
## otherwise, set it up to be scaffolded later
|
||||
obj.supportFile = path.join(sf, "index.js")
|
||||
return obj
|
||||
else
|
||||
log("support folder does not exist, set to default index.js")
|
||||
## otherwise, set it up to be scaffolded later
|
||||
obj.supportFile = path.join(sf, "index.js")
|
||||
else
|
||||
log("support file is not default")
|
||||
## they have it explicitly set, so it should be there
|
||||
errors.throw("SUPPORT_FILE_NOT_FOUND", path.resolve(obj.projectRoot, sf))
|
||||
|
||||
## set config.supportFolder to its directory
|
||||
obj.supportFolder = path.dirname(obj.supportFile)
|
||||
log "set support folder #{obj.supportFolder}"
|
||||
|
||||
return obj
|
||||
)
|
||||
.then () ->
|
||||
if obj.supportFile
|
||||
## set config.supportFolder to its directory
|
||||
obj.supportFolder = path.dirname(obj.supportFile)
|
||||
log "set support folder #{obj.supportFolder}"
|
||||
obj
|
||||
|
||||
setParentTestsPaths: (obj) ->
|
||||
## projectRoot: "/path/to/project"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
require("./util/http_overrides")
|
||||
require("./fs_warn")(require("fs-extra"))
|
||||
|
||||
os = require("os")
|
||||
fs = require("fs-extra")
|
||||
cwd = require("./cwd")
|
||||
Promise = require("bluebird")
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
{T, F} = require("ramda")
|
||||
|
||||
## warn users if somehow synchronous file methods are invoked
|
||||
## these methods due to "too many files" errors are a huge pain
|
||||
warnOnSyncFileSystem = ->
|
||||
console.error "WARNING: fs sync methods can fail due to EMFILE errors"
|
||||
console.error "Cypress only works reliably when ALL fs calls are async"
|
||||
console.error "You should modify these sync calls to be async"
|
||||
|
||||
topLines = (from, n) -> (text) ->
|
||||
text.split("\n").slice(from, n).join("\n")
|
||||
|
||||
# just hide this function itself
|
||||
# stripping top few lines of the stack
|
||||
getStack = () ->
|
||||
err = new Error()
|
||||
topLines(3, 10)(err.stack)
|
||||
|
||||
addSyncFileSystemWarnings = (fs) ->
|
||||
oldExistsSync = fs.existsSync
|
||||
fs.existsSync = (filename) ->
|
||||
warnOnSyncFileSystem()
|
||||
console.error(getStack())
|
||||
oldExistsSync(filename)
|
||||
|
||||
if not fs.pathExists
|
||||
# pathExists was introduced to fs-extra@3.0.0
|
||||
# if it does not exist mimic it using async methods
|
||||
# and convert result into boolean
|
||||
fs.pathExists = (filename) ->
|
||||
fs.statAsync(filename)
|
||||
.then(T)
|
||||
.catch({code: "ENOENT"}, F)
|
||||
|
||||
module.exports = addSyncFileSystemWarnings
|
||||
@@ -295,7 +295,9 @@ module.exports = {
|
||||
newState[keys.height] = height
|
||||
newState[keys.x] = x
|
||||
newState[keys.y] = y
|
||||
savedState(projectPath).set(newState)
|
||||
savedState(projectPath)
|
||||
.then (state) ->
|
||||
state.set(newState)
|
||||
, 500
|
||||
|
||||
win.on "moved", _.debounce ->
|
||||
@@ -305,17 +307,23 @@ module.exports = {
|
||||
newState = {}
|
||||
newState[keys.x] = x
|
||||
newState[keys.y] = y
|
||||
savedState(projectPath).set(newState)
|
||||
savedState(projectPath)
|
||||
.then (state) ->
|
||||
state.set(newState)
|
||||
, 500
|
||||
|
||||
win.webContents.on "devtools-opened", ->
|
||||
newState = {}
|
||||
newState[keys.devTools] = true
|
||||
savedState(projectPath).set(newState)
|
||||
savedState(projectPath)
|
||||
.then (state) ->
|
||||
state.set(newState)
|
||||
|
||||
win.webContents.on "devtools-closed", ->
|
||||
newState = {}
|
||||
newState[keys.devTools] = false
|
||||
savedState(projectPath).set(newState)
|
||||
savedState(projectPath)
|
||||
.then (state) ->
|
||||
state.set(newState)
|
||||
|
||||
}
|
||||
|
||||
@@ -82,7 +82,8 @@ module.exports = {
|
||||
bus.emit("menu:item:clicked", "log:out")
|
||||
})
|
||||
|
||||
savedState(options.projectPath).get()
|
||||
savedState(options.projectPath)
|
||||
.then (state) -> state.get()
|
||||
.then (state) =>
|
||||
Windows.open(@getWindowArgs(state, options))
|
||||
.then (win) =>
|
||||
|
||||
@@ -121,18 +121,22 @@ class Project extends EE
|
||||
|
||||
watchSupportFile: (config) ->
|
||||
if supportFile = config.supportFile
|
||||
if not fs.existsSync(supportFile)
|
||||
errors.throw("SUPPORT_FILE_NOT_FOUND", supportFile)
|
||||
fs.pathExists(supportFile)
|
||||
.then (found) =>
|
||||
if not found
|
||||
errors.throw("SUPPORT_FILE_NOT_FOUND", supportFile)
|
||||
|
||||
relativePath = path.relative(config.projectRoot, config.supportFile)
|
||||
if config.watchForFileChanges isnt false
|
||||
options = {
|
||||
onChange: _.bind(@server.onTestFileChange, @server, relativePath)
|
||||
}
|
||||
@watchers.watchBundle(relativePath, config, options)
|
||||
## ignore errors b/c we're just setting up the watching. errors
|
||||
## are handled by the spec controller
|
||||
.catch ->
|
||||
relativePath = path.relative(config.projectRoot, config.supportFile)
|
||||
if config.watchForFileChanges isnt false
|
||||
options = {
|
||||
onChange: _.bind(@server.onTestFileChange, @server, relativePath)
|
||||
}
|
||||
@watchers.watchBundle(relativePath, config, options)
|
||||
## ignore errors b/c we're just setting up the watching. errors
|
||||
## are handled by the spec controller
|
||||
.catch ->
|
||||
else
|
||||
Promise.resolve()
|
||||
|
||||
watchSettings: (onSettingsChanged) ->
|
||||
## bail if we havent been told to
|
||||
@@ -244,13 +248,16 @@ class Project extends EE
|
||||
throw new Error("Missing project config") if not @cfg
|
||||
throw new Error("Missing project root") if not @projectRoot
|
||||
newState = _.merge({}, @cfg.state, stateChanges)
|
||||
savedState(@projectRoot).set(newState)
|
||||
savedState(@projectRoot)
|
||||
.then (state) ->
|
||||
state.set(newState)
|
||||
.then =>
|
||||
@cfg.state = newState
|
||||
newState
|
||||
|
||||
_setSavedState: (cfg) ->
|
||||
savedState(@projectRoot).get()
|
||||
savedState(@projectRoot)
|
||||
.then (state) -> state.get()
|
||||
.then (state) ->
|
||||
cfg.state = state
|
||||
cfg
|
||||
|
||||
@@ -12,6 +12,8 @@ files = require("./controllers/files")
|
||||
proxy = require("./controllers/proxy")
|
||||
driver = require("./controllers/driver")
|
||||
staticCtrl = require("./controllers/static")
|
||||
la = require("lazy-ass")
|
||||
check = require("check-more-types")
|
||||
|
||||
module.exports = (app, config, request, getRemoteState, watchers, project) ->
|
||||
## routing for the actual specs which are processed automatically
|
||||
@@ -63,6 +65,7 @@ module.exports = (app, config, request, getRemoteState, watchers, project) ->
|
||||
## TODO: we should additionally send config for the socket.io route, etc
|
||||
## and any other __cypress namespaced files so that the runner does
|
||||
## not have to be aware of anything
|
||||
la(check.unemptyString(config.clientRoute), "missing client route in config", config)
|
||||
app.get config.clientRoute, (req, res) ->
|
||||
runner.serve(req, res, config, getRemoteState)
|
||||
|
||||
|
||||
@@ -20,17 +20,19 @@ stateFiles = {}
|
||||
# project.open().then(project.state).then(state)
|
||||
# state should have width = 200
|
||||
|
||||
# async promise-returning function
|
||||
findSavedSate = (projectPath) ->
|
||||
statePath = savedStateUtil.formStatePath(projectPath)
|
||||
fullStatePath = appData.projectsPath(statePath)
|
||||
log('full state path %s', fullStatePath)
|
||||
return stateFiles[fullStatePath] if stateFiles[fullStatePath]
|
||||
savedStateUtil.formStatePath(projectPath)
|
||||
.then (statePath) ->
|
||||
fullStatePath = appData.projectsPath(statePath)
|
||||
log('full state path %s', fullStatePath)
|
||||
return stateFiles[fullStatePath] if stateFiles[fullStatePath]
|
||||
|
||||
log('making new state file around %s', fullStatePath)
|
||||
stateFile = new FileUtil({
|
||||
path: fullStatePath
|
||||
})
|
||||
stateFiles[fullStatePath] = stateFile
|
||||
stateFile
|
||||
log('making new state file around %s', fullStatePath)
|
||||
stateFile = new FileUtil({
|
||||
path: fullStatePath
|
||||
})
|
||||
stateFiles[fullStatePath] = stateFile
|
||||
stateFile
|
||||
|
||||
module.exports = findSavedSate
|
||||
|
||||
@@ -8,6 +8,8 @@ express = require("express")
|
||||
Promise = require("bluebird")
|
||||
evilDns = require("evil-dns")
|
||||
httpProxy = require("http-proxy")
|
||||
la = require("lazy-ass")
|
||||
check = require("check-more-types")
|
||||
httpsProxy = require("@packages/https-proxy")
|
||||
log = require("debug")("cypress:server:server")
|
||||
cors = require("./util/cors")
|
||||
@@ -102,6 +104,7 @@ class Server
|
||||
e
|
||||
|
||||
open: (config = {}, project) ->
|
||||
la(_.isPlainObject(config), "expected plain config object", config)
|
||||
Promise.try =>
|
||||
## always reset any buffers
|
||||
## TODO: change buffers to be an instance
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
log = require('../log')
|
||||
cwd = require('../cwd')
|
||||
fs = require('fs')
|
||||
log = require('../log')
|
||||
cwd = require('../cwd')
|
||||
fs = require('fs-extra')
|
||||
md5 = require('md5')
|
||||
sanitize = require("sanitize-filename")
|
||||
Promise = require("bluebird")
|
||||
{ basename, join, isAbsolute } = require('path')
|
||||
md5 = require('md5')
|
||||
sanitize = require("sanitize-filename")
|
||||
|
||||
toHashName = (projectPath) ->
|
||||
throw new Error("Missing project path") unless projectPath
|
||||
@@ -12,26 +13,34 @@ toHashName = (projectPath) ->
|
||||
hash = md5(projectPath)
|
||||
"#{name}-#{hash}"
|
||||
|
||||
# async promise-returning method
|
||||
formStatePath = (projectPath) ->
|
||||
log('making saved state from %s', cwd())
|
||||
if projectPath
|
||||
log('for project path %s', projectPath)
|
||||
else
|
||||
log('missing project path, looking for project here')
|
||||
cypressJsonPath = cwd('cypress.json')
|
||||
if fs.existsSync(cypressJsonPath)
|
||||
log('found cypress file %s', cypressJsonPath)
|
||||
projectPath = cwd()
|
||||
Promise.resolve()
|
||||
.then ->
|
||||
log('making saved state from %s', cwd())
|
||||
if projectPath
|
||||
log('for project path %s', projectPath)
|
||||
else
|
||||
log('missing project path, looking for project here')
|
||||
|
||||
fileName = "state.json"
|
||||
if projectPath
|
||||
log("state path for project #{projectPath}")
|
||||
statePath = join(toHashName(projectPath), fileName)
|
||||
else
|
||||
log("state path for global mode")
|
||||
statePath = join("__global__", fileName)
|
||||
cypressJsonPath = cwd('cypress.json')
|
||||
fs.pathExists(cypressJsonPath)
|
||||
.then (found) ->
|
||||
if found
|
||||
log('found cypress file %s', cypressJsonPath)
|
||||
projectPath = cwd()
|
||||
return projectPath
|
||||
|
||||
return statePath
|
||||
.then (projectPath) ->
|
||||
fileName = "state.json"
|
||||
if projectPath
|
||||
log("state path for project #{projectPath}")
|
||||
statePath = join(toHashName(projectPath), fileName)
|
||||
else
|
||||
log("state path for global mode")
|
||||
statePath = join("__global__", fileName)
|
||||
|
||||
return statePath
|
||||
|
||||
module.exports = {
|
||||
toHashName: toHashName,
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"cors": "^2.8.3",
|
||||
"coveralls": "^2.11.8",
|
||||
"electron-osx-sign": "^0.3.0",
|
||||
"execa": "^0.8.0",
|
||||
"express-session": "^1.14.1",
|
||||
"express-useragent": "^1.0.4",
|
||||
"https-proxy-agent": "^1.0.0",
|
||||
@@ -88,6 +89,7 @@
|
||||
"cookie-parser": "^1.3.3",
|
||||
"data-uri-to-buffer": "0.0.4",
|
||||
"debug": "^2.6.8",
|
||||
"delay": "^2.0.0",
|
||||
"electron-context-menu": "^0.8.0",
|
||||
"electron-positioner": "3.0.0",
|
||||
"errorhandler": "1.1.1",
|
||||
|
||||
@@ -207,3 +207,13 @@ socket.emit("remote:response", "123-a-guid-as-an-id", {a: "new response data obj
|
||||
- `npm i`
|
||||
- Open new tab: `npm run watch`
|
||||
- `node_modules/.bin/nw .`
|
||||
|
||||
## Misc
|
||||
|
||||
**important** do not use sync file system methods to work with files. They can fail if
|
||||
there are too many files (the `EMILE` exception). Asynchronous file system methods
|
||||
all use [graceful-fs](https://github.com/isaacs/node-graceful-fs#readme) to retry and
|
||||
get around this problem.
|
||||
|
||||
* there is `fs.pathExists(filename)` method that is returning a promise, use that
|
||||
instead of `fs.exists` or `fs.existsSync`.
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
require("../spec_helper")
|
||||
|
||||
_ = require("lodash")
|
||||
R = require("ramda")
|
||||
cp = require("child_process")
|
||||
pr = require("../support/helpers/process")
|
||||
pkg = require("../../package.json")
|
||||
root = require("@packages/root")
|
||||
execa = require("execa")
|
||||
semver = require("semver")
|
||||
|
||||
anyLineWithCaret = (str) ->
|
||||
str[0] is ">"
|
||||
@@ -52,31 +55,46 @@ describe "CLI Interface", ->
|
||||
## caused false-positives in CI because tests were failing
|
||||
## but the exit code was always zero
|
||||
context "exit codes", ->
|
||||
beforeEach ->
|
||||
## run the start script directly
|
||||
## instead of going through npm wrapper
|
||||
@start = pkg.scripts.start
|
||||
describe "from start script command", ->
|
||||
beforeEach ->
|
||||
## run the start script directly
|
||||
## instead of going through npm wrapper
|
||||
@start = pkg.scripts.start
|
||||
|
||||
it "exits with code 22", (done) ->
|
||||
s = cp.exec("#{@start} --exit-with-code=22")
|
||||
s.on "close", (code) ->
|
||||
expect(code).to.eq(22)
|
||||
done()
|
||||
it "exits with code 22", (done) ->
|
||||
s = cp.exec("#{@start} --exit-with-code=22")
|
||||
s.on "close", (code) ->
|
||||
expect(code).to.eq(22)
|
||||
done()
|
||||
|
||||
it "exits with code 0", (done) ->
|
||||
s = cp.exec("#{@start} --exit-with-code=0")
|
||||
s.on "close", (code) ->
|
||||
expect(code).to.eq(0)
|
||||
done()
|
||||
it "exits with code 0", (done) ->
|
||||
s = cp.exec("#{@start} --exit-with-code=0")
|
||||
s.on "close", (code) ->
|
||||
expect(code).to.eq(0)
|
||||
done()
|
||||
|
||||
it "npm slurps up exit value and exits with 1 on failure", (done) ->
|
||||
s = cp.exec("npm start -- --exit-with-code=10")
|
||||
s.on "close", (code) ->
|
||||
expect(code).to.eq(1)
|
||||
done()
|
||||
describe "through NPM script", ->
|
||||
npmVersion = null
|
||||
|
||||
it "npm passes on 0 exit code", (done) ->
|
||||
s = cp.exec("npm start -- --exit-with-code=0")
|
||||
s.on "close", (code) ->
|
||||
expect(code).to.eq(0)
|
||||
done()
|
||||
isNpmSlurpingCode = () ->
|
||||
semver.lt(npmVersion, '4.0.0')
|
||||
|
||||
beforeEach ->
|
||||
execa("npm", ["-version"])
|
||||
.then R.prop("stdout")
|
||||
.then (version) ->
|
||||
npmVersion = version
|
||||
expect(npmVersion).to.be.a.string
|
||||
|
||||
it "npm slurps up or not exit value on failure", (done) ->
|
||||
expectedCode = if isNpmSlurpingCode() then 1 else 10
|
||||
s = cp.exec("npm start -- --exit-with-code=10")
|
||||
s.on "close", (code) ->
|
||||
expect(code).to.eq(expectedCode)
|
||||
done()
|
||||
|
||||
it "npm passes on 0 exit code", (done) ->
|
||||
s = cp.exec("npm start -- --exit-with-code=0")
|
||||
s.on "close", (code) ->
|
||||
expect(code).to.eq(0)
|
||||
done()
|
||||
|
||||
@@ -5,7 +5,6 @@ os = require("os")
|
||||
cp = require("child_process")
|
||||
path = require("path")
|
||||
{ EventEmitter } = require("events")
|
||||
{ unlinkSync: rm, existsSync: exists } = require("fs")
|
||||
http = require("http")
|
||||
Promise = require("bluebird")
|
||||
electron = require("electron")
|
||||
@@ -210,12 +209,16 @@ describe "lib/cypress", ->
|
||||
context "state", ->
|
||||
statePath = null
|
||||
beforeEach ->
|
||||
# TODO switch to async file system calls
|
||||
statePath = appData.projectsPath(formStatePath(@todosPath))
|
||||
rm(statePath) if exists(statePath)
|
||||
formStatePath(@todosPath)
|
||||
.then (statePathStart) ->
|
||||
statePath = appData.projectsPath(statePathStart)
|
||||
fs.pathExists(statePath)
|
||||
.then (found) ->
|
||||
if found
|
||||
fs.unlink(statePath)
|
||||
|
||||
afterEach ->
|
||||
rm(statePath)
|
||||
fs.unlink(statePath)
|
||||
|
||||
it "saves project state", ->
|
||||
Project.add(@todosPath)
|
||||
@@ -225,8 +228,10 @@ describe "lib/cypress", ->
|
||||
@expectExitWith(0)
|
||||
.then ->
|
||||
openProject.getProject().saveState()
|
||||
.then (state) ->
|
||||
expect(exists(statePath), "Finds saved stage file #{statePath}").to.be.true
|
||||
.then () ->
|
||||
fs.pathExists(statePath)
|
||||
.then (found) ->
|
||||
expect(found, "Finds saved stage file #{statePath}").to.be.true
|
||||
|
||||
it "runs project headlessly and exits with exit code 0 and yells about old version of CLI", ->
|
||||
Project.add(@todosPath)
|
||||
|
||||
@@ -65,59 +65,59 @@ describe "Routes", ->
|
||||
## get all the config defaults
|
||||
## and allow us to override them
|
||||
## for each test
|
||||
cfg = config.set(obj)
|
||||
config.set(obj)
|
||||
.then (cfg) =>
|
||||
## use a jar for each test
|
||||
## but reset it automatically
|
||||
## between test
|
||||
jar = rp.jar()
|
||||
|
||||
## use a jar for each test
|
||||
## but reset it automatically
|
||||
## between test
|
||||
jar = rp.jar()
|
||||
## use a custom request promise
|
||||
## to automatically backfill these
|
||||
## options including our proxy
|
||||
@rp = (options = {}) =>
|
||||
if _.isString(options)
|
||||
url = options
|
||||
options = {}
|
||||
|
||||
## use a custom request promise
|
||||
## to automatically backfill these
|
||||
## options including our proxy
|
||||
@rp = (options = {}) =>
|
||||
if _.isString(options)
|
||||
url = options
|
||||
options = {}
|
||||
_.defaults options, {
|
||||
url,
|
||||
proxy: @proxy,
|
||||
jar,
|
||||
simple: false,
|
||||
followRedirect: false,
|
||||
resolveWithFullResponse: true
|
||||
}
|
||||
rp(options)
|
||||
|
||||
_.defaults options, {
|
||||
url,
|
||||
proxy: @proxy,
|
||||
jar,
|
||||
simple: false,
|
||||
followRedirect: false,
|
||||
resolveWithFullResponse: true
|
||||
}
|
||||
rp(options)
|
||||
open = =>
|
||||
Promise.all([
|
||||
## open our https server
|
||||
httpsServer.start(8443),
|
||||
|
||||
open = =>
|
||||
Promise.all([
|
||||
## open our https server
|
||||
httpsServer.start(8443),
|
||||
## and open our cypress server
|
||||
@server = Server(Watchers())
|
||||
|
||||
## and open our cypress server
|
||||
@server = Server(Watchers())
|
||||
@server.open(cfg)
|
||||
.spread (port) =>
|
||||
if initialUrl
|
||||
@server._onDomainSet(initialUrl)
|
||||
|
||||
@server.open(cfg)
|
||||
.spread (port) =>
|
||||
if initialUrl
|
||||
@server._onDomainSet(initialUrl)
|
||||
@srv = @server.getHttpServer()
|
||||
|
||||
@srv = @server.getHttpServer()
|
||||
@session = new (Session({app: @srv}))
|
||||
|
||||
@session = new (Session({app: @srv}))
|
||||
@proxy = "http://localhost:" + port
|
||||
])
|
||||
|
||||
@proxy = "http://localhost:" + port
|
||||
])
|
||||
|
||||
if @server
|
||||
Promise.join(
|
||||
httpsServer.stop()
|
||||
@server.close()
|
||||
)
|
||||
.then(open)
|
||||
else
|
||||
open()
|
||||
if @server
|
||||
Promise.join(
|
||||
httpsServer.stop()
|
||||
@server.close()
|
||||
)
|
||||
.then(open)
|
||||
else
|
||||
open()
|
||||
|
||||
afterEach ->
|
||||
evilDns.clear()
|
||||
|
||||
@@ -27,61 +27,61 @@ describe "Server", ->
|
||||
## get all the config defaults
|
||||
## and allow us to override them
|
||||
## for each test
|
||||
cfg = config.set(obj)
|
||||
config.set(obj)
|
||||
.then (cfg) =>
|
||||
## use a jar for each test
|
||||
## but reset it automatically
|
||||
## between test
|
||||
jar = rp.jar()
|
||||
|
||||
## use a jar for each test
|
||||
## but reset it automatically
|
||||
## between test
|
||||
jar = rp.jar()
|
||||
## use a custom request promise
|
||||
## to automatically backfill these
|
||||
## options including our proxy
|
||||
@rp = (options = {}) =>
|
||||
if _.isString(options)
|
||||
url = options
|
||||
options = {}
|
||||
|
||||
## use a custom request promise
|
||||
## to automatically backfill these
|
||||
## options including our proxy
|
||||
@rp = (options = {}) =>
|
||||
if _.isString(options)
|
||||
url = options
|
||||
options = {}
|
||||
_.defaults options, {
|
||||
url
|
||||
proxy: @proxy
|
||||
jar
|
||||
simple: false
|
||||
followRedirect: false
|
||||
resolveWithFullResponse: true
|
||||
}
|
||||
rp(options)
|
||||
|
||||
_.defaults options, {
|
||||
url
|
||||
proxy: @proxy
|
||||
jar
|
||||
simple: false
|
||||
followRedirect: false
|
||||
resolveWithFullResponse: true
|
||||
}
|
||||
rp(options)
|
||||
open = =>
|
||||
Promise.all([
|
||||
## open our https server
|
||||
httpsServer.start(8443),
|
||||
|
||||
open = =>
|
||||
Promise.all([
|
||||
## open our https server
|
||||
httpsServer.start(8443),
|
||||
## and open our cypress server
|
||||
@server = Server()
|
||||
|
||||
## and open our cypress server
|
||||
@server = Server()
|
||||
@server.open(cfg)
|
||||
.spread (port) =>
|
||||
if initialUrl
|
||||
@server._onDomainSet(initialUrl)
|
||||
|
||||
@server.open(cfg)
|
||||
.spread (port) =>
|
||||
if initialUrl
|
||||
@server._onDomainSet(initialUrl)
|
||||
@srv = @server.getHttpServer()
|
||||
|
||||
@srv = @server.getHttpServer()
|
||||
# @session = new (Session({app: @srv}))
|
||||
|
||||
# @session = new (Session({app: @srv}))
|
||||
@proxy = "http://localhost:" + port
|
||||
|
||||
@proxy = "http://localhost:" + port
|
||||
@fileServer = @server._fileServer.address()
|
||||
])
|
||||
|
||||
@fileServer = @server._fileServer.address()
|
||||
])
|
||||
|
||||
if @server
|
||||
Promise.join(
|
||||
httpsServer.stop()
|
||||
@server.close()
|
||||
)
|
||||
.then(open)
|
||||
else
|
||||
open()
|
||||
if @server
|
||||
Promise.join(
|
||||
httpsServer.stop()
|
||||
@server.close()
|
||||
)
|
||||
.then(open)
|
||||
else
|
||||
open()
|
||||
|
||||
afterEach ->
|
||||
nock.cleanAll()
|
||||
|
||||
@@ -2,6 +2,9 @@ require("../../spec_helper")
|
||||
|
||||
_ = require("lodash")
|
||||
EE = require("events")
|
||||
la = require("lazy-ass")
|
||||
check = require("check-more-types")
|
||||
|
||||
menu = require("#{root}../lib/gui/menu")
|
||||
Windows = require("#{root}../lib/gui/windows")
|
||||
electron = require("#{root}../lib/browsers/electron")
|
||||
@@ -31,8 +34,10 @@ describe "lib/browsers/electron", ->
|
||||
context ".open", ->
|
||||
beforeEach ->
|
||||
@sandbox.stub(electron, "_render").resolves(@win)
|
||||
state = savedState()
|
||||
@sandbox.stub(state, "get").resolves(@state)
|
||||
savedState()
|
||||
.then (state) =>
|
||||
la(check.fn(state.get), "state is missing .get to stub", state)
|
||||
@sandbox.stub(state, "get").resolves(@state)
|
||||
|
||||
it "calls render with url, state, and options", ->
|
||||
electron.open("electron", @url, @options, @automation)
|
||||
|
||||
@@ -2,6 +2,7 @@ require("../spec_helper")
|
||||
|
||||
_ = require("lodash")
|
||||
path = require("path")
|
||||
R = require("ramda")
|
||||
config = require("#{root}lib/config")
|
||||
configUtil = require("#{root}lib/util/config")
|
||||
scaffold = require("#{root}lib/scaffold")
|
||||
@@ -412,7 +413,10 @@ describe "lib/config", ->
|
||||
beforeEach ->
|
||||
@defaults = (prop, value, cfg = {}, options = {}) =>
|
||||
cfg.projectRoot = "/foo/bar/"
|
||||
expect(config.mergeDefaults(cfg, options)[prop]).to.deep.eq(value)
|
||||
config.mergeDefaults(cfg, options)
|
||||
.then R.prop(prop)
|
||||
.then (result) ->
|
||||
expect(result).to.deep.eq(value)
|
||||
|
||||
it "port=null", ->
|
||||
@defaults "port", null
|
||||
@@ -504,29 +508,29 @@ describe "lib/config", ->
|
||||
@defaults "supportFile", false, {supportFile: false}
|
||||
|
||||
it "resets numTestsKeptInMemory to 0 when headless", ->
|
||||
cfg = config.mergeDefaults({projectRoot: "/foo/bar/"}, {isTextTerminal: true})
|
||||
|
||||
expect(cfg.numTestsKeptInMemory).to.eq(0)
|
||||
config.mergeDefaults({projectRoot: "/foo/bar/"}, {isTextTerminal: true})
|
||||
.then (cfg) ->
|
||||
expect(cfg.numTestsKeptInMemory).to.eq(0)
|
||||
|
||||
it "resets watchForFileChanges to false when headless", ->
|
||||
cfg = config.mergeDefaults({projectRoot: "/foo/bar/"}, {isTextTerminal: true})
|
||||
|
||||
expect(cfg.watchForFileChanges).to.be.false
|
||||
config.mergeDefaults({projectRoot: "/foo/bar/"}, {isTextTerminal: true})
|
||||
.then (cfg) ->
|
||||
expect(cfg.watchForFileChanges).to.be.false
|
||||
|
||||
it "can override morgan in options", ->
|
||||
cfg = config.mergeDefaults({projectRoot: "/foo/bar/"}, {morgan: false})
|
||||
|
||||
expect(cfg.morgan).to.be.false
|
||||
config.mergeDefaults({projectRoot: "/foo/bar/"}, {morgan: false})
|
||||
.then (cfg) ->
|
||||
expect(cfg.morgan).to.be.false
|
||||
|
||||
it "can override isTextTerminal in options", ->
|
||||
cfg = config.mergeDefaults({projectRoot: "/foo/bar/"}, {isTextTerminal: true})
|
||||
|
||||
expect(cfg.isTextTerminal).to.be.true
|
||||
config.mergeDefaults({projectRoot: "/foo/bar/"}, {isTextTerminal: true})
|
||||
.then (cfg) ->
|
||||
expect(cfg.isTextTerminal).to.be.true
|
||||
|
||||
it "can override socketId in options", ->
|
||||
cfg = config.mergeDefaults({projectRoot: "/foo/bar/"}, {socketId: 1234})
|
||||
|
||||
expect(cfg.socketId).to.eq(1234)
|
||||
config.mergeDefaults({projectRoot: "/foo/bar/"}, {socketId: 1234})
|
||||
.then (cfg) ->
|
||||
expect(cfg.socketId).to.eq(1234)
|
||||
|
||||
it "deletes envFile", ->
|
||||
obj = {
|
||||
@@ -541,15 +545,15 @@ describe "lib/config", ->
|
||||
}
|
||||
}
|
||||
|
||||
cfg = config.mergeDefaults(obj)
|
||||
|
||||
expect(cfg.environmentVariables).to.deep.eq({
|
||||
foo: "bar"
|
||||
bar: "baz"
|
||||
version: "1.0.1"
|
||||
})
|
||||
expect(cfg.env).to.eq(process.env["CYPRESS_ENV"])
|
||||
expect(cfg).not.to.have.property("envFile")
|
||||
config.mergeDefaults(obj)
|
||||
.then (cfg) ->
|
||||
expect(cfg.environmentVariables).to.deep.eq({
|
||||
foo: "bar"
|
||||
bar: "baz"
|
||||
version: "1.0.1"
|
||||
})
|
||||
expect(cfg.env).to.eq(process.env["CYPRESS_ENV"])
|
||||
expect(cfg).not.to.have.property("envFile")
|
||||
|
||||
it "merges env into @config.env", ->
|
||||
obj = {
|
||||
@@ -568,14 +572,14 @@ describe "lib/config", ->
|
||||
}
|
||||
}
|
||||
|
||||
cfg = config.mergeDefaults(obj, options)
|
||||
|
||||
expect(cfg.environmentVariables).to.deep.eq({
|
||||
host: "localhost"
|
||||
user: "brian"
|
||||
version: "0.13.1"
|
||||
foo: "bar"
|
||||
})
|
||||
config.mergeDefaults(obj, options)
|
||||
.then (cfg) ->
|
||||
expect(cfg.environmentVariables).to.deep.eq({
|
||||
host: "localhost"
|
||||
user: "brian"
|
||||
version: "0.13.1"
|
||||
foo: "bar"
|
||||
})
|
||||
|
||||
describe ".resolved", ->
|
||||
it "sets reporter and port to cli", ->
|
||||
@@ -588,38 +592,38 @@ describe "lib/config", ->
|
||||
port: 1234
|
||||
}
|
||||
|
||||
cfg = config.mergeDefaults(obj, options)
|
||||
|
||||
expect(cfg.resolved).to.deep.eq({
|
||||
port: { value: 1234, from: "cli" },
|
||||
hosts: { value: null, from: "default" }
|
||||
reporter: { value: "json", from: "cli" },
|
||||
reporterOptions: { value: null, from: "default" },
|
||||
baseUrl: { value: null, from: "default" },
|
||||
defaultCommandTimeout: { value: 4000, from: "default" },
|
||||
pageLoadTimeout: { value: 60000, from: "default" },
|
||||
requestTimeout: { value: 5000, from: "default" },
|
||||
responseTimeout: { value: 30000, from: "default" },
|
||||
execTimeout: { value: 60000, from: "default" },
|
||||
screenshotOnHeadlessFailure:{ value: true, from: "default" },
|
||||
numTestsKeptInMemory: { value: 50, from: "default" },
|
||||
waitForAnimations: { value: true, from: "default" },
|
||||
animationDistanceThreshold: { value: 5, from: "default" },
|
||||
trashAssetsBeforeHeadlessRuns: { value: true, from: "default" },
|
||||
watchForFileChanges: { value: true, from: "default" },
|
||||
chromeWebSecurity: { value: true, from: "default" },
|
||||
viewportWidth: { value: 1000, from: "default" },
|
||||
viewportHeight: { value: 660, from: "default" },
|
||||
fileServerFolder: { value: "", from: "default" },
|
||||
videoRecording: { value: true, from: "default" }
|
||||
videoCompression: { value: 32, from: "default" }
|
||||
videosFolder: { value: "cypress/videos", from: "default" },
|
||||
supportFile: { value: "cypress/support", from: "default" },
|
||||
fixturesFolder: { value: "cypress/fixtures", from: "default" },
|
||||
integrationFolder: { value: "cypress/integration", from: "default" },
|
||||
screenshotsFolder: { value: "cypress/screenshots", from: "default" },
|
||||
environmentVariables: { }
|
||||
})
|
||||
config.mergeDefaults(obj, options)
|
||||
.then (cfg) ->
|
||||
expect(cfg.resolved).to.deep.eq({
|
||||
port: { value: 1234, from: "cli" },
|
||||
hosts: { value: null, from: "default" }
|
||||
reporter: { value: "json", from: "cli" },
|
||||
reporterOptions: { value: null, from: "default" },
|
||||
baseUrl: { value: null, from: "default" },
|
||||
defaultCommandTimeout: { value: 4000, from: "default" },
|
||||
pageLoadTimeout: { value: 60000, from: "default" },
|
||||
requestTimeout: { value: 5000, from: "default" },
|
||||
responseTimeout: { value: 30000, from: "default" },
|
||||
execTimeout: { value: 60000, from: "default" },
|
||||
screenshotOnHeadlessFailure:{ value: true, from: "default" },
|
||||
numTestsKeptInMemory: { value: 50, from: "default" },
|
||||
waitForAnimations: { value: true, from: "default" },
|
||||
animationDistanceThreshold: { value: 5, from: "default" },
|
||||
trashAssetsBeforeHeadlessRuns: { value: true, from: "default" },
|
||||
watchForFileChanges: { value: true, from: "default" },
|
||||
chromeWebSecurity: { value: true, from: "default" },
|
||||
viewportWidth: { value: 1000, from: "default" },
|
||||
viewportHeight: { value: 660, from: "default" },
|
||||
fileServerFolder: { value: "", from: "default" },
|
||||
videoRecording: { value: true, from: "default" }
|
||||
videoCompression: { value: 32, from: "default" }
|
||||
videosFolder: { value: "cypress/videos", from: "default" },
|
||||
supportFile: { value: "cypress/support", from: "default" },
|
||||
fixturesFolder: { value: "cypress/fixtures", from: "default" },
|
||||
integrationFolder: { value: "cypress/integration", from: "default" },
|
||||
screenshotsFolder: { value: "cypress/screenshots", from: "default" },
|
||||
environmentVariables: { }
|
||||
})
|
||||
|
||||
it "sets config, envFile and env", ->
|
||||
@sandbox.stub(config, "getProcessEnvVars").returns({quux: "quux"})
|
||||
@@ -641,55 +645,55 @@ describe "lib/config", ->
|
||||
|
||||
options = {}
|
||||
|
||||
cfg = config.mergeDefaults(obj, options)
|
||||
|
||||
expect(cfg.resolved).to.deep.eq({
|
||||
port: { value: 2020, from: "config" },
|
||||
hosts: { value: null, from: "default" }
|
||||
reporter: { value: "spec", from: "default" },
|
||||
reporterOptions: { value: null, from: "default" },
|
||||
baseUrl: { value: "http://localhost:8080", from: "config" },
|
||||
defaultCommandTimeout: { value: 4000, from: "default" },
|
||||
pageLoadTimeout: { value: 60000, from: "default" },
|
||||
requestTimeout: { value: 5000, from: "default" },
|
||||
responseTimeout: { value: 30000, from: "default" },
|
||||
execTimeout: { value: 60000, from: "default" },
|
||||
numTestsKeptInMemory: { value: 50, from: "default" },
|
||||
waitForAnimations: { value: true, from: "default" },
|
||||
animationDistanceThreshold: { value: 5, from: "default" },
|
||||
screenshotOnHeadlessFailure:{ value: true, from: "default" },
|
||||
trashAssetsBeforeHeadlessRuns: { value: true, from: "default" },
|
||||
watchForFileChanges: { value: true, from: "default" },
|
||||
chromeWebSecurity: { value: true, from: "default" },
|
||||
viewportWidth: { value: 1000, from: "default" },
|
||||
viewportHeight: { value: 660, from: "default" },
|
||||
fileServerFolder: { value: "", from: "default" },
|
||||
videoRecording: { value: true, from: "default" }
|
||||
videoCompression: { value: 32, from: "default" }
|
||||
videosFolder: { value: "cypress/videos", from: "default" },
|
||||
supportFile: { value: "cypress/support", from: "default" },
|
||||
fixturesFolder: { value: "cypress/fixtures", from: "default" },
|
||||
integrationFolder: { value: "cypress/integration", from: "default" },
|
||||
screenshotsFolder: { value: "cypress/screenshots", from: "default" },
|
||||
environmentVariables: {
|
||||
foo: {
|
||||
value: "foo"
|
||||
from: "config"
|
||||
config.mergeDefaults(obj, options)
|
||||
.then (cfg) ->
|
||||
expect(cfg.resolved).to.deep.eq({
|
||||
port: { value: 2020, from: "config" },
|
||||
hosts: { value: null, from: "default" }
|
||||
reporter: { value: "spec", from: "default" },
|
||||
reporterOptions: { value: null, from: "default" },
|
||||
baseUrl: { value: "http://localhost:8080", from: "config" },
|
||||
defaultCommandTimeout: { value: 4000, from: "default" },
|
||||
pageLoadTimeout: { value: 60000, from: "default" },
|
||||
requestTimeout: { value: 5000, from: "default" },
|
||||
responseTimeout: { value: 30000, from: "default" },
|
||||
execTimeout: { value: 60000, from: "default" },
|
||||
numTestsKeptInMemory: { value: 50, from: "default" },
|
||||
waitForAnimations: { value: true, from: "default" },
|
||||
animationDistanceThreshold: { value: 5, from: "default" },
|
||||
screenshotOnHeadlessFailure:{ value: true, from: "default" },
|
||||
trashAssetsBeforeHeadlessRuns: { value: true, from: "default" },
|
||||
watchForFileChanges: { value: true, from: "default" },
|
||||
chromeWebSecurity: { value: true, from: "default" },
|
||||
viewportWidth: { value: 1000, from: "default" },
|
||||
viewportHeight: { value: 660, from: "default" },
|
||||
fileServerFolder: { value: "", from: "default" },
|
||||
videoRecording: { value: true, from: "default" }
|
||||
videoCompression: { value: 32, from: "default" }
|
||||
videosFolder: { value: "cypress/videos", from: "default" },
|
||||
supportFile: { value: "cypress/support", from: "default" },
|
||||
fixturesFolder: { value: "cypress/fixtures", from: "default" },
|
||||
integrationFolder: { value: "cypress/integration", from: "default" },
|
||||
screenshotsFolder: { value: "cypress/screenshots", from: "default" },
|
||||
environmentVariables: {
|
||||
foo: {
|
||||
value: "foo"
|
||||
from: "config"
|
||||
}
|
||||
bar: {
|
||||
value: "bar"
|
||||
from: "envFile"
|
||||
}
|
||||
baz: {
|
||||
value: "baz"
|
||||
from: "cli"
|
||||
}
|
||||
quux: {
|
||||
value: "quux"
|
||||
from: "env"
|
||||
}
|
||||
}
|
||||
bar: {
|
||||
value: "bar"
|
||||
from: "envFile"
|
||||
}
|
||||
baz: {
|
||||
value: "baz"
|
||||
from: "cli"
|
||||
}
|
||||
quux: {
|
||||
value: "quux"
|
||||
from: "env"
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
context ".parseEnv", ->
|
||||
it "merges together env from config, env from file, env from process, and env from CLI", ->
|
||||
@@ -799,8 +803,9 @@ describe "lib/config", ->
|
||||
obj = {
|
||||
projectRoot: "/_test-output/path/to/project"
|
||||
}
|
||||
|
||||
expect(config.setSupportFileAndFolder(obj)).to.eql(obj)
|
||||
config.setSupportFileAndFolder(obj)
|
||||
.then (result) ->
|
||||
expect(result).to.eql(obj)
|
||||
|
||||
it "sets the full path to the supportFile and supportFolder if it exists", ->
|
||||
projectRoot = process.cwd()
|
||||
@@ -810,14 +815,15 @@ describe "lib/config", ->
|
||||
supportFile: "test/unit/config_spec.coffee"
|
||||
})
|
||||
|
||||
expect(config.setSupportFileAndFolder(obj)).to.eql({
|
||||
projectRoot: projectRoot
|
||||
supportFile: "#{projectRoot}/test/unit/config_spec.coffee"
|
||||
supportFolder: "#{projectRoot}/test/unit"
|
||||
})
|
||||
config.setSupportFileAndFolder(obj)
|
||||
.then (result) ->
|
||||
expect(result).to.eql({
|
||||
projectRoot: projectRoot
|
||||
supportFile: "#{projectRoot}/test/unit/config_spec.coffee"
|
||||
supportFolder: "#{projectRoot}/test/unit"
|
||||
})
|
||||
|
||||
it "sets the supportFile to default index.js if it does not exist, support folder does not exist, and supportFile is the default", ->
|
||||
@sandbox.stub(fs, "existsSync").returns(false)
|
||||
projectRoot = process.cwd()
|
||||
|
||||
obj = config.setAbsolutePaths({
|
||||
@@ -825,11 +831,13 @@ describe "lib/config", ->
|
||||
supportFile: "cypress/support"
|
||||
})
|
||||
|
||||
expect(config.setSupportFileAndFolder(obj)).to.eql({
|
||||
projectRoot: projectRoot
|
||||
supportFile: "#{projectRoot}/cypress/support/index.js"
|
||||
supportFolder: "#{projectRoot}/cypress/support"
|
||||
})
|
||||
config.setSupportFileAndFolder(obj)
|
||||
.then (result) ->
|
||||
expect(result).to.eql({
|
||||
projectRoot: projectRoot
|
||||
supportFile: "#{projectRoot}/cypress/support/index.js"
|
||||
supportFolder: "#{projectRoot}/cypress/support"
|
||||
})
|
||||
|
||||
it "sets the supportFile to false if it does not exist, support folder exists, and supportFile is the default", ->
|
||||
projectRoot = path.join(process.cwd(), "test/support/fixtures/projects/blank-support")
|
||||
@@ -839,10 +847,12 @@ describe "lib/config", ->
|
||||
supportFile: "cypress/support"
|
||||
})
|
||||
|
||||
expect(config.setSupportFileAndFolder(obj)).to.eql({
|
||||
projectRoot: projectRoot
|
||||
supportFile: false
|
||||
})
|
||||
config.setSupportFileAndFolder(obj)
|
||||
.then (result) ->
|
||||
expect(result).to.eql({
|
||||
projectRoot: projectRoot
|
||||
supportFile: false
|
||||
})
|
||||
|
||||
it "throws error if supportFile is not default and does not exist", ->
|
||||
projectRoot = process.cwd()
|
||||
@@ -852,7 +862,9 @@ describe "lib/config", ->
|
||||
supportFile: "does/not/exist"
|
||||
})
|
||||
|
||||
expect(-> config.setSupportFileAndFolder(obj)).to.throw("Support file missing or invalid.")
|
||||
config.setSupportFileAndFolder(obj)
|
||||
.catch (err) ->
|
||||
expect(err.message).to.include("Support file missing or invalid.")
|
||||
|
||||
context ".setParentTestsPaths", ->
|
||||
it "sets parentTestsFolder and parentTestsFolderDisplay", ->
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
require("../../spec_helper")
|
||||
|
||||
_ = require("lodash")
|
||||
delay = require("delay")
|
||||
EE = require("events").EventEmitter
|
||||
BrowserWindow = require("electron").BrowserWindow
|
||||
Windows = require("#{root}../lib/gui/windows")
|
||||
@@ -48,17 +49,18 @@ describe "lib/gui/windows", ->
|
||||
|
||||
context ".trackState", ->
|
||||
beforeEach ->
|
||||
@state = savedState()
|
||||
@sandbox.stub(@state, "set")
|
||||
savedState()
|
||||
.then (@state) =>
|
||||
@sandbox.stub(@state, "set")
|
||||
|
||||
@projectPath = undefined
|
||||
@keys = {
|
||||
width: "theWidth"
|
||||
height: "someHeight"
|
||||
x: "anX"
|
||||
y: "aY"
|
||||
devTools: "whatsUpWithDevTools"
|
||||
}
|
||||
@projectPath = undefined
|
||||
@keys = {
|
||||
width: "theWidth"
|
||||
height: "someHeight"
|
||||
x: "anX"
|
||||
y: "aY"
|
||||
devTools: "whatsUpWithDevTools"
|
||||
}
|
||||
|
||||
it "saves size and position when window resizes, debounced", ->
|
||||
## tried using useFakeTimers here, but it didn't work for some
|
||||
@@ -69,20 +71,23 @@ describe "lib/gui/windows", ->
|
||||
@win.emit("resize")
|
||||
|
||||
expect(_.debounce).to.be.called
|
||||
expect(@state.set).to.be.calledWith({
|
||||
theWidth: 1
|
||||
someHeight: 2
|
||||
anX: 3
|
||||
aY: 4
|
||||
})
|
||||
delay(100)
|
||||
.then () =>
|
||||
expect(@state.set).to.be.calledWith({
|
||||
theWidth: 1
|
||||
someHeight: 2
|
||||
anX: 3
|
||||
aY: 4
|
||||
})
|
||||
|
||||
it "returns if window isDestroyed on resize", ->
|
||||
@win.isDestroyed.returns(true)
|
||||
|
||||
Windows.trackState(@projectPath, @win, @keys)
|
||||
@win.emit("resize")
|
||||
|
||||
expect(@state.set).not.to.be.called
|
||||
delay(100)
|
||||
.then () =>
|
||||
expect(@state.set).not.to.be.called
|
||||
|
||||
it "saves position when window moves, debounced", ->
|
||||
## tried using useFakeTimers here, but it didn't work for some
|
||||
@@ -91,10 +96,12 @@ describe "lib/gui/windows", ->
|
||||
Windows.trackState(@projectPath, @win, @keys)
|
||||
@win.emit("moved")
|
||||
|
||||
expect(@state.set).to.be.calledWith({
|
||||
anX: 3
|
||||
aY: 4
|
||||
})
|
||||
delay(100)
|
||||
.then () =>
|
||||
expect(@state.set).to.be.calledWith({
|
||||
anX: 3
|
||||
aY: 4
|
||||
})
|
||||
|
||||
it "returns if window isDestroyed on moved", ->
|
||||
@win.isDestroyed.returns(true)
|
||||
@@ -102,19 +109,25 @@ describe "lib/gui/windows", ->
|
||||
Windows.trackState(@projectPath, @win, @keys)
|
||||
@win.emit("moved")
|
||||
|
||||
expect(@state.set).not.to.be.called
|
||||
delay(100)
|
||||
.then () =>
|
||||
expect(@state.set).not.to.be.called
|
||||
|
||||
it "saves dev tools state when opened", ->
|
||||
Windows.trackState(@projectPath, @win, @keys)
|
||||
@win.webContents.emit("devtools-opened")
|
||||
|
||||
expect(@state.set).to.be.calledWith({whatsUpWithDevTools: true})
|
||||
delay(100)
|
||||
.then () =>
|
||||
expect(@state.set).to.be.calledWith({whatsUpWithDevTools: true})
|
||||
|
||||
it "saves dev tools state when closed", ->
|
||||
Windows.trackState(@projectPath, @win, @keys)
|
||||
@win.webContents.emit("devtools-closed")
|
||||
|
||||
expect(@state.set).to.be.calledWith({whatsUpWithDevTools: false})
|
||||
delay(100)
|
||||
.then () =>
|
||||
expect(@state.set).to.be.calledWith({whatsUpWithDevTools: false})
|
||||
|
||||
context ".automation", ->
|
||||
beforeEach ->
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
require("../spec_helper")
|
||||
|
||||
describe "misc tests", ->
|
||||
beforeEach () ->
|
||||
@sandbox.spy(console, "error")
|
||||
|
||||
it "warns when trying to use fs.existsSync", ->
|
||||
fs.existsSync(__filename)
|
||||
warning = "WARNING: fs sync methods can fail due to EMFILE errors"
|
||||
expect(console.error).to.be.calledWith(warning)
|
||||
# also print stack trace, maybe check that
|
||||
|
||||
context "fs.pathExists", ->
|
||||
it "finds this file", ->
|
||||
fs.pathExists(__filename)
|
||||
.then (found) ->
|
||||
expect(found).to.be.true
|
||||
|
||||
it "does not find non-existent file", ->
|
||||
fs.pathExists('does-not-exist')
|
||||
.then (found) ->
|
||||
expect(found).to.be.false
|
||||
@@ -29,8 +29,9 @@ describe "lib/project", ->
|
||||
settings.read(@todosPath).then (obj = {}) =>
|
||||
{@projectId} = obj
|
||||
|
||||
@config = config.set({projectName: "project", projectRoot: "/foo/bar"})
|
||||
@project = Project(@todosPath)
|
||||
config.set({projectName: "project", projectRoot: "/foo/bar"})
|
||||
.then (@config) =>
|
||||
@project = Project(@todosPath)
|
||||
|
||||
afterEach ->
|
||||
Fixtures.remove()
|
||||
@@ -51,10 +52,12 @@ describe "lib/project", ->
|
||||
@sandbox.stub(config, "get").withArgs(@todosPath).resolves({ integrationFolder })
|
||||
@sandbox.stub(@project, "determineIsNewProject").withArgs(integrationFolder).resolves(false)
|
||||
@project.cfg = { integrationFolder }
|
||||
savedState(@project.projectRoot).remove()
|
||||
savedState(@project.projectRoot)
|
||||
.then (state) -> state.remove()
|
||||
|
||||
afterEach ->
|
||||
savedState(@project.projectRoot).remove()
|
||||
savedState(@project.projectRoot)
|
||||
.then (state) -> state.remove()
|
||||
|
||||
it "saves state without modification", ->
|
||||
@project.saveState()
|
||||
@@ -88,18 +91,19 @@ describe "lib/project", ->
|
||||
@sandbox.stub(@project, "determineIsNewProject").withArgs(integrationFolder).resolves(false)
|
||||
|
||||
it "calls config.get with projectRoot + options + saved state", ->
|
||||
state = savedState(@todosPath)
|
||||
@sandbox.stub(state, "get").resolves({ reporterWidth: 225 })
|
||||
@project.getConfig({foo: "bar"})
|
||||
.then (cfg) ->
|
||||
expect(cfg).to.deep.eq({
|
||||
integrationFolder
|
||||
isNewProject: false
|
||||
baz: "quux"
|
||||
state: {
|
||||
reporterWidth: 225
|
||||
}
|
||||
})
|
||||
savedState(@todosPath)
|
||||
.then (state) =>
|
||||
@sandbox.stub(state, "get").resolves({ reporterWidth: 225 })
|
||||
@project.getConfig({foo: "bar"})
|
||||
.then (cfg) ->
|
||||
expect(cfg).to.deep.eq({
|
||||
integrationFolder
|
||||
isNewProject: false
|
||||
baz: "quux"
|
||||
state: {
|
||||
reporterWidth: 225
|
||||
}
|
||||
})
|
||||
|
||||
it "resolves if cfg is already set", ->
|
||||
@project.cfg = {
|
||||
@@ -115,19 +119,20 @@ describe "lib/project", ->
|
||||
})
|
||||
|
||||
it "sets cfg.isNewProject to true when state.showedOnBoardingModal is true", ->
|
||||
state = savedState(@todosPath)
|
||||
@sandbox.stub(state, "get").resolves({ showedOnBoardingModal: true })
|
||||
savedState(@todosPath)
|
||||
.then (state) =>
|
||||
@sandbox.stub(state, "get").resolves({ showedOnBoardingModal: true })
|
||||
|
||||
@project.getConfig({foo: "bar"})
|
||||
.then (cfg) ->
|
||||
expect(cfg).to.deep.eq({
|
||||
integrationFolder
|
||||
isNewProject: false
|
||||
baz: "quux"
|
||||
state: {
|
||||
showedOnBoardingModal: true
|
||||
}
|
||||
})
|
||||
@project.getConfig({foo: "bar"})
|
||||
.then (cfg) ->
|
||||
expect(cfg).to.deep.eq({
|
||||
integrationFolder
|
||||
isNewProject: false
|
||||
baz: "quux"
|
||||
state: {
|
||||
showedOnBoardingModal: true
|
||||
}
|
||||
})
|
||||
|
||||
context "#open", ->
|
||||
beforeEach ->
|
||||
@@ -143,7 +148,7 @@ describe "lib/project", ->
|
||||
@project.open(opts).then =>
|
||||
expect(@project.watchSettingsAndStartWebsockets).to.be.calledWith(opts, @project.cfg)
|
||||
|
||||
it "calls #scaffold with server config", ->
|
||||
it "calls #scaffold with server config promise", ->
|
||||
@project.open().then =>
|
||||
expect(@project.scaffold).to.be.calledWith(@config)
|
||||
|
||||
@@ -281,7 +286,7 @@ describe "lib/project", ->
|
||||
|
||||
context "#watchSupportFile", ->
|
||||
beforeEach ->
|
||||
@sandbox.stub(fs, "existsSync").returns(true)
|
||||
@sandbox.stub(fs, "pathExists").resolves(true)
|
||||
@project = Project("/_test-output/path/to/project")
|
||||
@project.server = {onTestFileChange: @sandbox.spy()}
|
||||
@watchBundle = @sandbox.stub(@project.watchers, "watchBundle").resolves()
|
||||
@@ -297,24 +302,26 @@ describe "lib/project", ->
|
||||
|
||||
it "calls watchers.watchBundle with relative path to file", ->
|
||||
@project.watchSupportFile(@config)
|
||||
|
||||
expect(@watchBundle).to.be.calledWith("foo/bar.js", @config)
|
||||
.then () =>
|
||||
expect(@watchBundle).to.be.calledWith("foo/bar.js", @config)
|
||||
|
||||
it "calls server.onTestFileChange when file changes", ->
|
||||
@project.watchSupportFile(@config)
|
||||
@watchBundle.firstCall.args[2].onChange()
|
||||
|
||||
expect(@project.server.onTestFileChange).to.be.calledWith("foo/bar.js")
|
||||
.then () =>
|
||||
@watchBundle.firstCall.args[2].onChange()
|
||||
expect(@project.server.onTestFileChange).to.be.calledWith("foo/bar.js")
|
||||
|
||||
it "does not add change listener when {watchForFileChanges: false}", ->
|
||||
@config.watchForFileChanges = false
|
||||
@project.watchSupportFile(@config)
|
||||
|
||||
expect(@watchBundle.firstCall.args[2]).to.be.undefined
|
||||
.then () =>
|
||||
expect(@watchBundle.firstCall.args[2]).to.be.undefined
|
||||
|
||||
it "throws when support file does not exist", ->
|
||||
fs.existsSync.returns(false)
|
||||
expect(=> @project.watchSupportFile(@config)).to.throw("Support file missing or invalid.")
|
||||
fs.pathExists.resolves(false)
|
||||
@project.watchSupportFile(@config)
|
||||
.catch (e) ->
|
||||
expect(e.message).to.include("Support file missing or invalid.")
|
||||
|
||||
context "#watchSettingsAndStartWebsockets", ->
|
||||
beforeEach ->
|
||||
|
||||
@@ -35,18 +35,24 @@ describe "lib/saved_state", ->
|
||||
it "is a function", ->
|
||||
expect(savedState).to.be.a("function")
|
||||
|
||||
it "returns an instance of FileUtil", ->
|
||||
expect(savedState()).to.be.instanceof(FileUtil)
|
||||
it "resolves with an instance of FileUtil", ->
|
||||
savedState()
|
||||
.then (state) ->
|
||||
expect(state).to.be.instanceof(FileUtil)
|
||||
|
||||
it "sets file path to app data path and file name to 'state'", ->
|
||||
statePath = savedState().path
|
||||
expected = path.join(appData.path(), "projects", "__global__", "state.json")
|
||||
expect(statePath).to.equal(expected)
|
||||
savedState()
|
||||
.then (state) ->
|
||||
statePath = state.path
|
||||
expected = path.join(appData.path(), "projects", "__global__", "state.json")
|
||||
expect(statePath).to.equal(expected)
|
||||
|
||||
it "caches state file instance per path", ->
|
||||
a = savedState("/foo/bar")
|
||||
b = savedState("/foo/bar")
|
||||
expect(a).to.equal(b)
|
||||
Promise.all([
|
||||
savedState("/foo/bar"),
|
||||
savedState("/foo/bar")
|
||||
]).spread (a, b) ->
|
||||
expect(a).to.equal(b)
|
||||
|
||||
it "returns different state file for different path", ->
|
||||
a = savedState("/foo/bar")
|
||||
|
||||
@@ -16,8 +16,10 @@ mockery.registerMock("morgan", -> morganFn)
|
||||
|
||||
describe "lib/server", ->
|
||||
beforeEach ->
|
||||
@config = config.set({projectRoot: "/foo/bar/"})
|
||||
@server = Server()
|
||||
config.set({projectRoot: "/foo/bar/"})
|
||||
.then (cfg) =>
|
||||
@config = cfg
|
||||
@server = Server()
|
||||
|
||||
afterEach ->
|
||||
@server and @server.close()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
require("../spec_helper")
|
||||
|
||||
path = require("path")
|
||||
R = require("ramda")
|
||||
settings = require("#{root}lib/util/settings")
|
||||
|
||||
projectRoot = process.cwd()
|
||||
@@ -46,11 +47,16 @@ describe "lib/settings", ->
|
||||
expect(err.message).to.include("SyntaxError")
|
||||
expect(err.message).to.include(projectRoot)
|
||||
|
||||
noArguments = R.nAry(0)
|
||||
|
||||
it "does not write initial file", ->
|
||||
settings.readEnv(projectRoot)
|
||||
.then (obj) ->
|
||||
expect(obj).to.deep.eq({})
|
||||
expect(fs.existsSync("cypress.env.json")).to.be.false
|
||||
.then () ->
|
||||
fs.pathExists("cypress.env.json")
|
||||
.then (found) ->
|
||||
expect(found).to.be.false
|
||||
|
||||
context ".id", ->
|
||||
beforeEach ->
|
||||
|
||||
Reference in New Issue
Block a user