Merge branch 'develop' into feature-multidomain

This commit is contained in:
Chris Breiding
2021-11-01 13:42:19 -04:00
112 changed files with 3820 additions and 2947 deletions
+32
View File
@@ -13,18 +13,35 @@ cypress.zip
Cached Theme.pak
Cached Theme Material Design.pak
# from data-context, compiled .js files
packages/data-context/src/**/*.js
# from desktop-gui
packages/desktop-gui/cypress/videos
packages/desktop-gui/src/jsconfig.json
# from driver
packages/driver/cypress/videos
packages/driver/cypress/screenshots
# from launcher, compiled .js files
packages/launcher/index.js
packages/launcher/lib/**/*.js
# from network, compiled .js files
packages/network/lib/**/*.js
# from net-stubbing, compiled .js files
packages/net-stubbing/lib/**/*.js
# from runner
packages/runner/cypress/videos
packages/runner/cypress/screenshots
# from proxy, compiled .js files
packages/proxy/lib/**/*.js
# npm packages
npm/**/cypress/screenshots
@@ -33,6 +50,10 @@ packages/example/app
packages/example/build
packages/example/cypress/integration
# from frontend-shared
packages/frontend-shared/cypress/e2e/.projects
packages/frontend-shared/src/public/shiki/themes/cypress.theme.json
# from server
packages/server/.cy
packages/server/.projects
@@ -40,6 +61,9 @@ packages/server/support
packages/server/test/support/fixtures/server/imgs
packages/server/test/support/fixtures/server/libs
# from socket, dist built files
packages/socket/lib/*.js
# from system-tests
system-tests/.projects
system-tests/fixtures/large-img
@@ -57,6 +81,10 @@ system-tests/fixtures/large-img
# from runner-ct
/packages/runner-ct/cypress/screenshots
# graphql, auto-generated
/packages/launchpad/src/generated
/packages/app/src/generated
# from npm/create-cypress-tests
/npm/create-cypress-tests/initial-template
/npm/create-cypress-tests/src/test-output
@@ -343,3 +371,7 @@ $RECYCLE.BIN/
# Circle cache artifacts
globbed_node_modules
# Autogenerated files, typically from graphql-code-generator
*.gen.ts
*.gen.json
+2 -2
View File
@@ -1,4 +1,4 @@
{
"chrome:beta": "95.0.4638.49",
"chrome:stable": "94.0.4606.81"
"chrome:beta": "96.0.4664.27",
"chrome:stable": "95.0.4638.69"
}
+5 -5
View File
@@ -960,7 +960,7 @@ jobs:
fi
- wait-on-circle-jobs:
job-names: >
desktop-gui-integration-tests-2x,
desktop-gui-integration-tests-7x,
desktop-gui-component-tests,
cli-visual-tests,
runner-integration-tests-chrome,
@@ -1189,9 +1189,9 @@ jobs:
- run-driver-integration-tests:
browser: electron
desktop-gui-integration-tests-2x:
desktop-gui-integration-tests-7x:
<<: *defaults
parallelism: 2
parallelism: 7
steps:
- restore_cached_workspace
- run:
@@ -2049,7 +2049,7 @@ linux-workflow: &linux-workflow
requires:
- build
- desktop-gui-integration-tests-2x:
- desktop-gui-integration-tests-7x:
requires:
- build
- desktop-gui-component-tests:
@@ -2119,7 +2119,7 @@ linux-workflow: &linux-workflow
- reporter-integration-tests
- Linux lint
- desktop-gui-component-tests
- desktop-gui-integration-tests-2x
- desktop-gui-integration-tests-7x
- runner-ct-integration-tests-chrome
- runner-integration-tests-firefox
- runner-integration-tests-chrome
+10 -6
View File
@@ -1,6 +1,5 @@
// @ts-check
const _ = require('lodash')
const R = require('ramda')
const commander = require('commander')
const { stripIndent } = require('common-tags')
const logSymbols = require('log-symbols')
@@ -279,12 +278,17 @@ const castCypressRunOptions = (opts) => {
// only properties that have type "string | false" in our TS definition
// require special handling, because CLI parsing takes care of purely
// boolean arguments
const result = R.evolve({
port: coerceAnyStringToInt,
configFile: coerceFalseOrString,
})(opts)
const castOpts = { ...opts }
return result
if (_.has(opts, 'port')) {
castOpts.port = coerceAnyStringToInt(opts.port)
}
if (_.has(opts, 'configFile')) {
castOpts.configFile = coerceFalseOrString(opts.configFile)
}
return castOpts
}
module.exports = {
+1 -2
View File
@@ -1,6 +1,5 @@
const chalk = require('chalk')
const { stripIndent, stripIndents } = require('common-tags')
const { merge } = require('ramda')
const la = require('lazy-ass')
const is = require('check-more-types')
@@ -241,7 +240,7 @@ const CYPRESS_RUN_BINARY = {
function addPlatformInformation (info) {
return util.getPlatformInfo().then((platform) => {
return merge(info, { platform })
return { ...info, platform }
})
}
+10 -5
View File
@@ -6,7 +6,6 @@ const os = require('os')
const chalk = require('chalk')
const prettyBytes = require('pretty-bytes')
const _ = require('lodash')
const R = require('ramda')
// color for numbers and show values
const g = chalk.green
@@ -22,14 +21,20 @@ methods.findProxyEnvironmentVariables = () => {
return _.pick(process.env, ['HTTP_PROXY', 'HTTPS_PROXY', 'NO_PROXY'])
}
const maskSensitiveVariables = R.evolve({
CYPRESS_RECORD_KEY: R.always('<redacted>'),
})
const maskSensitiveVariables = (obj) => {
const masked = { ...obj }
if (masked.CYPRESS_RECORD_KEY) {
masked.CYPRESS_RECORD_KEY = '<redacted>'
}
return masked
}
methods.findCypressEnvironmentVariables = () => {
const isCyVariable = (val, key) => key.startsWith('CYPRESS_')
return R.pickBy(isCyVariable)(process.env)
return _.pickBy(process.env, isCyVariable)
}
const formatCypressVariables = () => {
+3 -2
View File
@@ -1,4 +1,3 @@
const R = require('ramda')
const chalk = require('chalk')
let logs = []
@@ -36,7 +35,9 @@ const always = (...messages) => {
const logLines = (text) => {
const lines = text.split('\n')
R.forEach(log, lines)
for (const line of lines) {
log(line)
}
}
const print = () => {
+3 -4
View File
@@ -2,7 +2,6 @@ const _ = require('lodash')
const os = require('os')
const path = require('path')
const untildify = require('untildify')
const R = require('ramda')
const debug = require('debug')('cypress:cli')
const fs = require('../fs')
@@ -179,9 +178,9 @@ const getBinaryPkgAsync = (binaryDir) => {
})
}
const getBinaryPkgVersion = R.propOr(null, 'version')
const getBinaryElectronVersion = R.propOr(null, 'electronVersion')
const getBinaryElectronNodeVersion = R.propOr(null, 'electronNodeVersion')
const getBinaryPkgVersion = (o) => _.get(o, 'version', null)
const getBinaryElectronVersion = (o) => _.get(o, 'electronVersion', null)
const getBinaryElectronNodeVersion = (o) => _.get(o, 'electronNodeVersion', null)
module.exports = {
getPathToExecutable,
+9 -8
View File
@@ -1,5 +1,4 @@
const _ = require('lodash')
const R = require('ramda')
const os = require('os')
const ospath = require('ospath')
const crypto = require('crypto')
@@ -114,10 +113,9 @@ const logBrokenGtkDisplayWarning = () => {
}
function stdoutLineMatches (expectedLine, stdout) {
const lines = stdout.split('\n').map(R.trim)
const lineMatches = R.equals(expectedLine)
const lines = stdout.split('\n').map((val) => val.trim())
return lines.some(lineMatches)
return lines.some((line) => line === expectedLine)
}
/**
@@ -229,11 +227,14 @@ const parseOpts = (opts) => {
// some options might be quoted - which leads to unexpected results
// remove double quotes from certain options
const removeQuotes = {
group: dequote,
ciBuildId: dequote,
const cleanOpts = { ...opts }
const toDequote = ['group', 'ciBuildId']
for (const prop of toDequote) {
if (_.has(opts, prop)) {
cleanOpts[prop] = dequote(opts[prop])
}
}
const cleanOpts = R.evolve(removeQuotes, opts)
debug('parsed cli options %o', cleanOpts)
-1
View File
@@ -55,7 +55,6 @@
"ospath": "^1.2.2",
"pretty-bytes": "^5.6.0",
"proxy-from-env": "1.0.0",
"ramda": "~0.27.1",
"request-progress": "^3.0.0",
"supports-color": "^8.1.1",
"tmp": "~0.2.1",
+5
View File
@@ -44,6 +44,11 @@
"default": null,
"description": "The reporter options used. Supported options depend on the reporter. See https://on.cypress.io/reporters#Reporter-Options"
},
"slowTestThreshold": {
"type": "number",
"default": 10000,
"description": "Slow test threshold in milliseconds. Only affects the visual output of some reporters. For example, the spec reporter will display the test time in yellow if over the threshold. See https://on.cypress.io/configuration#Timeouts"
},
"testFiles": {
"type": [
"string",
+1 -2
View File
@@ -5,13 +5,12 @@ const makeUserPackageFile = require('../../scripts/build')
const snapshot = require('../support/snapshot')
const la = require('lazy-ass')
const is = require('check-more-types')
const R = require('ramda')
const hasVersion = (json) => {
return la(is.semver(json.version), 'cannot find version', json)
}
const changeVersion = R.assoc('version', 'x.y.z')
const changeVersion = (o) => ({ ...o, version: 'x.y.z' })
describe('package.json build', () => {
beforeEach(function () {
+3 -5
View File
@@ -2,7 +2,7 @@ require('../spec_helper')
const os = require('os')
const path = require('path')
const R = require('ramda')
const _ = require('lodash')
const snapshot = require('../support/snapshot')
const Promise = require('bluebird')
const tmp = Promise.promisifyAll(require('tmp'))
@@ -27,11 +27,10 @@ describe('cypress', function () {
sinon.stub(open, 'start').resolves()
})
const getCallArgs = R.path(['lastCall', 'args', 0])
const getStartArgs = () => {
expect(open.start).to.be.called
return getCallArgs(open.start)
return _.get(open.start, ['lastCall', 'args', 0])
}
it('calls open#start, passing in options', function () {
@@ -100,7 +99,6 @@ describe('cypress', function () {
})
})
const getCallArgs = R.path(['lastCall', 'args', 0])
const normalizeCallArgs = (args) => {
expect(args.outputPath).to.equal(outputPath)
delete args.outputPath
@@ -110,7 +108,7 @@ describe('cypress', function () {
const getStartArgs = () => {
expect(run.start).to.be.called
return normalizeCallArgs(getCallArgs(run.start))
return normalizeCallArgs(_.get(run.start, ['lastCall', 'args', 0]))
}
it('calls run#start, passing in options', () => {
+4
View File
@@ -91,6 +91,10 @@ declare namespace CypressCommandLine {
* Specify mocha reporter options
*/
reporterOptions: any
/**
* Slow test threshold in milliseconds. Only affects the visual output of some reporters. For example, the spec reporter will display the test time in yellow if over the threshold.
*/
slowTestThreshold: number
/**
* Specify the specs to run
*/
+6 -1
View File
@@ -2577,6 +2577,11 @@ declare namespace Cypress {
* @default "spec"
*/
reporterOptions: { [key: string]: any }
/**
* Slow test threshold in milliseconds. Only affects the visual output of some reporters. For example, the spec reporter will display the test time in yellow if over the threshold.
* @default 10000
*/
slowTestThreshold: number
/**
* Whether Cypress will watch and restart tests on test file changes
* @default true
@@ -5675,7 +5680,7 @@ declare namespace Cypress {
xhr: XMLHttpRequest
}
type Encodings = 'ascii' | 'base64' | 'binary' | 'hex' | 'latin1' | 'utf8' | 'utf-8' | 'ucs2' | 'ucs-2' | 'utf16le' | 'utf-16le'
type Encodings = 'ascii' | 'base64' | 'binary' | 'hex' | 'latin1' | 'utf8' | 'utf-8' | 'ucs2' | 'ucs-2' | 'utf16le' | 'utf-16le' | null
type PositionType = 'topLeft' | 'top' | 'topRight' | 'left' | 'center' | 'right' | 'bottomLeft' | 'bottom' | 'bottomRight'
type ViewportPreset = 'macbook-16' | 'macbook-15' | 'macbook-13' | 'macbook-11' | 'ipad-2' | 'ipad-mini' | 'iphone-xr' | 'iphone-x' | 'iphone-6+' | 'iphone-se2' | 'iphone-8' | 'iphone-7' | 'iphone-6' | 'iphone-5' | 'iphone-4' | 'iphone-3' | 'samsung-s10' | 'samsung-note9'
interface Offset {
+7
View File
@@ -1,3 +1,10 @@
# [create-cypress-tests-v1.1.3](https://github.com/cypress-io/cypress/compare/create-cypress-tests-v1.1.2...create-cypress-tests-v1.1.3) (2021-10-29)
### Bug Fixes
* revive type checker ([#18172](https://github.com/cypress-io/cypress/issues/18172)) ([af472b6](https://github.com/cypress-io/cypress/commit/af472b6419ecb2aec1abdb09df99b2fa5f56e033))
# [create-cypress-tests-v1.1.2](https://github.com/cypress-io/cypress/compare/create-cypress-tests-v1.1.1...create-cypress-tests-v1.1.2) (2021-06-17)
+7
View File
@@ -1,3 +1,10 @@
# [@cypress/schematic-v1.5.2](https://github.com/cypress-io/cypress/compare/@cypress/schematic-v1.5.1...@cypress/schematic-v1.5.2) (2021-10-29)
### Bug Fixes
* revive type checker ([#18172](https://github.com/cypress-io/cypress/issues/18172)) ([af472b6](https://github.com/cypress-io/cypress/commit/af472b6419ecb2aec1abdb09df99b2fa5f56e033))
# [@cypress/schematic-v1.5.1](https://github.com/cypress-io/cypress/compare/@cypress/schematic-v1.5.0...@cypress/schematic-v1.5.1) (2021-09-10)
+1 -2
View File
@@ -50,8 +50,7 @@
"testing"
],
"publishConfig": {
"access": "public",
"registry": "http://registry.npmjs.org/"
"access": "public"
},
"builders": "./src/builders/builders.json",
"ng-add": {
+1 -2
View File
@@ -178,8 +178,7 @@
}
},
"publishConfig": {
"access": "public",
"registry": "http://registry.npmjs.org/"
"access": "public"
},
"standard": {
"globals": [
+2
View File
@@ -3,6 +3,8 @@ const { createWebpackDevConfig } = require('@craco/craco')
const { getLegacyDevServer } = require('../utils/legacy-setup-dev-server')
function devServer (cypressDevServerConfig, cracoConfig) {
process.env.FAST_REFRESH = 'false'
return startDevServer({
options: cypressDevServerConfig,
webpackConfig: createWebpackDevConfig(cracoConfig),
+10 -2
View File
@@ -3,13 +3,21 @@ import type { Span } from 'next/dist/telemetry/trace/trace'
// Starting with v11.1.1, a trace is required.
// 'next/dist/telemetry/trace/trace' only exists since v10.0.9
// and our peerDeps support back to v8 so try-catch this import
// Starting from 12.0 trace is now located in 'next/dist/trace/trace'
export async function getRunWebpackSpan (): Promise<{ runWebpackSpan?: Span }> {
let trace: (name: string) => Span
try {
trace = await import('next/dist/telemetry/trace/trace').then((m) => m.trace)
try {
trace = await import('next/dist/telemetry/trace/trace').then((m) => m.trace)
return { runWebpackSpan: trace('cypress') }
return { runWebpackSpan: trace('cypress') }
} catch (_) {
// @ts-ignore
trace = await import('next/dist/trace/trace').then((m) => m.trace)
return { runWebpackSpan: trace('cypress') }
}
} catch (_) {
return {}
}
+7
View File
@@ -1,3 +1,10 @@
# [@cypress/vite-dev-server-v2.2.0](https://github.com/cypress-io/cypress/compare/@cypress/vite-dev-server-v2.1.1...@cypress/vite-dev-server-v2.2.0) (2021-10-15)
### Features
* normalized signatures webpack & vite servers ([#18379](https://github.com/cypress-io/cypress/issues/18379)) ([8f5308f](https://github.com/cypress-io/cypress/commit/8f5308f7068b80fb877da539ce34fb67ba497c4f))
# [@cypress/vite-dev-server-v2.1.1](https://github.com/cypress-io/cypress/compare/@cypress/vite-dev-server-v2.1.0...@cypress/vite-dev-server-v2.1.1) (2021-10-04)
+1 -2
View File
@@ -102,7 +102,6 @@
}
},
"publishConfig": {
"access": "public",
"registry": "http://registry.npmjs.org/"
"access": "public"
}
}
+7
View File
@@ -1,3 +1,10 @@
# [@cypress/webpack-dev-server-v1.7.0](https://github.com/cypress-io/cypress/compare/@cypress/webpack-dev-server-v1.6.0...@cypress/webpack-dev-server-v1.7.0) (2021-10-15)
### Features
* normalized signatures webpack & vite servers ([#18379](https://github.com/cypress-io/cypress/issues/18379)) ([8f5308f](https://github.com/cypress-io/cypress/commit/8f5308f7068b80fb877da539ce34fb67ba497c4f))
# [@cypress/webpack-dev-server-v1.6.0](https://github.com/cypress-io/cypress/compare/@cypress/webpack-dev-server-v1.5.0...@cypress/webpack-dev-server-v1.6.0) (2021-09-10)
+2 -3
View File
@@ -1,6 +1,6 @@
{
"name": "cypress",
"version": "8.6.0",
"version": "8.7.0",
"description": "Cypress.io end to end testing tool",
"private": true,
"scripts": {
@@ -94,7 +94,6 @@
"@types/mocha": "8.0.3",
"@types/node": "14.14.31",
"@types/prismjs": "1.16.0",
"@types/ramda": "0.25.47",
"@types/react": "16.9.50",
"@types/react-dom": "16.9.8",
"@types/request-promise": "4.1.45",
@@ -173,7 +172,6 @@
"pretty-ms": "7.0.0",
"print-arch": "1.0.0",
"proxyquire": "2.1.3",
"ramda": "0.27.1",
"semantic-release": "17.2.3",
"semantic-release-monorepo": "7.0.3",
"semver": "7.3.2",
@@ -247,6 +245,7 @@
"**/jquery": "3.1.1",
"**/pretty-format": "26.4.0",
"**/socket.io-parser": "4.0.4",
"**/ua-parser-js": "0.7.24",
"vue-template-compiler": "2.6.12"
}
}
@@ -37,6 +37,22 @@ describe('src/cy/commands/files', () => {
})
})
// https://github.com/cypress-io/cypress/issues/1558
it('passes explicit null encoding through to server and decodes response', () => {
Cypress.backend.resolves({
contents: Buffer.from('\n'),
filePath: '/path/to/foo.json',
})
cy.readFile('foo.json', null).then(() => {
expect(Cypress.backend).to.be.calledWith(
'read:file',
'foo.json',
{ encoding: null },
)
}).should('eql', Buffer.from('\n'))
})
it('sets the contents as the subject', () => {
Cypress.backend.resolves(okResponse)
@@ -340,6 +356,23 @@ describe('src/cy/commands/files', () => {
})
})
// https://github.com/cypress-io/cypress/issues/1558
it('explicit null encoding is sent to server as Buffer', () => {
Cypress.backend.resolves(okResponse)
cy.writeFile('foo.txt', Buffer.from([0, 0, 54, 255]), null).then(() => {
expect(Cypress.backend).to.be.calledWith(
'write:file',
'foo.txt',
Buffer.from([0, 0, 54, 255]),
{
encoding: null,
flag: 'w',
},
)
})
})
it('can take encoding as part of options', () => {
Cypress.backend.resolves(okResponse)
@@ -35,6 +35,17 @@ describe('src/cy/commands/fixtures', () => {
})
})
// https://github.com/cypress-io/cypress/issues/1558
it('passes explicit null encoding through to server and decodes response', () => {
Cypress.backend.withArgs('get:fixture').resolves(Buffer.from('\n'))
cy.fixture('foo', null).then((obj) => {
expect(Cypress.backend).to.be.calledWith('get:fixture', 'foo', {
encoding: null,
})
}).should('eql', Buffer.from('\n'))
})
it('can have encoding as second argument and options as third argument', () => {
Cypress.backend.withArgs('get:fixture').resolves({ foo: 'bar' })
@@ -23,11 +23,50 @@ describe('src/cypress/selector_playground', () => {
})
it('sets selector:playground:priority if selectorPriority specified', () => {
const selectorPriority = [
'data-1',
'data-2',
'id',
'class',
'tag',
'attributes',
'nth-child',
]
SelectorPlayground.defaults({
selectorPriority: ['foo'],
selectorPriority,
})
expect(SelectorPlayground.getSelectorPriority()).to.eql(['foo'])
expect(SelectorPlayground.getSelectorPriority()).to.eql(selectorPriority)
})
it('throws if selectorPriority contains an unsupported priority', () => {
const fn = () => {
SelectorPlayground.defaults({
selectorPriority: [
'id',
'name',
],
})
}
expect(fn).to.throw()
.with.property('message')
.and.include('`Cypress.SelectorPlayground.defaults()` called with invalid `selectorPriority` property. It must be one of: `data-*`, `id`, `class`, `tag`, `attributes`, `nth-child`. You passed: `name`')
})
it('throws if selectorPriority has an unsupported priority that contains a substring of a valid priority', () => {
const fn = () => {
SelectorPlayground.defaults({
selectorPriority: [
'idIsNotValid',
],
})
}
expect(fn).to.throw()
.with.property('message')
.and.include('`Cypress.SelectorPlayground.defaults()` called with invalid `selectorPriority` property. It must be one of: `data-*`, `id`, `class`, `tag`, `attributes`, `nth-child`. You passed: `idIsNotValid`')
})
it('sets selector:playground:on:element if onElement specified', () => {
+23 -5
View File
@@ -11,11 +11,16 @@ export default (Commands, Cypress, cy) => {
if (_.isObject(encoding)) {
userOptions = encoding
encoding = null
encoding = undefined
}
options = _.defaults({}, userOptions, {
encoding: encoding != null ? encoding : 'utf8',
// https://github.com/cypress-io/cypress/issues/1558
// If no encoding is specified, then Cypress has historically defaulted
// to `utf8`, because of it's focus on text files. This is in contrast to
// NodeJs, which defaults to binary. We allow users to pass in `null`
// to restore the default node behavior.
encoding: encoding === undefined ? 'utf8' : encoding,
log: true,
})
@@ -53,6 +58,14 @@ export default (Commands, Cypress, cy) => {
args: { cmd: 'readFile', action: 'read', file, filePath: err.filePath, error: err.message },
})
}).then(({ contents, filePath }) => {
// https://github.com/cypress-io/cypress/issues/1558
// We invoke Buffer.from() in order to transform this from an ArrayBuffer -
// which socket.io uses to transfer the file over the websocket - into a
// `Buffer`, which webpack polyfills in the browser.
if (options.encoding === null) {
contents = Buffer.from(contents)
}
consoleProps['File Path'] = filePath
consoleProps['Contents'] = contents
@@ -85,11 +98,16 @@ export default (Commands, Cypress, cy) => {
if (_.isObject(encoding)) {
userOptions = encoding
encoding = null
encoding = undefined
}
options = _.defaults({}, userOptions, {
encoding: encoding ? encoding : 'utf8',
// https://github.com/cypress-io/cypress/issues/1558
// If no encoding is specified, then Cypress has historically defaulted
// to `utf8`, because of it's focus on text files. This is in contrast to
// NodeJs, which defaults to binary. We allow users to pass in `null`
// to restore the default node behavior.
encoding: encoding === undefined ? 'utf8' : encoding,
flag: userOptions.flag ? userOptions.flag : 'w',
log: true,
})
@@ -120,7 +138,7 @@ export default (Commands, Cypress, cy) => {
})
}
if (_.isObject(contents)) {
if (_.isObject(contents) && !Buffer.isBuffer(contents)) {
contents = JSON.stringify(contents, null, 2)
}
+17 -1
View File
@@ -6,6 +6,10 @@ import Promise from 'bluebird'
import $errUtils from '../../cypress/error_utils'
const clone = (obj) => {
if (Buffer.isBuffer(obj)) {
return Buffer.from(obj)
}
return JSON.parse(JSON.stringify(obj))
}
@@ -47,7 +51,7 @@ export default (Commands, Cypress, cy, state, config) => {
options = args[1]
}
if (_.isString(args[0])) {
if (_.isString(args[0]) || args[0] === null) {
options.encoding = args[0]
}
@@ -64,6 +68,18 @@ export default (Commands, Cypress, cy, state, config) => {
return $errUtils.throwErr(response.__error)
}
// https://github.com/cypress-io/cypress/issues/1558
// We invoke Buffer.from() in order to transform this from an ArrayBuffer -
// which socket.io uses to transfer the file over the websocket - into a
// `Buffer`, which webpack polyfills in the browser.
if (options.encoding === null) {
response = Buffer.from(response)
} else if (response instanceof ArrayBuffer) {
// Cypress' behavior is to base64 encode binary files if the user
// doesn't explicitly pass `null` as the encoding.
response = Buffer.from(response).toString('base64')
}
// add the fixture to the cache
// so it can just be returned next time
cache[fixture] = response
@@ -1428,10 +1428,14 @@ export default {
message: '`Cypress.SelectorPlayground.defaults()` must be called with an object. You passed: `{{arg}}`',
docsUrl: 'https://on.cypress.io/selector-playground-api',
},
defaults_invalid_priority: {
defaults_invalid_priority_type: {
message: '`Cypress.SelectorPlayground.defaults()` called with invalid `selectorPriority` property. It must be an array. You passed: `{{arg}}`',
docsUrl: 'https://on.cypress.io/selector-playground-api',
},
defaults_invalid_priority: {
message: '`Cypress.SelectorPlayground.defaults()` called with invalid `selectorPriority` property. It must be one of: `data-*`, `id`, `class`, `tag`, `attributes`, `nth-child`. You passed: `{{arg}}`. Consider using the `onElement` property if a specific selector is desired.',
docsUrl: 'https://on.cypress.io/selector-playground-api',
},
defaults_invalid_on_element: {
message: '`Cypress.SelectorPlayground.defaults()` called with invalid `onElement` property. It must be a function. You passed: `{{arg}}`',
docsUrl: 'https://on.cypress.io/selector-playground-api',
+2
View File
@@ -500,6 +500,8 @@ const create = (specWindow, Cypress, config) => {
const _mocha = createMocha(specWindow)
_mocha.slow(config('slowTestThreshold'))
const _runner = getRunner(_mocha)
_mocha.suite.file = Cypress.spec.relative
+5 -1
View File
@@ -21,7 +21,7 @@ const TEST_BEFORE_RUN_EVENT = 'runner:test:before:run'
const TEST_AFTER_RUN_EVENT = 'runner:test:after:run'
const RUNNABLE_LOGS = 'routes agents commands hooks'.split(' ')
const RUNNABLE_PROPS = '_testConfig id order title _titlePath root hookName hookId err state failedFromHookId body speed type duration wallClockStartedAt wallClockDuration timings file originalTitle invocationDetails final currentRetry retries'.split(' ')
const RUNNABLE_PROPS = '_testConfig id order title _titlePath root hookName hookId err state failedFromHookId body speed type duration wallClockStartedAt wallClockDuration timings file originalTitle invocationDetails final currentRetry retries _slow'.split(' ')
const debug = debugFn('cypress:driver:runner')
const debugErrors = debugFn('cypress:driver:errors')
@@ -581,6 +581,10 @@ const normalize = (runnable, tests, initialTests, onRunnable, onLogsById, getRun
wrappedRunnable._testConfig = cfg
}
if (cfg.slowTestThreshold) {
runnable.slow(cfg.slowTestThreshold)
}
wrappedRunnable._titlePath = runnable.titlePath()
}
@@ -58,16 +58,25 @@ export default {
})
}
const { selectorPriority: priority, onElement } = props
const { selectorPriority, onElement } = props
if (priority) {
if (!_.isArray(priority)) {
$errUtils.throwErrByPath('selector_playground.defaults_invalid_priority', {
args: { arg: $utils.stringify(priority) },
if (selectorPriority) {
if (!_.isArray(selectorPriority)) {
$errUtils.throwErrByPath('selector_playground.defaults_invalid_priority_type', {
args: { arg: $utils.stringify(selectorPriority) },
})
}
// Validate that the priority is one of: "data-*", "id", "class", "tag", "attributes", "nth-child"
defaults.selectorPriority = priority
selectorPriority.forEach((priority) => {
if (!/^(data\-.*|id|class|tag|attributes|nth\-child)$/.test(priority)) {
$errUtils.throwErrByPath('selector_playground.defaults_invalid_priority', {
args: { arg: priority },
})
}
})
defaults.selectorPriority = selectorPriority
}
if (onElement) {
+32 -2
View File
@@ -1,8 +1,8 @@
# Electron
# @packages/electron
This is the lib responsible for installing + building Electron. This enables us to develop with the Electron shell that will match how the final compiled Cypress binary looks 1:1.
It does this by using `symlinks` while in development.
It does this by using symlinks while in development.
## Building
@@ -19,3 +19,33 @@ yarn workspace @packages/electron test
yarn workspace @packages/electron test-debug
yarn workspace @packages/electron test-watch
```
## Upgrading Electron
The version of `electron` that is bundled with Cypress should be kept as up-to-date as possible with the [stable Electron releases](https://www.electronjs.org/releases/stable). Many users expect the bundled Chromium and Node.js to be relatively recent. Also, historically, it has been extremely difficult to upgrade over multiple major versions of Electron at once, because of all the breaking changes in Electron and Node.js that impact Cypress.
Upgrading `electron` involves more than just bumping this package's `package.json`. Here are additional tasks to check off when upgrading Electron:
- [ ] **Write accurate changelog items.** The "User-facing changelog" for an Electron upgrade should mention the new Node.js and Chromium versions bundled.
- For example:
- Upgraded `electron` from `12.0.0-beta.14` to `13.1.7`.
- Upgraded bundled Node.js version from `14.6.0` to `14.17.0`.
- Upgraded bundled Chromium version from 89.0.0.1234 to 91.0.0.2345.
- [ ] **Determine if the Electron upgrade is a breaking change.** Electron upgrades constitute "breaking changes" in Cypress if:
- the major version number of Node.js changes, since users rely on the bundled Node.js to load plugins and `.js` fixtures, or
- there are changes to Electron that require new shared libraries to be installed on Linux, breaking existing CI setups, or
- there is some other change that would break existing usage of Cypress (for example, a Web API feature being removed/added to the bundled Chromium)
- [ ] **Create and publish Docker `base` and `browsers` family images matching the Node.js and Chromium versions in Electron.** The `browsers` image will be used for CI and the `base` will be used for any new `included` family images.
- See [`cypress-docker-images`](https://github.com/cypress-io/cypress-docker-images/).
- [ ] **Ensure that a matching Node.js version is enforced in the monorepo for local development and CI.** When Electron is upgraded, oftentimes, the bundled Node.js version that comes with Electron is updated as well. Because all unit and integration tests run in normal Node.js (not Electron's Node.js), it's important for this Node.js version to be synced with the monorepo. There are a few places where this needs to be done:
- [ ] [`/.node-version`](../../.node-version) - used by `nvm` and other Node version managers
- [ ] [`/appveyor.yml`](../../appveyor.yml) - update the `nodejs_version`
- [ ] [`/package.json`](../../package.json) - update `engines`
- [ ] [`/scripts/run-docker-local.sh`](../../scripts/run-docker-local.sh) - update Docker image to the new matching `browsers` image
- [ ] [`/circle.yml`](../../circle.yml)
- Update the Docker `image`s to the new matching `browsers` image.
- Update the `xcode` version to one with the same major Node.js version bundled. There is usually not an exact match, this is ok as long as the major version number as the same.
- [ ] Do a global search for the old Node.js version to identify any new areas that may need updating/unification, and update those locations (and this document!)
- [ ] **Manually smoke test `cypress open`.** Upgrading Electron can break the `desktop-gui` in unexpected ways. Since testing in this area is weak, double-check that things like launching `cypress open`, signing into the Dashboard, and launching Electron tests still work.
- [ ] **Fix failing tests.** Usually, these are due to breaking changes in either Node.js or Electron. Check the changelogs of both to find relevant changes.
+1 -2
View File
@@ -2,7 +2,6 @@ import { findApp, FindAppParams } from './util'
import type { Browser, DetectedBrowser } from '../types'
import * as linuxHelper from '../linux'
import { log } from '../log'
import { merge } from 'ramda'
import { get } from 'lodash'
type Detectors = {
@@ -105,7 +104,7 @@ export function detect (browser: Browser): Promise<DetectedBrowser> {
}
return findApp(findAppParams)
.then(merge({ name: browser.name }))
.then((val) => ({ name: browser.name, ...val }))
.catch(() => {
log('could not detect %s using traditional Mac methods', browser.name)
log('trying linux search')
+9 -4
View File
@@ -1,6 +1,5 @@
import { log } from '../log'
import { notInstalledErr } from '../errors'
import { prop, tap } from 'ramda'
import { utils } from '../utils'
import * as fs from 'fs-extra'
import * as os from 'os'
@@ -27,7 +26,7 @@ export function parsePlist (p: string, property: string): Promise<string> {
return fs
.readFile(pl, 'utf8')
.then(plist.parse)
.then(prop(property))
.then((val) => val[property])
.then(String) // explicitly convert value to String type
.catch(failed) // to make TS compiler happy
}
@@ -50,8 +49,14 @@ export function mdfind (id: string): Promise<string> {
}
return utils.execa(cmd)
.then(prop('stdout'))
.then(tap(logFound))
.then((val) => {
return val.stdout
})
.then((val) => {
logFound(val)
return val
})
.catch(failedToFind)
}
+19 -14
View File
@@ -1,7 +1,6 @@
import Bluebird from 'bluebird'
import { compact, extend, find } from 'lodash'
import _, { compact, extend, find } from 'lodash'
import os from 'os'
import { flatten, merge, pick, props, tap, uniqBy } from 'ramda'
import { browsers } from './browsers'
import * as darwinHelper from './darwin'
import { needsDarwinWorkaround, darwinDetectionWorkaround } from './darwin/util'
@@ -17,7 +16,7 @@ import type {
} from './types'
import * as windowsHelper from './windows'
type HasVersion = Partial<FoundBrowser> & {
type HasVersion = Omit<Partial<FoundBrowser>, 'version' | 'name'> & {
version: string
name: string
}
@@ -85,7 +84,7 @@ function lookup (
* one for each binary. If Windows is detected, only one `checkOneBrowser` will be called, because
* we don't use the `binary` field on Windows.
*/
function checkBrowser (browser: Browser): Bluebird<(boolean | FoundBrowser)[]> {
function checkBrowser (browser: Browser): Bluebird<(boolean | HasVersion)[]> {
if (Array.isArray(browser.binary) && os.platform() !== 'win32') {
return Bluebird.map(browser.binary, (binary: string) => {
return checkOneBrowser(extend({}, browser, { binary }))
@@ -95,9 +94,9 @@ function checkBrowser (browser: Browser): Bluebird<(boolean | FoundBrowser)[]> {
return Bluebird.map([browser], checkOneBrowser)
}
function checkOneBrowser (browser: Browser): Promise<boolean | FoundBrowser> {
function checkOneBrowser (browser: Browser): Promise<boolean | HasVersion> {
const platform = os.platform()
const pickBrowserProps = pick([
const pickBrowserProps = [
'name',
'family',
'channel',
@@ -111,7 +110,7 @@ function checkOneBrowser (browser: Browser): Promise<boolean | FoundBrowser> {
'info',
'minSupportedVersion',
'unsupportedVersion',
])
] as const
const logBrowser = (props: any) => {
log('setting major version for %j', props)
@@ -130,9 +129,13 @@ function checkOneBrowser (browser: Browser): Promise<boolean | FoundBrowser> {
log('checking one browser %s', browser.name)
return lookup(platform, browser)
.then(merge(browser))
.then(pickBrowserProps)
.then(tap(logBrowser))
.then((val) => ({ ...browser, ...val }))
.then((val) => _.pick(val, pickBrowserProps) as HasVersion)
.then((val) => {
logBrowser(val)
return val
})
.then((browser) => setMajorVersion(browser))
.catch(failed)
}
@@ -176,9 +179,11 @@ export const detect = (goalBrowsers?: Browser[], useDarwinWorkaround = true): Bl
})
}
const removeDuplicates = uniqBy((browser: FoundBrowser) => {
return props(['name', 'version'], browser)
})
const removeDuplicates = (val) => {
return _.uniqBy(val, (browser: FoundBrowser) => {
return `${browser.name}-${browser.version}`
})
}
const compactFalse = (browsers: any[]) => {
return compact(browsers) as FoundBrowser[]
}
@@ -186,7 +191,7 @@ export const detect = (goalBrowsers?: Browser[], useDarwinWorkaround = true): Bl
log('detecting if the following browsers are present %o', goalBrowsers)
return Bluebird.mapSeries(goalBrowsers, checkBrowser)
.then(flatten)
.then((val) => _.flatten(val))
.then(compactFalse)
.then(removeDuplicates)
}
+7 -4
View File
@@ -1,5 +1,4 @@
import { log } from '../log'
import { partial, trim, tap, prop } from 'ramda'
import type { FoundBrowser, Browser, PathData } from '../types'
import { notInstalledErr } from '../errors'
import { utils } from '../utils'
@@ -68,9 +67,13 @@ export function getVersionString (path: string) {
return Bluebird.resolve(utils.getOutput(path, ['--version']))
.timeout(30000, `Timed out after 30 seconds getting browser version for ${path}`)
.then(prop('stdout'))
.then(trim)
.then(tap(partial(log, ['stdout: "%s"'])))
.then((val) => val.stdout)
.then((val) => val.trim())
.then((val) => {
log('stdout: %s', val)
return val
})
}
export function getVersionNumber (version: string, browser: Browser) {
+7 -4
View File
@@ -1,7 +1,6 @@
import * as fse from 'fs-extra'
import os from 'os'
import { join, normalize, win32 } from 'path'
import { tap, trim, prop } from 'ramda'
import { get } from 'lodash'
import { notInstalledErr } from '../errors'
import { log } from '../log'
@@ -151,7 +150,11 @@ function getWindowsBrowser (browser: Browser): Promise<FoundBrowser> {
}
return getVersionString(path)
.then(tap(log))
.then((val) => {
log(val)
return val
})
.then(getVersion)
.then((version: string) => {
log('browser %s at \'%s\' version %s', browser.name, exePath, version)
@@ -193,8 +196,8 @@ export function getVersionString (path: string) {
]
return utils.execa('wmic', args)
.then(prop('stdout'))
.then(trim)
.then((val) => val.stdout)
.then((val) => val.trim())
}
export function getVersionNumber (version: string) {
-1
View File
@@ -19,7 +19,6 @@
"fs-extra": "8.1.0",
"lodash": "4.17.21",
"plist": "3.0.1",
"ramda": "0.27.1",
"semver": "7.3.5"
},
"devDependencies": {
+2 -2
View File
@@ -1,4 +1,5 @@
require('../spec_helper')
import _ from 'lodash'
import { detect, detectByPath, setMajorVersion } from '../../lib/detect'
import { goalBrowsers } from '../fixtures'
import { expect } from 'chai'
@@ -6,7 +7,6 @@ import { utils } from '../../lib/utils'
import sinon, { SinonStub } from 'sinon'
import os from 'os'
import { log } from '../log'
import { project } from 'ramda'
import * as darwinUtil from '../../lib/darwin/util'
const isWindows = () => {
@@ -20,7 +20,7 @@ describe('browser detection', () => {
log('detected browsers %j', browsers)
expect(browsers).to.be.an('array')
const mainProps = project(['name', 'version'], browsers)
const mainProps = browsers.map((val) => _.pick(val, ['name', 'version']))
log('%d browsers\n%j', browsers.length, mainProps)
+1 -1
View File
@@ -120,7 +120,7 @@ export async function setResponseFromFixture (getFixtureFn: GetFixtureFn, static
return
}
const data = await getFixtureFn(fixture.filePath, { encoding: fixture.encoding || null })
const data = await getFixtureFn(fixture.filePath, { encoding: fixture.encoding })
const { headers } = staticResponse
@@ -20,8 +20,10 @@ interface Overrides {
const noop = () => {}
class FakeEventManager {
reporterBus: { on: () => void }
constructor (overrides: Overrides = {}) {
this.saveState = overrides.saveState || noop
this.reporterBus = { on: noop }
}
start = noop
@@ -132,4 +134,29 @@ describe('RunnerCt', () => {
cy.get(selectors.noSpecSelectedReporter).should('exist')
})
})
context('current spec is deleted', () => {
it('removes selection', () => {
const state = makeState({
spec: { relative: '/test.js', absolute: 'root/test.js', name: 'test.js' },
specs: [
{ relative: '/test2.js', absolute: 'root/test2.js', name: 'test2.js' },
{ relative: '/test.js', absolute: 'root/test.js', name: 'test.js' },
],
})
mount(<RunnerCt
state={state}
// @ts-ignore - this is difficult to stub. Real one breaks things.
eventManager={new FakeEventManager()}
config={fakeConfig}
/>)
cy.contains('Your tests are loading').then(() => {
state.setSpecs([{ relative: '/test2.js', absolute: 'root/test2.js', name: 'test2.js' }])
})
cy.contains('No spec selected')
})
})
})
+12
View File
@@ -25,7 +25,19 @@ export abstract class BaseStore {
this.specRunId = nanoid()
}
@action checkCurrentSpecStillExists (specs: Cypress.Cypress['spec'][]) {
const newSpecsAbsolutes = new Set(specs.map((spec) => spec.absolute))
this.specs.forEach((oldSpec) => {
if (!newSpecsAbsolutes.has(oldSpec.absolute) && this.spec?.absolute === oldSpec.absolute) {
this.spec = undefined
}
})
}
@action setSpecs (specs: Cypress.Cypress['spec'][]) {
this.checkCurrentSpecStillExists(specs)
this.specs = specs
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+15 -21
View File
@@ -1,5 +1,4 @@
import _ from 'lodash'
import R from 'ramda'
import path from 'path'
import Promise from 'bluebird'
import deepDiff from 'return-deep-diff'
@@ -17,7 +16,7 @@ import findSystemNode from './util/find_system_node'
const debug = Debug('cypress:server:config')
import { options, breakingOptions } from './config_options'
import { getProcessEnvVars } from './util/config'
import { getProcessEnvVars, CYPRESS_SPECIAL_ENV_VARS } from './util/config'
export const RESOLVED_FROM = ['plugin', 'env', 'default', 'runtime', 'config'] as const
@@ -32,18 +31,6 @@ export type ResolvedConfigurationOptions = Partial<{
[x in keyof Cypress.ResolvedConfigOptions]: ResolvedFromConfig
}>
export const CYPRESS_ENV_PREFIX = 'CYPRESS_'
export const CYPRESS_ENV_PREFIX_LENGTH = 'CYPRESS_'.length
export const CYPRESS_RESERVED_ENV_VARS = [
'CYPRESS_INTERNAL_ENV',
]
export const CYPRESS_SPECIAL_ENV_VARS = [
'RECORD_KEY',
]
const dashesOrUnderscoresRe = /^(_-)+/
// takes an array and creates an index object of [keyKey]: [valueKey]
@@ -269,6 +256,11 @@ export function mergeDefaults (config: Record<string, any> = {}, options: Record
_.defaults(config, defaultValues)
// Default values can be functions, in which case they are evaluated
// at runtime - for example, slowTestThreshold where the default value
// varies between e2e and component testing.
config = _.mapValues(config, (value) => (typeof value === 'function' ? value(options) : value))
// split out our own app wide env from user env variables
// and delete envFile
config.env = parseEnv(config, options.env, resolved)
@@ -291,7 +283,7 @@ export function mergeDefaults (config: Record<string, any> = {}, options: Record
config.numTestsKeptInMemory = 0
}
config = setResolvedConfigValues(config, defaultValues, resolved)
config = setResolvedConfigValues(config, defaultValues, resolved, options)
if (config.port) {
config = setUrls(config)
@@ -316,10 +308,10 @@ export function mergeDefaults (config: Record<string, any> = {}, options: Record
.then(_.partialRight(setNodeBinary, options.onWarning))
}
export function setResolvedConfigValues (config, defaults, resolved) {
export function setResolvedConfigValues (config, defaults, resolved, options) {
const obj = _.clone(config)
obj.resolved = resolveConfigValues(config, defaults, resolved)
obj.resolved = resolveConfigValues(config, defaults, resolved, options)
debug('resolved config is %o', obj.resolved.browsers)
return obj
@@ -364,7 +356,7 @@ export function updateWithPluginValues (cfg, overrides) {
return errors.throw('CONFIG_VALIDATION_ERROR', errMsg)
})
let originalResolvedBrowsers = cfg && cfg.resolved && cfg.resolved.browsers && R.clone(cfg.resolved.browsers)
let originalResolvedBrowsers = cfg && cfg.resolved && cfg.resolved.browsers && _.cloneDeep(cfg.resolved.browsers)
if (!originalResolvedBrowsers) {
// have something to resolve with if plugins return nothing
@@ -378,7 +370,7 @@ export function updateWithPluginValues (cfg, overrides) {
debug('config diffs %o', diffs)
const userBrowserList = diffs && diffs.browsers && R.clone(diffs.browsers)
const userBrowserList = diffs && diffs.browsers && _.cloneDeep(diffs.browsers)
if (userBrowserList) {
debug('user browser list %o', userBrowserList)
@@ -424,7 +416,7 @@ export function updateWithPluginValues (cfg, overrides) {
// combines the default configuration object with values specified in the
// configuration file like "cypress.json". Values in configuration file
// overwrite the defaults.
export function resolveConfigValues (config, defaults, resolved = {}) {
export function resolveConfigValues (config, defaults, resolved = {}, options = {}) {
// pick out only known configuration keys
return _
.chain(config)
@@ -448,7 +440,9 @@ export function resolveConfigValues (config, defaults, resolved = {}) {
return source(r)
}
if (!(!_.isEqual(config[key], defaults[key]) && key !== 'browsers')) {
const defaultValue = typeof defaults[key] === 'function' ? defaults[key](options) : defaults[key]
if (!(!_.isEqual(config[key], defaultValue) && key !== 'browsers')) {
// "browsers" list is special, since it is dynamic by default
// and can only be ovewritten via plugins file
return source('default')
+4
View File
@@ -216,6 +216,10 @@ export const options = [
defaultValue: 'cypress/screenshots',
validation: v.isStringOrFalse,
isFolder: true,
}, {
name: 'slowTestThreshold',
defaultValue: (options: Record<string, any>) => options.testingType === 'component' ? 250 : 10000,
validation: v.isNumber,
}, {
name: 'socketId',
defaultValue: null,
+11 -8
View File
@@ -1,5 +1,4 @@
const _ = require('lodash')
const R = require('ramda')
const path = require('path')
const Promise = require('bluebird')
const cwd = require('../cwd')
@@ -89,7 +88,7 @@ module.exports = {
// desktop-gui/src/specs/specs-store.js
return spec.relative.toLowerCase().includes(specFilter.toLowerCase())
}
const specFilterFn = specFilter ? specFilterContains : R.T
const specFilterFn = specFilter ? specFilterContains : () => true
const getSpecsHelper = () => {
// grab all of the specs if this is ci
@@ -99,17 +98,21 @@ module.exports = {
debug('returning all specs')
return specsUtil.default.findSpecs(config)
.then(R.tap((specs) => {
return debug('found __all specs %o', specs)
}))
.then((specs) => {
debug('found __all specs %o', specs)
return specs
})
.filter(specFilterFn)
.filter((foundSpec) => {
return componentTestingEnabled
? foundSpec.specType === 'component'
: foundSpec.specType === 'integration'
}).then(R.tap((specs) => {
return debug('filtered __all specs %o', specs)
})).map((spec) => {
}).then((specs) => {
debug('filtered __all specs %o', specs)
return specs
}).map((spec) => {
// grab the name of each
return spec.absolute
}).map(convertSpecPath)
+1 -2
View File
@@ -9,7 +9,6 @@ require('./environment')
// essentially do it all again when we boot the correct
// mode.
const R = require('ramda')
const Promise = require('bluebird')
const debug = require('debug')('cypress:server:cypress')
const argsUtils = require('./util/args')
@@ -123,7 +122,7 @@ module.exports = {
// if the CLI passed "--" somewhere, we need to remove it
// for https://github.com/cypress-io/cypress/issues/5466
argv = R.without('--', argv)
argv = argv.filter((val) => val !== '--')
let options
+16 -9
View File
@@ -1,18 +1,25 @@
const Promise = require('bluebird')
const execa = require('execa')
const R = require('ramda')
const shellEnv = require('shell-env')
const _ = require('lodash')
const log = require('./log')
const utils = require('./util/shell')
const pickMainProps = R.pick(['stdout', 'stderr', 'code'])
const pickMainProps = (val) => _.pick(val, ['stdout', 'stderr', 'code'])
const trimStdio = R.evolve({
stdout: R.trim,
stderr: R.trim,
})
const trimStdio = (val) => {
const result = { ...val }
const loadShellVars = R.memoizeWith(R.toString, shellEnv)
if (_.isString(val.stdout)) {
result.stdout = val.stdout.trim()
}
if (_.isString(val.stderr)) {
result.stderr = val.stderr.trim()
}
return result
}
module.exports = {
run (projectRoot, options) {
@@ -38,9 +45,9 @@ module.exports = {
}
const run = () => {
return loadShellVars()
return shellEnv()
.then((shellVariables) => {
const env = R.mergeAll([{}, shellVariables, process.env, options.env])
const env = _.merge({}, shellVariables, process.env, options.env)
return utils.getShell(env.SHELL)
.then((shell) => {
+8 -3
View File
@@ -4,9 +4,14 @@ const { fs } = require('./util/fs')
module.exports = {
readFile (projectRoot, file, options = {}) {
const filePath = path.resolve(projectRoot, file)
const readFn = path.extname(filePath) === '.json' ? fs.readJsonAsync : fs.readFileAsync
const readFn = (path.extname(filePath) === '.json' && options.encoding !== null) ? fs.readJsonAsync : fs.readFileAsync
return readFn(filePath, options.encoding || 'utf8')
// https://github.com/cypress-io/cypress/issues/1558
// If no encoding is specified, then Cypress has historically defaulted
// to `utf8`, because of it's focus on text files. This is in contrast to
// NodeJs, which defaults to binary. We allow users to pass in `null`
// to restore the default node behavior.
return readFn(filePath, options.encoding === undefined ? 'utf8' : options.encoding)
.then((contents) => {
return {
contents,
@@ -22,7 +27,7 @@ module.exports = {
writeFile (projectRoot, file, contents, options = {}) {
const filePath = path.resolve(projectRoot, file)
const writeOptions = {
encoding: options.encoding || 'utf8',
encoding: options.encoding === undefined ? 'utf8' : options.encoding,
flag: options.flag || 'w',
}
+12 -4
View File
@@ -1,4 +1,3 @@
const _ = require('lodash')
const path = require('path')
const check = require('syntax-error')
const debug = require('debug')('cypress:server:fixture')
@@ -116,15 +115,24 @@ module.exports = {
},
parseFileByExtension (p, fixture, ext, options = {}) {
// https://github.com/cypress-io/cypress/issues/1558
// If the user explicitly specifies `null` as the encoding, we treat the
// file as binary regardless of extension. We base64 encode them for
// transmission over the websocket. There is a matching Buffer.from()
// in packages/driver/src/cy/commands/fixtures.ts
if (options.encoding === null) {
return this.parse(p, fixture)
}
switch (ext) {
case '.json': return this.parseJson(p, fixture)
case '.js': return this.parseJs(p, fixture)
case '.coffee': return this.parseCoffee(p, fixture)
case '.html': return this.parseHtml(p, fixture)
case '.png': case '.jpg': case '.jpeg': case '.gif': case '.tif': case '.tiff': case '.zip':
return this.parse(p, fixture, _.isNull(options.encoding) ? null : (options.encoding || 'base64'))
return this.parse(p, fixture, options.encoding)
default:
return this.parse(p, fixture, _.isNull(options.encoding) ? null : options.encoding)
return this.parse(p, fixture, options.encoding || 'utf8')
}
},
@@ -184,7 +192,7 @@ module.exports = {
.bind(this)
},
parse (p, fixture, encoding = 'utf8') {
parse (p, fixture, encoding) {
return fs.readFileAsync(p, encoding)
.bind(this)
},
+1 -6
View File
@@ -3,7 +3,6 @@ const debug = require('debug')('cypress:server:info')
const launcher = require('@packages/launcher')
const pluralize = require('pluralize')
const { stripIndent } = require('common-tags')
const { sortWith, ascend, prop } = require('ramda')
const browserUtils = require('../browsers/utils')
const _ = require('lodash')
const chalk = require('chalk')
@@ -83,11 +82,7 @@ const print = (browsers = []) => {
console.log('')
const sortByNameAndMajor = sortWith([
ascend(prop('name')),
ascend(prop('majorVersion')),
])
const sortedByNameAndMajorVersion = sortByNameAndMajor(browsers)
const sortedByNameAndMajorVersion = _.sortBy(browsers, ['name', 'majorVersion'])
sortedByNameAndMajorVersion.forEach((browser, k) => {
const text = stripIndent`
+29
View File
@@ -8,6 +8,7 @@ const Mocha = require('mocha-7.0.1')
const mochaReporters = require('mocha-7.0.1/lib/reporters')
const mochaCreateStatsCollector = require('mocha-7.0.1/lib/stats-collector')
const mochaColor = mochaReporters.Base.color
const mochaSymbols = mochaReporters.Base.symbols
const debug = require('debug')('cypress:server:reporter')
const Promise = require('bluebird')
@@ -293,6 +294,34 @@ class Reporter {
reporterOptions: this.reporterOptions,
})
if (this.reporterName === 'spec') {
// Unfortunately the reporter doesn't expose its indentation logic, so we have to replicate it here
let indents = 0
this.runner.on('suite', function (suite) {
++indents
})
this.runner.on('suite end', function () {
--indents
})
// Override the default reporter to always show test timing even for fast tests
// and display slow ones in yellow rather than red
this.runner._events.pass[2] = function (test) {
const durationColor = test.speed === 'slow' ? 'medium' : 'fast'
const fmt =
Array(indents).join(' ') +
mochaColor('checkmark', ` ${ mochaSymbols.ok}`) +
mochaColor('pass', ' %s') +
mochaColor(durationColor, ' (%dms)')
// Log: `✓ test title (300ms)` when a test passes
// eslint-disable-next-line no-console
console.log(fmt, test.title, test.duration)
}
}
this.runner.ignoreLeaks = true
}
+2 -3
View File
@@ -8,7 +8,6 @@ const glob = require('./util/glob')
const cwd = require('./cwd')
const debug = require('debug')('cypress:server:scaffold')
const errors = require('./errors')
const { isEmpty } = require('ramda')
const { isDefault } = require('./util/config')
const getExampleSpecsFullPaths = cypressEx.getPathToExamples()
@@ -116,8 +115,8 @@ const isNewProject = (config) => {
debug('determine if we should scaffold:')
// TODO: add tests for this
debug('- empty?', isEmpty(files))
if (isEmpty(files)) {
debug('- empty?', _.isEmpty(files))
if (_.isEmpty(files)) {
return true
}
+12 -5
View File
@@ -1,11 +1,18 @@
import _ from 'lodash'
import {
CYPRESS_ENV_PREFIX,
CYPRESS_ENV_PREFIX_LENGTH,
CYPRESS_RESERVED_ENV_VARS,
} from '../config'
import { coerce } from './coerce'
export const CYPRESS_ENV_PREFIX = 'CYPRESS_'
export const CYPRESS_ENV_PREFIX_LENGTH = 'CYPRESS_'.length
export const CYPRESS_RESERVED_ENV_VARS = [
'CYPRESS_INTERNAL_ENV',
]
export const CYPRESS_SPECIAL_ENV_VARS = [
'RECORD_KEY',
]
export const isDefault = (config: Record<string, any>, prop: string) => {
return config.resolved[prop].from === 'default'
}
+11 -5
View File
@@ -1,10 +1,16 @@
const R = require('ramda')
const addNewlineAtEveryNChar = (str, n) => {
// Add a newline char after every 'n' char
if (str) {
return R.splitEvery(n, str).join('\n')
if (!str) {
return str
}
let result = []
let idx = 0
while (idx < str.length) {
result.push(str.slice(idx, idx += n))
}
return result.join('\n')
}
module.exports = {
+1 -2
View File
@@ -1,7 +1,6 @@
const _ = require('lodash')
const Promise = require('bluebird')
const execa = require('execa')
const R = require('ramda')
const os = require('os')
const commandExistsModule = require('command-exists')
const log = require('../log')
@@ -71,7 +70,7 @@ const sourceShellCommand = function (cmd, shell) {
const findBash = () => {
return execa.shell('which bash')
.then(R.prop('stdout'))
.then((val) => val.stdout)
}
const getShell = function (shell) {
+2 -5
View File
@@ -1,5 +1,4 @@
import _ from 'lodash'
import R from 'ramda'
import la from 'lazy-ass'
import path from 'path'
import check from 'check-more-types'
@@ -171,15 +170,13 @@ function findSpecsOfType (searchFolder: string, commonSearchOptions: CommonSearc
return Bluebird.mapSeries(testFilesPatterns, findOnePattern).then(_.flatten)
}
const setTestType = (testType: Cypress.CypressSpecType) => R.map(R.set(R.lensProp('specType'), testType))
const findIntegrationSpecs = (searchFolder: string | undefined, commonSearchOptions: CommonSearchOptions, specPattern: string | undefined) => {
if (!searchFolder) {
return []
}
return findSpecsOfType(searchFolder, commonSearchOptions, specPattern)
.then(setTestType(SPEC_TYPES.INTEGRATION))
.then((val) => val.map((s) => ({ ...s, specType: SPEC_TYPES.INTEGRATION })))
}
const findComponentSpecs = (searchFolder: string | undefined | false, commonSearchOptions: CommonSearchOptions, specPattern: string | undefined) => {
@@ -188,7 +185,7 @@ const findComponentSpecs = (searchFolder: string | undefined | false, commonSear
}
return findSpecsOfType(searchFolder, commonSearchOptions, specPattern)
.then(setTestType(SPEC_TYPES.COMPONENT))
.then((val) => val.map((s) => ({ ...s, specType: SPEC_TYPES.COMPONENT })))
}
const printFoundSpecs = (foundSpecs: Cypress.Spec[]) => {
+1
View File
@@ -297,6 +297,7 @@ export async function process (name, cname, videoCompression, ffmpegchaptersConf
const outputOptions = [
'-preset fast',
`-crf ${videoCompression}`,
'-pix_fmt yuv420p',
]
if (addChaptersMeta) {
-1
View File
@@ -94,7 +94,6 @@
"ospath": "1.2.2",
"p-queue": "6.1.0",
"pluralize": "8.0.0",
"ramda": "0.27.1",
"randomstring": "1.1.5",
"recast": "0.20.4",
"resolve": "1.17.0",
+1 -2
View File
@@ -1,7 +1,6 @@
require('../spec_helper')
const _ = require('lodash')
const R = require('ramda')
const cp = require('child_process')
const pkg = require('../../package.json')
const execa = require('execa')
@@ -102,7 +101,7 @@ describe('CLI Interface', () => {
beforeEach(() => {
return execa('npm', ['-version'])
.then(R.prop('stdout'))
.then((val) => val.stdout)
.then((version) => {
npmVersion = version
@@ -1,7 +1,6 @@
/* eslint-disable no-restricted-properties */
require('../spec_helper')
const R = require('ramda')
const _ = require('lodash')
const path = require('path')
const EE = require('events')
@@ -1054,7 +1053,7 @@ describe('lib/cypress', () => {
// when we work with the browsers we set a few extra flags
const chrome = _.find(TYPICAL_BROWSERS, { name: 'chrome' })
const launchedChrome = R.merge(chrome, {
const launchedChrome = _.defaults({}, chrome, {
isHeadless: true,
isHeaded: false,
})
@@ -5,7 +5,7 @@ const utils = require(`${root}../lib/browsers/utils`)
const snapshot = require('snap-shot-it')
const normalizeBrowsers = (message) => {
return message.replace(/(found are: ).*/, '$1chrome, firefox, electron')
return message.replace(/(found on your system are:)(?:\n- .*)*/, '$1\n- chrome\n- firefox\n- electron')
}
// When we added component testing mode, we added the option for electron to be omitted
+11 -24
View File
@@ -1,7 +1,6 @@
require('../spec_helper')
const _ = require('lodash')
const R = require('ramda')
const debug = require('debug')('test')
const config = require(`${root}lib/config`)
const errors = require(`${root}lib/errors`)
@@ -1072,13 +1071,21 @@ describe('lib/config', () => {
cfg.projectRoot = '/foo/bar/'
return config.mergeDefaults(cfg, options)
.then(R.prop(prop))
.then((val) => val[prop])
.then((result) => {
expect(result).to.deep.eq(value)
})
}
})
it('slowTestThreshold=10000 for e2e', function () {
return this.defaults('slowTestThreshold', 10000, {}, { testingType: 'e2e' })
})
it('slowTestThreshold=250 for component', function () {
return this.defaults('slowTestThreshold', 250, {}, { testingType: 'component' })
})
it('port=null', function () {
return this.defaults('port', null)
})
@@ -1462,6 +1469,7 @@ describe('lib/config', () => {
retries: { value: { runMode: 0, openMode: 0 }, from: 'default' },
screenshotOnRunFailure: { value: true, from: 'default' },
screenshotsFolder: { value: 'cypress/screenshots', from: 'default' },
slowTestThreshold: { value: 10000, from: 'default' },
supportFile: { value: 'cypress/support', from: 'default' },
taskTimeout: { value: 60000, from: 'default' },
testFiles: { value: '**/*.*', from: 'default' },
@@ -1568,6 +1576,7 @@ describe('lib/config', () => {
retries: { value: { runMode: 0, openMode: 0 }, from: 'default' },
screenshotOnRunFailure: { value: true, from: 'default' },
screenshotsFolder: { value: 'cypress/screenshots', from: 'default' },
slowTestThreshold: { value: 10000, from: 'default' },
supportFile: { value: 'cypress/support', from: 'default' },
taskTimeout: { value: 60000, from: 'default' },
testFiles: { value: '**/*.*', from: 'default' },
@@ -2412,25 +2421,3 @@ describe('lib/config', () => {
})
})
})
describe('lib/util/config', () => {
context('.isDefault', () => {
it('returns true if value is default value', () => {
settings = { baseUrl: null }
const defaults = { baseUrl: null }
const resolved = {}
const merged = config.setResolvedConfigValues(settings, defaults, resolved)
expect(configUtil.isDefault(merged, 'baseUrl')).to.be.true
})
it('returns false if value is not default value', () => {
settings = { baseUrl: null }
const defaults = { baseUrl: 'http://localhost:8080' }
const resolved = {}
const merged = config.setResolvedConfigValues(settings, defaults, resolved)
expect(configUtil.isDefault(merged, 'baseUrl')).to.be.false
})
})
})
+16
View File
@@ -41,6 +41,13 @@ describe('lib/files', () => {
})
})
// https://github.com/cypress-io/cypress/issues/1558
it('explicit null encoding is sent to driver as a Buffer', function () {
return files.readFile(this.projectRoot, 'tests/_fixtures/ascii.foo', { encoding: null }).then(({ contents }) => {
expect(contents).to.eql(Buffer.from('\n'))
})
})
it('parses json to valid JS object', function () {
return files.readFile(this.projectRoot, 'tests/_fixtures/users.json').then(({ contents }) => {
expect(contents).to.eql([
@@ -75,6 +82,15 @@ describe('lib/files', () => {
})
})
// https://github.com/cypress-io/cypress/issues/1558
it('explicit null encoding is written exactly as received', function () {
return files.writeFile(this.projectRoot, '.projects/write_file.txt', Buffer.from(''), { encoding: null }).then(() => {
return files.readFile(this.projectRoot, '.projects/write_file.txt', { encoding: null }).then(({ contents }) => {
expect(contents).to.eql(Buffer.from(''))
})
})
})
it('overwrites existing file by default', function () {
return files.writeFile(this.projectRoot, '.projects/write_file.txt', 'foo').then(() => {
return files.readFile(this.projectRoot, '.projects/write_file.txt').then(({ contents }) => {
+44 -37
View File
@@ -18,6 +18,9 @@ describe('lib/fixture', () => {
FixturesHelper.scaffold()
this.todosPath = FixturesHelper.projectPath('todos')
this.read = (folder, image, encoding) => {
return fs.readFileAsync(path.join(folder, image), encoding)
}
return config.get(this.todosPath).then((cfg) => {
({ fixturesFolder: this.fixturesFolder } = cfg)
@@ -172,8 +175,8 @@ Expecting 'EOF', '}', ':', ',', ']', got 'STRING'\
return config.get(projectPath)
.then((cfg) => {
return fixture.get(cfg.fixturesFolder, 'foo')
.then((fixture) => {
expect(fixture).to.deep.eq({ 'bar': 'baz' })
.then((result) => {
expect(result).to.deep.eq({ 'bar': 'baz' })
})
})
})
@@ -325,6 +328,15 @@ John,Chef,1982
})
})
// https://github.com/cypress-io/cypress/issues/1558
context('binary files', () => {
it('returns file as buffer regardless of extension when passed null encoding', function () {
return fixture.get(this.fixturesFolder, 'nested/fixture.js', { encoding: null }).then((index) => {
expect(index).to.eql(Buffer.from('{nested: "fixture"}'))
})
})
})
context('file with unknown extension and encoding specified', () => {
it('returns text encoded as specified', function () {
return fixture.get(this.fixturesFolder, 'ascii.foo', { encoding: 'ascii' }).then((index) => {
@@ -334,69 +346,64 @@ John,Chef,1982
})
context('image files', () => {
beforeEach(function () {
this.read = (folder, image, encoding) => {
return fs.readFileAsync(path.join(folder, image), encoding)
}
})
it('returns png as string', function () {
return this.read(this.fixturesFolder, 'images/flower.png', 'base64')
.then((str) => {
it('returns png as buffer', function () {
return this.read(this.fixturesFolder, 'images/flower.png')
.then((file) => {
return fixture.get(this.fixturesFolder, 'images/flower.png')
.then((base64) => {
expect(base64).to.eq(str)
.then((result) => {
expect(result).to.eql(file)
})
})
})
it('returns jpg as string', function () {
return this.read(this.fixturesFolder, 'images/sample.jpg', 'base64')
.then((str) => {
it('returns jpg as buffer', function () {
return this.read(this.fixturesFolder, 'images/sample.jpg')
.then((file) => {
return fixture.get(this.fixturesFolder, 'images/sample.jpg')
.then((base64) => {
expect(base64).to.eq(str)
.then((result) => {
expect(result).to.eql(file)
})
})
})
it('returns gif as string', function () {
return this.read(this.fixturesFolder, 'images/word.gif', 'base64')
.then((str) => {
it('returns gif as buffer', function () {
return this.read(this.fixturesFolder, 'images/word.gif')
.then((file) => {
return fixture.get(this.fixturesFolder, 'images/word.gif')
.then((base64) => {
expect(base64).to.eq(str)
.then((result) => {
expect(result).to.eql(file)
})
})
})
it('returns tif as string', function () {
return this.read(this.fixturesFolder, 'images/sample.tif', 'base64')
.then((str) => {
it('returns tif as buffer', function () {
return this.read(this.fixturesFolder, 'images/sample.tif')
.then((file) => {
return fixture.get(this.fixturesFolder, 'images/sample.tif')
.then((base64) => {
expect(base64).to.eq(str)
.then((result) => {
expect(result).to.eql(file)
})
})
})
it('returns png as binary', function () {
it('returns png as binary if that encoding is requested', function () {
return this.read(this.fixturesFolder, 'images/flower.png', 'binary')
.then((bin) => {
.then((file) => {
return fixture.get(this.fixturesFolder, 'images/flower.png', { encoding: 'binary' })
.then((bin2) => {
expect(bin).to.eq(bin2)
.then((result) => {
expect(result).to.eq(file)
})
})
})
})
context('zip files', () => {
it('returns zip as base64 string', function () {
return fixture.get(this.fixturesFolder, 'example.zip').then((base64) => {
const str = 'UEsDBAoAAAAAAK2zOUcAAAAAAAAAAAAAAAAEABAAemlwL1VYDAAGAwZWBgMGVvUBFABQSwMECgAAAAAAo7M5RwAAAAAAAAAAAAAAAAkAEAB6aXAvYS50eHRVWAwA8QIGVvECBlb1ARQAUEsDBAoAAAAAAKSzOUcAAAAAAAAAAAAAAAAJABAAemlwL2IudHh0VVgMAPMCBlbzAgZW9QEUAFBLAwQKAAAAAAClszlHAAAAAAAAAAAAAAAACQAQAHppcC9jLnR4dFVYDAD1AgZW9QIGVvUBFABQSwMECgAAAAAApbM5RwAAAAAAAAAAAAAAAAkAEAB6aXAvZC50eHRVWAwA9gIGVvYCBlb1ARQAUEsDBAoAAAAAAKazOUcAAAAAAAAAAAAAAAAJABAAemlwL2UudHh0VVgMAPgCBlb4AgZW9QEUAFBLAwQKAAAAAACnszlHAAAAAAAAAAAAAAAACQAQAHppcC9mLnR4dFVYDAD5AgZW+QIGVvUBFABQSwMECgAAAAAAqLM5RwAAAAAAAAAAAAAAAAkAEAB6aXAvZy50eHRVWAwA+wIGVvsCBlb1ARQAUEsDBAoAAAAAAKizOUcAAAAAAAAAAAAAAAAJABAAemlwL2gudHh0VVgMAPwCBlb8AgZW9QEUAFBLAwQKAAAAAACpszlHAAAAAAAAAAAAAAAACQAQAHppcC9pLnR4dFVYDAD9AgZW/QIGVvUBFABQSwMECgAAAAAAqrM5RwAAAAAAAAAAAAAAAAkAEAB6aXAvai50eHRVWAwA/wIGVv8CBlb1ARQAUEsDBAoAAAAAAK2zOUcAAAAAAAAAAAAAAAAJABAAemlwL2sudHh0VVgMAAYDBlYGAwZW9QEUAFBLAQIVAwoAAAAAAK2zOUcAAAAAAAAAAAAAAAAEAAwAAAAAAAAAAEDtQQAAAAB6aXAvVVgIAAYDBlYGAwZWUEsBAhUDCgAAAAAAo7M5RwAAAAAAAAAAAAAAAAkADAAAAAAAAAAAQKSBMgAAAHppcC9hLnR4dFVYCADxAgZW8QIGVlBLAQIVAwoAAAAAAKSzOUcAAAAAAAAAAAAAAAAJAAwAAAAAAAAAAECkgWkAAAB6aXAvYi50eHRVWAgA8wIGVvMCBlZQSwECFQMKAAAAAAClszlHAAAAAAAAAAAAAAAACQAMAAAAAAAAAABApIGgAAAAemlwL2MudHh0VVgIAPUCBlb1AgZWUEsBAhUDCgAAAAAApbM5RwAAAAAAAAAAAAAAAAkADAAAAAAAAAAAQKSB1wAAAHppcC9kLnR4dFVYCAD2AgZW9gIGVlBLAQIVAwoAAAAAAKazOUcAAAAAAAAAAAAAAAAJAAwAAAAAAAAAAECkgQ4BAAB6aXAvZS50eHRVWAgA+AIGVvgCBlZQSwECFQMKAAAAAACnszlHAAAAAAAAAAAAAAAACQAMAAAAAAAAAABApIFFAQAAemlwL2YudHh0VVgIAPkCBlb5AgZWUEsBAhUDCgAAAAAAqLM5RwAAAAAAAAAAAAAAAAkADAAAAAAAAAAAQKSBfAEAAHppcC9nLnR4dFVYCAD7AgZW+wIGVlBLAQIVAwoAAAAAAKizOUcAAAAAAAAAAAAAAAAJAAwAAAAAAAAAAECkgbMBAAB6aXAvaC50eHRVWAgA/AIGVvwCBlZQSwECFQMKAAAAAACpszlHAAAAAAAAAAAAAAAACQAMAAAAAAAAAABApIHqAQAAemlwL2kudHh0VVgIAP0CBlb9AgZWUEsBAhUDCgAAAAAAqrM5RwAAAAAAAAAAAAAAAAkADAAAAAAAAAAAQKSBIQIAAHppcC9qLnR4dFVYCAD/AgZW/wIGVlBLAQIVAwoAAAAAAK2zOUcAAAAAAAAAAAAAAAAJAAwAAAAAAAAAAECkgVgCAAB6aXAvay50eHRVWAgABgMGVgYDBlZQSwUGAAAAAAwADAAfAwAAjwIAAAAA'
expect(base64).to.eq(str)
it('returns zip as buffer', function () {
return this.read(this.fixturesFolder, 'example.zip')
.then((file) => {
return fixture.get(this.fixturesFolder, 'example.zip').then((result) => {
expect(result).to.eql(file)
})
})
})
})
+2 -2
View File
@@ -1,10 +1,10 @@
require('../../spec_helper')
const _ = require('lodash')
const Promise = require('bluebird')
const electron = require('electron')
const stripAnsi = require('strip-ansi')
const snapshot = require('snap-shot-it')
const R = require('ramda')
const pkg = require('@packages/root')
const { fs } = require(`${root}../lib/util/fs`)
const user = require(`${root}../lib/user`)
@@ -862,7 +862,7 @@ describe('lib/modes/run', () => {
// for some reason I cannot stub property value using Sinon
let version
// save a copy of "true" experiments right away
const names = R.clone(experimental.names)
const names = _.cloneDeep(experimental.names)
before(() => {
// reset experiments names before each test
@@ -111,7 +111,6 @@ describe('lib/reporter', () => {
it('recursively creates suites for fullTitle', function () {
const args = this.reporter.parseArgs('fail', [this.testObj])
console.log(args)
expect(args[0]).to.eq('fail')
const title = 'TodoMVC - React When page is initially opened should focus on the todo input field'
+10
View File
@@ -456,6 +456,16 @@ describe('lib/socket', () => {
return this.client.emit('backend:request', 'get:fixture', 'does-not-exist.txt', {}, cb)
})
it('passes Buffers through intact', function (done) {
const cb = function (resp) {
expect(resp.response).to.eql(Buffer.from('[{"json": true}]'))
return done()
}
return this.client.emit('backend:request', 'get:fixture', 'foo', { encoding: null }, cb)
})
})
context('on(http:request)', () => {
@@ -1,12 +1,12 @@
require('../spec_helper')
require('../../spec_helper')
const path = require('path')
const os = require('os')
const snapshot = require('snap-shot-it')
const stripAnsi = require('strip-ansi')
const minimist = require('minimist')
const argsUtil = require(`${root}lib/util/args`)
const getWindowsProxyUtil = require(`${root}lib/util/get-windows-proxy`)
const argsUtil = require(`${root}../lib/util/args`)
const getWindowsProxyUtil = require(`${root}../lib/util/get-windows-proxy`)
const cwd = process.cwd()
@@ -1,6 +1,6 @@
require('../spec_helper')
require('../../spec_helper')
const CacheBuster = require(`${root}lib/util/cache_buster`)
const CacheBuster = require(`${root}../lib/util/cache_buster`)
describe('lib/cache_buster', () => {
context('#get', () => {
@@ -1,8 +1,8 @@
require('../spec_helper')
require('../../spec_helper')
const _ = require('lodash')
const { stripIndent } = require('common-tags')
const chromePolicyCheck = require(`${root}lib/util/chrome_policy_check`)
const chromePolicyCheck = require(`${root}../lib/util/chrome_policy_check`)
describe('lib/util/chrome_policy_check', () => {
context('.getRunner returns a function', () => {
@@ -1,8 +1,8 @@
const mockedEnv = require('mocked-env')
require('../spec_helper')
require('../../spec_helper')
const ciProvider = require(`${root}lib/util/ci_provider`)
const ciProvider = require(`${root}../lib/util/ci_provider`)
const expectsName = (name) => {
expect(ciProvider.provider(), 'CI providers detected name').to.eq(name)
@@ -1,7 +1,7 @@
require('../spec_helper')
require('../../spec_helper')
const { coerce } = require(`${root}lib/util/coerce`)
const { getProcessEnvVars } = require(`${root}lib/util/config`)
const { coerce } = require(`${root}../lib/util/coerce`)
const { getProcessEnvVars } = require(`${root}../lib/util/config`)
describe('lib/util/coerce', () => {
beforeEach(function () {
@@ -0,0 +1,48 @@
require('../../spec_helper')
const configUtil = require(`${root}../lib/util/config`)
describe('lib/util/config', () => {
context('.isDefault', () => {
it('returns true if value is default value', () => {
const options = {
resolved: {
baseUrl: { from: 'default' },
},
}
expect(configUtil.isDefault(options, 'baseUrl')).to.be.true
})
it('returns false if value is not default value', () => {
const options = {
resolved: {
baseUrl: { from: 'cli' },
},
}
expect(configUtil.isDefault(options, 'baseUrl')).to.be.false
})
})
context('.getProcessEnvVars', () => {
it('returns process envs prefixed with cypress', () => {
const envs = {
CYPRESS_BASE_URL: 'value',
RANDOM_ENV: 'ignored',
}
expect(configUtil.getProcessEnvVars(envs)).to.deep.eq({
BASE_URL: 'value',
})
})
it('does not return CYPRESS_RESERVED_ENV_VARS', () => {
const envs = {
CYPRESS_INTERNAL_ENV: 'value',
}
expect(configUtil.getProcessEnvVars(envs)).to.deep.eq({})
})
})
})
@@ -1,6 +1,6 @@
require('../spec_helper')
require('../../spec_helper')
const duration = require(`${root}lib/util/duration`)
const duration = require(`${root}../lib/util/duration`)
describe('lib/util/duration', () => {
context('.format', () => {
@@ -1,7 +1,7 @@
import '../spec_helper'
import '../../spec_helper'
import { connect, agent } from '@packages/network'
import { isListening } from '../../lib/util/ensure-url'
import { isListening } from '../../../lib/util/ensure-url'
import sinon from 'sinon'
import nock from 'nock'
@@ -1,13 +1,13 @@
require('../spec_helper')
require('../../spec_helper')
const os = require('os')
const path = require('path')
const Promise = require('bluebird')
const lockFile = Promise.promisifyAll(require('lockfile'))
const { fs } = require(`${root}lib/util/fs`)
const env = require(`${root}lib/util/env`)
const exit = require(`${root}lib/util/exit`)
const FileUtil = require(`${root}lib/util/file`)
const { fs } = require(`${root}../lib/util/fs`)
const env = require(`${root}../lib/util/env`)
const exit = require(`${root}../lib/util/exit`)
const FileUtil = require(`${root}../lib/util/file`)
describe('lib/util/file', () => {
beforeEach(function () {
@@ -1,7 +1,7 @@
require('../spec_helper')
require('../../spec_helper')
const humanInterval = require('human-interval')
const humanTime = require(`${root}lib/util/human_time`)
const humanTime = require(`${root}../lib/util/human_time`)
describe('lib/util/human_time', () => {
context('.long', () => {
@@ -1,6 +1,6 @@
import '../spec_helper'
import '../../spec_helper'
import newlines from '../../lib/util/newlines'
import newlines from '../../../lib/util/newlines'
describe('lib/util/newlines', function () {
it('inserts newline at each n char', function () {
@@ -1,7 +1,7 @@
require('../spec_helper')
require('../../spec_helper')
const cp = require('child_process')
const open = require(`${root}lib/util/open`)
const open = require(`${root}../lib/util/open`)
const platform = (p) => {
return Object.defineProperty(process, 'platform', {
@@ -1,6 +1,6 @@
require('../spec_helper')
require('../../spec_helper')
const origin = require(`${root}lib/util/origin`)
const origin = require(`${root}../lib/util/origin`)
describe('lib/util/origin', () => {
beforeEach(function () {
@@ -1,6 +1,6 @@
require('../spec_helper')
require('../../spec_helper')
const path_helpers = require(`${root}lib/util/path_helpers`)
const path_helpers = require(`${root}../lib/util/path_helpers`)
describe('lib/util/path_helpers', () => {
context('checkIfResolveChangedRootFolder', () => {
@@ -1,10 +1,10 @@
require('../spec_helper')
require('../../spec_helper')
const os = require('os')
const path = require('path')
const { fs } = require(`${root}/lib/util/fs`)
const findProcess = require(`${root}lib/util/find_process`)
const profileCleaner = require(`${root}lib/util/profile_cleaner`)
const { fs } = require(`${root}../lib/util/fs`)
const findProcess = require(`${root}../lib/util/find_process`)
const profileCleaner = require(`${root}../lib/util/profile_cleaner`)
const tmpDir = os.tmpdir()
const pidProfilesFolder = path.join(tmpDir, 'pid-profiles')
@@ -1,7 +1,7 @@
require('../spec_helper')
require('../../spec_helper')
const randomstring = require('randomstring')
const random = require(`${root}lib/util/random`)
const random = require(`${root}../lib/util/random`)
context('.id', () => {
it('returns random.generate string with length 5 by default', () => {
@@ -1,6 +1,6 @@
require('../spec_helper')
require('../../spec_helper')
const { apiRoutes, onRoutes } = require(`${root}/lib/util/routes`)
const { apiRoutes, onRoutes } = require(`${root}../lib/util/routes`)
describe('lib/util/routes', () => {
describe('api routes', () => {
@@ -1,9 +1,9 @@
require('../spec_helper')
require('../../spec_helper')
const R = require('ramda')
const _ = require('lodash')
const path = require('path')
const config = require(`${root}lib/config`)
const specsUtil = require(`${root}lib/util/specs`).default
const config = require(`${root}../lib/config`)
const specsUtil = require(`${root}../lib/util/specs`).default
const FixturesHelper = require('@tooling/system-tests/lib/fixtures')
const debug = require('debug')('test')
@@ -33,7 +33,7 @@ describe('lib/util/specs', () => {
it('returns absolute filenames', function () {
return specsUtil
.findSpecs(this.config)
.then((R.forEach(checkFoundSpec)))
.then(((specs) => specs.forEach(checkFoundSpec)))
})
it('handles fixturesFolder being false', function () {
@@ -65,7 +65,7 @@ describe('lib/util/specs', () => {
cfg.resolved.testingType = { value: 'component' }
return specsUtil.findSpecs(cfg)
}).then(R.project(['relative', 'specType']))
}).then((val) => val.map((spec) => _.pick(spec, ['relative', 'specType'])))
.then((files) => {
expect(files).to.deep.equal([
{
@@ -1,11 +1,11 @@
require('../spec_helper')
require('../../spec_helper')
const _ = require('lodash')
const fs = require('fs')
const stream = require('stream')
const Promise = require('bluebird')
const { concatStream } = require('@packages/network')
const { streamBuffer } = require('../../lib/util/stream_buffer')
const { streamBuffer } = require('../../../lib/util/stream_buffer')
function drain (stream) {
return new Promise((resolve) => {
@@ -1,4 +1,4 @@
import '../spec_helper'
import '../../spec_helper'
import { expect } from 'chai'
import execa from 'execa'
import proxyquire from 'proxyquire'
@@ -6,7 +6,7 @@ import proxyquire from 'proxyquire'
const ERROR_MESSAGE = 'Setting the NODE_TLS_REJECT_UNAUTHORIZED'
const TLS_CONNECT = `require('tls').connect().on('error', ()=>{});`
const SUPPRESS_WARNING = `require('${__dirname}/../../lib/util/suppress_warnings').suppress();`
const SUPPRESS_WARNING = `require('${__dirname}/../../../lib/util/suppress_warnings').suppress();`
describe('lib/util/suppress_warnings', function () {
it('tls.connect emits warning if NODE_TLS_REJECT_UNAUTHORIZED=0 and not suppressed', function () {
@@ -36,7 +36,7 @@ describe('lib/util/suppress_warnings', function () {
const emitWarning = sinon.spy(process, 'emitWarning')
// force typescript to always be non-requireable
const { suppress } = proxyquire('../../lib/util/suppress_warnings', {})
const { suppress } = proxyquire('../../../lib/util/suppress_warnings', {})
suppress()
@@ -1,11 +1,11 @@
require('../spec_helper')
require('../../spec_helper')
const snapshot = require('snap-shot-it')
const stripAnsi = require('strip-ansi')
const widestLine = require('widest-line')
const env = require(`${root}lib/util/env`)
const terminal = require(`${root}lib/util/terminal`)
const terminalSize = require(`${root}lib/util/terminal-size`)
const env = require(`${root}../lib/util/env`)
const terminal = require(`${root}../lib/util/terminal`)
const terminalSize = require(`${root}../lib/util/terminal-size`)
const sanitizeSnapshot = (str) => {
return snapshot(stripAnsi(str))
@@ -1,9 +1,9 @@
require('../spec_helper')
require('../../spec_helper')
const fs = require('fs')
const os = require('os')
const path = require('path')
const trash = require(`${root}lib/util/trash`)
const trash = require(`${root}../lib/util/trash`)
const populateDirectories = function (basePath) {
fs.mkdirSync(basePath)
@@ -1,8 +1,8 @@
require('../spec_helper')
require('../../spec_helper')
const tty = require('tty')
const ttyUtil = require(`${root}lib/util/tty`)
const terminalSize = require(`${root}lib/util/terminal-size`)
const ttyUtil = require(`${root}../lib/util/tty`)
const terminalSize = require(`${root}../lib/util/terminal-size`)
const ttys = [process.stdin.isTTY, process.stdout.isTTY, process.stderr.isTTY]
+12 -7
View File
@@ -10,7 +10,6 @@ const pluralize = require('pluralize')
const execa = require('execa')
const electron = require('@packages/electron')
const debug = require('debug')('cypress:binary')
const R = require('ramda')
const la = require('lazy-ass')
const check = require('check-more-types')
@@ -116,7 +115,11 @@ const buildCypressApp = function (platform, version, options = {}) {
return packages.runAllBuild()
// Promise.resolve()
.then(R.tap(logBuiltAllPackages))
.then((val) => {
logBuiltAllPackages(val)
return val
})
}
const copyPackages = function () {
@@ -343,7 +346,7 @@ require('./packages/server')\
console.log('in build folder %s', buildFolder)
return execa('ls', ['-la', buildFolder])
.then(R.prop('stdout'))
.then((val) => val.stdout)
.then(console.log)
}
@@ -430,14 +433,16 @@ require('./packages/server')\
}
const printDiskUsage = function (sizes) {
const bySize = R.sortBy(R.prop('1'))
return console.log(bySize(R.toPairs(sizes)))
return console.log(_.sortBy(_.toPairs(sizes), 1))
}
return execa('du', args)
.then(parseDiskUsage)
.then(R.tap(printDiskUsage))
.then((val) => {
printDiskUsage(val)
return val
})
.then((sizes) => {
return performanceTracking.track('test runner size', sizes)
})
+12 -22
View File
@@ -4,7 +4,6 @@ const bumpercar = require('@cypress/bumpercar')
const path = require('path')
const la = require('lazy-ass')
const check = require('check-more-types')
const R = require('ramda')
const { configFromEnvOrJsonFile, filenameToShellVariable } = require('@cypress/env-or-json-file')
const makeEmptyGithubCommit = require('make-empty-github-commit')
const parse = require('parse-github-repo-url')
@@ -88,7 +87,7 @@ const getCiConfig = function () {
return config
}
const awaitEachProjectAndProvider = function (projects, fn, filter = R.identity) {
const awaitEachProjectAndProvider = function (projects, fn, filter = (val) => val) {
const creds = getCiConfig()
// configure a new Bumpercar
@@ -119,7 +118,7 @@ const awaitEachProjectAndProvider = function (projects, fn, filter = R.identity)
car = bumpercar.create({ providers })
const filteredProjects = R.filter(filter, projects)
const filteredProjects = projects.filter(filter)
if (check.empty(filteredProjects)) {
console.log('⚠️ zero filtered projects left after filtering')
@@ -136,26 +135,17 @@ const awaitEachProjectAndProvider = function (projects, fn, filter = R.identity)
// do not trigger all projects if there is specific provider
// for example appVeyor should be used for Windows testing
const getFilterByProvider = function (providerName, platformName) {
let platformFilter; let providerFilter
return (val) => {
if (providerName && val.provider !== providerName) {
return false
}
if (providerName) {
console.log('only allow projects for provider', providerName)
providerFilter = R.propEq('provider', providerName)
} else {
providerFilter = R.identity
if (platformName && val.platform !== platformName) {
return false
}
return val
}
if (platformName) {
console.log('only allow projects for platform', platformName)
platformFilter = R.propEq('platform', platformName)
} else {
platformFilter = R.identity
}
// combined filter is when both filters pass
const projectFilter = R.allPass([providerFilter, platformFilter])
return projectFilter
}
module.exports = {
@@ -199,7 +189,7 @@ module.exports = {
}
return awaitEachProjectAndProvider(PROJECTS, updateProject, projectFilter)
.then(R.always(result))
.then(() => result)
},
// triggers test projects on multiple CIs
+1 -2
View File
@@ -12,7 +12,6 @@ const la = require('lazy-ass')
const check = require('check-more-types')
const debug = require('debug')('cypress:binary')
const questionsRemain = require('@cypress/questions-remain')
const R = require('ramda')
const rp = require('@cypress/request-promise')
const zip = require('./zip')
@@ -37,7 +36,7 @@ const fail = (str) => {
return console.log(chalk.bgRed(` ${chalk.black(str)} `))
}
const zippedFilename = R.always(upload.zipName)
const zippedFilename = () => upload.zipName
// goes through the list of properties and asks relevant question
// resolves with all relevant options set
+3 -3
View File
@@ -1,8 +1,8 @@
const path = require('path')
const la = require('lazy-ass')
const check = require('check-more-types')
const R = require('ramda')
const os = require('os')
const _ = require('lodash')
// canonical platform names
const platforms = {
@@ -11,11 +11,11 @@ const platforms = {
windows: 'win32',
}
const isValidPlatform = check.oneOf(R.values(platforms))
const isValidPlatform = check.oneOf(_.values(platforms))
const checkPlatform = (platform) => {
return la(isValidPlatform(platform),
'invalid build platform', platform, 'valid choices', R.values(platforms))
'invalid build platform', platform, 'valid choices', _.values(platforms))
}
const buildRootDir = () => {

Some files were not shown because too many files have changed in this diff Show More