iterate through specs in parallel (#2154)

- fixes: #2153
- fixes: #1566
- fixes: #1690
- fixes: #2275
- fixes: #2276
This commit is contained in:
Amir Rustamzadeh
2018-08-06 04:24:19 -07:00
committed by Brian Mann
parent 88379da700
commit f313dd0b84
89 changed files with 3147 additions and 788 deletions

View File

@@ -171,7 +171,9 @@ jobs:
paths:
- packages/ts/node_modules
- run: npm run stop-only
## TODO: this needs to be reenabled when
## we update stop-only
# - run: npm run stop-only
## now go build all of subpackages
- run: npm run build

View File

@@ -67,6 +67,9 @@ exports['shows help for run --foo 1'] = `
-c, --config <config> sets configuration values. separate multiple values with a comma. overrides any value in cypress.json.
-b, --browser <browser-name> runs Cypress in the browser with the given name. note: using an external browser will not record a video.
-P, --project <project-path> path to the project
--parallel enables concurrent runs and automatic load balancing of specs across multiple machines or processes
--group <name> a named group for recorded runs in the Cypress dashboard
--ci-build-id <id> the unique identifier for a run on your CI provider. typically a "BUILD_ID" env var. this value is automatically detected for most CI providers
--no-exit keep the browser open after tests finish
--dev runs cypress in development and bypasses binary check
-h, --help output usage information
@@ -94,14 +97,14 @@ exports['cli help command shows help 1'] = `
Options:
-v, --version Prints Cypress version
-v, --version prints Cypress version
-h, --help output usage information
Commands:
help Shows CLI help and exits
version Prints Cypress version
version prints Cypress version
run [options] Runs Cypress tests from the CLI without the GUI
open [options] Opens Cypress in the interactive GUI.
install [options] Installs the Cypress executable matching this package's version
@@ -131,14 +134,14 @@ exports['cli help command shows help for -h 1'] = `
Options:
-v, --version Prints Cypress version
-v, --version prints Cypress version
-h, --help output usage information
Commands:
help Shows CLI help and exits
version Prints Cypress version
version prints Cypress version
run [options] Runs Cypress tests from the CLI without the GUI
open [options] Opens Cypress in the interactive GUI.
install [options] Installs the Cypress executable matching this package's version
@@ -168,14 +171,14 @@ exports['cli help command shows help for --help 1'] = `
Options:
-v, --version Prints Cypress version
-v, --version prints Cypress version
-h, --help output usage information
Commands:
help Shows CLI help and exits
version Prints Cypress version
version prints Cypress version
run [options] Runs Cypress tests from the CLI without the GUI
open [options] Opens Cypress in the interactive GUI.
install [options] Installs the Cypress executable matching this package's version
@@ -207,14 +210,14 @@ exports['cli unknown command shows usage and exits 1'] = `
Options:
-v, --version Prints Cypress version
-v, --version prints Cypress version
-h, --help output usage information
Commands:
help Shows CLI help and exits
version Prints Cypress version
version prints Cypress version
run [options] Runs Cypress tests from the CLI without the GUI
open [options] Opens Cypress in the interactive GUI.
install [options] Installs the Cypress executable matching this package's version

View File

@@ -28,7 +28,7 @@ const parseOpts = (opts) => {
'project', 'spec', 'reporter', 'reporterOptions', 'path', 'destination',
'port', 'env', 'cypressVersion', 'config', 'record', 'key',
'browser', 'detached', 'headed', 'global', 'dev', 'force', 'exit',
'cachePath', 'cacheList', 'cacheClear'
'cachePath', 'cacheList', 'cacheClear', 'parallel', 'group', 'ciBuildId'
)
if (opts.exit) {
@@ -56,7 +56,7 @@ const descriptions = {
detached: 'runs Cypress application in detached mode',
project: 'path to the project',
global: 'force Cypress into global mode as if its globally installed',
version: 'Prints Cypress version',
version: 'prints Cypress version',
headed: 'displays the Electron browser instead of running headlessly',
dev: 'runs cypress in development and bypasses binary check',
forceInstall: 'force install the Cypress binary',
@@ -64,6 +64,9 @@ const descriptions = {
cachePath: 'print the cypress binary cache path',
cacheList: 'list the currently cached versions',
cacheClear: 'delete the Cypress binary cache',
group: 'a named group for recorded runs in the Cypress dashboard',
parallel: 'enables concurrent runs and automatic load balancing of specs across multiple machines or processes',
ciBuildId: 'the unique identifier for a run on your CI provider. typically a "BUILD_ID" env var. this value is automatically detected for most CI providers',
}
const knownCommands = ['version', 'run', 'open', 'install', 'verify', '-v', '--version', 'help', '-h', '--help', 'cache']
@@ -134,6 +137,9 @@ module.exports = {
.option('-c, --config <config>', text('config'))
.option('-b, --browser <browser-name>', text('browser'))
.option('-P, --project <project-path>', text('project'))
.option('--parallel', text('parallel'))
.option('--group <name>', text('group'))
.option('--ci-build-id <id>', text('ciBuildId'))
.option('--no-exit', text('exit'))
.option('--dev', text('dev'), coerceFalse)
.action((opts) => {

View File

@@ -64,6 +64,18 @@ const processRunOptions = (options = {}) => {
args.push('--record', options.record)
}
if (options.parallel) {
args.push('--parallel')
}
if (options.group) {
args.push('--group', options.group)
}
if (options.ciBuildId) {
args.push('--ci-build-id', options.ciBuildId)
}
if (options.outputPath) {
args.push('--output-path', options.outputPath)
}

View File

@@ -205,6 +205,20 @@ describe('cli', function () {
expect(run.start).to.be.calledWith({ exit: false })
})
it('calls run with --parallel', function () {
this.exec('run --parallel')
expect(run.start).to.be.calledWith({ parallel: true })
})
it('calls runs with --ci-build-id', function () {
this.exec('run --ci-build-id 123')
expect(run.start).to.be.calledWith({ ciBuildId: '123' })
})
it('calls runs with --group', function () {
this.exec('run --group staging')
expect(run.start).to.be.calledWith({ group: 'staging' })
})
})
context('cypress open', function () {

View File

@@ -26,11 +26,10 @@
"lint-coffee": "coffeelint scripts/**/*.coffee",
"lint": "npm run lint-js && npm run lint-coffee",
"pretest": "npm run lint && npm run all lint && npm run test-scripts",
"precommit": "lint-staged; npm run warn-only",
"precommit": "lint-staged",
"precommit-lint": "eslint --fix",
"prepush": "npm run stop-only",
"stop-only": "stop-only packages --exclude-dir .cy --exclude-dir .projects --exclude-dir node_modules --exclude-dir dist --exclude-dir dist-test --exclude-dir fixtures --exclude-dir lib --exclude-dir bower_components",
"warn-only": "stop-only --warn packages --exclude-dir .cy --exclude-dir .projects --exclude-dir node_modules --exclude-dir dist --exclude-dir dist-test --exclude-dir fixtures --exclude-dir lib --exclude-dir bower_components",
"stop-only": "stop-only --folder packages --skip .cy,.publish,.projects,node_modules,dist,dist-test,fixtures,lib,bower_components,spec_helper.coffee",
"warn-only": "stop-only --warn packages --skip .cy,.publish,.projects,node_modules,dist,dist-test,fixtures,lib,bower_components,spec_helper.coffee",
"bump": "node ./scripts/binary.js bump",
"set-next-ci-version": "node ./scripts/binary.js setNextVersion",
"binary-build": "node ./scripts/binary.js build",
@@ -80,7 +79,7 @@
"execa": "^0.8.0",
"execa-wrap": "^1.1.0",
"filesize": "^3.5.10",
"fs-extra": "^2.1.2",
"fs-extra": "^7.0.0",
"gift": "^0.10.0",
"gulp": "^3.9.1",
"gulp-awspublish": "^3.3.0",
@@ -108,8 +107,8 @@
"print-arch": "^1.0.0",
"ramda": "^0.24.1",
"shelljs": "^0.7.8",
"snap-shot-it": "^4.0.1",
"stop-only": "1.2.1",
"snap-shot-it": "^5.0.1",
"stop-only": "2.1.0",
"terminal-banner": "^1.0.0",
"typescript": "^2.3.4",
"vagrant": "0.0.1",

View File

@@ -1,4 +1,5 @@
exports['e2e async timeouts failing1 1'] = `
====================================================================================================
(Run Starting)
@@ -67,5 +68,5 @@ exports['e2e async timeouts failing1 1'] = `
1 of 1 failed (100%) XX:XX 1 - 1 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e baseUrl https passes 1'] = `
====================================================================================================
(Run Starting)
@@ -55,9 +56,11 @@ exports['e2e baseUrl https passes 1'] = `
All specs passed! XX:XX 1 1 - - -
`
exports['e2e baseUrl http passes 1'] = `
====================================================================================================
(Run Starting)
@@ -114,5 +117,5 @@ exports['e2e baseUrl http passes 1'] = `
All specs passed! XX:XX 1 1 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e blacklist passes 1'] = `
====================================================================================================
(Run Starting)
@@ -55,5 +56,5 @@ exports['e2e blacklist passes 1'] = `
All specs passed! XX:XX 1 1 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e browserify, babel, es2015 passes 1'] = `
====================================================================================================
(Run Starting)
@@ -57,9 +58,11 @@ exports['e2e browserify, babel, es2015 passes 1'] = `
All specs passed! XX:XX 3 3 - - -
`
exports['e2e browserify, babel, es2015 fails 1'] = `
====================================================================================================
(Run Starting)
@@ -88,7 +91,6 @@ SyntaxError: /foo/bar/.projects/e2e/lib/fail.js: Unexpected token (2:0)
> 2 |
| ^ while parsing file: /foo/bar/.projects/e2e/lib/fail.js
This occurred while Cypress was compiling and bundling your test code. This is usually caused by:
- A missing file or dependency
@@ -128,5 +130,5 @@ Fix the error in your code and re-run your tests.
1 of 1 failed (100%) XX:XX - - 1 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e busted support file passes 1'] = `
====================================================================================================
(Run Starting)
@@ -22,7 +23,6 @@ The error was:
Error: Cannot find module './does/not/exist' from '/foo/bar/.projects/busted-support-file/cypress/support'
This occurred while Cypress was compiling and bundling your test code. This is usually caused by:
- A missing file or dependency
@@ -62,5 +62,5 @@ Fix the error in your code and re-run your tests.
1 of 1 failed (100%) XX:XX - - 1 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e cache passes 1'] = `
====================================================================================================
(Run Starting)
@@ -58,5 +59,5 @@ exports['e2e cache passes 1'] = `
All specs passed! XX:XX 4 4 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e caught and uncaught hooks errors failing1 1'] = `
====================================================================================================
(Run Starting)
@@ -111,9 +112,11 @@ Because this error occurred during a 'before all' hook we are skipping the remai
1 of 1 failed (100%) XX:XX 11 5 3 - 3
`
exports['e2e caught and uncaught hooks errors failing2 1'] = `
====================================================================================================
(Run Starting)
@@ -198,9 +201,11 @@ Because this error occurred during a 'before each' hook we are skipping the rema
1 of 1 failed (100%) XX:XX 7 4 1 - 2
`
exports['e2e caught and uncaught hooks errors failing3 1'] = `
====================================================================================================
(Run Starting)
@@ -277,9 +282,11 @@ Because this error occurred during a 'before each' hook we are skipping all of t
1 of 1 failed (100%) XX:XX 4 - 1 - 3
`
exports['e2e caught and uncaught hooks errors failing4 1'] = `
====================================================================================================
(Run Starting)
@@ -362,5 +369,5 @@ Because this error occurred during a 'before each' hook we are skipping the rema
1 of 1 failed (100%) XX:XX 3 2 1 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e commands outside of test fails 1'] = `
====================================================================================================
(Run Starting)
@@ -87,5 +88,5 @@ We dynamically generated a new test to display this failure.
1 of 1 failed (100%) XX:XX 1 - 1 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e config passes 1'] = `
====================================================================================================
(Run Starting)
@@ -59,9 +60,11 @@ exports['e2e config passes 1'] = `
All specs passed! XX:XX 5 5 - - -
`
exports['e2e config fails 1'] = `
====================================================================================================
(Run Starting)
@@ -143,5 +146,5 @@ exports['e2e config fails 1'] = `
1 of 1 failed (100%) XX:XX 1 - 1 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e plugins fails when spec does not exist 1'] = `
====================================================================================================
(Run Starting)
@@ -23,8 +24,6 @@ The error was:
Error: ENOENT: no such file or directory, stat '/does/not/exist.js'
This occurred while Cypress was compiling and bundling your test code. This is usually caused by:
- A missing file or dependency
@@ -64,5 +63,5 @@ Fix the error in your code and re-run your tests.
1 of 1 failed (100%) XX:XX - - 1 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e cookies passes 1'] = `
====================================================================================================
(Run Starting)
@@ -60,5 +61,5 @@ exports['e2e cookies passes 1'] = `
All specs passed! XX:XX 6 6 - - -
`
`

View File

@@ -0,0 +1,241 @@
exports['RECORD_PARAMS_WITHOUT_RECORDING-ciBuildId 1'] = `
You passed the --ci-build-id, --group, or --parallel flag without also passing the --record flag.
The --ci-build-id flag you passed was: ciBuildId123
These flags can only be used when recording to the Cypress Dashboard service.
https://on.cypress.io/record-params-without-recording
`
exports['INCORRECT_CI_BUILD_ID_USAGE 1'] = `
You passed the --ci-build-id flag but did not provide either --group or --parallel.
The --ci-build-id flag you passed was: ciBuildId123
The --ci-build-id flag is used to either group or parallelize multiple runs together.
https://on.cypress.io/incorrect-ci-build-id-usage
`
exports['RECORD_PARAMS_WITHOUT_RECORDING-group 1'] = `
You passed the --ci-build-id, --group, or --parallel flag without also passing the --record flag.
The --group flag you passed was: e2e-tests
These flags can only be used when recording to the Cypress Dashboard service.
https://on.cypress.io/record-params-without-recording
`
exports['RECORD_PARAMS_WITHOUT_RECORDING-parallel 1'] = `
You passed the --ci-build-id, --group, or --parallel flag without also passing the --record flag.
The --parallel flag you passed was: true
These flags can only be used when recording to the Cypress Dashboard service.
https://on.cypress.io/record-params-without-recording
`
exports['RECORD_PARAMS_WITHOUT_RECORDING-group-parallel 1'] = `
You passed the --ci-build-id, --group, or --parallel flag without also passing the --record flag.
The --group flag you passed was: electron-smoke-tests
The --parallel flag you passed was: true
These flags can only be used when recording to the Cypress Dashboard service.
https://on.cypress.io/record-params-without-recording
`
exports['INDETERMINATE_CI_BUILD_ID-group 1'] = `
You passed the --group or --parallel flag but we could not automatically determine or generate a ciBuildId.
The --group flag you passed was: e2e-tests
In order to use either of these parameters a ciBuildId must be determined.
The ciBuildId is automatically detected if you are running Cypress in any of of the these CI providers:
- appveyor
- bamboo
- buildkite
- circle
- codeship
- drone
- gitlab
- jenkins
- semaphore
- shippable
- snap
- teamcity
- teamfoundation
- travis
- wercker
Because we could not automatically generate this ciBuildId, the --ci-build-id flag must be passed in manually.
https://on.cypress.io/indeterminate-ci-build-id
`
exports['INDETERMINATE_CI_BUILD_ID-parallel 1'] = `
You passed the --group or --parallel flag but we could not automatically determine or generate a ciBuildId.
The --parallel flag you passed was: true
In order to use either of these parameters a ciBuildId must be determined.
The ciBuildId is automatically detected if you are running Cypress in any of of the these CI providers:
- appveyor
- bamboo
- buildkite
- circle
- codeship
- drone
- gitlab
- jenkins
- semaphore
- shippable
- snap
- teamcity
- teamfoundation
- travis
- wercker
Because we could not automatically generate this ciBuildId, the --ci-build-id flag must be passed in manually.
https://on.cypress.io/indeterminate-ci-build-id
`
exports['INDETERMINATE_CI_BUILD_ID-parallel-group 1'] = `
You passed the --group or --parallel flag but we could not automatically determine or generate a ciBuildId.
The --group flag you passed was: e2e-tests-chrome
The --parallel flag you passed was: true
In order to use either of these parameters a ciBuildId must be determined.
The ciBuildId is automatically detected if you are running Cypress in any of of the these CI providers:
- appveyor
- bamboo
- buildkite
- circle
- codeship
- drone
- gitlab
- jenkins
- semaphore
- shippable
- snap
- teamcity
- teamfoundation
- travis
- wercker
Because we could not automatically generate this ciBuildId, the --ci-build-id flag must be passed in manually.
https://on.cypress.io/indeterminate-ci-build-id
`
exports['DASHBOARD_RUN_GROUP_NAME_NOT_UNIQUE 1'] = `
You passed the --group flag, but this group name has already been used for this run.
The existing run is: https://dashboard.cypress.io/runs/12345
The --group flag you passed was: electron-smoke-tests
The --ciBuildId flag you passed was: ciBuildId123
If you are trying to parallelize this run, then also pass the --parallel flag, else pass a different group name.
It also looks like you also passed in an explicit --ci-build-id flag.
This is only necessary if you are NOT running in one of our supported CI providers.
This flag must be unique for each new run, but must also be identical for each machine you are trying to --group or run in --parallel.
https://on.cypress.io/run-group-name-not-unique
`
exports['DASHBOARD_PARALLEL_GROUP_PARAMS_MISMATCH 1'] = `
You passed the --parallel flag, but this machine is sending different parameters from the first machine that started this parallel run.
The existing run is: https://dashboard.cypress.io/runs/12345
In order to run in parallel mode each machine must send the identical parameters such as:
- specs
- osName
- osVersion
- browserName
- browserVersion (major)
This machine sent the following parameters:
{
"osName": "darwin",
"osVersion": "v1",
"browserName": "Electron",
"browserVersion": "59.1.2.3",
"specs": [
"cypress/integration/app_spec.js"
]
}
https://on.cypress.io/parallel-group-params-mismatch
`
exports['DASHBOARD_PARALLEL_DISALLOWED 1'] = `
You passed the --parallel flag, but this run group was originally created without the --parallel flag.
The existing run is: https://dashboard.cypress.io/runs/12345
The --group flag you passed was: electron-smoke-tests
The --ciBuildId flag you passed was: ciBuildId123
You can not use the --parallel flag with this group.
https://on.cypress.io/parallel-disallowed
`
exports['DASHBOARD_PARALLEL_REQUIRED 1'] = `
You dot not pass the --parallel flag, but this run group was originally created with the --parallel flag.
The existing run is: https://dashboard.cypress.io/runs/12345
The --group flag you passed was: electron-smoke-tests
The --ciBuildId flag you passed was: ciBuildId123
You must use the --parallel flag with this group.
https://on.cypress.io/parallel-required
`
exports['DASHBOARD_ALREADY_COMPLETE 1'] = `
The run you are attempting access is already complete and will not accept new groups.
The existing run is: https://dashboard.cypress.io/runs/12345
When a run finishes all of its groups, it waits for a configurable set of time before finally completing. You must add more groups during that time period.
The --group flag you passed was: electron-smoke-tests
The --ciBuildId flag you passed was: ciBuildId123
https://on.cypress.io/already-complete
`
exports['DASHBOARD_STALE_RUN 1'] = `
You are attempting to pass the --parallel flag to a run that was completed over 24 hours ago.
The existing run is: https://dashboard.cypress.io/runs/12345
You cannot parallelize a run that has been complete for that long.
The --group flag you passed was: electron-smoke-tests
The --parallel flag you passed was: true
The --ciBuildId flag you passed was: ciBuildId123
https://on.cypress.io/stale-run
`

View File

@@ -1,4 +1,5 @@
exports['e2e domain passing 1'] = `
====================================================================================================
(Run Starting)
@@ -102,5 +103,5 @@ exports['e2e domain passing 1'] = `
All specs passed! XX:XX 6 6 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e form submissions passing 1'] = `
====================================================================================================
(Run Starting)
@@ -56,9 +57,11 @@ exports['e2e form submissions passing 1'] = `
All specs passed! XX:XX 2 2 - - -
`
exports['e2e form submissions failing 1'] = `
====================================================================================================
(Run Starting)
@@ -141,5 +144,5 @@ exports['e2e form submissions failing 1'] = `
1 of 1 failed (100%) XX:XX 1 - 1 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e go passes 1'] = `
====================================================================================================
(Run Starting)
@@ -56,5 +57,5 @@ exports['e2e go passes 1'] = `
All specs passed! XX:XX 2 2 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e iframes passes 1'] = `
====================================================================================================
(Run Starting)
@@ -62,5 +63,5 @@ exports['e2e iframes passes 1'] = `
All specs passed! XX:XX 8 8 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e images passes 1'] = `
====================================================================================================
(Run Starting)
@@ -56,5 +57,5 @@ exports['e2e images passes 1'] = `
All specs passed! XX:XX 2 2 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e issue 149 failing 1'] = `
====================================================================================================
(Run Starting)
@@ -66,5 +67,5 @@ exports['e2e issue 149 failing 1'] = `
1 of 1 failed (100%) XX:XX 2 1 1 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e issue 173 failing 1'] = `
====================================================================================================
(Run Starting)
@@ -79,5 +80,5 @@ exports['e2e issue 173 failing 1'] = `
1 of 1 failed (100%) XX:XX 2 1 1 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e issue 674 fails 1'] = `
====================================================================================================
(Run Starting)
@@ -77,5 +78,5 @@ Because this error occurred during a 'after each' hook we are skipping the remai
1 of 1 failed (100%) XX:XX 1 - 1 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e js error handling fails 1'] = `
====================================================================================================
(Run Starting)
@@ -143,5 +144,5 @@ https://on.cypress.io/uncaught-exception-from-application
1 of 1 failed (100%) XX:XX 8 3 5 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e new project passes 1'] = `
====================================================================================================
(Run Starting)
@@ -52,5 +53,5 @@ exports['e2e new project passes 1'] = `
All specs passed! XX:XX 1 1 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e only spec failing 1'] = `
====================================================================================================
(Run Starting)
@@ -55,5 +56,5 @@ exports['e2e only spec failing 1'] = `
All specs passed! XX:XX 1 1 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e page_loading passes 1'] = `
====================================================================================================
(Run Starting)
@@ -57,5 +58,5 @@ exports['e2e page_loading passes 1'] = `
All specs passed! XX:XX 2 2 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e plugins fails 1'] = `
====================================================================================================
(Run Starting)
@@ -32,7 +33,6 @@ Error: Async error from plugins file
at stack trace line
at stack trace line
at stack trace line
at stack trace line
(Results)
@@ -67,9 +67,11 @@ Error: Async error from plugins file
1 of 1 failed (100%) XX:XX - - 1 - -
`
exports['e2e plugins passes 1'] = `
====================================================================================================
(Run Starting)
@@ -125,9 +127,11 @@ exports['e2e plugins passes 1'] = `
All specs passed! XX:XX 2 2 - - -
`
exports['e2e plugins can modify config from plugins 1'] = `
====================================================================================================
(Run Starting)
@@ -183,9 +187,11 @@ exports['e2e plugins can modify config from plugins 1'] = `
All specs passed! XX:XX 2 2 - - -
`
exports['e2e plugins works with user extensions 1'] = `
====================================================================================================
(Run Starting)
@@ -240,9 +246,11 @@ A video will not be recorded when using this browser.
All specs passed! XX:XX 1 1 - - -
`
exports['e2e plugins handles absolute path to pluginsFile 1'] = `
====================================================================================================
(Run Starting)
@@ -297,9 +305,11 @@ exports['e2e plugins handles absolute path to pluginsFile 1'] = `
All specs passed! XX:XX 1 1 - - -
`
exports['e2e plugins calls after:screenshot for cy.screenshot() and failure screenshots 1'] = `
====================================================================================================
(Run Starting)
@@ -372,5 +382,5 @@ exports['e2e plugins calls after:screenshot for cy.screenshot() and failure scre
1 of 1 failed (100%) XX:XX 4 3 1 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e promises failing1 1'] = `
====================================================================================================
(Run Starting)
@@ -72,5 +73,5 @@ exports['e2e promises failing1 1'] = `
1 of 1 failed (100%) XX:XX 2 - 2 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e record passing passes 1'] = `
====================================================================================================
(Run Starting)
@@ -8,6 +9,7 @@ exports['e2e record passing passes 1'] = `
Browser: FooBrowser 88
Specs: 4 found (record_error_spec.coffee, record_fail_spec.coffee, record_pass_spec.coff
Searched: cypress/integration/record*
Params: Group: false, Parallel: false
Run URL: https://dashboard.cypress.io/#/projects/cjvoj7/runs/12 │
@@ -15,6 +17,7 @@ exports['e2e record passing passes 1'] = `
Running: record_error_spec.coffee... (1 of 4)
Estimated: 8 seconds
Oops...we found an error preparing this test file:
@@ -24,7 +27,6 @@ The error was:
Error: Cannot find module '../it/does/not/exist' from '/foo/bar/.projects/e2e/cypress/integration'
This occurred while Cypress was compiling and bundling your test code. This is usually caused by:
- A missing file or dependency
@@ -43,6 +45,7 @@ Fix the error in your code and re-run your tests.
Screenshots: 0
Video: true
Duration: X seconds
Estimated: 8 seconds
Spec Ran: record_error_spec.coffee
@@ -60,6 +63,7 @@ Fix the error in your code and re-run your tests.
Running: record_fail_spec.coffee... (2 of 4)
Estimated: 8 seconds
record fails
@@ -89,6 +93,7 @@ Because this error occurred during a 'before each' hook we are skipping the rema
Screenshots: 1
Video: true
Duration: X seconds
Estimated: 8 seconds
Spec Ran: record_fail_spec.coffee
@@ -112,6 +117,7 @@ Because this error occurred during a 'before each' hook we are skipping the rema
Running: record_pass_spec.coffee... (3 of 4)
Estimated: 8 seconds
record pass
@@ -134,6 +140,7 @@ Because this error occurred during a 'before each' hook we are skipping the rema
Screenshots: 1
Video: true
Duration: X seconds
Estimated: 8 seconds
Spec Ran: record_pass_spec.coffee
@@ -150,6 +157,7 @@ Because this error occurred during a 'before each' hook we are skipping the rema
Running: record_uncaught_spec.coffee... (4 of 4)
Estimated: 8 seconds
1) An uncaught error was detected outside of a test
@@ -186,6 +194,7 @@ We dynamically generated a new test to display this failure.
Screenshots: 1
Video: true
Duration: X seconds
Estimated: 8 seconds
Spec Ran: record_uncaught_spec.coffee
@@ -228,20 +237,11 @@ We dynamically generated a new test to display this failure.
Recorded Run: https://dashboard.cypress.io/#/projects/cjvoj7/runs/12
`
exports['e2e record api interaction errors recordKey and projectId errors and exits 1'] = `We failed trying to authenticate this project: pid123
Your Record Key is invalid: f858a...ee7e1
It may have been recently revoked by you or another user.
Please log into the Dashboard to see the updated token.
https://on.cypress.io/dashboard/projects/pid123
`
exports['e2e record api interaction errors project 404 errors and exits 1'] = `We could not find a project with the ID: pid123
exports['e2e record api interaction errors project 404 errors and exits 1'] = `
We could not find a project with the ID: pid123
This projectId came from your cypress.json file or an environment variable.
@@ -252,9 +252,11 @@ We will list the correct projectId in the 'Settings' tab.
Alternatively, you can create a new project using the Desktop Application.
https://on.cypress.io/dashboard
`
exports['e2e record api interaction errors create run warns and does not create or update instances 1'] = `Warning: We encountered an error talking to our servers.
exports['e2e record api interaction errors create run 500 warns and does not create or update instances 1'] = `
Warning: We encountered an error talking to our servers.
This run will not be recorded.
@@ -319,9 +321,11 @@ StatusCodeError: 500 - "Internal Server Error"
All specs passed! XX:XX 2 1 - 1 -
`
exports['e2e record api interaction errors create instance does not update instance 1'] = `
====================================================================================================
(Run Starting)
@@ -331,6 +335,7 @@ exports['e2e record api interaction errors create instance does not update insta
Browser: FooBrowser 88
Specs: 1 found (record_pass_spec.coffee)
Searched: cypress/integration/record_pass*
Params: Group: false, Parallel: false
Run URL: https://dashboard.cypress.io/#/projects/cjvoj7/runs/12 │
@@ -392,9 +397,11 @@ StatusCodeError: 500 - "Internal Server Error"
Recorded Run: https://dashboard.cypress.io/#/projects/cjvoj7/runs/12
`
exports['e2e record api interaction errors update instance does not update instance stdout 1'] = `
====================================================================================================
(Run Starting)
@@ -404,6 +411,7 @@ exports['e2e record api interaction errors update instance does not update insta
Browser: FooBrowser 88
Specs: 1 found (record_pass_spec.coffee)
Searched: cypress/integration/record_pass*
Params: Group: false, Parallel: false
Run URL: https://dashboard.cypress.io/#/projects/cjvoj7/runs/12 │
@@ -411,6 +419,7 @@ exports['e2e record api interaction errors update instance does not update insta
Running: record_pass_spec.coffee... (1 of 1)
Estimated: 8 seconds
record pass
@@ -433,6 +442,7 @@ exports['e2e record api interaction errors update instance does not update insta
Screenshots: 1
Video: true
Duration: X seconds
Estimated: 8 seconds
Spec Ran: record_pass_spec.coffee
@@ -468,9 +478,11 @@ StatusCodeError: 500 - "Internal Server Error"
Recorded Run: https://dashboard.cypress.io/#/projects/cjvoj7/runs/12
`
exports['e2e record api interaction errors update instance stdout warns but proceeds 1'] = `
====================================================================================================
(Run Starting)
@@ -480,6 +492,7 @@ exports['e2e record api interaction errors update instance stdout warns but proc
Browser: FooBrowser 88
Specs: 1 found (record_pass_spec.coffee)
Searched: cypress/integration/record_pass*
Params: Group: false, Parallel: false
Run URL: https://dashboard.cypress.io/#/projects/cjvoj7/runs/12 │
@@ -487,6 +500,7 @@ exports['e2e record api interaction errors update instance stdout warns but proc
Running: record_pass_spec.coffee... (1 of 1)
Estimated: 8 seconds
record pass
@@ -509,6 +523,7 @@ exports['e2e record api interaction errors update instance stdout warns but proc
Screenshots: 1
Video: true
Duration: X seconds
Estimated: 8 seconds
Spec Ran: record_pass_spec.coffee
@@ -545,22 +560,11 @@ StatusCodeError: 500 - "Internal Server Error"
Recorded Run: https://dashboard.cypress.io/#/projects/cjvoj7/runs/12
`
exports['e2e record failing errors and exits without projectId 1'] = `You passed the --record flag but this project has not been setup to record.
This project is missing the 'projectId' inside of 'cypress.json'.
We cannot uniquely identify this project without this id.
You need to setup this project to record. This will generate a unique 'projectId'.
Alternatively if you omit the --record flag this project will run without recording.
https://on.cypress.io/recording-project-runs
`
exports['e2e record recordKey errors and exits without recordKey 1'] = `You passed the --record flag but did not provide us your Record Key.
exports['e2e record recordKey errors and exits without recordKey 1'] = `
You passed the --record flag but did not provide us your Record Key.
You can pass us your Record Key like this:
@@ -569,9 +573,11 @@ You can pass us your Record Key like this:
You can also set the key as an environment variable with the name CYPRESS_RECORD_KEY.
https://on.cypress.io/how-do-i-record-runs
`
exports['e2e record projectId errors and exits without projectId 1'] = `You passed the --record flag but this project has not been setup to record.
exports['e2e record projectId errors and exits without projectId 1'] = `
You passed the --record flag but this project has not been setup to record.
This project is missing the 'projectId' inside of 'cypress.json'.
@@ -582,9 +588,11 @@ You need to setup this project to record. This will generate a unique 'projectId
Alternatively if you omit the --record flag this project will run without recording.
https://on.cypress.io/recording-project-runs
`
exports['e2e record api interaction errors recordKey and projectId errors and exits on 401 1'] = `We failed trying to authenticate this project: pid123
exports['e2e record api interaction errors recordKey and projectId errors and exits on 401 1'] = `
We failed trying to authenticate this project: pid123
Your Record Key is invalid: f858a...ee7e1
@@ -593,9 +601,11 @@ It may have been recently revoked by you or another user.
Please log into the Dashboard to see the updated token.
https://on.cypress.io/dashboard/projects/pid123
`
exports['e2e record video recording does not upload when not enabled 1'] = `
====================================================================================================
(Run Starting)
@@ -605,6 +615,7 @@ exports['e2e record video recording does not upload when not enabled 1'] = `
Browser: FooBrowser 88
Specs: 1 found (record_pass_spec.coffee)
Searched: cypress/integration/record_pass*
Params: Group: false, Parallel: false
Run URL: https://dashboard.cypress.io/#/projects/cjvoj7/runs/12 │
@@ -612,6 +623,7 @@ exports['e2e record video recording does not upload when not enabled 1'] = `
Running: record_pass_spec.coffee... (1 of 1)
Estimated: 8 seconds
record pass
@@ -634,6 +646,7 @@ exports['e2e record video recording does not upload when not enabled 1'] = `
Screenshots: 1
Video: false
Duration: X seconds
Estimated: 8 seconds
Spec Ran: record_pass_spec.coffee
@@ -663,9 +676,11 @@ exports['e2e record video recording does not upload when not enabled 1'] = `
Recorded Run: https://dashboard.cypress.io/#/projects/cjvoj7/runs/12
`
exports['e2e record api interaction errors uploading assets warns but proceeds 1'] = `
====================================================================================================
(Run Starting)
@@ -675,6 +690,7 @@ exports['e2e record api interaction errors uploading assets warns but proceeds 1
Browser: FooBrowser 88
Specs: 1 found (record_pass_spec.coffee)
Searched: cypress/integration/record_pass*
Params: Group: false, Parallel: false
Run URL: https://dashboard.cypress.io/#/projects/cjvoj7/runs/12 │
@@ -682,6 +698,7 @@ exports['e2e record api interaction errors uploading assets warns but proceeds 1
Running: record_pass_spec.coffee... (1 of 1)
Estimated: 8 seconds
record pass
@@ -704,6 +721,7 @@ exports['e2e record api interaction errors uploading assets warns but proceeds 1
Screenshots: 1
Video: true
Duration: X seconds
Estimated: 8 seconds
Spec Ran: record_pass_spec.coffee
@@ -740,23 +758,29 @@ exports['e2e record api interaction errors uploading assets warns but proceeds 1
Recorded Run: https://dashboard.cypress.io/#/projects/cjvoj7/runs/12
`
exports['e2e record misconfiguration errors and exits when no browser found 1'] = `Can't run because you've entered an invalid browser.
exports['e2e record misconfiguration errors and exits when no browser found 1'] = `
Can't run because you've entered an invalid browser.
Browser: 'browserDoesNotExist' was not found on your system.
Available browsers found are: browser1, browser2, browser3
`
exports['e2e record misconfiguration errors and exits when no specs found 1'] = `Can't run because no spec files were found.
exports['e2e record misconfiguration errors and exits when no specs found 1'] = `
Can't run because no spec files were found.
We searched for any files matching this glob pattern:
cypress/integration/notfound/**
`
exports['e2e record recordKey warns but does not exit when is forked pr 1'] = `Warning: It looks like you are trying to record this run from a forked PR.
exports['e2e record recordKey warns but does not exit when is forked pr 1'] = `
Warning: It looks like you are trying to record this run from a forked PR.
The 'Record Key' is missing. Your CI provider is likely not passing private environment variables to builds from forks.
@@ -821,5 +845,491 @@ This error will not alter the exit code.
All specs passed! XX:XX 2 1 - 1 -
`
exports['e2e record parallelization passes in parallel with group 1'] = `
====================================================================================================
(Run Starting)
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 4 found (record_error_spec.coffee, record_fail_spec.coffee, record_pass_spec.coff
Searched: cypress/integration/record*
Params: Group: prod-e2e, Parallel: true
Run URL: https://dashboard.cypress.io/#/projects/cjvoj7/runs/12 │
Running: record_pass_spec.coffee... (1 of 4)
Estimated: 1 second
record pass
passes
- is pending
1 passing
1 pending
(Results)
Tests: 2
Passing: 1
Failing: 0
Pending: 1
Skipped: 0
Screenshots: 1
Video: true
Duration: X seconds
Estimated: 1 second
Spec Ran: record_pass_spec.coffee
(Screenshots)
- /foo/bar/.projects/e2e/cypress/screenshots/record_pass_spec.coffee/yay it passes.png (202x1002)
(Uploading Results)
- Done Uploading (1/1) /foo/bar/.projects/e2e/cypress/screenshots/record_pass_spec.coffee/yay it passes.png
====================================================================================================
(Run Finished)
Spec Tests Passing Failing Pending Skipped
record_pass_spec.coffee XX:XX 2 1 - 1 -
All specs passed! XX:XX 2 1 - 1 -
Recorded Run: https://dashboard.cypress.io/#/projects/cjvoj7/runs/12
`
exports['e2e record parallelization passes in parallel with group 2'] = `
====================================================================================================
(Run Starting)
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 4 found (record_error_spec.coffee, record_fail_spec.coffee, record_pass_spec.coff
Searched: cypress/integration/record*
Params: Group: prod-e2e, Parallel: true
Run URL: https://dashboard.cypress.io/#/projects/cjvoj7/runs/12 │
Running: record_error_spec.coffee... (2 of 4)
Estimated: 1 second
Oops...we found an error preparing this test file:
/foo/bar/.projects/e2e/cypress/integration/record_error_spec.coffee
The error was:
Error: Cannot find module '../it/does/not/exist' from '/foo/bar/.projects/e2e/cypress/integration'
This occurred while Cypress was compiling and bundling your test code. This is usually caused by:
- A missing file or dependency
- A syntax error in the file or one of its dependencies
Fix the error in your code and re-run your tests.
(Results)
Tests: 0
Passing: 0
Failing: 1
Pending: 0
Skipped: 0
Screenshots: 0
Video: true
Duration: X seconds
Estimated: 1 second
Spec Ran: record_error_spec.coffee
(Video)
- Started processing: Compressing to 32 CRF
- Finished processing: /foo/bar/.projects/e2e/cypress/videos/abc123.mp4 (X seconds)
(Uploading Results)
- Done Uploading (1/1) /foo/bar/.projects/e2e/cypress/videos/abc123.mp4
Running: record_fail_spec.coffee... (3 of 4)
Estimated: 2 seconds
record fails
1) "before each" hook for "fails 1"
0 passing
1 failing
1) record fails "before each" hook for "fails 1":
Error: foo
Because this error occurred during a 'before each' hook we are skipping the remaining tests in the current suite: 'record fails'
at stack trace line
(Results)
Tests: 2
Passing: 0
Failing: 1
Pending: 0
Skipped: 1
Screenshots: 1
Video: true
Duration: X seconds
Estimated: 2 seconds
Spec Ran: record_fail_spec.coffee
(Screenshots)
- /foo/bar/.projects/e2e/cypress/screenshots/record_fail_spec.coffee/record fails -- fails 1 -- before each hook (failed).png (1280x720)
(Video)
- Started processing: Compressing to 32 CRF
- Finished processing: /foo/bar/.projects/e2e/cypress/videos/abc123.mp4 (X seconds)
(Uploading Results)
- Done Uploading (1/2) /foo/bar/.projects/e2e/cypress/screenshots/record_fail_spec.coffee/record fails -- fails 1 -- before each hook (failed).png
- Done Uploading (2/2) /foo/bar/.projects/e2e/cypress/videos/abc123.mp4
Running: record_uncaught_spec.coffee... (4 of 4)
Estimated: 3 seconds
1) An uncaught error was detected outside of a test
0 passing
1 failing
1) An uncaught error was detected outside of a test:
Uncaught Error: instantly fails
This error originated from your test code, not from Cypress.
When Cypress detects uncaught errors originating from your test code it will automatically fail the current test.
Cypress could not associate this error to any specific test.
We dynamically generated a new test to display this failure.
at stack trace line
at stack trace line
at stack trace line
at stack trace line
(Results)
Tests: 1
Passing: 0
Failing: 1
Pending: 0
Skipped: 0
Screenshots: 1
Video: true
Duration: X seconds
Estimated: 3 seconds
Spec Ran: record_uncaught_spec.coffee
(Screenshots)
- /foo/bar/.projects/e2e/cypress/screenshots/record_uncaught_spec.coffee/An uncaught error was detected outside of a test (failed).png (1280x720)
(Video)
- Started processing: Compressing to 32 CRF
- Finished processing: /foo/bar/.projects/e2e/cypress/videos/abc123.mp4 (X seconds)
(Uploading Results)
- Done Uploading (1/2) /foo/bar/.projects/e2e/cypress/screenshots/record_uncaught_spec.coffee/An uncaught error was detected outside of a test (failed).png
- Done Uploading (2/2) /foo/bar/.projects/e2e/cypress/videos/abc123.mp4
====================================================================================================
(Run Finished)
Spec Tests Passing Failing Pending Skipped
record_error_spec.coffee XX:XX - - 1 - -
record_fail_spec.coffee XX:XX 2 - 1 - 1
record_uncaught_spec.coffee XX:XX 1 - 1 - -
3 of 3 failed (100%) XX:XX 3 - 3 - 1
Recorded Run: https://dashboard.cypress.io/#/projects/cjvoj7/runs/12
`
exports['e2e record api interaction errors create run 422 errors and exits when group name is in use 1'] = `
You passed the --group flag, but this group name has already been used for this run.
The existing run is: https://dashboard.cypress.io/runs/12345
The --group flag you passed was: e2e-tests
If you are trying to parallelize this run, then also pass the --parallel flag, else pass a different group name.
https://on.cypress.io/run-group-name-not-unique
`
exports['e2e record api interaction errors create run unknown 422 errors and exits when there is an unknown 422 response 1'] = `
We encountered an unexpected error talking to our servers.
There is likely something wrong with the request.
The --group flag you passed was: e2e-tests
The --parallel flag you passed was: true
The --ciBuildId flag you passed was: ciBuildId123
The server's response was:
StatusCodeError: 422
{
"code": "SOMETHING_UNKNOWN",
"message": "An unknown message here from the server."
}
`
exports['e2e record api interaction errors create run 500 warns but proceeds when grouping without parallelization 1'] = `
Warning: We encountered an error talking to our servers.
This run will not be recorded.
This error will not alter the exit code.
StatusCodeError: 500 - "Internal Server Error"
====================================================================================================
(Run Starting)
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 1 found (record_pass_spec.coffee)
Searched: cypress/integration/record_pass*
Running: record_pass_spec.coffee... (1 of 1)
record pass
passes
- is pending
1 passing
1 pending
(Results)
Tests: 2
Passing: 1
Failing: 0
Pending: 1
Skipped: 0
Screenshots: 1
Video: true
Duration: X seconds
Spec Ran: record_pass_spec.coffee
(Screenshots)
- /foo/bar/.projects/e2e/cypress/screenshots/record_pass_spec.coffee/yay it passes.png (202x1002)
====================================================================================================
(Run Finished)
Spec Tests Passing Failing Pending Skipped
record_pass_spec.coffee XX:XX 2 1 - 1 -
All specs passed! XX:XX 2 1 - 1 -
`
exports['e2e record api interaction errors create run 500 does not proceed and exits with error when parallelizing 1'] = `
We encountered an unexpected error talking to our servers.
Because you passed the --parallel flag, this run cannot proceed because it requires a valid response from our servers.
The --group flag you passed was: foo
The --ciBuildId flag you passed was: ciBuildId123
The server's response was:
StatusCodeError: 500 - "Internal Server Error"
`
exports['e2e record api interaction errors create instance 500 does not proceed and exits with error when parallelizing and creating instance 1'] = `
====================================================================================================
(Run Starting)
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 1 found (record_pass_spec.coffee)
Searched: cypress/integration/record_pass*
Params: Group: foo, Parallel: true
Run URL: https://dashboard.cypress.io/#/projects/cjvoj7/runs/12 │
We encountered an unexpected error talking to our servers.
Because you passed the --parallel flag, this run cannot proceed because it requires a valid response from our servers.
The --group flag you passed was: foo
The --ciBuildId flag you passed was: ciBuildId123
The server's response was:
StatusCodeError: 500 - "Internal Server Error"
`
exports['e2e record api interaction errors update instance 500 does not proceed and exits with error when parallelizing and updating instance 1'] = `
====================================================================================================
(Run Starting)
Cypress: 1.2.3
Browser: FooBrowser 88
Specs: 1 found (record_pass_spec.coffee)
Searched: cypress/integration/record_pass*
Params: Group: foo, Parallel: true
Run URL: https://dashboard.cypress.io/#/projects/cjvoj7/runs/12 │
Running: record_pass_spec.coffee... (1 of 1)
Estimated: 5 seconds
record pass
passes
- is pending
1 passing
1 pending
(Results)
Tests: 2
Passing: 1
Failing: 0
Pending: 1
Skipped: 0
Screenshots: 1
Video: true
Duration: X seconds
Estimated: 5 seconds
Spec Ran: record_pass_spec.coffee
(Screenshots)
- /foo/bar/.projects/e2e/cypress/screenshots/record_pass_spec.coffee/yay it passes.png (202x1002)
(Uploading Results)
We encountered an unexpected error talking to our servers.
Because you passed the --parallel flag, this run cannot proceed because it requires a valid response from our servers.
The --group flag you passed was: foo
The --ciBuildId flag you passed was: ciBuildId123
The server's response was:
StatusCodeError: 500 - "Internal Server Error"
`

View File

@@ -1,4 +1,5 @@
exports['e2e reporters reports error if cannot load reporter 1'] = `Could not load reporter by name: module-does-not-exist
exports['e2e reporters reports error if cannot load reporter 1'] = `
Could not load reporter by name: module-does-not-exist
We searched for the reporter in these paths:
@@ -10,9 +11,11 @@ The error we received was:
Cannot find module '/foo/bar/.projects/e2e/node_modules/module-does-not-exist'
Learn more at stack trace line
`
exports['e2e reporters supports junit reporter and reporter options 1'] = `
====================================================================================================
(Run Starting)
@@ -61,9 +64,11 @@ exports['e2e reporters supports junit reporter and reporter options 1'] = `
All specs passed! XX:XX 1 1 - - -
`
exports['e2e reporters supports local custom reporter 1'] = `
====================================================================================================
(Run Starting)
@@ -114,9 +119,11 @@ finished!
All specs passed! XX:XX 1 1 - - -
`
exports['e2e reporters mochawesome passes with mochawesome@1.5.2 npm custom reporter 1'] = `
====================================================================================================
(Run Starting)
@@ -179,9 +186,11 @@ exports['e2e reporters mochawesome passes with mochawesome@1.5.2 npm custom repo
All specs passed! XX:XX 1 1 - - -
`
exports['e2e reporters mochawesome fails with mochawesome@1.5.2 npm custom reporter 1'] = `
====================================================================================================
(Run Starting)
@@ -289,9 +298,11 @@ Because this error occurred during a 'after all' hook we are skipping the remain
1 of 1 failed (100%) XX:XX 6 1 3 1 1
`
exports['e2e reporters mochawesome passes with mochawesome@2.3.1 npm custom reporter 1'] = `
====================================================================================================
(Run Starting)
@@ -352,9 +363,11 @@ exports['e2e reporters mochawesome passes with mochawesome@2.3.1 npm custom repo
All specs passed! XX:XX 1 1 - - -
`
exports['e2e reporters mochawesome fails with mochawesome@2.3.1 npm custom reporter 1'] = `
====================================================================================================
(Run Starting)
@@ -460,9 +473,11 @@ Because this error occurred during a 'after all' hook we are skipping the remain
1 of 1 failed (100%) XX:XX 6 1 3 1 1
`
exports['e2e reporters mochawesome passes with mochawesome@3.0.1 npm custom reporter 1'] = `
====================================================================================================
(Run Starting)
@@ -523,9 +538,11 @@ exports['e2e reporters mochawesome passes with mochawesome@3.0.1 npm custom repo
All specs passed! XX:XX 1 1 - - -
`
exports['e2e reporters mochawesome fails with mochawesome@3.0.1 npm custom reporter 1'] = `
====================================================================================================
(Run Starting)
@@ -631,9 +648,11 @@ Because this error occurred during a 'after all' hook we are skipping the remain
1 of 1 failed (100%) XX:XX 6 1 3 1 1
`
exports['e2e reporters reports error when thrown from reporter 1'] = `Could not load reporter by name: reporters/throws.js
exports['e2e reporters reports error when thrown from reporter 1'] = `
Could not load reporter by name: reporters/throws.js
We searched for the reporter in these paths:
@@ -675,7 +694,6 @@ Error: this reporter threw an error
at stack trace line
at stack trace line
Learn more at stack trace line
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e requests passes 1'] = `
====================================================================================================
(Run Starting)
@@ -66,9 +67,11 @@ exports['e2e requests passes 1'] = `
All specs passed! XX:XX 12 12 - - -
`
exports['e2e requests fails when network immediately fails 1'] = `
====================================================================================================
(Run Starting)
@@ -194,9 +197,11 @@ RequestError: Error: connect ECONNREFUSED 127.0.0.1:16795
1 of 1 failed (100%) XX:XX 1 - 1 - -
`
exports['e2e requests fails on status code 1'] = `
====================================================================================================
(Run Starting)
@@ -315,5 +320,5 @@ Body: Service Unavailable
1 of 1 failed (100%) XX:XX 1 - 1 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e return value failing1 1'] = `
====================================================================================================
(Run Starting)
@@ -131,5 +132,5 @@ https://on.cypress.io/returning-value-and-commands-in-custom-command
1 of 1 failed (100%) XX:XX 2 - 2 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['lib/plugins/child/run_plugins sends error message if pluginsFile is missing 1'] = `Error: Cannot find module '/does/not/exist.coffee'
exports['lib/plugins/child/run_plugins sends error message if pluginsFile is missing 1'] = `
Error: Cannot find module '/does/not/exist.coffee'
at Function.Module._resolveFilename <path>module.js
at Module._load <path>module.js
at Function.hookedLoader [as _load] <path>mockery.js
@@ -22,9 +23,11 @@ exports['lib/plugins/child/run_plugins sends error message if pluginsFile is mis
at runCallback <path>timers.js
at tryOnImmediate <path>timers.js
at processImmediate [as _immediateCallback] <path>timers.js
`
exports['lib/plugins/child/run_plugins sends error message if requiring pluginsFile errors 1'] = `Error: error thrown by pluginsFile
exports['lib/plugins/child/run_plugins sends error message if requiring pluginsFile errors 1'] = `
Error: error thrown by pluginsFile
at Object.<anonymous> <path>throws_error.coffee
at Object.<anonymous> <path>throws_error.coffee
at Module._compile <path>module.js
@@ -53,15 +56,15 @@ exports['lib/plugins/child/run_plugins sends error message if requiring pluginsF
at runCallback <path>timers.js
at tryOnImmediate <path>timers.js
at processImmediate [as _immediateCallback] <path>timers.js
`
exports['lib/plugins/child/run_plugins sends error message if pluginsFile has syntax error 1'] = `<path>syntax_error.coffee) error: missing }
exports['lib/plugins/child/run_plugins sends error message if pluginsFile has syntax error 1'] = `
<path>syntax_error.coffee) error: missing }
<color-code>{<color-code>
<color-code>^<color-code>`
<color-code>^<color-code>
`
exports['lib/plugins/child/run_plugins sends error message if pluginsFile does not export a function 1'] = `null`
exports['lib/plugins/child/run_plugins on \'load\' message sends error if pluginsFile function throws an error 1'] = {
"name": "ReferenceError",
"message": "foo is not defined"
}
exports['lib/plugins/child/run_plugins sends error message if pluginsFile does not export a function 1'] = `
null
`

View File

@@ -285,7 +285,8 @@ exports['lib/scaffold .fileTree leaves out support if configured to false 1'] =
}
]
exports['lib/scaffold .support creates supportFolder and commands.js and index.js when supportFolder does not exist 1'] = `// ***********************************************
exports['lib/scaffold .support creates supportFolder and commands.js and index.js when supportFolder does not exist 1'] = `
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
@@ -310,9 +311,11 @@ exports['lib/scaffold .support creates supportFolder and commands.js and index.j
//
// -- This is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
`
exports['lib/scaffold .support creates supportFolder and commands.js and index.js when supportFolder does not exist 2'] = `// ***********************************************************
exports['lib/scaffold .support creates supportFolder and commands.js and index.js when supportFolder does not exist 2'] = `
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
@@ -332,6 +335,7 @@ import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')
`
exports['lib/scaffold .fileTree leaves out plugins if configured to false 1'] = [
@@ -423,7 +427,8 @@ exports['lib/scaffold .fileTree leaves out plugins if configured to false 1'] =
}
]
exports['lib/scaffold .plugins creates pluginsFile when pluginsFolder does not exist 1'] = `// ***********************************************************
exports['lib/scaffold .plugins creates pluginsFile when pluginsFolder does not exist 1'] = `
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
@@ -440,4 +445,5 @@ module.exports = (on, config) => {
// <backtick>on<backtick> is used to hook into various events Cypress emits
// <backtick>config<backtick> is the resolved Cypress config
}
`

View File

@@ -1,4 +1,5 @@
exports['e2e screenshot element capture passes 1'] = `
====================================================================================================
(Run Starting)
@@ -68,5 +69,5 @@ exports['e2e screenshot element capture passes 1'] = `
All specs passed! XX:XX 1 1 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e screenshot fullPage capture passes 1'] = `
====================================================================================================
(Run Starting)
@@ -68,5 +69,5 @@ exports['e2e screenshot fullPage capture passes 1'] = `
All specs passed! XX:XX 1 1 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e screenshot in nested spec passes 1'] = `
====================================================================================================
(Run Starting)
@@ -58,5 +59,5 @@ exports['e2e screenshot in nested spec passes 1'] = `
All specs passed! XX:XX 1 1 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e screenshot viewport capture passes 1'] = `
====================================================================================================
(Run Starting)
@@ -83,5 +84,5 @@ exports['e2e screenshot viewport capture passes 1'] = `
All specs passed! XX:XX 1 1 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e screenshots passes 1'] = `
====================================================================================================
(Run Starting)
@@ -133,5 +134,5 @@ Because this error occurred during a 'after each' hook we are skipping the remai
1 of 1 failed (100%) XX:XX 19 15 4 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e server sent events passes 1'] = `
====================================================================================================
(Run Starting)
@@ -55,5 +56,5 @@ exports['e2e server sent events passes 1'] = `
All specs passed! XX:XX 1 1 - - -
`
`

View File

@@ -1,14 +0,0 @@
exports['e2e specs failing when no specs found 1'] = `Can't run because no spec files were found.
We searched for any files inside of this folder:
/foo/bar/.projects/e2e/cypress/specs
`
exports['e2e specs failing when no spec pattern found 1'] = `Can't run because no spec files were found.
We searched for any files matching this glob pattern:
cypress/integration/cypress/integration/**notfound**
`

View File

@@ -0,0 +1,17 @@
exports['e2e specs failing when no specs found 1'] = `
Can't run because no spec files were found.
We searched for any files inside of this folder:
/foo/bar/.projects/e2e/cypress/specs
`
exports['e2e specs failing when no spec pattern found 1'] = `
Can't run because no spec files were found.
We searched for any files matching this glob pattern:
cypress/integration/cypress/integration/**notfound**
`

View File

@@ -1,4 +1,5 @@
exports['e2e stdout displays errors from failures 1'] = `
====================================================================================================
(Run Starting)
@@ -133,9 +134,11 @@ The internal Cypress web server responded with:
1 of 1 failed (100%) XX:XX 5 2 3 - -
`
exports['e2e stdout displays errors from exiting early due to bundle errors 1'] = `
====================================================================================================
(Run Starting)
@@ -202,9 +205,11 @@ Fix the error in your code and re-run your tests.
1 of 1 failed (100%) XX:XX - - 1 - -
`
exports['e2e stdout does not duplicate suites or tests between visits 1'] = `
====================================================================================================
(Run Starting)
@@ -272,9 +277,11 @@ exports['e2e stdout does not duplicate suites or tests between visits 1'] = `
All specs passed! XX:XX 8 8 - - -
`
exports['e2e stdout logs that electron cannot be recorded in headed mode 1'] = `
====================================================================================================
(Run Starting)
@@ -329,9 +336,11 @@ A video will not be recorded when using this mode.
All specs passed! XX:XX 1 1 - - -
`
exports['e2e stdout logs that chrome cannot be recorded 1'] = `
====================================================================================================
(Run Starting)
@@ -386,5 +395,5 @@ A video will not be recorded when using this browser.
All specs passed! XX:XX 1 1 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e subdomain passes 1'] = `
====================================================================================================
(Run Starting)
@@ -64,5 +65,5 @@ exports['e2e subdomain passes 1'] = `
All specs passed! XX:XX 9 7 - 2 -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e task fails 1'] = `
====================================================================================================
(Run Starting)
@@ -84,5 +85,5 @@ https://on.cypress.io/api/task
1 of 1 failed (100%) XX:XX 1 - 1 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e task fails 1'] = `
====================================================================================================
(Run Starting)
@@ -126,5 +127,5 @@ https://on.cypress.io/api/task
1 of 1 failed (100%) XX:XX 2 - 2 - -
`
`

View File

@@ -1,44 +0,0 @@
exports['lib/util/terminal .table draws a table with 2px margin-left 1'] = `  Spec  Skipped  Pending  Passing  Failing 
 
  foo.js 4 3 2 1 
 
  bar.js 0 0 0 15 
 
  fail/is/whale.js 25 5 100 3 
 `
exports['lib/util/terminal .table draws two tables as summary view 1'] = `  Spec  Skipped  Pending  Passing  Failing 
 
  foo.js 4 3 2 1 
 
  bar.js 0 0 0 15 
 
  fail/is/whale.js 25 5 100 3 
 `
exports['lib/util/terminal .table draws multiple specs summary table 1'] = ` Spec Tests Passing Failing Pending Skipped
foo.js 00:49 7 4 3 2 1
bar.js 796ms 0 0 0 0 15
fail/is/whale.js 03:28 30 25 5 100 3
2 of 3 passed (66%) 1:05:36 37 29 8 102 18 `
exports['lib/util/terminal .table draws single spec summary table 1'] = `
Tests: 1
Passing: 2
Failing: 3
Pending: 4
Skipped: 5
Duration: 6
Screenshots: 7
Video: true
Spec: foo/bar/baz.js
`
exports['lib/util/terminal .table draws a page divider 1'] = `
Running: foo/bar/baz.js... (100 of 200) `

View File

@@ -0,0 +1,31 @@
exports['lib/util/terminal .table draws multiple specs summary table 1'] = `
Spec Tests Passing Failing Pending Skipped
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ foo.js 00:49 7 4 3 2 1 │
├────────────────────────────────────────────────────────────────────────────────────────────────┤
│ bar.js 796ms 0 0 0 0 15 │
├────────────────────────────────────────────────────────────────────────────────────────────────┤
│ fail/is/whale.js 03:28 30 25 5 100 3 │
└────────────────────────────────────────────────────────────────────────────────────────────────┘
2 of 3 passed (66%) 1:05:36 37 29 8 102 18
`
exports['lib/util/terminal .table draws single spec summary table 1'] = `
┌──────────────────────────────┐
│ Tests: 1 │
│ Passing: 2 │
│ Failing: 3 │
│ Pending: 4 │
│ Skipped: 5 │
│ Duration: 6 │
│ Screenshots: 7 │
│ Video: true │
│ Spec: foo/bar/baz.js │
└──────────────────────────────┘
`
exports['lib/util/terminal .table draws a page divider 1'] = `
────────────────────────────────────────────────────────────────────────────────────────────────────
Running: foo/bar/baz.js... (100 of 200)
`

View File

@@ -1,4 +1,5 @@
exports['e2e uncaught errors failing1 1'] = `
====================================================================================================
(Run Starting)
@@ -76,9 +77,11 @@ We dynamically generated a new test to display this failure.
1 of 1 failed (100%) XX:XX 1 - 1 - -
`
exports['e2e uncaught errors failing2 1'] = `
====================================================================================================
(Run Starting)
@@ -157,9 +160,11 @@ We dynamically generated a new test to display this failure.
1 of 1 failed (100%) XX:XX 1 - 1 - -
`
exports['e2e uncaught errors failing3 1'] = `
====================================================================================================
(Run Starting)
@@ -232,9 +237,11 @@ When Cypress detects uncaught errors originating from your test code it will aut
1 of 1 failed (100%) XX:XX 1 - 1 - -
`
exports['e2e uncaught errors failing4 1'] = `
====================================================================================================
(Run Starting)
@@ -312,9 +319,11 @@ Because this error occurred during a 'before all' hook we are skipping the remai
1 of 1 failed (100%) XX:XX 2 1 1 - -
`
exports['e2e uncaught errors failing5 1'] = `
====================================================================================================
(Run Starting)
@@ -405,5 +414,5 @@ exports['e2e uncaught errors failing5 1'] = `
1 of 1 failed (100%) XX:XX 8 4 4 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e uncaught support file errors failing 1'] = `
====================================================================================================
(Run Starting)
@@ -75,5 +76,5 @@ We dynamically generated a new test to display this failure.
1 of 1 failed (100%) XX:XX 1 - 1 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e user agent passes on chrome 1'] = `
====================================================================================================
(Run Starting)
@@ -56,9 +57,11 @@ A video will not be recorded when using this browser.
All specs passed! XX:XX 2 2 - - -
`
exports['e2e user agent passes on electron 1'] = `
====================================================================================================
(Run Starting)
@@ -116,5 +119,5 @@ exports['e2e user agent passes on electron 1'] = `
All specs passed! XX:XX 2 2 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e viewport passes 1'] = `
====================================================================================================
(Run Starting)
@@ -57,5 +58,5 @@ exports['e2e viewport passes 1'] = `
All specs passed! XX:XX 3 3 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e visit low response timeout passes 1'] = `
====================================================================================================
(Run Starting)
@@ -72,9 +73,11 @@ exports['e2e visit low response timeout passes 1'] = `
All specs passed! XX:XX 13 13 - - -
`
exports['e2e visit low response timeout fails when network connection immediately fails 1'] = `
====================================================================================================
(Run Starting)
@@ -179,9 +182,11 @@ Error: connect ECONNREFUSED 127.0.0.1:16795
1 of 1 failed (100%) XX:XX 1 - 1 - -
`
exports['e2e visit low response timeout fails when server responds with 500 1'] = `
====================================================================================================
(Run Starting)
@@ -274,9 +279,11 @@ If you do not want status codes to cause failures pass the option: 'failOnStatus
1 of 1 failed (100%) XX:XX 1 - 1 - -
`
exports['e2e visit low response timeout fails when file server responds with 404 1'] = `
====================================================================================================
(Run Starting)
@@ -369,9 +376,11 @@ The internal Cypress web server responded with:
1 of 1 failed (100%) XX:XX 1 - 1 - -
`
exports['e2e visit low response timeout fails when content type isnt html 1'] = `
====================================================================================================
(Run Starting)
@@ -466,9 +475,11 @@ cy.request() will automatically get and set cookies and enable you to parse resp
1 of 1 failed (100%) XX:XX 1 - 1 - -
`
exports['e2e visit normal response timeouts fails when visit times out 1'] = `
====================================================================================================
(Run Starting)
@@ -589,5 +600,5 @@ When this 'load' event occurs, Cypress will continue running commands.
1 of 1 failed (100%) XX:XX 2 - 2 - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e web security when enabled fails 1'] = `
====================================================================================================
(Run Starting)
@@ -163,9 +164,11 @@ https://on.cypress.io/cross-origin-violation
1 of 1 failed (100%) XX:XX 3 - 3 - -
`
exports['e2e web security when disabled passes 1'] = `
====================================================================================================
(Run Starting)
@@ -224,5 +227,5 @@ A video will not be recorded when using this browser.
All specs passed! XX:XX 3 3 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e websockets passes 1'] = `
====================================================================================================
(Run Starting)
@@ -55,5 +56,5 @@ exports['e2e websockets passes 1'] = `
All specs passed! XX:XX 1 1 - - -
`
`

View File

@@ -1,4 +1,5 @@
exports['e2e xhr passes 1'] = `
====================================================================================================
(Run Starting)
@@ -63,5 +64,5 @@ exports['e2e xhr passes 1'] = `
All specs passed! XX:XX 8 8 - - -
`
`

View File

@@ -31,7 +31,16 @@ rp = request.defaults (params = {}, callback) ->
method = params.method.toLowerCase()
debug(
"request to url: %s with params: %o",
"#{params.method} #{params.url}",
_.pick(params, "body", "headers")
)
request[method](params, callback)
.promise()
.tap (resp) ->
debug("response %o", resp)
formatResponseBody = (err) ->
## if the body is JSON object
@@ -57,6 +66,8 @@ isRetriableError = (err) ->
(err instanceof Promise.TimeoutError) or (500 <= err.statusCode < 600)
module.exports = {
rp
ping: ->
rp.get(routes.ping())
.catch(tagError)
@@ -113,28 +124,25 @@ module.exports = {
createRun: (options = {}) ->
body = _.pick(options, [
"projectId"
"recordKey"
"ci"
"specs",
"commit"
"platform"
"specPattern"
"group",
"platform",
"parallel",
"ciBuildId",
"projectId",
"recordKey",
"specPattern",
])
## temporary hack to get around
## the latest schema requirements
body.group = null
body.parallel = null
body.ciBuildId = null
rp.post({
body
url: routes.runs()
json: true
timeout: options.timeout ? MUTATING_TIMEOUT
headers: {
"x-route-version": "3"
"x-route-version": "4"
}
})
.catch(errors.StatusCodeError, formatResponseBody)
@@ -156,11 +164,9 @@ module.exports = {
json: true
timeout: timeout ? MUTATING_TIMEOUT
headers: {
"x-route-version": "4"
"x-route-version": "5"
}
})
.promise()
.get("instanceId")
.catch(errors.StatusCodeError, formatResponseBody)
.catch(tagError)
@@ -208,7 +214,6 @@ module.exports = {
bearer: authToken
}
})
.promise()
.timeout(timeout)
.catch(tagError)
@@ -294,7 +299,6 @@ module.exports = {
url: routes.auth(),
json: true
})
.promise()
.get("url")
.catch(tagError)
@@ -310,7 +314,6 @@ module.exports = {
"x-route-version": "2"
}
})
.promise()
.get("apiToken")
.catch(tagError)

View File

@@ -1,5 +1,6 @@
_ = require("lodash")
os = require("os")
path = require("path")
Promise = require("bluebird")
extension = require("@packages/extension")
debug = require("debug")("cypress:server:browsers")
@@ -64,6 +65,17 @@ defaultArgs = [
"--disable-default-apps"
]
pluginsBeforeBrowserLaunch = (browser, args) ->
## bail if we're not registered to this event
return args if not plugins.has("before:browser:launch")
plugins.execute("before:browser:launch", browser, args)
.then (newArgs) ->
debug("got user args for 'before:browser:launch'", newArgs)
## reset args if we got 'em
return newArgs ? args
_normalizeArgExtensions = (dest, args) ->
loadExtension = _.find args, (arg) ->
arg.includes(LOAD_EXTENSION)
@@ -80,15 +92,23 @@ _normalizeArgExtensions = (dest, args) ->
args
## we now store the extension in each browser profile
_removeRootExtension = ->
fs
.removeAsync(appData.path("extensions"))
.catchReturn(null) ## noop if doesn't exist fails for any reason
module.exports = {
_normalizeArgExtensions
_writeExtension: (proxyUrl, socketIoRoute) ->
_removeRootExtension
_writeExtension: (browserName, isTextTerminal, proxyUrl, socketIoRoute) ->
## get the string bytes for the final extension file
extension.setHostAndPath(proxyUrl, socketIoRoute)
.then (str) ->
extensionDest = appData.path("extensions", "chrome")
extensionBg = appData.path("extensions", "chrome", "background.js")
extensionDest = utils.getExtensionDir(browserName, isTextTerminal)
extensionBg = path.join(extensionDest, "background.js")
## copy the extension src to the extension dist
utils.copyExtension(pathToExtension, extensionDest)
@@ -130,41 +150,43 @@ module.exports = {
args
open: (browserName, url, options = {}, automation) ->
args = @_getArgs(options)
{ isTextTerminal } = options
Promise
.try ->
## bail if we're not registered to this event
return if not plugins.has("before:browser:launch")
.try =>
args = @_getArgs(options)
plugins.execute("before:browser:launch", options.browser, args)
.then (newArgs) ->
debug("got user args for 'before:browser:launch'", newArgs)
## reset args if we got 'em
if newArgs
args = newArgs
.then =>
Promise.all([
## ensure that we have a clean cache dir
## before launching the browser every time
utils.ensureCleanCache(browserName)
utils.ensureCleanCache(browserName, isTextTerminal),
@_writeExtension(options.proxyUrl, options.socketIoRoute)
pluginsBeforeBrowserLaunch(options.browser, args)
])
.spread (cacheDir, dest) ->
## normalize the --load-extensions argument by
## massaging what the user passed into our own
args = _normalizeArgExtensions(dest, args)
.spread (cacheDir, args) =>
Promise.all([
@_writeExtension(
browserName,
isTextTerminal,
options.proxyUrl,
options.socketIoRoute
),
userDir = utils.getProfileDir(browserName)
_removeRootExtension(),
])
.spread (extDest) ->
## normalize the --load-extensions argument by
## massaging what the user passed into our own
args = _normalizeArgExtensions(extDest, args)
## this overrides any previous user-data-dir args
## by being the last one
args.push("--user-data-dir=#{userDir}")
args.push("--disk-cache-dir=#{cacheDir}")
userDir = utils.getProfileDir(browserName, isTextTerminal)
debug("launch in chrome: %s, %s", url, args)
## this overrides any previous user-data-dir args
## by being the last one
args.push("--user-data-dir=#{userDir}")
args.push("--disk-cache-dir=#{cacheDir}")
utils.launch(browserName, url, args)
debug("launch in chrome: %s, %s", url, args)
utils.launch(browserName, url, args)
}

View File

@@ -2,10 +2,12 @@ _ = require("lodash")
EE = require("events")
Promise = require("bluebird")
debug = require("debug")("cypress:server:browsers:electron")
plugins = require("../plugins")
menu = require("../gui/menu")
Windows = require("../gui/windows")
appData = require("../util/app_data")
plugins = require("../plugins")
savedState = require("../saved_state")
profileCleaner = require("../util/profile_cleaner")
module.exports = {
_defaultOptions: (projectRoot, state, options) ->
@@ -20,6 +22,7 @@ module.exports = {
minWidth: 100
minHeight: 100
contextMenu: true
partition: @_getPartition(options)
trackState: {
width: "browserWidth"
height: "browserHeight"
@@ -89,6 +92,16 @@ module.exports = {
win.loadURL(url)
.return(win)
_getPartition: (options) ->
if options.isTextTerminal
## create dynamic persisted run
## to enable parallelization
return "persist:run-#{process.pid}"
## we're in interactive mode and always
## use the same session
return "persist:interactive"
_clearCache: (webContents) ->
new Promise (resolve) ->
webContents.session.clearCache(resolve)
@@ -108,6 +121,7 @@ module.exports = {
{ projectRoot, isTextTerminal } = options
debug("open %o", { browserName, url })
savedState(projectRoot, isTextTerminal)
.then (state) ->
debug("got saved state")

View File

@@ -59,6 +59,8 @@ module.exports = {
throwBrowserNotFound
removeOldProfiles: utils.removeOldProfiles
get: utils.getBrowsers
launch: utils.launch

View File

@@ -3,24 +3,72 @@ Promise = require("bluebird")
launcher = require("@packages/launcher")
fs = require("../util/fs")
appData = require("../util/app_data")
profileCleaner = require("../util/profile_cleaner")
profiles = appData.path("browsers")
PATH_TO_BROWSERS = appData.path("browsers")
copyExtension = (src, dest) ->
fs.copyAsync(src, dest)
getPartition = (isTextTerminal) ->
if isTextTerminal
return "run-#{process.pid}"
return "interactive"
getProfileDir = (browserName, isTextTerminal) ->
path.join(
PATH_TO_BROWSERS,
browserName,
getPartition(isTextTerminal),
)
getExtensionDir = (browserName, isTextTerminal) ->
path.join(
getProfileDir(browserName, isTextTerminal),
"CypressExtension"
)
ensureCleanCache = (browserName, isTextTerminal) ->
p = path.join(
getProfileDir(browserName, isTextTerminal),
"CypressCache"
)
fs
.removeAsync(p)
.then ->
fs.ensureDirAsync(p)
.return(p)
removeOldProfiles = ->
## a profile is considered old if it was used
## in a previous run for a PID that is either
## no longer active, or isnt a cypress related process
pathToProfiles = path.join(PATH_TO_BROWSERS, "*")
pathToPartitions = appData.electronPartitionsPath()
Promise.all([
## we now store profiles in either interactive or run-* folders
## so we need to remove the old root profiles that existed before
profileCleaner.removeRootProfile(pathToProfiles, [
path.join(pathToProfiles, "run-*")
path.join(pathToProfiles, "interactive")
])
profileCleaner.removeInactiveByPid(pathToProfiles, "run-"),
profileCleaner.removeInactiveByPid(pathToPartitions, "run-"),
])
module.exports = {
getProfileDir: (name) ->
path.join(profiles, name)
copyExtension
ensureCleanCache: (name) ->
p = path.join(profiles, name, "CypressCache")
getProfileDir
fs
.removeAsync(p)
.then ->
fs.ensureDirAsync(p)
.return(p)
getExtensionDir
copyExtension: (src, dest) ->
fs.copyAsync(src, dest)
ensureCleanCache
removeOldProfiles
getBrowsers: ->
## TODO: accept an options object which

File diff suppressed because it is too large Load Diff

View File

@@ -142,6 +142,7 @@ module.exports = {
onCrashed: ->
onNewWindow: ->
webPreferences: {
partition: null
chromeWebSecurity: true
nodeIntegration: false
backgroundThrottling: false
@@ -158,6 +159,9 @@ module.exports = {
if options.chromeWebSecurity is false
options.webPreferences.webSecurity = false
if options.partition
options.webPreferences.partition = options.partition
win = @_newBrowserWindow(options)
win.on "blur", ->

View File

@@ -56,12 +56,37 @@ warnIfProjectIdButNoRecordOption = (projectId, options) ->
## record mode
errors.warning("PROJECT_ID_AND_KEY_BUT_MISSING_RECORD_OPTION", projectId)
throwIfIndeterminateCiBuildId = (ciBuildId, parallel, group) ->
if (not ciBuildId and not ciProvider.provider()) and (parallel or group)
errors.throw(
"INDETERMINATE_CI_BUILD_ID",
{
group,
parallel
},
ciProvider.list()
)
throwIfRecordParamsWithoutRecording = (record, ciBuildId, parallel, group) ->
if not record and _.some([ciBuildId, parallel, group])
errors.throw("RECORD_PARAMS_WITHOUT_RECORDING", {
ciBuildId,
group,
parallel
})
throwIfIncorrectCiBuildIdUsage = (ciBuildId, parallel, group) ->
## we've been given an explicit ciBuildId
## but no parallel or group flag
if ciBuildId and (not parallel and not group)
errors.throw("INCORRECT_CI_BUILD_ID_USAGE", { ciBuildId })
throwIfNoProjectId = (projectId) ->
if not projectId
errors.throw("CANNOT_RECORD_NO_PROJECT_ID")
getSpecRelativePath = (spec) ->
_.get(spec, "relative")
_.get(spec, "relative", null)
uploadArtifacts = (options = {}) ->
{ video, screenshots, videoUploadUrl, shouldUploadVideo, screenshotUploadUrls } = options
@@ -138,7 +163,7 @@ updateInstanceStdout = (options = {}) ->
.finally(capture.restore)
updateInstance = (options = {}) ->
{ instanceId, results, captured } = options
{ instanceId, results, captured, group, parallel, ciBuildId } = options
{ stats, tests, hooks, video, screenshots, reporterStats, error } = results
video = Boolean(video)
@@ -172,6 +197,15 @@ updateInstance = (options = {}) ->
stack: err.stack
})
if parallel
return errors.throw("DASHBOARD_CANNOT_PROCEED_IN_PARALLEL", {
error: err,
flags: {
group,
ciBuildId,
},
})
errors.warning("DASHBOARD_CANNOT_CREATE_RUN_OR_INSTANCE", err)
## dont log exceptions if we have a 503 status code
@@ -182,7 +216,13 @@ updateInstance = (options = {}) ->
null
createRun = (options = {}) ->
{ projectId, recordKey, platform, git, specPattern, specs } = options
_.defaults(options, {
group: null,
parallel: null,
ciBuildId: null,
})
{ projectId, recordKey, platform, git, specPattern, specs, parallel, ciBuildId, group } = options
recordKey ?= env.get("CYPRESS_RECORD_KEY") or env.get("CYPRESS_CI_KEY")
@@ -201,15 +241,22 @@ createRun = (options = {}) ->
if specPattern
specPattern = specPattern.join(",")
if ciBuildId
## stringify
ciBuildId = String(ciBuildId)
specs = _.map(specs, getSpecRelativePath)
makeRequest = ->
api.createRun({
specPattern
specs
group
parallel
platform
ciBuildId
projectId
recordKey
platform
specPattern
ci: {
params: ciProvider.ciParams()
provider: ciProvider.provider()
@@ -237,12 +284,83 @@ createRun = (options = {}) ->
switch err.statusCode
when 401
recordKey = recordKey.slice(0, 5) + "..." + recordKey.slice(-5)
errors.throw("RECORD_KEY_NOT_VALID", recordKey, projectId)
errors.throw("DASHBOARD_RECORD_KEY_NOT_VALID", recordKey, projectId)
when 404
errors.throw("DASHBOARD_PROJECT_NOT_FOUND", projectId)
when 412
errors.throw("DASHBOARD_INVALID_RUN_REQUEST", err.error)
when 422
{ code, payload } = err.error
runUrl = _.get(payload, "runUrl")
switch code
when "RUN_GROUP_NAME_NOT_UNIQUE"
errors.throw("DASHBOARD_RUN_GROUP_NAME_NOT_UNIQUE", {
group,
runUrl,
ciBuildId,
})
when "PARALLEL_GROUP_PARAMS_MISMATCH"
{ browserName, browserVersion, osName, osVersion } = platform
errors.throw("DASHBOARD_PARALLEL_GROUP_PARAMS_MISMATCH", {
group,
runUrl,
ciBuildId,
parameters: {
osName,
osVersion,
browserName,
browserVersion,
specs,
}
})
when "PARALLEL_DISALLOWED"
errors.throw("DASHBOARD_PARALLEL_DISALLOWED", {
group,
runUrl,
ciBuildId,
})
when "PARALLEL_REQUIRED"
errors.throw("DASHBOARD_PARALLEL_REQUIRED", {
group,
runUrl,
ciBuildId,
})
when "ALREADY_COMPLETE"
errors.throw("DASHBOARD_ALREADY_COMPLETE", {
runUrl,
group,
parallel,
ciBuildId,
})
when "STALE_RUN"
errors.throw("DASHBOARD_STALE_RUN", {
runUrl,
group,
parallel,
ciBuildId,
})
else
errors.throw("DASHBOARD_UNKNOWN_INVALID_REQUEST", {
error: err,
flags: {
group,
parallel,
ciBuildId,
},
})
else
if parallel
return errors.throw("DASHBOARD_CANNOT_PROCEED_IN_PARALLEL", {
error: err,
flags: {
group,
ciBuildId,
},
})
## warn the user that assets will be not recorded
errors.warning("DASHBOARD_CANNOT_CREATE_RUN_OR_INSTANCE", err)
@@ -252,7 +370,7 @@ createRun = (options = {}) ->
.return(null)
createInstance = (options = {}) ->
{ runId, groupId, machineId, platform, spec } = options
{ runId, group, groupId, parallel, machineId, ciBuildId, platform, spec } = options
spec = getSpecRelativePath(spec)
@@ -274,6 +392,15 @@ createInstance = (options = {}) ->
stack: err.stack
})
if parallel
return errors.throw("DASHBOARD_CANNOT_PROCEED_IN_PARALLEL", {
error: err,
flags: {
group,
ciBuildId,
},
})
errors.warning("DASHBOARD_CANNOT_CREATE_RUN_OR_INSTANCE", err)
## dont log exceptions if we have a 503 status code
@@ -284,7 +411,7 @@ createInstance = (options = {}) ->
null
createRunAndRecordSpecs = (options = {}) ->
{ specPattern, specs, sys, browser, projectId, projectRoot, runAllSpecs } = options
{ specPattern, specs, sys, browser, projectId, projectRoot, runAllSpecs, parallel, ciBuildId, group } = options
recordKey = options.key
@@ -302,8 +429,11 @@ createRunAndRecordSpecs = (options = {}) ->
createRun({
git
specs
group
parallel
platform
recordKey
ciBuildId
projectId
specPattern
})
@@ -317,6 +447,8 @@ createRunAndRecordSpecs = (options = {}) ->
instanceId = null
beforeSpecRun = (spec) ->
debug("before spec run %o", { spec })
capture.restore()
captured = capture.stdout()
@@ -324,18 +456,32 @@ createRunAndRecordSpecs = (options = {}) ->
createInstance({
spec
runId
group
groupId
platform
parallel
ciBuildId
machineId
})
.then (id) ->
instanceId = id
.then (resp = {}) ->
{ instanceId } = resp
afterSpecRun = (results, config) ->
## pull off only what we need
return _
.chain(resp)
.pick("spec", "claimedInstances", "totalInstances")
.extend({
estimated: resp.estimatedWallClockDuration
})
.value()
afterSpecRun = (spec, results, config) ->
## dont do anything if we failed to
## create the instance
return if not instanceId
debug("after spec run %o", { spec })
console.log("")
terminal.header("Uploading Results", {
@@ -345,9 +491,12 @@ createRunAndRecordSpecs = (options = {}) ->
console.log("")
updateInstance({
group
config
results
captured
parallel
ciBuildId
instanceId
})
.then (resp) ->
@@ -388,8 +537,14 @@ module.exports = {
throwIfNoProjectId
throwIfIndeterminateCiBuildId
throwIfIncorrectCiBuildIdUsage
warnIfProjectIdButNoRecordOption
throwIfRecordParamsWithoutRecording
createRunAndRecordSpecs
}

View File

@@ -86,6 +86,11 @@ formatSpecSummary = (name, failures) ->
]
.join(" ")
formatRecordParams = (runUrl, parallel, group) ->
if runUrl
group or= false
"Group: #{group}, Parallel: #{Boolean(parallel)}"
formatSpecPattern = (specPattern) ->
if specPattern
specPattern.join(", ")
@@ -103,7 +108,7 @@ formatSpecs = (specs) ->
.join("")
displayRunStarting = (options = {}) ->
{ specs, specPattern, browser, runUrl } = options
{ specs, specPattern, browser, runUrl, parallel, group } = options
console.log("")
@@ -128,6 +133,7 @@ displayRunStarting = (options = {}) ->
[gray("Browser:"), formatBrowser(browser)]
[gray("Specs:"), formatSpecs(specs)]
[gray("Searched:"), formatSpecPattern(specPattern)]
[gray("Params:"), formatRecordParams(runUrl, parallel, group)]
[gray("Run URL:"), runUrl]
])
.filter(_.property(1))
@@ -139,15 +145,17 @@ displayRunStarting = (options = {}) ->
console.log("")
displaySpecHeader = (name, curr, total) ->
displaySpecHeader = (name, curr, total, estimated) ->
console.log("")
PADDING = 2
table = terminal.table({
colWidths: [80, 20]
colAligns: ["left", "right"]
type: "pageDivider"
style: {
"padding-left": 2
"padding-left": PADDING
}
})
@@ -159,7 +167,11 @@ displaySpecHeader = (name, curr, total) ->
console.log(table.toString())
collectTestResults = (obj = {}) ->
if estimated
estimatedLabel = " ".repeat(PADDING) + "Estimated:"
console.log(estimatedLabel, humanTime.long(estimated))
collectTestResults = (obj = {}, estimated) ->
{
name: _.get(obj, 'spec.name')
tests: _.get(obj, 'stats.tests')
@@ -168,11 +180,12 @@ collectTestResults = (obj = {}) ->
failures: _.get(obj, 'stats.failures')
skipped: _.get(obj, 'stats.skipped' )
duration: humanTime.long(_.get(obj, 'stats.wallClockDuration'))
estimated: estimated and humanTime.long(estimated)
screenshots: obj.screenshots and obj.screenshots.length
video: Boolean(obj.video)
}
renderSummaryTable = (runUrl, results) ->
renderSummaryTable = (runUrl) -> (results) ->
{ runs } = results
console.log("")
@@ -250,6 +263,56 @@ renderSummaryTable = (runUrl, results) ->
console.log(terminal.renderTables(table4))
console.log("")
iterateThroughSpecs = (options = {}) ->
{ specs, runEachSpec, parallel, beforeSpecRun, afterSpecRun, config } = options
serial = ->
Promise.mapSeries(specs, runEachSpec)
serialWithRecord = ->
Promise
.mapSeries specs, (spec, index, length) ->
beforeSpecRun(spec)
.then ({ estimated }) ->
runEachSpec(spec, index, length, estimated)
.tap (results) ->
afterSpecRun(spec, results, config)
parallelWithRecord = (runs) ->
beforeSpecRun()
.then ({ spec, claimedInstances, totalInstances, estimated }) ->
## no more specs to run?
if not spec
## then we're done!
return runs
## find the actual spec object amongst
## our specs array since the API sends us
## the relative name
spec = _.find(specs, { relative: spec })
runEachSpec(spec, claimedInstances - 1, totalInstances, estimated)
.tap (results) ->
runs.push(results)
afterSpecRun(spec, results, config)
.then ->
## recurse
parallelWithRecord(runs)
switch
when parallel
## if we are running in parallel
## then ask the server for the next spec
parallelWithRecord([])
when beforeSpecRun
## else iterate serialially and record
## the results of each spec
serialWithRecord()
else
## else iterate in serial
serial()
getProjectId = (project, id) ->
id ?= env.get("CYPRESS_PROJECT_ID")
@@ -288,7 +351,7 @@ openProjectCreate = (projectRoot, socketId, options) ->
socketId
morgan: false
report: true
isTextTerminal: options.isTextTerminal ? true
isTextTerminal: options.isTextTerminal
onError: (err) ->
console.log("")
console.log(err.stack)
@@ -316,6 +379,12 @@ createAndOpenProject = (socketId, options) ->
projectId: getProjectId(project, projectId)
})
removeOldProfiles = ->
browsers.removeOldProfiles()
.catch (err) ->
## dont make removing old browsers profiles break the build
errors.warning("CANNOT_REMOVE_OLD_BROWSER_PROFILES", err.stack)
trashAssets = (config = {}) ->
if config.trashAssetsBeforeRuns isnt true
return Promise.resolve()
@@ -375,8 +444,8 @@ module.exports = {
obj
displayResults: (obj = {}) ->
results = collectTestResults(obj)
displayResults: (obj = {}, estimated) ->
results = collectTestResults(obj, estimated)
c = if results.failures then "red" else "green"
@@ -390,7 +459,7 @@ module.exports = {
type: "outsideBorder"
})
data = _.map [
data = _.chain([
["Tests:", results.tests]
["Passing:", results.passes]
["Failing:", results.failures]
@@ -399,11 +468,15 @@ module.exports = {
["Screenshots:", results.screenshots]
["Video:", results.video]
["Duration:", results.duration]
["Estimated:", results.estimated] if estimated
["Spec Ran:", results.name]
], (arr) ->
])
.compact()
.map (arr) ->
[key, val] = arr
[color(key, "gray"), color(val, c)]
.value()
table.push(data...)
@@ -593,7 +666,7 @@ module.exports = {
project.on("socket:connected", fn)
waitForTestsToFinishRunning: (options = {}) ->
{ project, screenshots, started, end, name, cname, videoCompression, videoUploadOnPasses, exit, spec } = options
{ project, screenshots, started, end, name, cname, videoCompression, videoUploadOnPasses, exit, spec, estimated } = options
@listenForProjectEnd(project, exit)
.then (obj) =>
@@ -617,7 +690,7 @@ module.exports = {
finish = ->
return obj
@displayResults(obj)
@displayResults(obj, estimated)
if screenshots and screenshots.length
@displayScreenshots(screenshots)
@@ -665,7 +738,7 @@ module.exports = {
}
runSpecs: (options = {}) ->
{ config, browser, sys, headed, outputPath, specs, specPattern, beforeSpecRun, afterSpecRun, runUrl } = options
{ config, browser, sys, headed, outputPath, specs, specPattern, beforeSpecRun, afterSpecRun, runUrl, parallel, group } = options
isHeadless = browser.name is "electron" and not headed
@@ -694,33 +767,29 @@ module.exports = {
displayRunStarting({
specs
group
runUrl
browser
parallel
specPattern
})
runEachSpec = (spec, index, length) =>
Promise
.try ->
if beforeSpecRun
debug("before spec run %o", spec)
runEachSpec = (spec, index, length, estimated) =>
displaySpecHeader(spec.name, index + 1, length, estimated)
beforeSpecRun(spec)
.then =>
displaySpecHeader(spec.name, index + 1, length)
@runSpec(spec, options)
@runSpec(spec, options, estimated)
.get("results")
.tap (results) ->
debug("spec results %o", results)
if afterSpecRun
debug("after spec run %o", spec)
afterSpecRun(results, config)
Promise
.mapSeries(specs, runEachSpec)
iterateThroughSpecs({
specs
config
parallel
runEachSpec
afterSpecRun
beforeSpecRun
})
.then (runs = []) ->
results.startedTestsAt = start = getRun(_.first(runs), "stats.wallClockStartedAt")
results.endedTestsAt = end = getRun(_.last(runs), "stats.wallClockEndedAt")
@@ -738,7 +807,7 @@ module.exports = {
writeOutput(outputPath, results)
.return(results)
runSpec: (spec = {}, options = {}) ->
runSpec: (spec = {}, options = {}, estimated) ->
{ project, browser, video, videosFolder } = options
{ isHeadless, isHeaded } = browser
@@ -797,6 +866,7 @@ module.exports = {
cname
started
project
estimated
screenshots
exit: options.exit
videoCompression: options.videoCompression
@@ -831,12 +901,13 @@ module.exports = {
debug("run mode ready with options %o", options)
_.defaults(options, {
isTextTerminal: true
browser: "electron"
})
socketId = random.id()
{ projectRoot, record, key } = options
{ projectRoot, record, key, ciBuildId, parallel, group } = options
browserName = options.browser
@@ -852,15 +923,19 @@ module.exports = {
.then ({ project, projectId, config }) =>
## if we have a project id and a key but record hasnt been given
recordMode.warnIfProjectIdButNoRecordOption(projectId, options)
recordMode.throwIfRecordParamsWithoutRecording(record, ciBuildId, parallel, group)
if record
recordMode.throwIfNoProjectId(projectId)
recordMode.throwIfIncorrectCiBuildIdUsage(ciBuildId, parallel, group)
recordMode.throwIfIndeterminateCiBuildId(ciBuildId, parallel, group)
Promise.all([
system.info(),
browsers.ensureAndGetByName(browserName),
@findSpecs(config, specPattern),
trashAssets(config),
removeOldProfiles()
])
.spread (sys = {}, browser = {}, specs = []) =>
## return only what is return to the specPattern
@@ -877,9 +952,11 @@ module.exports = {
projectRoot
specPattern
socketId
parallel
browser
project
runUrl
group
config
specs
sys
@@ -891,7 +968,7 @@ module.exports = {
headed: options.headed
outputPath: options.outputPath
})
.tap(_.partial(renderSummaryTable, runUrl))
.tap(renderSummaryTable(runUrl))
if record
{ projectName } = config
@@ -900,7 +977,10 @@ module.exports = {
key
sys
specs
group
browser
parallel
ciBuildId
projectId
projectRoot
projectName

View File

@@ -6,13 +6,15 @@ la = require("lazy-ass")
check = require("check-more-types")
log = require("debug")("cypress:server:appdata")
pkg = require("@packages/root")
cwd = require("../cwd")
fs = require("../util/fs")
cwd = require("../cwd")
name = pkg.productName or pkg.name
data = ospath.data()
PRODUCT_NAME = pkg.productName or pkg.name
OS_DATA_PATH = ospath.data()
if not name
ELECTRON_APP_DATA_PATH = path.join(OS_DATA_PATH, PRODUCT_NAME)
if not PRODUCT_NAME
throw new Error("Root package is missing name")
getSymlinkType = ->
@@ -52,10 +54,14 @@ module.exports = {
path: (paths...) ->
la(check.unemptyString(process.env.CYPRESS_ENV),
"expected CYPRESS_ENV, found", process.env.CYPRESS_ENV)
p = path.join(data, name, "cy", process.env.CYPRESS_ENV, paths...)
p = path.join(ELECTRON_APP_DATA_PATH, "cy", process.env.CYPRESS_ENV, paths...)
log("path: %s", p)
p
electronPartitionsPath: ->
path.join(ELECTRON_APP_DATA_PATH, "Partitions")
projectsPath: (paths...) ->
@path("projects", paths...)

View File

@@ -10,7 +10,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 runMode outputPath 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 parallel ciBuildId group".split(" ")
# returns true if the given string has double quote character "
# only at the last position.
@@ -121,6 +121,7 @@ module.exports = {
"run-project": "runProject"
"return-pkg": "returnPkg"
"run-mode": "isTextTerminal"
"ci-build-id": "ciBuildId"
"exit-with-code": "exitWithCode"
"reporter-options": "reporterOptions"
"output-path": "outputPath"

View File

@@ -311,7 +311,12 @@ commitDefaults = (existingInfo) ->
_.transform existingInfo, (memo, value, key) ->
memo[key] = _.defaultTo(value ? commitParamsObj[key], null)
list = ->
_.keys(CI_PROVIDERS)
module.exports = {
list
provider
ciParams

View File

@@ -0,0 +1,9 @@
const findProcess = require('find-process')
const byPid = (pid) => {
return findProcess('pid', pid)
}
module.exports = {
byPid,
}

View File

@@ -0,0 +1,90 @@
const _ = require('lodash')
const path = require('path')
const debug = require('debug')('cypress:server:profilecleaner')
const fs = require('./fs')
const glob = require('./glob')
const findProcess = require('./find_process')
const includesCypress = (str) => {
return _.chain(str).lowerCase().includes('cypress').value()
}
const isCypressProcess = (process) => {
debug('got process %o', process)
return _.some([process.cmd, process.name], includesCypress)
}
const getPidFromFolder = (folder, pidPrefix) => {
return _.toNumber(
path.basename(folder).replace(pidPrefix, '')
)
}
const folderWithPid = (pidPrefix) => (folder) => {
return {
folder,
pid: getPidFromFolder(folder, pidPrefix),
}
}
// find all the pids not associated to a cypress process
const inactivePids = ({ pid }) => {
debug('finding process by pid:', pid)
if (!_.isFinite(pid)) {
return null
}
return findProcess.byPid(pid)
.then((processes) => {
// return true if no processes are a cypress process
return !_.some(processes, isCypressProcess)
})
}
const removeProfile = ({ pid, folder }) => {
debug('removing old profile %o', { pid, folder })
return fs.removeAsync(folder)
}
const removeMatch = (match) => {
debug('removed root profile object %o', { path: match })
return fs.removeAsync(match)
}
const removeInactiveByPid = (pathToProfiles, pidPrefix) => {
const pattern = path.join(pathToProfiles, `${pidPrefix}*`)
return glob(pattern, { absolute: true })
.tap((folders) => {
debug('found %d profile folders: %o', folders.length, folders)
})
.map(folderWithPid(pidPrefix))
.filter(inactivePids)
.map(removeProfile)
}
const removeRootProfile = (pathToProfiles, ignore) => {
const pattern = path.join(pathToProfiles, '*')
return glob(pattern, { absolute: true, dot: true, ignore })
.tap((matches) => {
debug('found %d root level profile matches: %o', matches.length, matches)
})
.map(removeMatch)
.catchReturn(null) // swallow errors
}
module.exports = {
inactivePids,
isCypressProcess,
getPidFromFolder,
removeRootProfile,
removeInactiveByPid,
}

View File

@@ -67,7 +67,7 @@
"react": "^15.2.1",
"repl.history": "^0.1.3",
"run-sequence": "^1.0.2",
"snap-shot-it": "2.0.0",
"snap-shot-it": "5.0.1",
"ssestream": "^1.0.1",
"stream-to-promise": "^1.1.0",
"supertest": "^0.15.0",
@@ -110,8 +110,9 @@
"evil-dns": "^0.2.0",
"execa": "^0.8.0",
"express": "4.16.2",
"find-process": "^1.1.1",
"fluent-ffmpeg": "^2.1.0",
"fs-extra": "4.0.1",
"fs-extra": "4.0.3",
"getos": "^2.8.2",
"glob": "7.1.2",
"graceful-fs": "^4.1.11",

View File

@@ -304,6 +304,145 @@ describe "e2e record", ->
expect(forthInstanceStdout.body.stdout).not.to.include("record_fail_spec.coffee")
expect(forthInstanceStdout.body.stdout).not.to.include("record_pass_spec.coffee")
context "parallelization", ->
allSpecs = [
"cypress/integration/record_error_spec.coffee",
"cypress/integration/record_fail_spec.coffee",
"cypress/integration/record_pass_spec.coffee",
"cypress/integration/record_uncaught_spec.coffee",
]
postInstanceResponses = (specs) ->
return _
.chain(specs)
.map (spec, i) ->
return {
spec
instanceId
estimatedWallClockDuration: (i + 1) * 1000
}
.concat({
spec: null
instanceId: null,
estimatedWallClockDuration: null
})
.value()
## a1 does 3 specs, b2 does 1 spec
a1Specs = _.without(allSpecs, "cypress/integration/record_pass_spec.coffee")
b2Specs = _.difference(allSpecs, a1Specs)
firstRunResponse = false
waitUntilSecondInstanceClaims = null
claimed = []
responses = {
a1: postInstanceResponses(a1Specs)
b2: postInstanceResponses(b2Specs)
}
## replace the 1st + 2nd routes object
routes = defaultRoutes.slice(0)
routes[0] = {
method: "post"
url: "/runs"
req: "postRunRequest@2.1.0",
res: (req, res) ->
{ group, ciBuildId } = req.body
expect(group).to.eq("prod-e2e")
expect(ciBuildId).to.eq("ciBuildId123")
## if this is the first response
## give machineId a1, else b2
if not firstRunResponse
firstRunResponse = true
machineId = "a1ad2bcf-6398-46ed-b201-2fd90b188d5f"
else
machineId = "b2bd2bcf-6398-46ed-b201-2fd90b188d5f"
res.json(
_.extend({}, postRunResponse, { machineId })
)
}
routes[1] = {
method: "post"
url: "/runs/:id/instances"
req: "postRunInstanceRequest@2.1.0",
res: (req, res) ->
{ machineId, spec } = req.body
expect(spec).to.be.null
mId = machineId.slice(0, 2)
respond = ->
resp = responses[mId].shift()
## if theres a spec to claim
if resp.spec
claimed.push(resp)
resp.claimedInstances = claimed.length
resp.totalInstances = allSpecs.length
jsonSchemas.assertSchema("postRunInstanceResponse", "2.1.0")(resp)
res.json(resp)
## when the 1st machine attempts to claim its FIRST spec, we
## automatically delay it until the 2nd machine claims its FIRST
## spec so that the request URL's are deterministic
if mId is "a1" and claimed.length is 0
waitUntilSecondInstanceClaims = ->
waitUntilSecondInstanceClaims = null
respond()
else
respond()
waitUntilSecondInstanceClaims?()
}
setup(routes)
it "passes in parallel with group", ->
Promise.all([
e2e.exec(@, {
key: "f858a2bc-b469-4e48-be67-0876339ee7e1"
spec: "record*"
group: "prod-e2e"
record: true
parallel: true
snapshot: true
ciBuildId: "ciBuildId123"
expectedExitCode: 3
config: {
trashAssetsBeforeRuns: false
}
})
.get("stdout"),
## stagger the 2nd instance
## starting up a bit
Promise
.delay(3000)
.then =>
e2e.exec(@, {
key: "f858a2bc-b469-4e48-be67-0876339ee7e1"
spec: "record*"
group: "prod-e2e"
record: true
parallel: true
snapshot: true
ciBuildId: "ciBuildId123"
expectedExitCode: 0
config: {
trashAssetsBeforeRuns: false
}
})
.get("stdout")
])
context "misconfiguration", ->
setup([])
@@ -423,7 +562,7 @@ describe "e2e record", ->
expectedExitCode: 1
})
describe "create run", ->
describe "create run 500", ->
routes = [{
method: "post"
url: "/runs"
@@ -450,6 +589,192 @@ describe "e2e record", ->
"POST /runs"
])
it "warns but proceeds when grouping without parallelization", ->
process.env.DISABLE_API_RETRIES = "true"
e2e.exec(@, {
key: "f858a2bc-b469-4e48-be67-0876339ee7e1"
spec: "record_pass*"
group: "foo"
record: true
snapshot: true
ciBuildId: "ciBuildId123"
expectedExitCode: 0
})
.then ->
urls = getRequestUrls()
expect(urls).to.deep.eq([
"POST /runs"
])
it "does not proceed and exits with error when parallelizing", ->
process.env.DISABLE_API_RETRIES = "true"
e2e.exec(@, {
key: "f858a2bc-b469-4e48-be67-0876339ee7e1"
spec: "record_pass*"
group: "foo"
record: true
parallel: true
snapshot: true
ciBuildId: "ciBuildId123"
expectedExitCode: 1
})
.then ->
urls = getRequestUrls()
expect(urls).to.deep.eq([
"POST /runs"
])
describe "create instance 500", ->
routes = defaultRoutes.slice(0)
routes[1] = {
method: "post"
url: "/runs/:id/instances"
req: "postRunInstanceRequest@2.1.0",
res: (req, res) -> res.sendStatus(500)
}
setup(routes)
it "does not proceed and exits with error when parallelizing and creating instance", ->
process.env.DISABLE_API_RETRIES = "true"
e2e.exec(@, {
key: "f858a2bc-b469-4e48-be67-0876339ee7e1"
spec: "record_pass*"
group: "foo"
record: true
parallel: true
snapshot: true
ciBuildId: "ciBuildId123"
expectedExitCode: 1
})
.then ->
urls = getRequestUrls()
expect(urls).to.deep.eq([
"POST /runs",
"POST /runs/#{runId}/instances"
])
describe "update instance 500", ->
routes = defaultRoutes.slice(0)
routes[1] = {
method: "post"
url: "/runs/:id/instances"
req: "postRunInstanceRequest@2.1.0",
res: (req, res) ->
res.json({
instanceId
spec: "cypress/integration/record_pass_spec.coffee"
estimatedWallClockDuration: 5000
totalInstances: 1
claimedInstances: 1
})
}
routes[2] = {
method: "put"
url: "/instances/:id"
req: "putInstanceRequest@2.0.0",
res: (req, res) -> res.sendStatus(500)
}
setup(routes)
it "does not proceed and exits with error when parallelizing and updating instance", ->
process.env.DISABLE_API_RETRIES = "true"
e2e.exec(@, {
key: "f858a2bc-b469-4e48-be67-0876339ee7e1"
spec: "record_pass*"
group: "foo"
record: true
parallel: true
snapshot: true
ciBuildId: "ciBuildId123"
expectedExitCode: 1
})
.then ->
urls = getRequestUrls()
expect(urls).to.deep.eq([
"POST /runs",
"POST /runs/#{runId}/instances"
"PUT /instances/e9e81b5e-cc58-4026-b2ff-8ae3161435a6"
])
describe "create run 422", ->
routes = [{
method: "post"
url: "/runs"
req: "postRunRequest@2.1.0",
res: (req, res) -> res.status(422).json({
code: "RUN_GROUP_NAME_NOT_UNIQUE"
message: "Run group name cannot be used again without passing the parallel flag."
payload: {
runUrl: "https://dashboard.cypress.io/runs/12345"
}
})
}]
setup(routes)
## the other 422 tests for this are in integration/cypress_spec
it "errors and exits when group name is in use", ->
process.env.CIRCLECI = "1"
e2e.exec(@, {
key: "f858a2bc-b469-4e48-be67-0876339ee7e1"
spec: "record_pass*"
group: "e2e-tests"
record: true
snapshot: true
expectedExitCode: 1
})
.then ->
urls = getRequestUrls()
expect(urls).to.deep.eq([
"POST /runs"
])
describe "create run unknown 422", ->
routes = [{
method: "post"
url: "/runs"
req: "postRunRequest@2.1.0",
res: (req, res) -> res.status(422).json({
code: "SOMETHING_UNKNOWN"
message: "An unknown message here from the server."
})
}]
setup(routes)
it "errors and exits when there is an unknown 422 response", ->
e2e.exec(@, {
key: "f858a2bc-b469-4e48-be67-0876339ee7e1"
spec: "record_pass*"
group: "e2e-tests"
record: true
parallel: true
snapshot: true
ciBuildId: "ciBuildId123"
expectedExitCode: 1
})
.then ->
urls = getRequestUrls()
expect(urls).to.deep.eq([
"POST /runs"
])
describe "create instance", ->
routes = [
{

View File

@@ -1,11 +1,14 @@
e2e = require("../support/helpers/e2e")
describe.skip "e2e window.open", ->
describe "e2e window.open", ->
e2e.setup()
it "passes", ->
e2e.exec(@, {
spec: "window_open_spec.coffee"
snapshot: true
expectedExitCode: 0
})
## skipping this for now due to
## snap-shot-it monkey patching
## .only causing test failures
# it "passes", ->
# e2e.exec(@, {
# spec: "window_open_spec.coffee"
# snapshot: true
# expectedExitCode: 0
# })

View File

@@ -11,6 +11,8 @@ electron = require("electron")
commitInfo = require("@cypress/commit-info")
isForkPr = require("is-fork-pr")
Fixtures = require("../support/helpers/fixtures")
snapshot = require("snap-shot-it")
stripAnsi = require("strip-ansi")
pkg = require("@packages/root")
launcher = require("@packages/launcher")
extension = require("@packages/extension")
@@ -40,6 +42,7 @@ videoCapture = require("#{root}lib/video_capture")
browserUtils = require("#{root}lib/browsers/utils")
openProject = require("#{root}lib/open_project")
env = require("#{root}lib/util/env")
system = require("#{root}lib/util/system")
appData = require("#{root}lib/util/app_data")
formStatePath = require("#{root}lib/util/saved_state").formStatePath
@@ -62,15 +65,25 @@ TYPICAL_BROWSERS = [
version: '62.0.3197.0',
path: '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
majorVersion: '62'
}, {
name: 'electron',
version: '',
path: '',
majorVersion: '',
info: 'Electron is the default browser that comes with Cypress. This is the browser that runs in headless mode. Selecting this browser is useful when debugging. The version number indicates the underlying Chromium version that Electron uses.'
}
]
previousCwd = process.cwd()
snapshotConsoleLogs = (name) ->
args = _
.chain(console.log.args)
.map (innerArgs) ->
innerArgs.join(" ")
.join("\n")
.value()
## our cwd() is currently the project
## so must switch back to original
process.chdir(previousCwd)
snapshot(name, stripAnsi(args))
describe "lib/cypress", ->
require("mocha-banner").register()
@@ -460,6 +473,17 @@ describe "lib/cypress", ->
expect(console.log).to.be.calledWithMatch("cypress run --record")
expect(console.log).to.be.calledWithMatch("https://on.cypress.io/recording-project-runs")
it "logs warning when removing old browser profiles fails", ->
err = new Error('foo')
sinon.stub(browsers, 'removeOldProfiles').rejects(err)
cypress.start(["--run-project=#{@todosPath}"])
.then =>
expect(errors.warning).to.be.calledWith("CANNOT_REMOVE_OLD_BROWSER_PROFILES", err.stack)
expect(console.log).to.be.calledWithMatch("Warning: We failed to remove old browser profiles from previous runs.")
expect(console.log).to.be.calledWithMatch(err.message)
it "does not log warning when no projectId", ->
cypress.start(["--run-project=#{@pristinePath}", "--key=asdf"])
.then =>
@@ -634,7 +658,9 @@ describe "lib/cypress", ->
describe "state", ->
beforeEach ->
formStatePath(@todosPath)
appData.remove()
.then =>
formStatePath(@todosPath)
.then (statePathStart) =>
@statePath = appData.projectsPath(statePathStart)
@@ -924,6 +950,246 @@ describe "lib/cypress", ->
expect(console.log).to.be.calledWithMatch("cypress run --record")
@expectExitWith(3)
it "errors and exits when using --group but ciBuildId could not be generated", ->
sinon.stub(ciProvider, "provider").returns(null)
cypress.start([
"--run-project=#{@recordPath}",
"--record"
"--key=token-123",
"--group=e2e-tests",
])
.then =>
@expectExitWithErr("INDETERMINATE_CI_BUILD_ID")
snapshotConsoleLogs("INDETERMINATE_CI_BUILD_ID-group")
it "errors and exits when using --parallel but ciBuildId could not be generated", ->
sinon.stub(ciProvider, "provider").returns(null)
cypress.start([
"--run-project=#{@recordPath}",
"--record"
"--key=token-123",
"--parallel",
])
.then =>
@expectExitWithErr("INDETERMINATE_CI_BUILD_ID")
snapshotConsoleLogs("INDETERMINATE_CI_BUILD_ID-parallel")
it "errors and exits when using --parallel and --group but ciBuildId could not be generated", ->
sinon.stub(ciProvider, "provider").returns(null)
cypress.start([
"--run-project=#{@recordPath}",
"--record"
"--key=token-123",
"--group=e2e-tests-chrome",
"--parallel",
])
.then =>
@expectExitWithErr("INDETERMINATE_CI_BUILD_ID")
snapshotConsoleLogs("INDETERMINATE_CI_BUILD_ID-parallel-group")
it "errors and exits when using --ci-build-id with no group or parallelization", ->
cypress.start([
"--run-project=#{@recordPath}",
"--record"
"--key=token-123",
"--ci-build-id=ciBuildId123",
])
.then =>
@expectExitWithErr("INCORRECT_CI_BUILD_ID_USAGE")
snapshotConsoleLogs("INCORRECT_CI_BUILD_ID_USAGE")
it "errors and exits when using --ci-build-id without recording", ->
cypress.start([
"--run-project=#{@recordPath}",
"--ci-build-id=ciBuildId123",
])
.then =>
@expectExitWithErr("RECORD_PARAMS_WITHOUT_RECORDING")
snapshotConsoleLogs("RECORD_PARAMS_WITHOUT_RECORDING-ciBuildId")
it "errors and exits when using --group without recording", ->
cypress.start([
"--run-project=#{@recordPath}",
"--group=e2e-tests",
])
.then =>
@expectExitWithErr("RECORD_PARAMS_WITHOUT_RECORDING")
snapshotConsoleLogs("RECORD_PARAMS_WITHOUT_RECORDING-group")
it "errors and exits when using --parallel without recording", ->
cypress.start([
"--run-project=#{@recordPath}",
"--parallel",
])
.then =>
@expectExitWithErr("RECORD_PARAMS_WITHOUT_RECORDING")
snapshotConsoleLogs("RECORD_PARAMS_WITHOUT_RECORDING-parallel")
it "errors and exits when using --group and --parallel without recording", ->
cypress.start([
"--run-project=#{@recordPath}",
"--group=electron-smoke-tests",
"--parallel",
])
.then =>
@expectExitWithErr("RECORD_PARAMS_WITHOUT_RECORDING")
snapshotConsoleLogs("RECORD_PARAMS_WITHOUT_RECORDING-group-parallel")
it "errors and exits when group name is not unique and explicitly passed ciBuildId", ->
err = new Error()
err.statusCode = 422
err.error = {
code: "RUN_GROUP_NAME_NOT_UNIQUE"
payload: {
runUrl: "https://dashboard.cypress.io/runs/12345"
}
}
api.createRun.rejects(err)
cypress.start([
"--run-project=#{@recordPath}",
"--record"
"--key=token-123",
"--group=electron-smoke-tests",
"--ciBuildId=ciBuildId123",
])
.then =>
@expectExitWithErr("DASHBOARD_RUN_GROUP_NAME_NOT_UNIQUE")
snapshotConsoleLogs("DASHBOARD_RUN_GROUP_NAME_NOT_UNIQUE")
it "errors and exits when parallel group params are different", ->
sinon.stub(system, "info").returns({
osName: "darwin"
osVersion: "v1"
})
sinon.stub(browsers, "ensureAndGetByName").returns({
version: "59.1.2.3"
displayName: "Electron"
})
err = new Error()
err.statusCode = 422
err.error = {
code: "PARALLEL_GROUP_PARAMS_MISMATCH"
payload: {
runUrl: "https://dashboard.cypress.io/runs/12345"
}
}
api.createRun.rejects(err)
cypress.start([
"--run-project=#{@recordPath}",
"--record"
"--key=token-123",
"--parallel"
"--group=electron-smoke-tests",
"--ciBuildId=ciBuildId123",
])
.then =>
@expectExitWithErr("DASHBOARD_PARALLEL_GROUP_PARAMS_MISMATCH")
snapshotConsoleLogs("DASHBOARD_PARALLEL_GROUP_PARAMS_MISMATCH")
it "errors and exits when parallel is not allowed", ->
err = new Error()
err.statusCode = 422
err.error = {
code: "PARALLEL_DISALLOWED"
payload: {
runUrl: "https://dashboard.cypress.io/runs/12345"
}
}
api.createRun.rejects(err)
cypress.start([
"--run-project=#{@recordPath}",
"--record"
"--key=token-123",
"--parallel"
"--group=electron-smoke-tests",
"--ciBuildId=ciBuildId123",
])
.then =>
@expectExitWithErr("DASHBOARD_PARALLEL_DISALLOWED")
snapshotConsoleLogs("DASHBOARD_PARALLEL_DISALLOWED")
it "errors and exits when parallel is required", ->
err = new Error()
err.statusCode = 422
err.error = {
code: "PARALLEL_REQUIRED"
payload: {
runUrl: "https://dashboard.cypress.io/runs/12345"
}
}
api.createRun.rejects(err)
cypress.start([
"--run-project=#{@recordPath}",
"--record"
"--key=token-123",
"--parallel"
"--group=electron-smoke-tests",
"--ciBuildId=ciBuildId123",
])
.then =>
@expectExitWithErr("DASHBOARD_PARALLEL_REQUIRED")
snapshotConsoleLogs("DASHBOARD_PARALLEL_REQUIRED")
it "errors and exits when run is already complete", ->
err = new Error()
err.statusCode = 422
err.error = {
code: "ALREADY_COMPLETE"
payload: {
runUrl: "https://dashboard.cypress.io/runs/12345"
}
}
api.createRun.rejects(err)
cypress.start([
"--run-project=#{@recordPath}",
"--record"
"--key=token-123",
"--group=electron-smoke-tests",
"--ciBuildId=ciBuildId123",
])
.then =>
@expectExitWithErr("DASHBOARD_ALREADY_COMPLETE")
snapshotConsoleLogs("DASHBOARD_ALREADY_COMPLETE")
it "errors and exits when run is stale", ->
err = new Error()
err.statusCode = 422
err.error = {
code: "STALE_RUN"
payload: {
runUrl: "https://dashboard.cypress.io/runs/12345"
}
}
api.createRun.rejects(err)
cypress.start([
"--run-project=#{@recordPath}",
"--record"
"--key=token-123",
"--parallel"
"--group=electron-smoke-tests",
"--ciBuildId=ciBuildId123",
])
.then =>
@expectExitWithErr("DASHBOARD_STALE_RUN")
snapshotConsoleLogs("DASHBOARD_STALE_RUN")
context "--return-pkg", ->
beforeEach ->
console.log.restore()

View File

@@ -18,6 +18,27 @@ require("chai")
.use(require("@cypress/sinon-chai"))
.use(require("chai-uuid"))
if process.env.UPDATE
throw new Error("You're using UPDATE=1 which is the old way of updating snapshots.\n\nThe correct environment variable is SNAPSHOT_UPDATE=1")
if process.env.UPDATE_SNAPSHOT
throw new Error("You're using UPDATE_SNAPSHOT=1\n\nThe correct environment variable is SNAPSHOT_UPDATE=1")
if process.env.UPDATE_SNAPSHOTS
throw new Error("You're using UPDATE_SNAPSHOTS=1\n\nThe correct environment variable is SNAPSHOT_UPDATE=1")
hasOnly = false
## hack for older version of mocha so that
## snap-shot-it can find suite._onlyTests
["it", "describe", "context"].forEach (prop) ->
backup = global[prop].only
global[prop].only = ->
hasOnly = true
backup.apply(@, arguments)
env = _.clone(process.env)
sinon.usingPromise(Promise)
@@ -52,6 +73,9 @@ mockery.registerSubstitute(
mockery.registerMock("original-fs", {})
before ->
if hasOnly
@test.parent._onlyTests = [true]
appData.ensure()
beforeEach ->

View File

@@ -246,6 +246,15 @@ module.exports = {
if options.record
args.push("--record")
if options.parallel
args.push("--parallel")
if options.group
args.push("--group=#{options.group}")
if options.ciBuildId
args.push("--ci-build-id=#{options.ciBuildId}")
if options.key
args.push("--key=#{options.key}")

View File

@@ -1,7 +1,6 @@
require("../spec_helper")
_ = require("lodash")
rp = require("request-promise")
os = require("os")
nmi = require("node-machine-id")
pkg = require("@packages/root")
@@ -128,7 +127,7 @@ describe "lib/api", ->
expect(err.message).to.eq("Error: ESOCKETTIMEDOUT")
it "sets timeout to 10 seconds", ->
sinon.stub(rp, "get").returns({
sinon.stub(api.rp, "get").returns({
catch: -> {
catch: -> {
then: (fn) -> fn()
@@ -140,7 +139,7 @@ describe "lib/api", ->
api.getProjectRuns("id-123", "auth-token-123")
.then (ret) ->
expect(rp.get).to.be.calledWithMatch({timeout: 10000})
expect(api.rp.get).to.be.calledWithMatch({timeout: 10000})
it "GET /projects/:id/runs failure formatting", ->
nock("http://localhost:1234")
@@ -234,7 +233,7 @@ describe "lib/api", ->
it "POST /runs + returns runId", ->
nock("http://localhost:1234")
.matchHeader("x-route-version", "3")
.matchHeader("x-route-version", "4")
.matchHeader("x-os-name", "linux")
.matchHeader("x-cypress-version", pkg.version)
.post("/runs", @buildProps)
@@ -248,7 +247,7 @@ describe "lib/api", ->
it "POST /runs failure formatting", ->
nock("http://localhost:1234")
.matchHeader("x-route-version", "3")
.matchHeader("x-route-version", "4")
.matchHeader("x-os-name", "linux")
.matchHeader("x-cypress-version", pkg.version)
.post("/runs", @buildProps)
@@ -276,7 +275,7 @@ describe "lib/api", ->
it "handles timeouts", ->
nock("http://localhost:1234")
.matchHeader("x-route-version", "3")
.matchHeader("x-route-version", "4")
.matchHeader("x-os-name", "linux")
.matchHeader("x-cypress-version", pkg.version)
.post("/runs")
@@ -291,16 +290,16 @@ describe "lib/api", ->
.catch (err) ->
expect(err.message).to.eq("Error: ESOCKETTIMEDOUT")
it "sets timeout to 60 seconds", ->
sinon.stub(rp, "post").resolves({runId: 'foo'})
it "sets timeout to 10 seconds", ->
sinon.stub(api.rp, "post").resolves({runId: 'foo'})
api.createRun({})
.then ->
expect(rp.post).to.be.calledWithMatch({timeout: 60000})
expect(api.rp.post).to.be.calledWithMatch({timeout: 60000})
it "tags errors", ->
nock("http://localhost:1234")
.matchHeader("x-route-version", "3")
.matchHeader("x-route-version", "4")
.matchHeader("authorization", "Bearer auth-token-123")
.matchHeader("accept-encoding", /gzip/)
.post("/runs", @buildProps)
@@ -332,7 +331,7 @@ describe "lib/api", ->
os.platform.returns("darwin")
nock("http://localhost:1234")
.matchHeader("x-route-version", "4")
.matchHeader("x-route-version", "5")
.matchHeader("x-os-name", "darwin")
.matchHeader("x-cypress-version", pkg.version)
.post("/runs/run-id-123/instances", @postProps)
@@ -341,12 +340,13 @@ describe "lib/api", ->
})
api.createInstance(@createProps)
.get("instanceId")
.then (instanceId) ->
expect(instanceId).to.eq("instance-id-123")
it "POST /runs/:id/instances failure formatting", ->
nock("http://localhost:1234")
.matchHeader("x-route-version", "4")
.matchHeader("x-route-version", "5")
.matchHeader("x-os-name", "linux")
.matchHeader("x-cypress-version", pkg.version)
.post("/runs/run-id-123/instances")
@@ -374,7 +374,7 @@ describe "lib/api", ->
it "handles timeouts", ->
nock("http://localhost:1234")
.matchHeader("x-route-version", "4")
.matchHeader("x-route-version", "5")
.matchHeader("x-os-name", "linux")
.matchHeader("x-cypress-version", pkg.version)
.post("/runs/run-id-123/instances")
@@ -391,13 +391,13 @@ describe "lib/api", ->
expect(err.message).to.eq("Error: ESOCKETTIMEDOUT")
it "sets timeout to 60 seconds", ->
sinon.stub(rp, "post").returns({
promise: -> Promise.resolve({ instanceId: "instanceId123" })
sinon.stub(api.rp, "post").resolves({
instanceId: "instanceId123"
})
api.createInstance({})
.then ->
expect(rp.post).to.be.calledWithMatch({timeout: 60000})
expect(api.rp.post).to.be.calledWithMatch({timeout: 60000})
it "tags errors", ->
nock("http://localhost:1234")
@@ -484,11 +484,11 @@ describe "lib/api", ->
expect(err.message).to.eq("Error: ESOCKETTIMEDOUT")
it "sets timeout to 60 seconds", ->
sinon.stub(rp, "put").resolves()
sinon.stub(api.rp, "put").resolves()
api.updateInstance({})
.then ->
expect(rp.put).to.be.calledWithMatch({timeout: 60000})
expect(api.rp.put).to.be.calledWithMatch({timeout: 60000})
it "tags errors", ->
nock("http://localhost:1234")
@@ -564,11 +564,11 @@ describe "lib/api", ->
expect(err.message).to.eq("Error: ESOCKETTIMEDOUT")
it "sets timeout to 60 seconds", ->
sinon.stub(rp, "put").resolves()
sinon.stub(api.rp, "put").resolves()
api.updateInstanceStdout({})
.then ->
expect(rp.put).to.be.calledWithMatch({timeout: 60000})
expect(api.rp.put).to.be.calledWithMatch({timeout: 60000})
it "tags errors", ->
nock("http://localhost:1234")
@@ -956,9 +956,9 @@ describe "lib/api", ->
it "by default times outs after 3 seconds", ->
## return our own specific promise
## so we can spy on the timeout function
p = Promise.resolve()
p = Promise.resolve({})
sinon.spy(p, "timeout")
sinon.stub(rp.Request.prototype, "promise").returns(p)
sinon.stub(api.rp, "post").returns(p)
@setup({foo: "bar"}, "auth-token-123")
api.createRaygunException({foo: "bar"}, "auth-token-123").then ->

View File

@@ -37,7 +37,9 @@ describe "lib/browsers/chrome", ->
it "normalizes --load-extension if provided in plugin", ->
plugins.has.returns(true)
plugins.execute.resolves(["--foo=bar", "--load-extension=/foo/bar/baz.js"])
plugins.execute.resolves([
"--foo=bar", "--load-extension=/foo/bar/baz.js"
])
pathToTheme = extension.getPathToTheme()

View File

@@ -95,6 +95,9 @@ describe "lib/modes/record", ->
projectId = "pId123"
specPattern = ["spec/pattern1", "spec/pattern2"]
projectRoot = "project/root"
ciBuildId = "ciId123"
parallel = null
group = null
runAllSpecs = sinon.stub()
sys = {
osCpus: 1
@@ -111,7 +114,10 @@ describe "lib/modes/record", ->
key
sys
specs
group
browser
parallel
ciBuildId
projectId
projectRoot
specPattern
@@ -120,6 +126,21 @@ describe "lib/modes/record", ->
.then ->
expect(commitInfo.commitInfo).to.be.calledWith(projectRoot)
expect(api.createRun).to.be.calledWith({
group
parallel
projectId
ciBuildId
recordKey: key
specPattern: "spec/pattern1,spec/pattern2"
specs: ["path/to/spec/a", "path/to/spec/b"]
platform: {
osCpus: 1
osName: 2
osMemory: 3
osVersion: 4
browserName: "chrome"
browserVersion: "59"
}
ci: {
params: {
foo: "bar"

View File

@@ -49,6 +49,7 @@ describe "lib/modes/run", ->
options = {
port: 8080
env: {foo: "bar"}
isTextTerminal: true
projectRoot: "/_test-output/path/to/project/foo"
}

View File

@@ -0,0 +1,91 @@
require("../spec_helper")
os = require("os")
path = require("path")
fs = require("#{root}/lib/util/fs")
findProcess = require("#{root}lib/util/find_process")
profileCleaner = require("#{root}lib/util/profile_cleaner")
tmpDir = os.tmpdir()
pidProfilesFolder = path.join(tmpDir, "pid-profiles")
describe "lib/util/profile_cleaner", ->
context '.isCypressProcess', ->
it 'finds cypress processes by name or cmd', ->
isProc = (obj, bool) ->
expect(profileCleaner.isCypressProcess(obj), JSON.stringify(obj)).to.eq(bool)
processes = [
{
name: 'CYPRESS'
},
{
cmd: 'path/to/Cypress -- some args'
},
{
name: 'nope',
cmd: 'not found'
}
]
isProc(processes[0], true)
isProc(processes[1], true)
isProc(processes[2], false)
context ".removeInactiveByPid", ->
beforeEach ->
sinon.stub(findProcess, 'byPid')
.withArgs(53301)
.resolves([
{
pid: '53301'
ppid: '53300',
uid: '501',
gid: '20',
name: 'Cypress',
cmd: '/Users/bmann/Library/Caches/Cypress/3.0.3/Cypress.app/Contents/MacOS/Cypress --project /Users/bmann/Dev/cypress-dashboard --cwd /Users/bmann/Dev/cypress-dashboard'
}
])
.withArgs(12345)
.resolves([
{
pid: '12345'
name: 'Foo',
cmd: 'node foo bar'
}
])
.withArgs(9999)
.resolves([])
createFolder = (folder) ->
fs.ensureDirAsync(path.join(pidProfilesFolder, folder))
Promise.all([
createFolder("run-9999")
createFolder("run-12345")
createFolder("run-53301")
createFolder("foo-53301")
])
afterEach ->
fs.removeAsync(pidProfilesFolder)
it "removes profiles which are not cypress pids", ->
expected = (folder, condition) ->
pathToFolder = path.join(pidProfilesFolder, folder)
fs
.pathExists(pathToFolder)
.then (bool) ->
expect(bool, "expected folder: #{pathToFolder} to exist? #{condition}").to.eq(condition)
profileCleaner.removeInactiveByPid(pidProfilesFolder, "run-")
.then ->
Promise.all([
expected('run-9999', false),
expected('run-12345', false),
expected('run-53301', true),
expected('foo-53301', true),
])
.finally ->
findProcess.byPid.restore()

View File

@@ -0,0 +1,26 @@
const fs = require('fs-extra')
const glob = require('glob')
const Promise = require('bluebird')
const globAsync = Promise.promisify(glob)
const endingNewLines = /\s+$/g
const contentBetweenBackticksRe = /\`([\s\S]+?)\`/g
globAsync('packages/server/__snapshots__/*')
.map((file) => {
return fs.readFile(file, 'utf8')
.then((str) => {
return str
.replace(
contentBetweenBackticksRe,
'`\n$1\n`'
)
.split('`\n\n\n').join('`\n\n')
.split('\n\n\n\n`').join('\n\n\n`')
.split(endingNewLines).join('\n')
})
.then((str) => {
return fs.writeFile(file, str)
})
})

View File

@@ -0,0 +1,15 @@
const fs = require('fs-extra')
const glob = require('glob')
const Promise = require('bluebird')
const globAsync = Promise.promisify(glob)
globAsync('packages/*/__snapshots__/*.coffee')
.map((file) => {
const renamed = `${file}.js`
/* eslint-disable no-console */
console.log('renaming', file, '->', renamed)
return fs.rename(file, renamed)
})