Issue 1140 (#1584)

* extract random string to util

* run specs in isolation, aggregate totalFailures, display output per spec, enable globbing for specs

* extract electron app ready into its own module

* WIP: e2e tests around spec isolation, snapshots, stdout, and complete test results

* rename 'headless' to 'runMode' for clarity

- WIP: sync up config values using the word ‘headless’
- TODO: sync up documentation as well
- TODO: rename ‘headed’ to ‘interactive mode’

* rename 'headed' to 'interactiveMode' for clarity

* fixes #1140

* fix merge conflict

* cleanup some leftover dead code, formatting [skip ci]
This commit is contained in:
Brian Mann
2018-04-15 01:45:40 -04:00
committed by GitHub
parent d2cf0d942c
commit ae19afa34b
14 changed files with 156 additions and 157 deletions

View File

@@ -149,11 +149,11 @@ module.exports = {
when options.runProject
## go into headless mode when running
## until completion + exit
options.mode = "headless"
options.mode = "run"
else
## set the default mode as headed
options.mode ?= "headed"
## set the default mode as interactive
options.mode ?= "interactive"
## remove mode from options
mode = options.mode
@@ -220,7 +220,7 @@ module.exports = {
.then(exit)
.catch(exitErr)
when "headless"
when "run"
## run headlessly and exit
## with num of totalFailures
@runElectron(mode, options)
@@ -228,7 +228,7 @@ module.exports = {
.then(exit)
.catch(exitErr)
when "headed"
when "interactive"
@runElectron(mode, options)
when "record"

View File

@@ -101,7 +101,6 @@ handleEvent = (options, bus, event, id, type, arg) ->
.catch(sendErr)
when "launch:browser"
# headless.createWindows(arg, true)
openProject.launch(arg.browser, arg.spec, {
projectPath: options.projectPath
onBrowserOpen: ->

View File

@@ -14,7 +14,7 @@ module.exports = {
withDevTools: false
})
## this set by modes/headed.coffee and needs to be preserved if the menu
## this set by modes/interactive.coffee and needs to be preserved if the menu
## is set again by launcher.coffee when the Electron browser is run
if options.onLogOutClicked
onLogOutClicked = options.onLogOutClicked

View File

@@ -2,7 +2,7 @@ module.exports = (mode, options) ->
switch mode
when "record"
require("./record").run(options)
when "headless"
require("./headless").run(options)
when "headed"
require("./headed").run(options)
when "run"
require("./run").run(options)
when "interactive"
require("./interactive").run(options)

View File

@@ -2,7 +2,7 @@ _ = require("lodash")
os = require("os")
chalk = require("chalk")
Promise = require("bluebird")
headless = require("./headless")
runMode = require("./run")
api = require("../api")
logger = require("../logger")
errors = require("../errors")
@@ -253,7 +253,7 @@ module.exports = {
didUploadAssets = false
headless.run(options)
runMode.run(options)
.then (results = {}) =>
## if we got a instanceId then attempt to
## upload these assets
@@ -263,7 +263,7 @@ module.exports = {
didUploadAssets = ret isnt null
.return(results)
.finally =>
headless.allDone()
runMode.allDone()
if didUploadAssets
stdout.restore()
@@ -271,6 +271,6 @@ module.exports = {
else
stdout.restore()
headless.allDone()
runMode.allDone()
return results
}

View File

@@ -5,7 +5,7 @@ chalk = require("chalk")
human = require("human-interval")
Promise = require("bluebird")
pkg = require("@packages/root")
debug = require("debug")("cypress:server:headless")
debug = require("debug")("cypress:server:run")
ss = require("../screenshots")
user = require("../user")
stats = require("../stats")

View File

@@ -9,7 +9,7 @@ nestedObjectsInCurlyBracesRe = /\{(.+?)\}/g
nestedArraysInSquareBracketsRe = /\[(.+?)\]/g
everythingAfterFirstEqualRe = /=(.+)/
whitelist = "cwd appPath execPath apiKey smokeTest getKey generateKey runProject project spec reporter reporterOptions port env ci record updating ping key logs clearLogs returnPkg version mode headed config exit exitWithCode browser headless outputPath group groupId parallel parallelId".split(" ")
whitelist = "cwd appPath execPath apiKey smokeTest getKey generateKey runProject project spec reporter reporterOptions port env ci record updating ping key logs clearLogs returnPkg version mode headed config exit exitWithCode browser runMode outputPath group groupId parallel parallelId".split(" ")
# returns true if the given string has double quote character "
# only at the last position.
@@ -86,7 +86,7 @@ module.exports = {
"clear-logs": "clearLogs"
"run-project": "runProject"
"return-pkg": "returnPkg"
"headless": "isTextTerminal"
"runMode": "isTextTerminal"
"exit-with-code": "exitWithCode"
"reporter-options": "reporterOptions"
"output-path": "outputPath"

View File

@@ -20,8 +20,8 @@ settings = require("#{root}lib/util/settings")
Events = require("#{root}lib/gui/events")
Windows = require("#{root}lib/gui/windows")
record = require("#{root}lib/modes/record")
headed = require("#{root}lib/modes/headed")
headless = require("#{root}lib/modes/headless")
interactiveMode = require("#{root}lib/modes/interactive")
runMode = require("#{root}lib/modes/run")
api = require("#{root}lib/api")
cwd = require("#{root}lib/cwd")
user = require("#{root}lib/user")
@@ -230,8 +230,8 @@ describe "lib/cypress", ->
context "--run-project", ->
beforeEach ->
@sandbox.stub(electron.app, "on").withArgs("ready").yieldsAsync()
@sandbox.stub(headless, "waitForSocketConnection")
@sandbox.stub(headless, "listenForProjectEnd").resolves({stats: {failures: 0} })
@sandbox.stub(runMode, "waitForSocketConnection")
@sandbox.stub(runMode, "listenForProjectEnd").resolves({stats: {failures: 0} })
@sandbox.stub(browsers, "open")
@sandbox.stub(commitInfo, "getRemoteOrigin").resolves("remoteOrigin")
@@ -242,7 +242,7 @@ describe "lib/cypress", ->
@expectExitWith(0)
it "runs project headlessly and exits with exit code 10", ->
@sandbox.stub(headless, "runSpecs").resolves({ totalFailures: 10 })
@sandbox.stub(runMode, "runSpecs").resolves({ totalFailures: 10 })
cypress.start(["--run-project=#{@todosPath}"])
.then =>
@@ -303,14 +303,14 @@ describe "lib/cypress", ->
expect(browsers.open).to.be.calledWithMatch("electron", {url: "http://localhost:8888/__/#/tests/integration/test2.coffee"})
@expectExitWith(0)
it "scaffolds out integration and example_spec if they do not exist when not headless", ->
it "scaffolds out integration and example_spec if they do not exist when not runMode", ->
config.get(@pristinePath)
.then (cfg) =>
fs.statAsync(cfg.integrationFolder)
.then ->
throw new Error("integrationFolder should not exist!")
.catch =>
cypress.start(["--run-project=#{@pristinePath}", "--no-headless"])
cypress.start(["--run-project=#{@pristinePath}", "--no-runMode"])
.then =>
fs.statAsync(cfg.integrationFolder)
.then =>
@@ -339,7 +339,7 @@ describe "lib/cypress", ->
.then =>
@expectExitWithErr("PROJECT_DOES_NOT_EXIST", @pristinePath)
it "does not scaffold integration or example_spec when headless", ->
it "does not scaffold integration or example_spec when runMode", ->
settings.write(@pristinePath, {})
.then =>
cypress.start(["--run-project=#{@pristinePath}"])
@@ -356,7 +356,7 @@ describe "lib/cypress", ->
.then ->
throw new Error("fixturesFolder should not exist!")
.catch =>
cypress.start(["--run-project=#{@pristinePath}", "--no-headless"])
cypress.start(["--run-project=#{@pristinePath}", "--no-runMode"])
.then =>
fs.statAsync(cfg.fixturesFolder)
.then =>
@@ -371,7 +371,7 @@ describe "lib/cypress", ->
.then ->
throw new Error("supportFolder should not exist!")
.catch {code: "ENOENT"}, =>
cypress.start(["--run-project=#{@pristinePath}", "--no-headless"])
cypress.start(["--run-project=#{@pristinePath}", "--no-runMode"])
.then =>
fs.statAsync(supportFolder)
.then =>
@@ -478,7 +478,7 @@ describe "lib/cypress", ->
outputPath = "./.results/results.json"
headless.listenForProjectEnd.resolves(_.clone(obj))
runMode.listenForProjectEnd.resolves(_.clone(obj))
cypress.start([
"--run-project=#{@todosPath}",
@@ -771,7 +771,7 @@ describe "lib/cypress", ->
describe "--port", ->
beforeEach ->
headless.listenForProjectEnd.resolves({stats: {failures: 0} })
runMode.listenForProjectEnd.resolves({stats: {failures: 0} })
it "can change the default port to 5555", ->
listen = @sandbox.spy(http.Server.prototype, "listen")
@@ -801,7 +801,7 @@ describe "lib/cypress", ->
process.env = _.omit(process.env, "CYPRESS_DEBUG")
headless.listenForProjectEnd.resolves({stats: {failures: 0} })
runMode.listenForProjectEnd.resolves({stats: {failures: 0} })
afterEach ->
process.env = @env
@@ -876,8 +876,8 @@ describe "lib/cypress", ->
remote: "https://github.com/foo/bar.git"
})
@sandbox.stub(browsers, "open")
@sandbox.stub(headless, "waitForSocketConnection")
@sandbox.stub(headless, "waitForTestsToFinishRunning").resolves({
@sandbox.stub(runMode, "waitForSocketConnection")
@sandbox.stub(runMode, "waitForTestsToFinishRunning").resolves({
stats: {
tests: 1
passes: 2
@@ -1129,7 +1129,7 @@ describe "lib/cypress", ->
expect(console.log).to.be.calledWith("abc123")
@expectExitWith(0)
context "headed", ->
context "interactive", ->
beforeEach ->
@win = {
on: @sandbox.stub()
@@ -1151,12 +1151,12 @@ describe "lib/cypress", ->
delete process.env.CYPRESS_responseTimeout
delete process.env.CYPRESS_watch_for_file_changes
it "passes options to headed.ready", ->
@sandbox.stub(headed, "ready")
it "passes options to interactiveMode.ready", ->
@sandbox.stub(interactiveMode, "ready")
cypress.start(["--updating", "--port=2121", "--config=pageLoadTimeout=1000"])
.then ->
expect(headed.ready).to.be.calledWithMatch({
expect(interactiveMode.ready).to.be.calledWithMatch({
updating: true
config: {
port: 2121
@@ -1266,8 +1266,8 @@ describe "lib/cypress", ->
context "no args", ->
beforeEach ->
@sandbox.stub(electron.app, "on").withArgs("ready").yieldsAsync()
@sandbox.stub(headed, "ready").resolves()
@sandbox.stub(interactiveMode, "ready").resolves()
it "runs headed and does not exit", ->
it "runs interactiveMode and does not exit", ->
cypress.start().then ->
expect(headed.ready).to.be.calledOnce
expect(interactiveMode.ready).to.be.calledOnce

View File

@@ -624,12 +624,12 @@ describe "lib/config", ->
hosts: "foo=bar|baz=quux"
})
it "resets numTestsKeptInMemory to 0 when headless", ->
it "resets numTestsKeptInMemory to 0 when runMode", ->
config.mergeDefaults({projectRoot: "/foo/bar/"}, {isTextTerminal: true})
.then (cfg) ->
expect(cfg.numTestsKeptInMemory).to.eq(0)
it "resets watchForFileChanges to false when headless", ->
it "resets watchForFileChanges to false when runMode", ->
config.mergeDefaults({projectRoot: "/foo/bar/"}, {isTextTerminal: true})
.then (cfg) ->
expect(cfg.watchForFileChanges).to.be.false

View File

@@ -7,31 +7,31 @@ user = require("#{root}../lib/user")
logger = require("#{root}../lib/logger")
Updater = require("#{root}../lib/updater")
savedState = require("#{root}../lib/saved_state")
headed = require("#{root}../lib/modes/headed")
menu = require("#{root}../lib/gui/menu")
Events = require("#{root}../lib/gui/events")
Windows = require("#{root}../lib/gui/windows")
interactiveMode = require("#{root}../lib/modes/interactive")
describe "gui/headed", ->
describe "gui/interactive", ->
context ".isMac", ->
it "returns true if os.platform is darwin", ->
@sandbox.stub(os, "platform").returns("darwin")
expect(headed.isMac()).to.be.true
expect(interactiveMode.isMac()).to.be.true
it "returns false if os.platform isnt darwin", ->
@sandbox.stub(os, "platform").returns("linux64")
expect(headed.isMac()).to.be.false
expect(interactiveMode.isMac()).to.be.false
context ".getWindowArgs", ->
it "exits process when onClose is called", ->
@sandbox.stub(process, "exit")
headed.getWindowArgs({}).onClose()
interactiveMode.getWindowArgs({}).onClose()
expect(process.exit).to.be.called
it "tracks state properties", ->
trackState = headed.getWindowArgs({}).trackState
trackState = interactiveMode.getWindowArgs({}).trackState
args = _.pick(trackState, "width", "height", "x", "y", "devTools")
@@ -44,28 +44,28 @@ describe "gui/headed", ->
})
it "renders with saved width if it exists", ->
expect(headed.getWindowArgs({appWidth: 1}).width).to.equal(1)
expect(interactiveMode.getWindowArgs({appWidth: 1}).width).to.equal(1)
it "renders with default width if no width saved", ->
expect(headed.getWindowArgs({}).width).to.equal(800)
expect(interactiveMode.getWindowArgs({}).width).to.equal(800)
it "renders with saved height if it exists", ->
expect(headed.getWindowArgs({appHeight: 2}).height).to.equal(2)
expect(interactiveMode.getWindowArgs({appHeight: 2}).height).to.equal(2)
it "renders with default height if no height saved", ->
expect(headed.getWindowArgs({}).height).to.equal(550)
expect(interactiveMode.getWindowArgs({}).height).to.equal(550)
it "renders with saved x if it exists", ->
expect(headed.getWindowArgs({appX: 3}).x).to.equal(3)
expect(interactiveMode.getWindowArgs({appX: 3}).x).to.equal(3)
it "renders with no x if no x saved", ->
expect(headed.getWindowArgs({}).x).to.be.undefined
expect(interactiveMode.getWindowArgs({}).x).to.be.undefined
it "renders with saved y if it exists", ->
expect(headed.getWindowArgs({appY: 4}).y).to.equal(4)
expect(interactiveMode.getWindowArgs({appY: 4}).y).to.equal(4)
it "renders with no y if no y saved", ->
expect(headed.getWindowArgs({}).y).to.be.undefined
expect(interactiveMode.getWindowArgs({}).y).to.be.undefined
describe "on window focus", ->
beforeEach ->
@@ -74,14 +74,14 @@ describe "gui/headed", ->
it "calls menu.set withDevTools: true when in dev env", ->
env = process.env["CYPRESS_ENV"]
process.env["CYPRESS_ENV"] = "development"
headed.getWindowArgs({}).onFocus()
interactiveMode.getWindowArgs({}).onFocus()
expect(menu.set.lastCall.args[0].withDevTools).to.be.true
process.env["CYPRESS_ENV"] = env
it "calls menu.set withDevTools: false when not in dev env", ->
env = process.env["CYPRESS_ENV"]
process.env["CYPRESS_ENV"] = "production"
headed.getWindowArgs({}).onFocus()
interactiveMode.getWindowArgs({}).onFocus()
expect(menu.set.lastCall.args[0].withDevTools).to.be.false
process.env["CYPRESS_ENV"] = env
@@ -102,31 +102,31 @@ describe "gui/headed", ->
@sandbox.stub(os, "platform").returns("someOs")
opts = {}
headed.ready(opts).then ->
interactiveMode.ready(opts).then ->
expect(Events.start).to.be.called
expect(Events.start.lastCall.args[0].onFocusTests).to.be.a("function")
expect(Events.start.lastCall.args[0].os).to.equal("someOs")
it "calls menu.set", ->
headed.ready({}).then ->
interactiveMode.ready({}).then ->
expect(menu.set).to.be.calledOnce
it "calls menu.set withDevTools: true when in dev env", ->
env = process.env["CYPRESS_ENV"]
process.env["CYPRESS_ENV"] = "development"
headed.ready({}).then ->
interactiveMode.ready({}).then ->
expect(menu.set.lastCall.args[0].withDevTools).to.be.true
process.env["CYPRESS_ENV"] = env
it "calls menu.set withDevTools: false when not in dev env", ->
env = process.env["CYPRESS_ENV"]
process.env["CYPRESS_ENV"] = "production"
headed.ready({}).then ->
interactiveMode.ready({}).then ->
expect(menu.set.lastCall.args[0].withDevTools).to.be.false
process.env["CYPRESS_ENV"] = env
it "resolves with win", ->
headed.ready({}).then (win) =>
interactiveMode.ready({}).then (win) =>
expect(win).to.eq(@win)
context ".run", ->
@@ -134,8 +134,8 @@ describe "gui/headed", ->
@sandbox.stub(electron.app, "on").withArgs("ready").yieldsAsync()
it "calls ready with options", ->
@sandbox.stub(headed, "ready")
@sandbox.stub(interactiveMode, "ready")
opts = {}
headed.run(opts).then ->
expect(headed.ready).to.be.calledWith(opts)
interactiveMode.run(opts).then ->
expect(interactiveMode.ready).to.be.calledWith(opts)

View File

@@ -10,7 +10,7 @@ upload = require("#{root}../lib/upload")
Project = require("#{root}../lib/project")
terminal = require("#{root}../lib/util/terminal")
record = require("#{root}../lib/modes/record")
headless = require("#{root}../lib/modes/headless")
runMode = require("#{root}../lib/modes/run")
ciProvider = require("#{root}../lib/util/ci_provider")
commitInfo = require("@cypress/commit-info")
snapshot = require("snap-shot-it")
@@ -396,7 +396,7 @@ describe "lib/modes/record", ->
@sandbox.stub(record, "uploadStdout").resolves()
@sandbox.stub(Project, "id").resolves("id-123")
@sandbox.stub(Project, "config").resolves({projectName: "projectName"})
@sandbox.stub(headless, "run").resolves({tests: 2, passes: 1})
@sandbox.stub(runMode, "run").resolves({tests: 2, passes: 1})
@sandbox.spy(Project, "add")
it "ensures id", ->
@@ -432,12 +432,12 @@ describe "lib/modes/record", ->
passes: 1
})
it "calls headless.run + ensureAuthToken + allDone into options", ->
it "calls runMode.run + ensureAuthToken + allDone into options", ->
opts = {foo: "bar"}
record.run(opts)
.then ->
expect(headless.run).to.be.calledWith({projectId: "id-123", foo: "bar", ensureAuthToken: false, allDone: false})
expect(runMode.run).to.be.calledWith({projectId: "id-123", foo: "bar", ensureAuthToken: false, allDone: false})
it "calls uploadAssets with instanceId, stats, and stdout", ->
@sandbox.stub(stdout, "capture").returns({
@@ -484,7 +484,7 @@ describe "lib/modes/record", ->
.then (stats) ->
expect(record.uploadStdout).to.be.calledWith("instance-id-123", "foobarbaz")
it "captures stdout from headless.run and headless.allDone", ->
it "captures stdout from runMode.run and runMode.allDone", ->
fn = ->
console.log("foo")
console.log("bar")
@@ -492,8 +492,8 @@ describe "lib/modes/record", ->
Promise.resolve({failures: 0})
headless.run.restore()
@sandbox.stub(headless, "run", fn)
runMode.run.restore()
@sandbox.stub(runMode, "run", fn)
record.run({})
.then (stats) ->
@@ -502,7 +502,7 @@ describe "lib/modes/record", ->
expect(str).to.include("foo\nbar\nbaz")
expect(str).to.include("All Done")
it "calls headless.allDone on uploadAssets success", ->
it "calls runMode.allDone on uploadAssets success", ->
@sandbox.spy(terminal, "header")
record.run({})
@@ -514,7 +514,7 @@ describe "lib/modes/record", ->
passes: 1
})
it "calls headless.allDone on uploadAssets failure", ->
it "calls runMode.allDone on uploadAssets failure", ->
@sandbox.spy(terminal, "header")
@sandbox.stub(api, "updateInstance").rejects(new Error)
record.uploadAssets.restore()
@@ -528,7 +528,7 @@ describe "lib/modes/record", ->
passes: 1
})
it "calls headless.allDone on createInstance failure", ->
it "calls runMode.allDone on createInstance failure", ->
@sandbox.spy(terminal, "header")
record.createInstance.resolves(null)

View File

@@ -8,12 +8,12 @@ errors = require("#{root}../lib/errors")
config = require("#{root}../lib/config")
Project = require("#{root}../lib/project")
Reporter = require("#{root}../lib/reporter")
headless = require("#{root}../lib/modes/headless")
runMode = require("#{root}../lib/modes/run")
openProject = require("#{root}../lib/open_project")
random = require("#{root}../lib/util/random")
specsUtil = require("#{root}../lib/util/specs")
describe "lib/modes/headless", ->
describe "lib/modes/run", ->
beforeEach ->
@projectInstance = Project("/_test-output/path/to/project")
@@ -27,7 +27,7 @@ describe "lib/modes/headless", ->
projectPath: "/_test-output/path/to/project/foo"
}
headless.createOpenProject(1234, options)
runMode.createOpenProject(1234, options)
it "calls openProject.create with projectPath + options", ->
expect(openProject.create).to.be.calledWithMatch("/_test-output/path/to/project/foo", {
@@ -49,16 +49,16 @@ describe "lib/modes/headless", ->
context ".getElectronProps", ->
it "sets width and height", ->
props = headless.getElectronProps()
props = runMode.getElectronProps()
expect(props.width).to.eq(1280)
expect(props.height).to.eq(720)
it "sets show to boolean", ->
props = headless.getElectronProps(false)
props = runMode.getElectronProps(false)
expect(props.show).to.be.false
props = headless.getElectronProps(true)
props = runMode.getElectronProps(true)
expect(props.show).to.be.true
it "sets recordFrameRate and onPaint when write is true", ->
@@ -68,7 +68,7 @@ describe "lib/modes/headless", ->
toJPEG: @sandbox.stub().returns("imgdata")
}
props = headless.getElectronProps(true, {}, write)
props = runMode.getElectronProps(true, {}, write)
expect(props.recordFrameRate).to.eq(20)
@@ -77,7 +77,7 @@ describe "lib/modes/headless", ->
expect(write).to.be.calledWith("imgdata")
it "does not set recordFrameRate or onPaint when write is falsy", ->
props = headless.getElectronProps(true, {}, false)
props = runMode.getElectronProps(true, {}, false)
expect(props).not.to.have.property("recordFrameRate")
expect(props).not.to.have.property("onPaint")
@@ -85,7 +85,7 @@ describe "lib/modes/headless", ->
it "sets options.show = false onNewWindow callback", ->
options = {show: true}
props = headless.getElectronProps()
props = runMode.getElectronProps()
props.onNewWindow(null, null, null, null, options)
expect(options.show).to.eq(false)
@@ -96,7 +96,7 @@ describe "lib/modes/headless", ->
emit = @sandbox.stub(@projectInstance, "emit")
props = headless.getElectronProps(true, @projectInstance)
props = runMode.getElectronProps(true, @projectInstance)
props.onCrashed()
@@ -108,14 +108,14 @@ describe "lib/modes/headless", ->
beforeEach ->
@launch = @sandbox.stub(openProject, "launch")
@sandbox.stub(headless, "getElectronProps").returns({foo: "bar"})
@sandbox.stub(runMode, "getElectronProps").returns({foo: "bar"})
@sandbox.stub(headless, "screenshotMetadata").returns({a: "a"})
@sandbox.stub(runMode, "screenshotMetadata").returns({a: "a"})
it "gets electron props by default", ->
screenshots = []
headless.launchBrowser({
runMode.launchBrowser({
browser: undefined
project: @projectInstance
write: "write"
@@ -126,7 +126,7 @@ describe "lib/modes/headless", ->
}
})
expect(headless.getElectronProps).to.be.calledWith(false, @projectInstance, "write")
expect(runMode.getElectronProps).to.be.calledWith(false, @projectInstance, "write")
expect(@launch).to.be.calledWithMatch("electron", "/path/to/spec", {foo: "bar"})
@@ -142,14 +142,14 @@ describe "lib/modes/headless", ->
expect(screenshots).to.deep.eq([{a: "a"}])
it "can launch chrome", ->
headless.launchBrowser({
runMode.launchBrowser({
browser: "chrome"
spec: {
absolute: "/path/to/spec"
}
})
expect(headless.getElectronProps).not.to.be.called
expect(runMode.getElectronProps).not.to.be.called
expect(@launch).to.be.calledWithMatch("chrome", "/path/to/spec", {})
@@ -160,28 +160,28 @@ describe "lib/modes/headless", ->
it "calls video process with name, cname and videoCompression", ->
end = -> Promise.resolve()
headless.postProcessRecording(end, "foo", "foo-compress", 32, true)
runMode.postProcessRecording(end, "foo", "foo-compress", 32, true)
.then ->
expect(video.process).to.be.calledWith("foo", "foo-compress", 32)
it "does not call video process when videoCompression is false", ->
end = -> Promise.resolve()
headless.postProcessRecording(end, "foo", "foo-compress", false, true)
runMode.postProcessRecording(end, "foo", "foo-compress", false, true)
.then ->
expect(video.process).not.to.be.called
it "calls video process if we have been told to upload videos", ->
end = -> Promise.resolve()
headless.postProcessRecording(end, "foo", "foo-compress", 32, true)
runMode.postProcessRecording(end, "foo", "foo-compress", 32, true)
.then ->
expect(video.process).to.be.calledWith("foo", "foo-compress", 32)
it "does not call video process if there are no failing tests and we have set not to upload video on passing", ->
end = -> Promise.resolve()
headless.postProcessRecording(end, "foo", "foo-compress", 32, false)
runMode.postProcessRecording(end, "foo", "foo-compress", 32, false)
.then ->
expect(video.process).not.to.be.called
@@ -190,14 +190,14 @@ describe "lib/modes/headless", ->
@sandbox.spy(errors, "warning")
@sandbox.spy(errors, "get")
@sandbox.spy(openProject, "closeBrowser")
@sandbox.stub(headless, "launchBrowser").resolves()
@sandbox.stub(headless, "waitForSocketConnection").resolves(Promise.delay(1000))
@sandbox.stub(runMode, "launchBrowser").resolves()
@sandbox.stub(runMode, "waitForSocketConnection").resolves(Promise.delay(1000))
emit = @sandbox.stub(@projectInstance, "emit")
headless.waitForBrowserToConnect({project: @projectInstance, timeout: 10})
runMode.waitForBrowserToConnect({project: @projectInstance, timeout: 10})
.then ->
expect(openProject.closeBrowser).to.be.calledThrice
expect(headless.launchBrowser).to.be.calledThrice
expect(runMode.launchBrowser).to.be.calledThrice
expect(errors.warning).to.be.calledWith("TESTS_DID_NOT_START_RETRYING", "Retrying...")
expect(errors.warning).to.be.calledWith("TESTS_DID_NOT_START_RETRYING", "Retrying again...")
expect(errors.get).to.be.calledWith("TESTS_DID_NOT_START_FAILED")
@@ -211,13 +211,13 @@ describe "lib/modes/headless", ->
})
it "attaches fn to 'socket:connected' event", ->
headless.waitForSocketConnection(@projectStub, 1234)
runMode.waitForSocketConnection(@projectStub, 1234)
expect(@projectStub.on).to.be.calledWith("socket:connected")
it "calls removeListener if socketId matches id", ->
@projectStub.on.yields(1234)
headless.waitForSocketConnection(@projectStub, 1234)
runMode.waitForSocketConnection(@projectStub, 1234)
.then =>
expect(@projectStub.removeListener).to.be.calledWith("socket:connected")
@@ -226,7 +226,7 @@ describe "lib/modes/headless", ->
process.nextTick =>
@projectInstance.emit("socket:connected", 1234)
headless.waitForSocketConnection(@projectInstance, 1234)
runMode.waitForSocketConnection(@projectInstance, 1234)
.then (ret) ->
expect(ret).to.be.undefined
@@ -234,12 +234,12 @@ describe "lib/modes/headless", ->
process.nextTick =>
@projectInstance.emit("socket:connected", 12345)
headless
.waitForSocketConnection(@projectInstance, 1234)
.timeout(50)
.then ->
throw new Error("should time out and not resolve")
.catch Promise.TimeoutError, (err) ->
runMode
.waitForSocketConnection(@projectInstance, 1234)
.timeout(50)
.then ->
throw new Error("should time out and not resolve")
.catch Promise.TimeoutError, (err) ->
it "actually removes the listener", ->
process.nextTick =>
@@ -250,7 +250,7 @@ describe "lib/modes/headless", ->
@projectInstance.emit("socket:connected", 1234)
expect(@projectInstance.listeners("socket:connected")).to.have.length(0)
headless.waitForSocketConnection(@projectInstance, 1234)
runMode.waitForSocketConnection(@projectInstance, 1234)
context ".waitForTestsToFinishRunning", ->
beforeEach ->
@@ -272,14 +272,14 @@ describe "lib/modes/headless", ->
}
@sandbox.stub(Reporter, "setVideoTimestamp").withArgs(started, results.tests).returns([1,2,3])
@sandbox.stub(headless, "postProcessRecording").resolves()
@sandbox.spy(headless, "displayStats")
@sandbox.spy(headless, "displayScreenshots")
@sandbox.stub(runMode, "postProcessRecording").resolves()
@sandbox.spy(runMode, "displayStats")
@sandbox.spy(runMode, "displayScreenshots")
process.nextTick =>
@projectInstance.emit("end", results)
headless.waitForTestsToFinishRunning({
runMode.waitForTestsToFinishRunning({
project: @projectInstance,
name: "foo.mp4"
cname: "foo-compressed.mp4"
@@ -294,12 +294,12 @@ describe "lib/modes/headless", ->
}
})
.then (obj) ->
expect(headless.postProcessRecording).to.be.calledWith(end, "foo.mp4", "foo-compressed.mp4", 32, true)
expect(runMode.postProcessRecording).to.be.calledWith(end, "foo.mp4", "foo-compressed.mp4", 32, true)
results = headless.collectTestResults(obj)
results = runMode.collectTestResults(obj)
expect(headless.displayStats).to.be.calledWith(results)
expect(headless.displayScreenshots).to.be.calledWith(screenshots)
expect(runMode.displayStats).to.be.calledWith(results)
expect(runMode.displayScreenshots).to.be.calledWith(screenshots)
expect(obj).to.deep.eq({
spec: "cypress/integration/spec.js"
@@ -322,16 +322,16 @@ describe "lib/modes/headless", ->
screenshots = [{}, {}, {}]
end = ->
@sandbox.stub(headless, "postProcessRecording").resolves()
@sandbox.spy(headless, "displayStats")
@sandbox.spy(headless, "displayScreenshots")
@sandbox.stub(runMode, "postProcessRecording").resolves()
@sandbox.spy(runMode, "displayStats")
@sandbox.spy(runMode, "displayScreenshots")
process.nextTick =>
expect(@projectInstance.listeners("exitEarlyWithErr")).to.have.length(1)
@projectInstance.emit("exitEarlyWithErr", err.message)
expect(@projectInstance.listeners("exitEarlyWithErr")).to.have.length(0)
headless.waitForTestsToFinishRunning({
runMode.waitForTestsToFinishRunning({
project: @projectInstance,
name: "foo.mp4"
cname: "foo-compressed.mp4"
@@ -346,11 +346,11 @@ describe "lib/modes/headless", ->
}
})
.then (obj) ->
expect(headless.postProcessRecording).to.be.calledWith(end, "foo.mp4", "foo-compressed.mp4", 32, true)
expect(runMode.postProcessRecording).to.be.calledWith(end, "foo.mp4", "foo-compressed.mp4", 32, true)
results = headless.collectTestResults(obj)
expect(headless.displayStats).to.be.calledWith(results)
expect(headless.displayScreenshots).to.be.calledWith(screenshots)
results = runMode.collectTestResults(obj)
expect(runMode.displayStats).to.be.calledWith(results)
expect(runMode.displayScreenshots).to.be.calledWith(screenshots)
expect(obj).to.deep.eq({
error: err.message
@@ -373,11 +373,11 @@ describe "lib/modes/headless", ->
failingTests: []
})
@sandbox.spy(headless, "postProcessRecording")
@sandbox.spy(runMode, "postProcessRecording")
@sandbox.spy(video, "process")
end = @sandbox.stub().resolves()
headless.waitForTestsToFinishRunning({
runMode.waitForTestsToFinishRunning({
project: @projectInstance,
name: "foo.mp4"
cname: "foo-compressed.mp4"
@@ -387,7 +387,7 @@ describe "lib/modes/headless", ->
end
})
.then (obj) ->
expect(headless.postProcessRecording).to.be.calledWith(end, "foo.mp4", "foo-compressed.mp4", 32, false)
expect(runMode.postProcessRecording).to.be.calledWith(end, "foo.mp4", "foo-compressed.mp4", 32, false)
expect(video.process).not.to.be.called
@@ -396,7 +396,7 @@ describe "lib/modes/headless", ->
process.nextTick =>
@projectInstance.emit("end", {foo: "bar"})
headless.listenForProjectEnd(@projectInstance)
runMode.listenForProjectEnd(@projectInstance)
.then (obj) ->
expect(obj).to.deep.eq({
foo: "bar"
@@ -408,7 +408,7 @@ describe "lib/modes/headless", ->
@projectInstance.emit("end", {foo: "bar"})
expect(@projectInstance.listeners("end")).to.have.length(0)
headless.listenForProjectEnd(@projectInstance)
runMode.listenForProjectEnd(@projectInstance)
context ".run browser vs video recording", ->
beforeEach ->
@@ -416,10 +416,10 @@ describe "lib/modes/headless", ->
@sandbox.stub(user, "ensureAuthToken")
@sandbox.stub(Project, "ensureExists").resolves()
@sandbox.stub(random, "id").returns(1234)
@sandbox.stub(headless, "createOpenProject").resolves(openProject)
@sandbox.stub(headless, "waitForSocketConnection").resolves()
@sandbox.stub(headless, "waitForTestsToFinishRunning").resolves({ stats: { failures: 10 } })
@sandbox.spy(headless, "waitForBrowserToConnect")
@sandbox.stub(runMode, "createOpenProject").resolves(openProject)
@sandbox.stub(runMode, "waitForSocketConnection").resolves()
@sandbox.stub(runMode, "waitForTestsToFinishRunning").resolves({ stats: { failures: 10 } })
@sandbox.spy(runMode, "waitForBrowserToConnect")
@sandbox.stub(video, "start").resolves()
@sandbox.stub(openProject, "launch").resolves()
@sandbox.stub(openProject, "getProject").resolves(@projectInstance)
@@ -439,30 +439,30 @@ describe "lib/modes/headless", ->
])
it "shows no warnings for default browser", ->
headless.run()
runMode.run()
.then ->
expect(errors.warning).to.not.be.called
it "shows no warnings for electron browser", ->
headless.run({browser: "electron"})
runMode.run({browser: "electron"})
.then ->
expect(errors.warning).to.not.be.calledWith("CANNOT_RECORD_VIDEO_FOR_THIS_BROWSER")
it "disables video recording on headed runs", ->
headless.run({headed: true})
it "disables video recording on interactive mode runs", ->
runMode.run({headed: true})
.then ->
expect(errors.warning).to.be.calledWith("CANNOT_RECORD_VIDEO_HEADED")
it "disables video recording for non-electron browser", ->
headless.run({browser: "chrome"})
runMode.run({browser: "chrome"})
.then ->
expect(errors.warning).to.be.calledWith("CANNOT_RECORD_VIDEO_FOR_THIS_BROWSER")
it "names video file with spec name", ->
headless.run()
runMode.run()
.then =>
expect(video.start).to.be.calledWith("videos/foo_spec.js.mp4")
expect(headless.waitForTestsToFinishRunning).to.be.calledWithMatch({
expect(runMode.waitForTestsToFinishRunning).to.be.calledWithMatch({
cname: "videos/foo_spec.js-compressed.mp4"
})
@@ -473,10 +473,10 @@ describe "lib/modes/headless", ->
@sandbox.stub(user, "ensureAuthToken")
@sandbox.stub(Project, "ensureExists").resolves()
@sandbox.stub(random, "id").returns(1234)
@sandbox.stub(headless, "createOpenProject").resolves(openProject)
@sandbox.stub(headless, "waitForSocketConnection").resolves()
@sandbox.stub(headless, "waitForTestsToFinishRunning").resolves({ stats: { failures: 10 } })
@sandbox.spy(headless, "waitForBrowserToConnect")
@sandbox.stub(runMode, "createOpenProject").resolves(openProject)
@sandbox.stub(runMode, "waitForSocketConnection").resolves()
@sandbox.stub(runMode, "waitForTestsToFinishRunning").resolves({ stats: { failures: 10 } })
@sandbox.spy(runMode, "waitForBrowserToConnect")
@sandbox.stub(openProject, "launch").resolves()
@sandbox.stub(openProject, "getProject").resolves(@projectInstance)
@sandbox.stub(specsUtil, "find").resolves([
@@ -488,37 +488,37 @@ describe "lib/modes/headless", ->
])
it "no longer ensures user session", ->
headless.run()
runMode.run()
.then ->
expect(user.ensureAuthToken).not.to.be.called
it "resolves with object and totalFailures", ->
headless.run()
runMode.run()
.then (results) ->
expect(results).to.have.property("totalFailures", 10)
it "passes id + options to openProject", ->
headless.run({foo: "bar"})
runMode.run({foo: "bar"})
.then ->
expect(headless.createOpenProject).to.be.calledWithMatch(1234, {foo: "bar"})
expect(runMode.createOpenProject).to.be.calledWithMatch(1234, {foo: "bar"})
it "passes project + id to waitForBrowserToConnect", ->
headless.run()
runMode.run()
.then =>
expect(headless.waitForBrowserToConnect).to.be.calledWithMatch({
expect(runMode.waitForBrowserToConnect).to.be.calledWithMatch({
project: @projectInstance
socketId: 1234
})
it "passes project to waitForTestsToFinishRunning", ->
headless.run()
runMode.run()
.then =>
expect(headless.waitForTestsToFinishRunning).to.be.calledWithMatch({
expect(runMode.waitForTestsToFinishRunning).to.be.calledWithMatch({
project: @projectInstance
})
it "passes headed to openProject.launch", ->
headless.run({headed: true})
runMode.run({headed: true})
.then ->
expect(openProject.launch).to.be.calledWithMatch(
"electron",

View File

@@ -39,7 +39,7 @@ describe "lib/controllers/spec", ->
@handle(specName).then =>
expect(@res.sendFile).to.be.calledWith(outputFilePath)
it "sends a client-side error in headed mode", ->
it "sends a client-side error in interactive mode", ->
preprocessor.getFile.rejects(new Error("Reason request failed"))
@handle(specName).then =>
@@ -47,7 +47,7 @@ describe "lib/controllers/spec", ->
expect(@res.send.firstCall.args[0]).to.include("(function")
expect(@res.send.firstCall.args[0]).to.include("Reason request failed")
it "logs the error and exits in headless mode", ->
it "logs the error and exits in run mode", ->
@sandbox.stub(errors, "log")
preprocessor.getFile.rejects(new Error("Reason request failed"))