mirror of
https://github.com/cypress-io/cypress.git
synced 2026-01-22 07:00:18 -06:00
* create directory path from screenshot name * fix screenshot e2e specs * ensure unique file paths for non-named screenshots * append failure screenshots with ‘— failure’ * fix snapshot differences caused by slow computer * fix driver specs * fix minutes/seconds e2e snapshot replacer * fix minutes/seconds e2e snapshot replacer again * fix e2e specs failing due to screenshot path differences * more snapshot fixes * more snapshot fixes * more snapshot fixes * fix reporter showing wrong path for nested spec when no tests * nest non-named screenshots in path based on spec path * fix specs * fix snapshot * test that server + project state is reset between specs in cypress run mode * rename spec.path to spec.relative. pass around the spec object instead of a string path - store state on the project for current spec + browsers - simplify how desktop gui passes around spec object - fixes #1921 - make all specs a real spec model - rename ‘Run all tests’ to ‘Run all specs’ * remove pretty-error dependency * fixes #1919 and #1918, add Cypress.spec and Cypress.browser * fixes all the failing tests * fixes failing tests * types: Cypress.spec * add types for Cypress.browser * fixes more failing tests * enable null for spec props when running "All Specs" * read comments per PR https://github.com/cypress-io/cypress/pull/1858#issuecomment-396121876 * fixes failing tests * fix linting * fix types assertion * fixes failing tests * fixes failing tests, update from -- failed to (failed) * ugh regexp * fixes more tests * add name, specName, and testFailure to the afterScreenshot props * fix failing tests. append (failed) for failed screenshots - use { testFailure: true } to indicate a failing test screenshot for use in props
132 lines
3.6 KiB
CoffeeScript
132 lines
3.6 KiB
CoffeeScript
_ = require("lodash")
|
||
EE = require("events")
|
||
path = require("path")
|
||
debug = require("debug")("cypress:server:preprocessor")
|
||
Promise = require("bluebird")
|
||
appData = require("../util/app_data")
|
||
cwd = require("../cwd")
|
||
plugins = require("../plugins")
|
||
savedState = require("../util/saved_state")
|
||
|
||
errorMessage = (err = {}) ->
|
||
(err.stack ? err.annotated ? err.message ? err.toString())
|
||
## strip out stack noise from parser like
|
||
## at Parser.pp$5.raise (/path/to/node_modules/babylon/lib/index.js:4215:13)
|
||
.replace(/\n\s*at.*/g, "")
|
||
.replace(/From previous event:\n?/g, "")
|
||
|
||
clientSideError = (err) ->
|
||
console.log(err.stack)
|
||
|
||
err = errorMessage(err)
|
||
## \n doesn't come through properly so preserve it so the
|
||
## runner can do the right thing
|
||
.replace(/\n/g, '{newline}')
|
||
## babel adds syntax highlighting for the console in the form of
|
||
## [90m that need to be stripped out or they appear in the error message
|
||
.replace(/\[\d{1,3}m/g, '')
|
||
|
||
"""
|
||
(function () {
|
||
Cypress.action("spec:script:error", {
|
||
type: "BUNDLE_ERROR",
|
||
error: #{JSON.stringify(err)}
|
||
})
|
||
}())
|
||
"""
|
||
|
||
getOutputPath = (config, filePath) ->
|
||
appData.projectsPath(savedState.toHashName(config.projectRoot), "bundles", filePath)
|
||
|
||
baseEmitter = new EE()
|
||
fileObjects = {}
|
||
fileProcessors = {}
|
||
|
||
setDefaultPreprocessor = ->
|
||
debug("set default preprocessor")
|
||
|
||
browserify = require("@cypress/browserify-preprocessor")
|
||
plugins.register("file:preprocessor", browserify())
|
||
|
||
plugins.registerHandler (ipc) ->
|
||
ipc.on "preprocessor:rerun", (filePath) ->
|
||
debug("ipc preprocessor:rerun event")
|
||
baseEmitter.emit("file:updated", filePath)
|
||
|
||
baseEmitter.on "close", (filePath) ->
|
||
debug("base emitter plugin close event")
|
||
ipc.send("preprocessor:close", filePath)
|
||
|
||
module.exports = {
|
||
errorMessage
|
||
|
||
clientSideError
|
||
|
||
emitter: baseEmitter
|
||
|
||
getFile: (filePath, config) ->
|
||
filePath = path.resolve(config.projectRoot, filePath)
|
||
|
||
debug("getFile #{filePath}")
|
||
|
||
if not fileObject = fileObjects[filePath]
|
||
## we should be watching the file if we are NOT
|
||
## in a text terminal aka cypress run
|
||
## TODO: rename this to config.isRunMode
|
||
## vs config.isInterativeMode
|
||
shouldWatch = not config.isTextTerminal
|
||
|
||
baseFilePath = filePath
|
||
.replace(config.projectRoot, "")
|
||
.replace(config.integrationFolder, "")
|
||
|
||
fileObject = fileObjects[filePath] = _.extend(new EE(), {
|
||
filePath,
|
||
shouldWatch,
|
||
outputPath: getOutputPath(config, baseFilePath)
|
||
})
|
||
|
||
fileObject.on "rerun", ->
|
||
debug("file object rerun event")
|
||
baseEmitter.emit("file:updated", filePath)
|
||
|
||
baseEmitter.once "close", ->
|
||
debug("base emitter native close event")
|
||
fileObject.emit("close")
|
||
|
||
if not plugins.has("file:preprocessor")
|
||
setDefaultPreprocessor(config)
|
||
|
||
if config.isTextTerminal and fileProcessor = fileProcessors[filePath]
|
||
debug("headless and already processed")
|
||
return fileProcessor
|
||
|
||
preprocessor = fileProcessors[filePath] = Promise.try ->
|
||
plugins.execute("file:preprocessor", fileObject)
|
||
|
||
return preprocessor
|
||
|
||
removeFile: (filePath, config) ->
|
||
filePath = path.resolve(config.projectRoot, filePath)
|
||
|
||
return if not fileProcessors[filePath]
|
||
|
||
debug("removeFile #{filePath}")
|
||
|
||
baseEmitter.emit("close", filePath)
|
||
|
||
if fileObject = fileObjects[filePath]
|
||
fileObject.emit("close")
|
||
|
||
delete fileObjects[filePath]
|
||
delete fileProcessors[filePath]
|
||
|
||
close: ->
|
||
debug("close preprocessor")
|
||
|
||
fileObjects = {}
|
||
fileProcessors = {}
|
||
baseEmitter.emit("close")
|
||
baseEmitter.removeAllListeners()
|
||
}
|