Merge branch 'develop' into feature-multidomain

This commit is contained in:
Chris Breiding
2022-02-14 14:57:40 -05:00
332 changed files with 16487 additions and 2928 deletions
+2
View File
@@ -1,3 +1,5 @@
* text=auto
*.json text eol=lf
packages/errors/__snapshot-html__/** linguist-generated=true
-2
View File
@@ -1,2 +0,0 @@
# Always validate the PR title, and ignore the commits
titleOnly: true
@@ -0,0 +1,21 @@
name: "Semantic Pull Request"
on:
pull_request_target:
types:
- opened
- edited
- synchronize
jobs:
main:
name: Lint Title
runs-on: ubuntu-latest
steps:
# use a fork of the GitHub action - we cannot pull in untrusted third party actions
# see https://github.com/cypress-io/cypress/pull/20091#discussion_r801799647
- uses: cypress-io/action-semantic-pull-request@v4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
validateSingleCommit: true
+8
View File
@@ -18,6 +18,8 @@ packages/config/lib/*.js
# from data-context, compiled .js files
packages/data-context/src/**/*.js
packages/errors/src/**/*.js
packages/errors/test/**/*.js
# from desktop-gui
packages/desktop-gui/cypress/videos
@@ -68,6 +70,7 @@ packages/socket/lib/*.js
# from system-tests
system-tests/.projects
system-tests/.http-mitm-proxy
system-tests/fixtures/large-img
# from npm/react
@@ -83,6 +86,11 @@ system-tests/fixtures/large-img
# from runner-ct
/packages/runner-ct/cypress/screenshots
# from errors
/packages/errors/__snapshot-images__
/packages/errors/__snapshot-md__
/packages/errors/__snapshot-html-local__
# graphql, auto-generated
/packages/launchpad/src/generated
/packages/app/src/generated
+2 -2
View File
@@ -36,6 +36,6 @@
"i18n-ally.keystyle": "nested",
// Volar is the main extension that powers Vue's language features.
"volar.autoCompleteRefs": false,
"volar.takeOverMode.enabled": true
// "volar.autoCompleteRefs": false,
"volar.takeOverMode.enabled": true,
}
-25
View File
@@ -1,19 +1,9 @@
exports['list of all projects'] = [
{
"repo": "cypress-io/cypress-test-tiny",
"provider": "circle",
"platform": "win32"
},
{
"repo": "cypress-io/cypress-test-example-repos",
"provider": "circle",
"platform": "win32"
},
{
"repo": "cypress-io/cypress-test-tiny",
"provider": "circle",
"platform": "linux"
},
{
"repo": "cypress-io/cypress-test-module-api",
"provider": "circle",
@@ -24,11 +14,6 @@ exports['list of all projects'] = [
"provider": "circle",
"platform": "linux"
},
{
"repo": "cypress-io/cypress-test-nested-projects",
"provider": "circle",
"platform": "linux"
},
{
"repo": "cypress-io/cypress-test-ci-environments",
"provider": "circle",
@@ -39,11 +24,6 @@ exports['list of all projects'] = [
"provider": "circle",
"platform": "linux"
},
{
"repo": "cypress-io/cypress-test-tiny",
"provider": "circle",
"platform": "darwin"
},
{
"repo": "cypress-io/cypress-test-example-repos",
"provider": "circle",
@@ -52,11 +32,6 @@ exports['list of all projects'] = [
]
exports['should have just circle and darwin projects'] = [
{
"repo": "cypress-io/cypress-test-tiny",
"provider": "circle",
"platform": "darwin"
},
{
"repo": "cypress-io/cypress-test-example-repos",
"provider": "circle",
+1 -1
View File
@@ -1,4 +1,4 @@
{
"chrome:beta": "98.0.4758.80",
"chrome:beta": "99.0.4844.27",
"chrome:stable": "98.0.4758.80"
}
+9 -86
View File
@@ -89,7 +89,7 @@ executors:
# https://github.com/CircleCI-Public/windows-orb/blob/master/src/executors/default.yml
# https://circleci.com/docs/2.0/hello-world-windows/#software-pre-installed-in-the-windows-image
windows: &windows-executor
machine:
machine:
image: windows-server-2019-vs2019:stable
shell: bash.exe -eo pipefail
resource_class: windows.medium
@@ -151,7 +151,7 @@ commands:
- cypress
- .ssh
- node_modules # contains the npm i -g modules
install_cache_helpers_dependencies:
steps:
- run:
@@ -987,6 +987,7 @@ jobs:
- run:
name: Linting 🧹
command: |
yarn clean
git clean -df
yarn lint
- run:
@@ -1075,12 +1076,14 @@ jobs:
# run unit tests from each individual package
- run: yarn test
- verify-mocha-results:
expectedResultCount: 9
expectedResultCount: 10
- store_test_results:
path: /tmp/cypress
# CLI tests generate HTML files with sample CLI command output
- store_artifacts:
path: cli/test/html
- store_artifacts:
path: packages/errors/__snapshot-images__
- store-npm-logs
unit-tests-release:
@@ -1913,13 +1916,6 @@ jobs:
repo: cypress-example-kitchensink
browser: "electron"
test-binary-against-awesome-typescript-loader:
<<: *defaults
steps:
- test-binary-against-repo:
repo: cypress-test-awesome-typescript-loader
browser: "electron"
test-binary-against-kitchensink-firefox:
<<: *defaults
resource_class: medium
@@ -1944,33 +1940,6 @@ jobs:
repo: cypress-example-todomvc
browser: firefox
test-binary-against-conduit-chrome:
<<: *defaults
resource_class: medium
steps:
- test-binary-against-repo:
repo: cypress-example-conduit-app
browser: chrome
command: "npm run cypress:run"
wait-on: http://localhost:3000
test-binary-against-api-testing-firefox:
<<: *defaults
steps:
- test-binary-against-repo:
repo: cypress-example-api-testing
browser: firefox
command: "npm run cy:run"
test-binary-against-piechopper-firefox:
<<: *defaults
resource_class: medium
steps:
- test-binary-against-repo:
repo: cypress-example-piechopper
browser: firefox
command: "npm run cypress:run"
test-binary-against-cypress-realworld-app:
<<: *defaults
resource_class: medium+
@@ -2239,26 +2208,6 @@ linux-workflow: &linux-workflow
- test-binary-against-kitchensink:
requires:
- create-build-artifacts
# when working on a feature or a fix,
# you are probably working in a branch
# and you want to run a specific PR in the cypress-example-recipes
# against this branch. This workflow job includes
# the job but only when it runs on specific branch
# DO NOT DELETE THIS JOB BEFORE MERGING TO DEVELOP
# on "develop" this branch will be ignored anyway
# and someone else might use this job definition for another
# feature branch and would just update the branch filter
# - test-binary-against-recipe-pull-request:
# name: Test cypress run parsing
# filters:
# branches:
# only:
# - cli-to-module-api-7760
# requires:
# - create-build-artifacts
- test-binary-against-awesome-typescript-loader:
requires:
- create-build-artifacts
- test-binary-and-npm-against-other-projects:
context: test-runner:trigger-test-jobs
<<: *mainBuildFilters
@@ -2278,12 +2227,7 @@ linux-workflow: &linux-workflow
<<: *mainBuildFilters
requires:
- create-build-artifacts
# Re-enable when the cypress-example-conduit-app project is fixed.
# https://github.com/cypress-io/cypress-example-conduit-app/issues/346
# - test-binary-against-conduit-chrome:
# <<: *mainBuildFilters
# requires:
# - create-build-artifacts
- test-binary-against-recipes-firefox:
<<: *mainBuildFilters
requires:
@@ -2296,14 +2240,6 @@ linux-workflow: &linux-workflow
<<: *mainBuildFilters
requires:
- create-build-artifacts
- test-binary-against-api-testing-firefox:
<<: *mainBuildFilters
requires:
- create-build-artifacts
- test-binary-against-piechopper-firefox:
<<: *mainBuildFilters
requires:
- create-build-artifacts
- test-binary-against-cypress-realworld-app:
<<: *mainBuildFilters
requires:
@@ -2359,19 +2295,6 @@ mac-workflow: &mac-workflow
requires:
- darwin-build
- test-binary-against-kitchensink:
name: darwin-test-binary-against-kitchensink
executor: mac
requires:
- darwin-create-build-artifacts
- test-binary-against-staging:
context: test-runner:record-tests
name: darwin-test-binary-against-staging
executor: mac
requires:
- darwin-create-build-artifacts
- test-binary-and-npm-against-other-projects:
context: test-runner:trigger-test-jobs
name: darwin-test-binary-and-npm-against-other-projects
@@ -2399,14 +2322,14 @@ windows-workflow: &windows-workflow
executor: windows
requires:
- windows-build
- unit-tests:
name: windows-unit-tests
executor: windows
resource_class: windows.medium
requires:
- windows-build
- create-build-artifacts:
name: windows-create-build-artifacts
executor: windows
+85
View File
@@ -0,0 +1,85 @@
## Error Handling in Cypress
Clear, consistent, errors are one of the important parts of the Cypress experience. When something goes wrong, there should be clear, actionable feedback for the user about exactly *what* went wrong, *where* it went wrong, and next steps on how to fix.
### @packages/errors
All error related logic for the server should be added to `@packages/errors`. This logic has been separated out from the `@packages/server` to enable strict type checking & use in other packages we have added in the `10.0-release` branch.
Summary of the Errors package:
- `errors.ts`: A key/value mapping of known errors to functions returning "ErrorTemplates", described below, also includes/re-exports several helper utilities:
- `get` / `getError`: builds & retrieves the error as a `CypressError`, should be the main way we retrieve errors throughout Cypress. Aliased as `errors.get` for existing use in the server package
- `throw` / `throwErr`: Get & throw the error, so we can spy/stub it in a test. Aliased as `errors.throw` for existing use in the server package
- `logWarning`: Logs the error as a warning to the console, aliased as `errors.log` for existing use in the server package
- `errTemplate.ts`: Tagged template literal formatting the error as described below
- `stackUtils.ts`: Utilities for working with a stack trace, extended by the driver package
### errTemplate
The `errTemplate` is a tagged template literal. It allows us to maintain consistent behavior & formatting in our error messages, when we see a variable, we format it depending on the target environment.
The error message returns a message that defaults to being formatted for the terminal, and has a `forBrowser` method which returns the error message where the variables are wrapped in backticks '`' for Markdown display in the browser.
Return Value of `errTemplate` (`ErrTemplateResult`):
```ts
{
// Will always exist, this is the terminal-formatted error message
message: string,
// Will always exist, this is the browser-formatted error message
messageMarkdown: string,
details?: string, // Exists if there is `details()` call in the errTemplate
originalError?: ErrorLike // Exists if an error was passed into the `details()`
}
```
#### Example:
```ts
CANNOT_TRASH_ASSETS: (arg1: string) => {
return errTemplate`\
Warning: We failed to trash the existing run results.
This error will not alter the exit code.
${details(arg1)}`
},
```
In this case, `arg1` will be highlighted in yellow when printed to the terminal.
```ts
PLUGINS_FILE_ERROR: (arg1: string, arg2: Error) => {
return errTemplate`\
The plugins file is missing or invalid.
Your \`pluginsFile\` is set to ${arg1}, but either the file is missing, it contains a syntax error, or threw an error when required. The \`pluginsFile\` must be a \`.js\`, \`.ts\`, or \`.coffee\` file.
Or you might have renamed the extension of your \`pluginsFile\`. If that's the case, restart the test runner.
Please fix this, or set \`pluginsFile\` to \`false\` if a plugins file is not necessary for your project.
${details(arg2)}
`
},
```
`arg1` will be highlighted in `blue` for the terminal, and wrapped in backticks when called with `forBrowser`. Details will be printed in `yellow` as a stack trace when printed to the terminal, or shown as a stack-trace in the browser.
### Error Wrapping
Any time we know about an edge case that is an error, we should define an error in `errors.ts`. This error should be retrieved by `getError`, which converts it to a `CypressError`.
The `CypressError` is an `Error` containing the message returned from the `errTemplate`. The `stack` is set to that of the `originalError` if it exists (i.e. the error object passed into `details`), otherwise it's the `stack` from where the `getError` / `throwError` is called.
The `CypressError` has an `isCypressErr` prop which we use as a duck-type guard against exiting the process when logging exceptions. It also maintains a reference to the `originalError` if it exists.
### Child-Process Errors
All errors that occur in a child process spawned by Cypress should be sent over the `ipc` bridge using `util.serializeError`.
This ensures the `name`, `message`, `stack`, and any other relevant details are preserved and can be handled by the standard process of Cypress' error standardization / wrapping.
+7
View File
@@ -1,3 +1,10 @@
# [@cypress/react-v5.12.2](https://github.com/cypress-io/cypress/compare/@cypress/react-v5.12.1...@cypress/react-v5.12.2) (2022-02-08)
### Bug Fixes
* remove nullish coalescing in js files to support node 12 ([#20094](https://github.com/cypress-io/cypress/issues/20094)) ([dd11945](https://github.com/cypress-io/cypress/commit/dd11945f5330c14e1540133187415f341794d6f6))
# [@cypress/react-v5.12.1](https://github.com/cypress-io/cypress/compare/@cypress/react-v5.12.0...@cypress/react-v5.12.1) (2022-01-10)
@@ -2,7 +2,7 @@
const path = require('path')
function getTranspileFolders (config) {
const rawFolders = config.addTranspiledFolders ?? []
const rawFolders = config.addTranspiledFolders || []
const folders = rawFolders.map((folder) => path.resolve(config.projectRoot, folder))
// user can disable folders, so check first
+2 -2
View File
@@ -56,8 +56,8 @@ Install `@cypress/vue` or `@cypress/react` to get this package working properly
- The HTML page calls a script that loads support file and the specs using a native `import()` function
- Then triggers the loaded tests
Vite is reponsible for compiling and bundling all the files. We use its error overlay to display any transpiling error.
Omly runtime errors have to be handled through cypress
Vite is responsible for compiling and bundling all the files. We use its error overlay to display any transpiling error.
Only runtime errors have to be handled through cypress
## Changelog
@@ -1,15 +1,15 @@
// This file is merged in a <script type=module> into index.html
// it will be used to load and kick start the selected spec
const supportPath = import.meta.env.__cypress_supportPath
const originAutUrl = import.meta.env.__cypress_originAutUrl
import specLoaders from 'cypress:spec-loaders'
import { hasSupportPath, originAutUrl } from 'cypress:config'
const specPath = window.location.pathname.replace(originAutUrl, '')
const importsToLoad = [() => import(/* @vite-ignore */ specPath)]
const specLoader = specLoaders[specPath]
const importsToLoad = [specLoader || (() => import(/* @vite-ignore */ specPath))]
if (supportPath) {
importsToLoad.unshift(() => import(/* @vite-ignore */ supportPath))
if (hasSupportPath) {
importsToLoad.unshift(() => import('cypress:support-path'))
}
const CypressInstance = window.Cypress = parent.Cypress
@@ -46,3 +46,4 @@ CypressInstance.on('test:before:run', () => {
// Make usage of node test plugins possible
window.global = window
window.process = typeof process !== 'undefined' ? process : {}
+14 -6
View File
@@ -1,19 +1,27 @@
import { debug as debugFn } from 'debug'
import { InlineConfig } from 'vite'
import { start as createDevServer, StartDevServerOptions } from './startServer'
import { createServer, InlineConfig } from 'vite'
import { resolveServerConfig, StartDevServerOptions } from './resolveServerConfig'
const debug = debugFn('cypress:vite-dev-server:vite')
export { StartDevServerOptions }
export async function startDevServer (startDevServerArgs: StartDevServerOptions): Promise<Cypress.ResolvedDevServerConfig> {
const viteDevServer = await createDevServer(startDevServerArgs)
if (!startDevServerArgs.viteConfig) {
debug('User did not pass in any Vite dev server configuration')
startDevServerArgs.viteConfig = {}
}
const app = await viteDevServer.listen()
const port = app.config.server.port!
debug('starting vite dev server')
const resolvedConfig = await resolveServerConfig(startDevServerArgs)
const port = resolvedConfig.server!.port!
const viteDevServer = await createServer(resolvedConfig)
await viteDevServer.listen()
debug('Component testing vite server started on port', port)
return { port, close: app.httpServer!.close }
return { port, close: viteDevServer.close }
}
export type CypressViteDevServerConfig = Omit<InlineConfig, 'base' | 'root'>
+43 -30
View File
@@ -1,13 +1,10 @@
import { resolve, sep } from 'path'
import { readFile } from 'fs'
import { promisify } from 'util'
import { readFile } from 'fs/promises'
import Debug from 'debug'
import { ModuleNode, Plugin, ViteDevServer } from 'vite'
import { ModuleNode, normalizePath, Plugin, ViteDevServer } from 'vite'
const debug = Debug('cypress:vite-dev-server:plugin')
const read = promisify(readFile)
const pluginName = 'cypress-transform-html'
const OSSepRE = new RegExp(`\\${sep}`, 'g')
@@ -48,40 +45,56 @@ export const makeCypressPlugin = (
const posixSupportFilePath = supportFilePath ? convertPathToPosix(resolve(projectRoot, supportFilePath)) : undefined
const normalizedSupportFilePath = posixSupportFilePath ? `${base}@fs/${posixSupportFilePath}` : undefined
return {
name: pluginName,
enforce: 'pre',
config (_, env) {
if (env) {
return {
define: {
'import.meta.env.__cypress_supportPath': JSON.stringify(normalizedSupportFilePath),
'import.meta.env.__cypress_originAutUrl': JSON.stringify(`__cypress/iframes/${convertPathToPosix(projectRoot)}/`),
},
}
}
},
configResolved (config) {
base = config.base
},
transformIndexHtml () {
debug('transformIndexHtml with base', base)
async transformIndexHtml () {
const indexHtmlPath = resolve(__dirname, '..', 'index.html')
const indexHtmlContent = await readFile(indexHtmlPath, { encoding: 'utf8' })
// find </body> last index
const endOfBody = indexHtmlContent.lastIndexOf('</body>')
return [
// load the script at the end of the body
// script has to be loaded when the vite client is connected
{
tag: 'script',
injectTo: 'body',
attrs: { type: 'module' },
children: `import(${JSON.stringify(`${base}@fs/${INIT_FILEPATH}`)})`,
},
]
// insert the script in the end of the body
return `${indexHtmlContent.substring(0, endOfBody)
}<script src="${base}cypress:client-init-test" type="module"></script>${
indexHtmlContent.substring(endOfBody)
}`
},
resolveId (id) {
if (id === 'cypress:config') {
return id
}
if (id === 'cypress:support-path') {
return posixSupportFilePath
}
if (id === 'cypress:spec-loaders') {
return id
}
if (id === '/cypress:client-init-test') {
return INIT_FILEPATH
}
},
load (id) {
if (id === 'cypress:spec-loaders') {
return `export default {\n${specs.map((s) => {
return `${JSON.stringify(s.relative)}:()=>import(${JSON.stringify(s.absolute)})`
}).join(',\n')}\n}`
}
if (id === 'cypress:config') {
return `
export const hasSupportPath = ${JSON.stringify(!!supportFilePath)}
export const originAutUrl = ${JSON.stringify(`/__cypress/iframes/${normalizePath(projectRoot)}/`)}`
}
},
configureServer: async (server: ViteDevServer) => {
const indexHtml = await read(resolve(__dirname, '..', 'index.html'), { encoding: 'utf8' })
const indexHtml = await readFile(resolve(__dirname, '..', 'index.html'), { encoding: 'utf8' })
const transformedIndexHtml = await server.transformIndexHtml(base, indexHtml)
@@ -20,7 +20,7 @@ export interface StartDevServerOptions {
viteConfig?: Omit<InlineConfig, 'base' | 'root'>
}
const resolveServerConfig = async ({ viteConfig, options }: StartDevServerOptions): Promise<InlineConfig> => {
export const resolveServerConfig = async ({ viteConfig, options }: StartDevServerOptions): Promise<InlineConfig> => {
const { projectRoot, supportFile } = options.config
const requiredOptions: InlineConfig = {
@@ -74,15 +74,3 @@ const resolveServerConfig = async ({ viteConfig, options }: StartDevServerOption
return finalConfig
}
export async function start (devServerOptions: StartDevServerOptions): Promise<ViteDevServer> {
if (!devServerOptions.viteConfig) {
debug('User did not pass in any Vite dev server configuration')
devServerOptions.viteConfig = {}
}
debug('starting vite dev server')
const resolvedConfig = await resolveServerConfig(devServerOptions)
return createServer(resolvedConfig)
}
+4 -7
View File
@@ -1,12 +1,9 @@
module.exports = {
...require('../../.releaserc.base'),
branches: [
// we need to keep this branch in here even if no used because semantic-release demands
// that we have at least one branch that has no config
'next/npm/vue',
// this line forces releasing 2.X releases on the latest channel
{ name: 'npm/vue/v2', range: '2.X.X' },
// this one releases v3 on master as beta on the next channel
{ name: 'master', channel: 'next' },
// this one releases v3 on master on the latest channel
'master',
// this line forces releasing 2.X releases on the v2 channel
{ name: 'npm/vue/v2', range: '2.X.X', channel: 'v2' },
],
}
+2 -17
View File
@@ -24,7 +24,7 @@ It uses [Vue Test Utils](https://github.com/vuejs/vue-test-utils) under the hood
- Requires Cypress v7.0.0 or later
- Requires [Node](https://nodejs.org/en/) version 12 or above
- Supports webpack-based projects, vite in alpha, if you would like us to support another, please [create an issue](https://github.com/cypress-io/cypress/issues/new?assignees=&labels=npm:%20@cypress/vue&template=3-feature.md) or, if an issue already exists subscribe to it.
- Supports projects built with Vue CLI, Vite, and Webpack. If you would like us to support another build configuration, please [create an issue](https://github.com/cypress-io/cypress/issues/new?assignees=&labels=npm:%20@cypress/vue&template=3-feature.md).
Now you are ready to install.
@@ -61,8 +61,7 @@ module.exports = (on) => {
Install dev dependencies
```shell
npm i -D @cypress/webpack-dev-server \
vue-loader vue-template-compiler css-loader
npm i -D @cypress/webpack-dev-server @cypress/vue
```
And write a test
@@ -617,20 +616,6 @@ yarn workspace @cypress/vue cy:open
Larger tests that use full application and run on CI (see [circle.yml](circle.yml)) are located in the folder [examples](examples).
### Debugging
Run Cypress with environment variable
```
DEBUG=@cypress/vue
```
If some deeply nested objects are abbreviated and do not print fully, set the maximum logging depth
```
DEBUG=@cypress/vue DEBUG_DEPTH=10
```
## Related info
- [Testing Vue web applications with Vuex data store & REST backend](https://www.cypress.io/blog/2017/11/28/testing-vue-web-application-with-vuex-data-store-and-rest-backend/)
+7
View File
@@ -1,3 +1,10 @@
# [@cypress/webpack-dev-server-v1.8.1](https://github.com/cypress-io/cypress/compare/@cypress/webpack-dev-server-v1.8.0...@cypress/webpack-dev-server-v1.8.1) (2022-02-08)
### Bug Fixes
* detect newly added specs in dev-server compilation ([#17950](https://github.com/cypress-io/cypress/issues/17950)) ([f9ce67c](https://github.com/cypress-io/cypress/commit/f9ce67cfb6fed74a3549e7aff7ce0a5b217d9a13))
# [@cypress/webpack-dev-server-v1.8.0](https://github.com/cypress-io/cypress/compare/@cypress/webpack-dev-server-v1.7.0...@cypress/webpack-dev-server-v1.8.0) (2021-12-16)
+1 -1
View File
@@ -6,7 +6,7 @@
"scripts": {
"build": "tsc",
"build-prod": "tsc",
"test": "node ./test-wds-3.js",
"test": "node ./test-deps.js",
"test-all": "tsc && mocha -r @packages/ts/register test/**/*.spec.ts test/*.spec.ts --exit",
"watch": "tsc -w"
},
+1
View File
@@ -20,6 +20,7 @@ export async function startDevServer (startDevServerArgs: StartDevServer, exitPr
return new Promise<ResolvedDevServerConfig>(async (resolve, reject) => {
if (webpackDevServerFacts.isV3()) {
// @ts-ignore
const server: Server = webpackDevServer.listen(0, '127.0.0.1', () => {
// FIXME: handle address returning a string
const port = (server.address() as AddressInfo).port
+6 -1
View File
@@ -5,6 +5,7 @@ import debugFn from 'debug'
import * as path from 'path'
import { CypressCTWebpackContext } from './plugin'
const debug = debugFn('cypress:webpack-dev-server:webpack')
import type { LoaderContext } from 'webpack'
/**
* @param {ComponentSpec} file spec to create import string from.
@@ -49,7 +50,11 @@ function buildSpecs (projectRoot: string, files: Cypress.Cypress['spec'][] = [])
}
// Runs the tests inside the iframe
export default function loader (this: CypressCTWebpackContext) {
export default function loader (this: CypressCTWebpackContext & LoaderContext<void>) {
// In Webpack 5, a spec added after the dev-server is created won't
// be included in the compilation. Disabling the caching of this loader ensures
// we regenerate our specs and include any new ones in the compilation.
this.cacheable(false)
const { files, projectRoot, supportFile } = this._cypress
const supportFileAbsolutePath = supportFile ? JSON.stringify(path.resolve(projectRoot, supportFile)) : undefined
+1 -1
View File
@@ -83,7 +83,7 @@ export async function start ({ webpackConfig: userWebpackConfig, template, optio
hot: false,
}
// @ts-expect-error Webpack types are clashing between Webpack and WebpackDevServer
// @ts-ignore Webpack types are clashing between Webpack and WebpackDevServer
return new WebpackDevServer(webpackDevServerConfig, compiler)
}
+79
View File
@@ -0,0 +1,79 @@
const execa = require('execa')
const pkg = require('./package.json')
const fs = require('fs')
/**
* This file installs dependencies that we support but don't have coverage for.
* We read package.json, update the dependency, then re-run yarn install.
* After it finishes, pass or fail,
* we revert the package.json back to the original state.
*/
const main = async () => {
const depsToTest = [
[
{
name: 'webpack-dev-server',
version: '3.11.0',
type: 'devDependencies',
},
],
[
{ name: 'webpack', version: '5.53.0', type: 'devDependencies' },
{
name: 'html-webpack-plugin',
version: '5.3.2',
type: 'devDependencies',
},
],
]
const originalPkg = JSON.stringify(pkg, null, 2)
const install = () => execa('yarn', ['install', '--ignore-scripts'], { stdio: 'inherit' })
const exit = async (exitCode) => {
fs.writeFileSync('package.json', originalPkg, 'utf8')
await install()
process.exit(exitCode)
}
for (const deps of depsToTest) {
const pkg = JSON.parse(originalPkg)
const depsInfo = JSON.stringify(deps)
deps.forEach(({ type, name, version }) => (pkg[type][name] = version))
// eslint-disable-next-line no-console
console.log('[@cypress/webpack-dev-server]: updating package.json...')
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2), 'utf8')
// eslint-disable-next-line no-console
console.log('[@cypress/webpack-dev-server]: install dependencies...')
await install()
// eslint-disable-next-line no-console
console.log(
`[@cypress/webpack-dev-server]: Testing with deps: ${depsInfo}`,
)
const { exitCode } = await execa('yarn', ['test-all'], {
stdio: 'inherit',
})
if (typeof exitCode !== 'number') {
// eslint-disable-next-line no-console
console.error(
`Testing with deps: ${depsInfo} finished with missing exit code from execa (received ${exitCode})`,
)
}
if (exitCode !== 0) {
exit(exitCode)
}
}
exit(0)
}
// execute main function if called from command line
if (require.main === module) {
main()
}
-49
View File
@@ -1,49 +0,0 @@
const execa = require('execa')
const pkg = require('./package.json')
const fs = require('fs')
/**
* This file installs WebpackDevServer 3 and runs the tests for the dev-server.
* We read package.json, update the webpack version, then re-run yarn install.
* After it finishes, pass or fail,
* we revert the package.json back to the original state.
*
* The tests for the example projects (inside of examples) run with WebpackDevServer 3.
* This ensures we have some coverage for both versions.
*/
const main = async () => {
const originalPkg = JSON.stringify(pkg, null, 2)
const resetPkg = async () => {
fs.writeFileSync('package.json', originalPkg, 'utf8')
await execa('yarn', ['install'], { stdio: 'inherit' })
}
const checkExit = async ({ exitCode }) => {
if (typeof exitCode !== 'number') {
// eslint-disable-next-line no-console
console.error(`Finished with missing exit code from execa (received ${exitCode})`)
}
await resetPkg()
process.exit(exitCode)
}
pkg.devDependencies['webpack-dev-server'] = '3.11.0'
// eslint-disable-next-line no-console
console.log('[@cypress/webpack-dev-server]: updating package.json...')
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2))
// eslint-disable-next-line no-console
console.log('[@cypress/webpack-dev-server]: install dependencies...')
await execa('yarn', ['install'], { stdio: 'inherit' })
const { exitCode } = await execa('yarn', ['test-all'], { stdio: 'inherit' })
await checkExit({ exitCode })
}
// execute main function if called from command line
if (require.main === module) {
main()
}
+21 -10
View File
@@ -118,7 +118,10 @@ describe('#startDevServer', () => {
return new Promise((res) => {
devServerEvents.on('dev-server:compile:error', (err: string) => {
expect(err).to.contain('./test/fixtures/compilation-fails.spec.js 1:5')
if (webpackDevServerFacts.isV3()) {
expect(err).to.contain('./test/fixtures/compilation-fails.spec.js 1:5')
}
expect(err).to.contain('Module parse failed: Unexpected token (1:5)')
expect(err).to.contain('You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders')
expect(err).to.contain('> this is an invalid spec file')
@@ -128,7 +131,7 @@ describe('#startDevServer', () => {
})
})
it('touches browser.js when a spec file is added', async function () {
it('touches browser.js when a spec file is added and recompile', async function () {
const devServerEvents = new EventEmitter()
const { close } = await startDevServer({
webpackConfig,
@@ -140,19 +143,27 @@ describe('#startDevServer', () => {
})
const newSpec: Cypress.Cypress['spec'] = {
name: './some-newly-created-spec.js',
relative: './some-newly-created-spec.js',
absolute: '/some-newly-created-spec.js',
name: `${root}/test/fixtures/bar.spec.js`,
relative: `${root}/test/fixtures/bar.spec.js`,
absolute: `${root}/test/fixtures/bar.spec.js`,
}
const oldmtime = fs.statSync('./dist/browser.js').mtimeMs
return new Promise((res) => {
devServerEvents.emit('dev-server:specs:changed', [newSpec])
const updatedmtime = fs.statSync('./dist/browser.js').mtimeMs
let firstCompile = true
expect(oldmtime).to.not.equal(updatedmtime)
close(() => res())
return new Promise((res) => {
devServerEvents.on('dev-server:compile:success', () => {
if (firstCompile) {
firstCompile = false
devServerEvents.emit('dev-server:specs:changed', [newSpec])
const updatedmtime = fs.statSync('./dist/browser.js').mtimeMs
expect(oldmtime).to.not.equal(updatedmtime)
} else {
close(() => res())
}
})
})
})
+1
View File
@@ -0,0 +1 @@
const bar = () => {}
+7
View File
@@ -1,3 +1,10 @@
# [@cypress/webpack-preprocessor-v5.11.1](https://github.com/cypress-io/cypress/compare/@cypress/webpack-preprocessor-v5.11.0...@cypress/webpack-preprocessor-v5.11.1) (2022-02-08)
### Bug Fixes
* detect newly added specs in dev-server compilation ([#17950](https://github.com/cypress-io/cypress/issues/17950)) ([f9ce67c](https://github.com/cypress-io/cypress/commit/f9ce67cfb6fed74a3549e7aff7ce0a5b217d9a13))
# [@cypress/webpack-preprocessor-v5.11.0](https://github.com/cypress-io/cypress/compare/@cypress/webpack-preprocessor-v5.10.0...@cypress/webpack-preprocessor-v5.11.0) (2021-12-16)
+3 -3
View File
@@ -44,9 +44,9 @@ module.exports = (on) => {
## Examples
- [React app](examples/react-app) shows how to point Cypress at Webpack configuration from `react-scripts` dependency
- [use-babelrc](examples/use-babelrc) shows how to use your project's `.babelrc` with Webpack
- [use-ts-loader](examples/use-ts-loader) shows how to transpile TypeScript specs following [Webpack TypeScript guide](https://webpack.js.org/guides/typescript/)
- [React app](https://github.com/cypress-io/cypress/tree/develop/npm/webpack-preprocessor/examples/react-app) shows how to point Cypress at Webpack configuration from `react-scripts` dependency
- [use-babelrc](https://github.com/cypress-io/cypress/tree/develop/npm/webpack-preprocessor/examples/use-babelrc) shows how to use your project's `.babelrc` with Webpack
- [use-ts-loader](https://github.com/cypress-io/cypress/tree/develop/npm/webpack-preprocessor/examples/use-ts-loader) shows how to transpile TypeScript specs following [Webpack TypeScript guide](https://webpack.js.org/guides/typescript/)
## Options
+4 -2
View File
@@ -14,9 +14,11 @@ const fs = require('fs')
const main = async () => {
const originalPkg = JSON.stringify(pkg, null, 2)
const install = () => execa('yarn', ['install', '--ignore-scripts'], { stdio: 'inherit' })
const resetPkg = async () => {
fs.writeFileSync('package.json', originalPkg, 'utf8')
await execa('yarn', ['install'], { stdio: 'inherit' })
await install()
}
const checkExit = async ({ exitCode, step }) => {
@@ -40,7 +42,7 @@ const main = async () => {
// eslint-disable-next-line no-console
console.log('[@cypress/webpack-preprocessor]: install dependencies...')
await execa('yarn', ['install'], { stdio: 'inherit' })
await install()
const unit = await execa('yarn', ['test-unit'], { stdio: 'inherit' })
+5 -4
View File
@@ -17,15 +17,17 @@
"bump": "node ./scripts/binary.js bump",
"check-node-version": "node scripts/check-node-version.js",
"check-terminal": "node scripts/check-terminal.js",
"clean": "lerna run clean --parallel --no-bail",
"clean": "lerna run clean --parallel --no-bail || echo 'ok, errors while cleaning'",
"clean-deps": "find . -depth -name node_modules -type d -exec rm -rf {} \\;",
"clean-untracked-files": "git clean -d -f",
"precypress:open": "yarn ensure-deps",
"cypress:open": "cypress open --dev --global",
"cypress:open:ct": "cypress open-ct --dev --global",
"precypress:open:debug": "yarn ensure-deps",
"cypress:open:debug": "node ./scripts/debug.js cypress:open",
"precypress:run": "yarn ensure-deps",
"cypress:run": "cypress run --dev",
"cypress:run:ct": "cypress run-ct --dev",
"precypress:run:debug": "yarn ensure-deps",
"cypress:run:debug": "node ./scripts/debug.js cypress:run",
"cypress:verify": "cypress verify --dev",
@@ -46,7 +48,7 @@
"stop-only": "npx stop-only --skip .cy,.publish,.projects,node_modules,dist,dist-test,fixtures,lib,bower_components,src,__snapshots__ --exclude e2e.ts,cypress-tests.ts,*only_spec.js",
"stop-only-all": "yarn stop-only --folder packages",
"pretest": "yarn ensure-deps",
"test": "yarn lerna exec yarn test --scope cypress --scope \"'@packages/{config,electron,extension,https-proxy,launcher,net-stubbing,network,proxy,rewriter,runner,runner-shared,socket}'\"",
"test": "yarn lerna exec yarn test --scope cypress --scope \"'@packages/{config,errors,electron,extension,https-proxy,launcher,net-stubbing,network,proxy,rewriter,runner,runner-shared,socket}'\"",
"test-debug": "lerna exec yarn test-debug --ignore \"'@packages/{desktop-gui,driver,root,static,web-config}'\"",
"pretest-e2e": "yarn ensure-deps",
"test-integration": "lerna exec yarn test-integration --ignore \"'@packages/{desktop-gui,driver,root,static,web-config}'\"",
@@ -103,7 +105,6 @@
"@types/sinon-chai": "3.2.3",
"@typescript-eslint/eslint-plugin": "4.18.0",
"@typescript-eslint/parser": "4.18.0",
"ansi-styles": "3.2.1",
"arg": "4.1.2",
"ascii-table": "0.0.9",
"aws-sdk": "2.814.0",
@@ -181,7 +182,7 @@
"snap-shot-it": "7.9.3",
"start-server-and-test": "1.10.8",
"stop-only": "3.0.1",
"strip-ansi": "4.0.0",
"strip-ansi": "6.0.0",
"term-to-html": "1.2.0",
"terminal-banner": "1.1.0",
"through": "2.3.8",
+143 -74
View File
@@ -6,73 +6,113 @@ exports['empty list of browsers'] = `
Expected at least one browser
`
exports['browsers list with a string'] = `
Found an error while validating the \`browsers\` list. Expected \`name\` to be a non-empty string. Instead the value was: \`"foo"\`
`
exports['browsers list with a string'] = {
"key": "name",
"value": "foo",
"type": "a non-empty string",
"list": "browsers"
}
exports['not one of the strings error message'] = `
Expected \`test\` to be one of these values: "foo", "bar". Instead the value was: \`"nope"\`
`
exports['not one of the strings error message'] = {
"key": "test",
"value": "nope",
"type": "one of these values: \"foo\", \"bar\""
}
exports['number instead of string'] = `
Expected \`test\` to be one of these values: "foo", "bar". Instead the value was: \`42\`
`
exports['number instead of string'] = {
"key": "test",
"value": 42,
"type": "one of these values: \"foo\", \"bar\""
}
exports['null instead of string'] = `
Expected \`test\` to be one of these values: "foo", "bar". Instead the value was: \`null\`
`
exports['null instead of string'] = {
"key": "test",
"value": null,
"type": "one of these values: \"foo\", \"bar\""
}
exports['not one of the numbers error message'] = `
Expected \`test\` to be one of these values: 1, 2, 3. Instead the value was: \`4\`
`
exports['not one of the numbers error message'] = {
"key": "test",
"value": 4,
"type": "one of these values: 1, 2, 3"
}
exports['string instead of a number'] = `
Expected \`test\` to be one of these values: 1, 2, 3. Instead the value was: \`"foo"\`
`
exports['string instead of a number'] = {
"key": "test",
"value": "foo",
"type": "one of these values: 1, 2, 3"
}
exports['null instead of a number'] = `
Expected \`test\` to be one of these values: 1, 2, 3. Instead the value was: \`null\`
`
exports['null instead of a number'] = {
"key": "test",
"value": null,
"type": "one of these values: 1, 2, 3"
}
exports['not string or array'] = `
Expected \`mockConfigKey\` to be a string or an array of strings. Instead the value was: \`null\`
`
exports['not string or array'] = {
"key": "mockConfigKey",
"value": null,
"type": "a string or an array of strings"
}
exports['array of non-strings'] = `
Expected \`mockConfigKey\` to be a string or an array of strings. Instead the value was: \`[1,2,3]\`
`
exports['array of non-strings'] = {
"key": "mockConfigKey",
"value": [
1,
2,
3
],
"type": "a string or an array of strings"
}
exports['invalid retry value'] = `
Expected \`mockConfigKey\` to be a positive number or null or an object with keys "openMode" and "runMode" with values of numbers or nulls. Instead the value was: \`"1"\`
`
exports['invalid retry value'] = {
"key": "mockConfigKey",
"value": "1",
"type": "a positive number or null or an object with keys \"openMode\" and \"runMode\" with values of numbers or nulls"
}
exports['invalid retry object'] = `
Expected \`mockConfigKey\` to be a positive number or null or an object with keys "openMode" and "runMode" with values of numbers or nulls. Instead the value was: \`{"fakeMode":1}\`
`
exports['invalid retry object'] = {
"key": "mockConfigKey",
"value": {
"fakeMode": 1
},
"type": "a positive number or null or an object with keys \"openMode\" and \"runMode\" with values of numbers or nulls"
}
exports['missing https protocol'] = `
Expected \`clientCertificates[0].url\` to be an https protocol. Instead the value was: \`"http://url.com"\`
`
exports['missing https protocol'] = {
"key": "clientCertificates[0].url",
"value": "http://url.com",
"type": "an https protocol"
}
exports['invalid url'] = `
Expected \`clientCertificates[0].url\` to be a valid URL. Instead the value was: \`"not *"\`
`
exports['invalid url'] = {
"key": "clientCertificates[0].url",
"value": "not *",
"type": "a valid URL"
}
exports['not qualified url'] = `
Expected \`mockConfigKey\` to be a fully qualified URL (starting with \`http://\` or \`https://\`). Instead the value was: \`"url.com"\`
`
exports['not qualified url'] = {
"key": "mockConfigKey",
"value": "url.com",
"type": "a fully qualified URL (starting with `http://` or `https://`)"
}
exports['empty string'] = `
Expected \`mockConfigKey\` to be a fully qualified URL (starting with \`http://\` or \`https://\`). Instead the value was: \`""\`
`
exports['empty string'] = {
"key": "mockConfigKey",
"value": "",
"type": "a fully qualified URL (starting with `http://` or `https://`)"
}
exports['config/lib/validation .isValidClientCertificatesSet returns error message for certs not passed as an array array 1'] = `
Expected \`mockConfigKey\` to be a positive number or null or an object with keys "openMode" and "runMode" with values of numbers or nulls. Instead the value was: \`"1"\`
`
exports['config/lib/validation .isValidClientCertificatesSet returns error message for certs not passed as an array array 1'] = {
"key": "mockConfigKey",
"value": "1",
"type": "a positive number or null or an object with keys \"openMode\" and \"runMode\" with values of numbers or nulls"
}
exports['config/lib/validation .isValidClientCertificatesSet returns error message for certs object without url 1'] = `
Expected \`clientCertificates[0].url\` to be a URL matcher. Instead the value was: \`undefined\`
`
exports['config/lib/validation .isValidClientCertificatesSet returns error message for certs object without url 1'] = {
"key": "clientCertificates[0].url",
"type": "a URL matcher"
}
exports['config/lib/validation .isValidBrowser passes valid browsers and forms error messages for invalid ones isValidBrowser 1'] = {
"name": "isValidBrowser",
@@ -115,7 +155,14 @@ exports['config/lib/validation .isValidBrowser passes valid browsers and forms e
"name": "No display name",
"family": "chromium"
},
"expect": "Expected `displayName` to be a non-empty string. Instead the value was: `{\"name\":\"No display name\",\"family\":\"chromium\"}`"
"expect": {
"key": "displayName",
"value": {
"name": "No display name",
"family": "chromium"
},
"type": "a non-empty string"
}
},
{
"given": {
@@ -123,35 +170,57 @@ exports['config/lib/validation .isValidBrowser passes valid browsers and forms e
"displayName": "Bad family browser",
"family": "unknown family"
},
"expect": "Expected `family` to be either chromium or firefox. Instead the value was: `{\"name\":\"bad family\",\"displayName\":\"Bad family browser\",\"family\":\"unknown family\"}`"
"expect": {
"key": "family",
"value": {
"name": "bad family",
"displayName": "Bad family browser",
"family": "unknown family"
},
"type": "either chromium or firefox"
}
}
]
}
exports['config/lib/validation .isPlainObject returns error message when value is a not an object 1'] = `
Expected \`mockConfigKey\` to be a plain object. Instead the value was: \`1\`
`
exports['config/lib/validation .isPlainObject returns error message when value is a not an object 1'] = {
"key": "mockConfigKey",
"value": 1,
"type": "a plain object"
}
exports['config/lib/validation .isNumber returns error message when value is a not a number 1'] = `
Expected \`mockConfigKey\` to be a number. Instead the value was: \`"string"\`
`
exports['config/lib/validation .isNumber returns error message when value is a not a number 1'] = {
"key": "mockConfigKey",
"value": "string",
"type": "a number"
}
exports['config/lib/validation .isNumberOrFalse returns error message when value is a not number or false 1'] = `
Expected \`mockConfigKey\` to be a number or false. Instead the value was: \`null\`
`
exports['config/lib/validation .isNumberOrFalse returns error message when value is a not number or false 1'] = {
"key": "mockConfigKey",
"value": null,
"type": "a number or false"
}
exports['config/lib/validation .isBoolean returns error message when value is a not a string 1'] = `
Expected \`mockConfigKey\` to be a string. Instead the value was: \`1\`
`
exports['config/lib/validation .isBoolean returns error message when value is a not a string 1'] = {
"key": "mockConfigKey",
"value": 1,
"type": "a string"
}
exports['config/lib/validation .isString returns error message when value is a not a string 1'] = `
Expected \`mockConfigKey\` to be a string. Instead the value was: \`1\`
`
exports['config/lib/validation .isString returns error message when value is a not a string 1'] = {
"key": "mockConfigKey",
"value": 1,
"type": "a string"
}
exports['config/lib/validation .isArray returns error message when value is a non-array 1'] = `
Expected \`mockConfigKey\` to be an array. Instead the value was: \`1\`
`
exports['config/lib/validation .isArray returns error message when value is a non-array 1'] = {
"key": "mockConfigKey",
"value": 1,
"type": "an array"
}
exports['config/lib/validation .isStringOrFalse returns error message when value is neither string nor false 1'] = `
Expected \`mockConfigKey\` to be a string or false. Instead the value was: \`null\`
`
exports['config/lib/validation .isStringOrFalse returns error message when value is neither string nor false 1'] = {
"key": "mockConfigKey",
"value": null,
"type": "a string or false"
}
+9 -12
View File
@@ -11,17 +11,12 @@ const path = require('path')
const str = JSON.stringify
const { isArray, isString, isFinite: isNumber } = _
/**
* Forms good Markdown-like string message.
* @param {string} key - The key that caused the error
* @param {string} type - The expected type name
* @param {any} value - The actual value
* @returns {string} Formatted error message
*/
const errMsg = (key, value, type) => {
return `Expected \`${key}\` to be ${type}. Instead the value was: \`${str(
return {
key,
value,
)}\``
type,
}
}
const isFullyQualifiedUrl = (value) => {
@@ -91,10 +86,12 @@ const isValidBrowserList = (key, browsers) => {
}
for (let k = 0; k < browsers.length; k += 1) {
const err = isValidBrowser(browsers[k])
const validationResult = isValidBrowser(browsers[k])
if (err !== true) {
return `Found an error while validating the \`browsers\` list. ${err}`
if (validationResult !== true) {
validationResult.list = 'browsers'
return validationResult
}
}
+2 -1
View File
@@ -104,7 +104,8 @@ describe('config/lib/index', () => {
'baseUrl': ' ',
}, errorFn)
expect(errorFn).to.have.been.calledWithMatch(/Expected `baseUrl`/)
expect(errorFn).to.have.been.calledWithMatch({ key: 'baseUrl' })
expect(errorFn).to.have.been.calledWithMatch({ type: 'a fully qualified URL (starting with `http://` or `https://`)' })
})
})
@@ -124,7 +124,13 @@ describe('Error Message', function () {
.should('contain', 'this is markdown')
})
it('shows error details if provided', function () {
it('shows error details collapsed if cypress originalError provided', function () {
this.detailsErr.originalError = {
...this.detailsErr,
stack: this.detailsErr.details,
isCypressErr: true,
}
cy.stub(this.ipc, 'onProjectError').yields(null, this.detailsErr)
this.start()
@@ -134,6 +140,20 @@ describe('Error Message', function () {
cy.get('details.details-body > summary').should('contain', 'ReferenceError')
})
it('shows error details open if non cypress originalError provided', function () {
this.detailsErr.originalError = {
...this.detailsErr,
stack: this.detailsErr.details,
}
cy.stub(this.ipc, 'onProjectError').yields(null, this.detailsErr)
this.start()
cy.get('.error').contains('ReferenceError: alsdkjf is not defined')
cy.get('details.details-body').should('have.attr', 'open')
cy.get('details.details-body > summary').should('contain', 'ReferenceError')
})
it('doesn\'t show error details if not provided', function () {
cy.stub(this.ipc, 'onProjectError').yields(null, this.err)
this.start()
@@ -173,7 +193,7 @@ describe('Error Message', function () {
this.detailsErr = {
name: 'Error',
message: messageText,
stack: '[object Object]↵',
stack: 'ReferenceError: alsdkjf is not defined',
details: 'ReferenceError: alsdkjf is not defined',
}
@@ -219,7 +239,12 @@ describe('Error Message', function () {
})
it('does not overlay the nav/footer when long details are expanded (issue #4959)', function () {
this.detailsErr.details = `${this.detailsErr.details}${this.detailsErr.details}` // make details longer
this.detailsErr.originalError = {
...this.detailsErr,
stack: `${this.detailsErr.details}${this.detailsErr.details}`, // make details longer
isCypressErr: true,
}
this.ipc.openProject.rejects(this.detailsErr)
this.start()
@@ -229,7 +254,12 @@ describe('Error Message', function () {
})
it('it scrolls the error details when details are expanded (issue #4959)', function () {
this.detailsErr.details = `${this.detailsErr.details}${this.detailsErr.details}` // make details longer
this.detailsErr.originalError = {
...this.detailsErr,
stack: `${this.detailsErr.details}${this.detailsErr.details}`, // make details longer
isCypressErr: true,
}
this.ipc.openProject.rejects(this.detailsErr)
this.start()
@@ -9,7 +9,7 @@ import Markdown from 'markdown-it'
const _copyErrorDetails = (err) => {
let details = [
`**Message:** ${err.message}`,
`**Message:** ${err.messageMarkdown || err.message}`,
]
if (err.details) {
@@ -33,14 +33,14 @@ const md = new Markdown({
})
const ErrorDetails = observer(({ err }) => {
let details = _.clone(err.details).split('\n')
let details = _.clone(err.stack).split('\n')
const detailsTitle = details.shift()
const detailsBody = details.join('\n')
if (detailsBody) {
return (
<pre>
<details className='details-body'>
<details className='details-body' open={!err.isCypressErr}>
<summary>{detailsTitle}</summary>
{detailsBody}
</details>
@@ -85,10 +85,10 @@ class ErrorMessage extends Component {
</p>
<span className='alert-content'>
<div ref={(node) => this.errorMessageNode = node} dangerouslySetInnerHTML={{
__html: md.render(err.message),
__html: md.render(err.messageMarkdown || err.message),
}}></div>
{err.details && (
<ErrorDetails err={err} />
{err.originalError && (
<ErrorDetails err={err.originalError} />
)}
{err.portInUse && (
<div>
@@ -96,7 +96,7 @@ class ErrorMessage extends Component {
<p>To fix, stop the other running process or change the port in {configFileFormatted(this.props.project.configFile)}</p>
</div>
)}
{err.stack2 && (
{!err.originalError && err.stack2 && (
<details className='stacktrace'>
<summary>Stack trace</summary>
<pre>{err.stack2}</pre>
@@ -6,3 +6,7 @@
width: 100%;
overflow: auto;
}
details.stacktrace summary {
display: list-item;
}
@@ -1,19 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title>type('{enter}') </title>
<title>Click Event by cy.type()</title>
<meta charset="UTF-8" />
</head>
<body>
<button id="reset">clear log</button>
<button id="target-button-tag">click me then press enter</button>
<input id="target-input-button" type="button" value="click me then press enter" />
<input id="target-input-image" type="image" value="click me then press enter" />
<input id="target-input-reset" type="reset" value="click me then press enter" />
<input id="target-input-submit" type="submit" value="click me then press enter" />
<input id="target-input-checkbox" type="checkbox" value="click me then press enter" />
<input id="target-input-radio" type="radio" value="click me then press enter" />
<button id="target-button-tag">button tag</button>
<input id="target-input-button" type="button" value="input button" />
<input id="target-input-image" type="image" value="input image" />
<input id="target-input-reset" type="reset" value="input reset" />
<input id="target-input-submit" type="submit" value="input submit" />
<input id="target-input-checkbox" type="checkbox" value="input checkbox" />
<input id="target-input-radio" type="radio" value="input radio" />
<div id="log"></div>
@@ -66,10 +66,10 @@
target.addEventListener("click", () => {
updateLog("click");
});
target.addEventListener("keyup", () => {
target.addEventListener("keyup", (event) => {
updateLog("keyup");
});
});
</script>
</body>
</html>
</html>
@@ -0,0 +1,32 @@
<html>
<head>
<meta charset='utf-8'>
<title>Select event counter</title>
</head>
<label>Choose an ice cream flavor:
<select class='ice-cream' name='ice-cream'>
<option value=''>Select One …</option>
<option value='chocolate' selected>Chocolate</option>
<option value='sardine'>Sardine</option>
<option value='vanilla'>Vanilla</option>
</select>
</label>
<div id='change-result'></div>
<div id='input-result'></div>
<script>
const selectElement = document.querySelector('.ice-cream');
let numOfTimesOnChangeFired = 0;
selectElement.addEventListener('change', (event) => {
const result = document.querySelector('#change-result');
result.textContent = `Number of times onChange event fired: ${++numOfTimesOnChangeFired}`;
});
let numOfTimesInputFired = 0;
selectElement.addEventListener('input', (event) => {
const result = document.querySelector('#input-result');
result.textContent = `Number of times input event fired: ${++numOfTimesInputFired}`;
});
</script>
</html>
@@ -325,6 +325,25 @@ describe('src/cy/commands/actions/select', () => {
expect(fired).to.deep.eq(events)
})
})
// https://github.com/cypress-io/cypress/issues/19494
it('does not fire `change`, `input` events when selecting the same option again', () => {
cy.visit('fixtures/select-event-counter.html')
// Nothing happens when selecting the option with `selected` attribute
cy.get('.ice-cream').select('Chocolate')
cy.get('#change-result').should('not.have.text', 'Number of times onChange event fired: 1')
cy.get('#input-result').should('not.have.text', 'Number of times input event fired: 1')
cy.get('.ice-cream').select('Sardine')
cy.get('#change-result').should('have.text', 'Number of times onChange event fired: 1')
cy.get('#input-result').should('have.text', 'Number of times input event fired: 1')
// Select the option that is already selected - `change`, `input` events should not fire.
cy.get('.ice-cream').select('Sardine')
cy.get('#change-result').should('have.text', 'Number of times onChange event fired: 1')
cy.get('#input-result').should('have.text', 'Number of times input event fired: 1')
})
})
describe('errors', {
@@ -365,7 +384,7 @@ describe('src/cy/commands/actions/select', () => {
done()
})
cy.get('#select-maps').select('de_dust2').select('de_aztec')
cy.get('#select-maps').select('de_aztec').select('de_dust2')
})
it('throws when more than 1 element in the collection', (done) => {
@@ -647,7 +666,7 @@ describe('src/cy/commands/actions/select', () => {
done()
})
cy.get('#select-maps').select('de_dust2').then(($select) => { })
cy.get('#select-maps').select('de_aztec').then(($select) => { })
})
it('snapshots after clicking', () => {
@@ -560,7 +560,7 @@ describe('src/cy/commands/actions/type - #type', () => {
// https://github.com/cypress-io/cypress/issues/19541
describe(`type('{enter}') and click event on button-like elements`, () => {
beforeEach(() => {
cy.visit('fixtures/type-enter.html')
cy.visit('fixtures/click-event-by-type.html')
})
describe('triggers', () => {
@@ -574,8 +574,7 @@ describe('src/cy/commands/actions/type - #type', () => {
targets.forEach((targetId) => {
it(`${targetId}`, () => {
cy.get(`#target-${targetId}`).focus()
cy.get(`#target-${targetId}`).type('{enter}')
cy.get(`#target-${targetId}`).focus().type('{enter}')
cy.get('li').eq(0).should('have.text', 'keydown')
cy.get('li').eq(1).should('have.text', 'keypress')
@@ -593,8 +592,7 @@ describe('src/cy/commands/actions/type - #type', () => {
targets.forEach((targetId) => {
it(`${targetId}`, () => {
cy.get(`#target-${targetId}`).focus()
cy.get(`#target-${targetId}`).type('{enter}')
cy.get(`#target-${targetId}`).focus().type('{enter}')
cy.get('li').eq(0).should('have.text', 'keydown')
cy.get('li').eq(1).should('have.text', 'keypress')
@@ -604,6 +602,154 @@ describe('src/cy/commands/actions/type - #type', () => {
})
})
describe(`type(' ') fires click event on button-like elements`, () => {
beforeEach(() => {
cy.visit('fixtures/click-event-by-type.html')
})
const targets = [
'#target-button-tag',
'#target-input-button',
'#target-input-image',
'#target-input-reset',
'#target-input-submit',
]
describe(`triggers with single space`, () => {
targets.forEach((target) => {
it(target, () => {
const events = []
$(target).on('keydown keypress keyup click', (evt) => {
events.push(evt.type)
})
cy.get(target).focus().type(' ').then(() => {
expect(events).to.deep.eq([
'keydown',
'keypress',
'keyup',
'click',
])
})
cy.get('li').eq(0).should('have.text', 'keydown')
cy.get('li').eq(1).should('have.text', 'keypress')
cy.get('li').eq(2).should('have.text', 'keyup')
cy.get('li').eq(3).should('have.text', 'click')
})
})
})
describe(`does not trigger if keyup prevented`, () => {
targets.forEach((target) => {
it(`${target} does not fire click event`, () => {
const events = []
$(target)
.on('keydown keypress keyup click', (evt) => {
events.push(evt.type)
})
.on('keyup', (evt) => {
evt.preventDefault()
})
cy.get(target).focus().type(' ').then(() => {
expect(events).to.deep.eq([
'keydown',
'keypress',
'keyup',
])
})
cy.get('li').should('have.length', 3)
cy.get('li').eq(0).should('have.text', 'keydown')
cy.get('li').eq(1).should('have.text', 'keypress')
cy.get('li').eq(2).should('have.text', 'keyup')
})
})
})
describe('triggers after other characters', () => {
targets.forEach((target) => {
it(target, () => {
const events = []
$(target).on('keydown keypress keyup click', (evt) => {
events.push(evt.type)
})
cy.get(target).focus().type('asd ').then(() => {
expect(events).to.deep.eq([
'keydown',
'keypress',
'keyup',
'keydown',
'keypress',
'keyup',
'keydown',
'keypress',
'keyup',
'keydown',
'keypress',
'keyup',
'click',
])
})
cy.get('li').eq(12).should('have.text', 'click')
})
})
})
describe('checkbox', () => {
it('checkbox is checked/unchecked', () => {
cy.get(`#target-input-checkbox`).focus().type(' ')
cy.get('li').eq(0).should('have.text', 'keydown')
cy.get('li').eq(1).should('have.text', 'keypress')
cy.get('li').eq(2).should('have.text', 'keyup')
cy.get('li').eq(3).should('have.text', 'click')
cy.get('#target-input-checkbox').should('be.checked')
cy.get(`#target-input-checkbox`).type(' ')
cy.get('li').eq(4).should('have.text', 'keydown')
cy.get('li').eq(5).should('have.text', 'keypress')
cy.get('li').eq(6).should('have.text', 'keyup')
cy.get('li').eq(7).should('have.text', 'click')
cy.get('#target-input-checkbox').should('not.be.checked')
})
})
describe('radio', () => {
it('radio fires click event when it is not checked', () => {
cy.get(`#target-input-radio`).focus().type(' ')
cy.get('li').eq(0).should('have.text', 'keydown')
cy.get('li').eq(1).should('have.text', 'keypress')
cy.get('li').eq(2).should('have.text', 'keyup')
cy.get('li').eq(3).should('have.text', 'click')
cy.get('#target-input-radio').should('be.checked')
})
it('radio does not fire click event when it is checked', () => {
// We're clicking here first to make the radio element checked.
cy.get(`#target-input-radio`).click().type(' ')
// item 0 is click event. It's fired because we want to make sure our radio button is checked.
cy.get('li').eq(1).should('have.text', 'keydown')
cy.get('li').eq(2).should('have.text', 'keypress')
cy.get('li').eq(3).should('have.text', 'keyup')
cy.get('#target-input-radio').should('be.checked')
})
})
})
describe('tabindex', () => {
beforeEach(function () {
this.$div = cy.$$('#tabindex')
@@ -0,0 +1,227 @@
const { assertLogLength } = require('../../../support/utils')
const { _ } = Cypress
describe('src/cy/commands/querying', () => {
beforeEach(() => {
cy.visit('/fixtures/dom.html')
})
context('#focused', () => {
it('returns the activeElement', () => {
const $button = cy.$$('#button')
$button.get(0).focus()
expect(cy.state('document').activeElement).to.eq($button.get(0))
cy.focused().then(($focused) => {
expect($focused.get(0)).to.eq($button.get(0))
})
})
it('returns null if no activeElement', () => {
const $button = cy.$$('#button')
$button.get(0).focus()
$button.get(0).blur()
cy.focused().should('not.exist').then(($focused) => {
expect($focused).to.be.null
})
})
describe('assertion verification', () => {
beforeEach(function () {
cy.on('log:added', (attrs, log) => {
if (log.get('name') === 'assert') {
this.lastLog = log
}
})
return null
})
it('eventually passes the assertion', () => {
cy.on('command:retry', _.after(2, () => {
cy.$$(':text:first').addClass('focused').focus()
}))
cy.focused().should('have.class', 'focused').then(function () {
const { lastLog } = this
expect(lastLog.get('name')).to.eq('assert')
expect(lastLog.get('state')).to.eq('passed')
expect(lastLog.get('ended')).to.be.true
})
})
// https://github.com/cypress-io/cypress/issues/409
it('retries on an elements value', () => {
const $input = cy.$$('input:first')
cy.on('command:retry', _.after(2, () => {
$input.val('1234')
$input.get(0).focus()
}))
cy.focused().should('have.value', '1234').then(function () {
const { lastLog } = this
expect(lastLog.get('name')).to.eq('assert')
expect(lastLog.get('state')).to.eq('passed')
expect(lastLog.get('ended')).to.be.true
})
})
})
describe('.log', () => {
beforeEach(function () {
cy.$$('input:first').get(0).focus()
cy.on('log:added', (attrs, log) => {
if (log.get('name') === 'focused') {
this.lastLog = log
}
})
return null
})
it('is a parent command', () => {
cy.get('body').focused().then(function () {
const { lastLog } = this
expect(lastLog.get('type')).to.eq('parent')
})
})
it('ends immediately', () => {
cy.focused().then(function () {
const { lastLog } = this
expect(lastLog.get('ended')).to.be.true
expect(lastLog.get('state')).to.eq('passed')
})
})
it('snapshots immediately', () => {
cy.focused().then(function () {
const { lastLog } = this
expect(lastLog.get('snapshots').length).to.eq(1)
expect(lastLog.get('snapshots')[0]).to.be.an('object')
})
})
it('passes in $el', () => {
cy.get('input:first').focused().then(function ($input) {
const { lastLog } = this
expect(lastLog.get('$el')).to.eq($input)
})
})
it('#consoleProps', () => {
cy.get('input:first').focused().then(function ($input) {
expect(this.lastLog.invoke('consoleProps')).to.deep.eq({
Command: 'focused',
Yielded: $input.get(0),
Elements: 1,
})
})
})
it('#consoleProps with null element', () => {
const button = cy.$$('#button')
button.get(0).focus()
button.get(0).blur()
cy.focused().should('not.exist').then(function () {
expect(this.lastLog.invoke('consoleProps')).to.deep.eq({
Command: 'focused',
Yielded: '--nothing--',
Elements: 0,
})
})
})
})
describe('errors', {
defaultCommandTimeout: 100,
}, () => {
beforeEach(function () {
this.logs = []
cy.on('log:added', (attrs, log) => {
this.lastLog = log
this.logs.push(log)
})
return null
})
it('fails waiting for the element to exist', (done) => {
const button = cy.$$('#button')
button.get(0).focus()
button.get(0).blur()
cy.on('fail', (err) => {
expect(err.message).to.include('Expected to find element: `focused`, but never found it.')
done()
})
cy.focused()
})
it('fails waiting for the focused element not to exist', (done) => {
cy.$$('input:first').focus()
cy.on('fail', (err) => {
expect(err.message).to.include('Expected <input#input> not to exist in the DOM, but it was continuously found.')
done()
})
cy.focused().should('not.exist')
})
it('eventually fails the assertion', function (done) {
cy.$$('input:first').focus()
cy.on('fail', (err) => {
const { lastLog } = this
expect(err.message).to.include(lastLog.get('error').message)
expect(err.message).not.to.include('undefined')
expect(lastLog.get('name')).to.eq('assert')
expect(lastLog.get('state')).to.eq('failed')
expect(lastLog.get('error')).to.be.an.instanceof(chai.AssertionError)
done()
})
cy.focused().should('have.class', 'focused')
})
it('does not log an additional log on failure', function (done) {
cy.on('fail', () => {
assertLogLength(this.logs, 2)
done()
})
cy.focused().should('have.class', 'focused')
})
})
})
})
@@ -7,331 +7,6 @@ describe('src/cy/commands/querying', () => {
cy.visit('/fixtures/dom.html')
})
context('#focused', () => {
it('returns the activeElement', () => {
const $button = cy.$$('#button')
$button.get(0).focus()
expect(cy.state('document').activeElement).to.eq($button.get(0))
cy.focused().then(($focused) => {
expect($focused.get(0)).to.eq($button.get(0))
})
})
it('returns null if no activeElement', () => {
const $button = cy.$$('#button')
$button.get(0).focus()
$button.get(0).blur()
cy.focused().should('not.exist').then(($focused) => {
expect($focused).to.be.null
})
})
describe('assertion verification', () => {
beforeEach(function () {
cy.on('log:added', (attrs, log) => {
if (log.get('name') === 'assert') {
this.lastLog = log
}
})
return null
})
it('eventually passes the assertion', () => {
cy.on('command:retry', _.after(2, () => {
cy.$$(':text:first').addClass('focused').focus()
}))
cy.focused().should('have.class', 'focused').then(function () {
const { lastLog } = this
expect(lastLog.get('name')).to.eq('assert')
expect(lastLog.get('state')).to.eq('passed')
expect(lastLog.get('ended')).to.be.true
})
})
// https://github.com/cypress-io/cypress/issues/409
it('retries on an elements value', () => {
const $input = cy.$$('input:first')
cy.on('command:retry', _.after(2, () => {
$input.val('1234')
$input.get(0).focus()
}))
cy.focused().should('have.value', '1234').then(function () {
const { lastLog } = this
expect(lastLog.get('name')).to.eq('assert')
expect(lastLog.get('state')).to.eq('passed')
expect(lastLog.get('ended')).to.be.true
})
})
})
describe('.log', () => {
beforeEach(function () {
cy.$$('input:first').get(0).focus()
cy.on('log:added', (attrs, log) => {
if (log.get('name') === 'focused') {
this.lastLog = log
}
})
return null
})
it('is a parent command', () => {
cy.get('body').focused().then(function () {
const { lastLog } = this
expect(lastLog.get('type')).to.eq('parent')
})
})
it('ends immediately', () => {
cy.focused().then(function () {
const { lastLog } = this
expect(lastLog.get('ended')).to.be.true
expect(lastLog.get('state')).to.eq('passed')
})
})
it('snapshots immediately', () => {
cy.focused().then(function () {
const { lastLog } = this
expect(lastLog.get('snapshots').length).to.eq(1)
expect(lastLog.get('snapshots')[0]).to.be.an('object')
})
})
it('passes in $el', () => {
cy.get('input:first').focused().then(function ($input) {
const { lastLog } = this
expect(lastLog.get('$el')).to.eq($input)
})
})
it('#consoleProps', () => {
cy.get('input:first').focused().then(function ($input) {
expect(this.lastLog.invoke('consoleProps')).to.deep.eq({
Command: 'focused',
Yielded: $input.get(0),
Elements: 1,
})
})
})
it('#consoleProps with null element', () => {
const button = cy.$$('#button')
button.get(0).focus()
button.get(0).blur()
cy.focused().should('not.exist').then(function () {
expect(this.lastLog.invoke('consoleProps')).to.deep.eq({
Command: 'focused',
Yielded: '--nothing--',
Elements: 0,
})
})
})
})
describe('errors', {
defaultCommandTimeout: 100,
}, () => {
beforeEach(function () {
this.logs = []
cy.on('log:added', (attrs, log) => {
this.lastLog = log
this.logs.push(log)
})
return null
})
it('fails waiting for the element to exist', (done) => {
const button = cy.$$('#button')
button.get(0).focus()
button.get(0).blur()
cy.on('fail', (err) => {
expect(err.message).to.include('Expected to find element: `focused`, but never found it.')
done()
})
cy.focused()
})
it('fails waiting for the focused element not to exist', (done) => {
cy.$$('input:first').focus()
cy.on('fail', (err) => {
expect(err.message).to.include('Expected <input#input> not to exist in the DOM, but it was continuously found.')
done()
})
cy.focused().should('not.exist')
})
it('eventually fails the assertion', function (done) {
cy.$$('input:first').focus()
cy.on('fail', (err) => {
const { lastLog } = this
expect(err.message).to.include(lastLog.get('error').message)
expect(err.message).not.to.include('undefined')
expect(lastLog.get('name')).to.eq('assert')
expect(lastLog.get('state')).to.eq('failed')
expect(lastLog.get('error')).to.be.an.instanceof(chai.AssertionError)
done()
})
cy.focused().should('have.class', 'focused')
})
it('does not log an additional log on failure', function (done) {
cy.on('fail', () => {
assertLogLength(this.logs, 2)
done()
})
cy.focused().should('have.class', 'focused')
})
})
})
context('#root', () => {
it('returns html', () => {
const html = cy.$$('html')
cy.root().then(($html) => {
expect($html.get(0)).to.eq(html.get(0))
})
})
it('returns withinSubject if exists', () => {
const form = cy.$$('form')
cy.get('form').within(() => {
cy
.get('input')
.root().then(($root) => {
expect($root.get(0)).to.eq(form.get(0))
})
})
})
it('eventually resolves', () => {
_.delay(() => {
cy.$$('html').addClass('foo').addClass('bar')
}
, 100)
cy.root().should('have.class', 'foo').and('have.class', 'bar')
})
describe('.log', () => {
beforeEach(function () {
this.logs = []
cy.on('log:added', (attrs, log) => {
if (attrs.name === 'root') {
this.lastLog = log
this.logs.push(log)
}
})
return null
})
it('can turn off logging', () => {
cy.root({ log: false }).then(function () {
expect(this.log).to.be.undefined
})
})
it('logs immediately before resolving', (done) => {
cy.on('log:added', (attrs, log) => {
if (log.get('name') === 'root') {
expect(log.get('state')).to.eq('pending')
expect(log.get('message')).to.eq('')
done()
}
})
cy.root()
})
it('snapshots after clicking', () => {
cy.root().then(function () {
const { lastLog } = this
expect(lastLog.get('snapshots').length).to.eq(1)
expect(lastLog.get('snapshots')[0]).to.be.an('object')
})
})
it('sets $el to document', () => {
const html = cy.$$('html')
cy.root().then(function () {
expect(this.lastLog.get('$el').get(0)).to.eq(html.get(0))
})
})
it('sets $el to withinSubject', () => {
const form = cy.$$('form')
cy.get('form').within(() => {
cy
.get('input')
.root().then(function ($root) {
expect(this.lastLog.get('$el').get(0)).to.eq(form.get(0))
})
})
})
it('consoleProps', () => {
cy.root().then(function ($root) {
const consoleProps = this.lastLog.invoke('consoleProps')
expect(consoleProps).to.deep.eq({
Command: 'root',
Yielded: $root.get(0),
})
})
})
})
})
context('#get', {
defaultCommandTimeout: 200,
}, () => {
@@ -0,0 +1,114 @@
const { _ } = Cypress
describe('src/cy/commands/querying', () => {
beforeEach(() => {
cy.visit('/fixtures/dom.html')
})
context('#root', () => {
it('returns html', () => {
const html = cy.$$('html')
cy.root().then(($html) => {
expect($html.get(0)).to.eq(html.get(0))
})
})
it('returns withinSubject if exists', () => {
const form = cy.$$('form')
cy.get('form').within(() => {
cy
.get('input')
.root().then(($root) => {
expect($root.get(0)).to.eq(form.get(0))
})
})
})
it('eventually resolves', () => {
_.delay(() => {
cy.$$('html').addClass('foo').addClass('bar')
}
, 100)
cy.root().should('have.class', 'foo').and('have.class', 'bar')
})
describe('.log', () => {
beforeEach(function () {
this.logs = []
cy.on('log:added', (attrs, log) => {
if (attrs.name === 'root') {
this.lastLog = log
this.logs.push(log)
}
})
return null
})
it('can turn off logging', () => {
cy.root({ log: false }).then(function () {
expect(this.log).to.be.undefined
})
})
it('logs immediately before resolving', (done) => {
cy.on('log:added', (attrs, log) => {
if (log.get('name') === 'root') {
expect(log.get('state')).to.eq('pending')
expect(log.get('message')).to.eq('')
done()
}
})
cy.root()
})
it('snapshots after clicking', () => {
cy.root().then(function () {
const { lastLog } = this
expect(lastLog.get('snapshots').length).to.eq(1)
expect(lastLog.get('snapshots')[0]).to.be.an('object')
})
})
it('sets $el to document', () => {
const html = cy.$$('html')
cy.root().then(function () {
expect(this.lastLog.get('$el').get(0)).to.eq(html.get(0))
})
})
it('sets $el to withinSubject', () => {
const form = cy.$$('form')
cy.get('form').within(() => {
cy
.get('input')
.root().then(function ($root) {
expect(this.lastLog.get('$el').get(0)).to.eq(form.get(0))
})
})
})
it('consoleProps', () => {
cy.root().then(function ($root) {
const consoleProps = this.lastLog.invoke('consoleProps')
expect(consoleProps).to.deep.eq({
Command: 'root',
Yielded: $root.get(0),
})
})
})
})
})
})
+9 -3
View File
@@ -1,11 +1,17 @@
// @ts-nocheck
import $ from 'jquery'
import JQuery from 'jquery'
import _ from 'lodash'
import { scrollTo } from './jquery.scrollto'
import $dom from '../dom'
// Add missing types.
interface ExtendedJQueryStatic extends JQueryStatic {
find: any
expr: JQuery.Selectors & { filters: any }
}
const $: ExtendedJQueryStatic = JQuery as any
// force jquery to have the same visible
// and hidden logic as cypress
+20
View File
@@ -54,6 +54,18 @@ export function create (chai) {
typeof object.nodeName === 'string'
}
// We can't just check if object instanceof ShadowRoot, because it might be the document of an iframe,
// which in Chrome 99+ is a separate class, and instanceof ShadowRoot returns false.
const isShadowRoot = function (object) {
return isDOMElement(object.host) && object.host.shadowRoot === object
}
// We can't just check if object instanceof Document, because it might be the document of an iframe,
// which in Chrome 99+ is a separate class, and instanceof Document returns false.
const isDocument = function (object) {
return object.defaultView && object.defaultView === object.defaultView.window
}
let formatValueHook
const setFormatValueHook = (fn) => formatValueHook = fn
@@ -124,6 +136,14 @@ export function create (chai) {
}
}
if (isShadowRoot(value)) {
return value.innerHTML
}
if (isDocument(value)) {
return value.documentElement.outerHTML
}
// Look up the keys of the object.
let visibleKeys = getEnumerableProperties(value)
let keys = ctx.showHidden ? getProperties(value) : visibleKeys
@@ -1,4 +1,3 @@
// @ts-nocheck
import _ from 'lodash'
import Promise from 'bluebird'
@@ -7,7 +6,7 @@ import $utils from '../../../cypress/utils'
import $errUtils from '../../../cypress/error_utils'
import $elements from '../../../dom/elements'
const checkOrUncheck = (Cypress, cy, type, subject, values = [], userOptions = {}) => {
const checkOrUncheck = (Cypress, cy, type, subject, values: any[] = [], userOptions = {}) => {
// we're not handling conversion of values to strings
// in case we've received numbers
@@ -18,15 +17,15 @@ const checkOrUncheck = (Cypress, cy, type, subject, values = [], userOptions = {
values = []
} else {
// make sure we're an array of values
values = [].concat(values)
values = ([] as any[]).concat(values)
}
// keep an array of subjects which
// are potentially reduced down
// to new filtered subjects
const matchingElements = []
const matchingElements: HTMLElement[] = []
const options = _.defaults({}, userOptions, {
const options: Record<string, any> = _.defaults({}, userOptions, {
$el: subject,
log: true,
force: false,
@@ -75,7 +74,7 @@ const checkOrUncheck = (Cypress, cy, type, subject, values = [], userOptions = {
matchingElements.push(el)
}
const consoleProps = {
const consoleProps: Record<string, any> = {
'Applied To': $dom.getElements($el),
'Elements': $el.length,
}
@@ -252,6 +252,8 @@ export default (Commands, Cypress, cy) => {
interval: options.interval,
})
}).then(() => {
const oldValue = options.$el[0].selectedIndex
// reset the selects value after we've
// fired all the proper click events
// for the options
@@ -279,6 +281,12 @@ export default (Commands, Cypress, cy) => {
options.$el[0].selectedIndex = selectedIndex
}
// https://github.com/cypress-io/cypress/issues/19494
// When user selects the same option again, `input`, `change` events should not be fired.
if (options.$el[0].selectedIndex === oldValue) {
return
}
const input = new Event('input', {
bubbles: true,
cancelable: false,
@@ -1,5 +1,3 @@
// @ts-nocheck
import _ from 'lodash'
import Promise from 'bluebird'
@@ -59,7 +57,7 @@ export default (Commands, Cypress, cy, state, config) => {
({ options: userOptions, position, x, y } = $actionability.getPositionFromArguments(positionOrX, y, userOptions))
const options = _.defaults({}, userOptions, {
const options: Record<string, any> = _.defaults({}, userOptions, {
log: true,
$el: subject,
bubbles: true,
@@ -1,4 +1,3 @@
// @ts-nocheck
import _ from 'lodash'
import Promise from 'bluebird'
@@ -15,7 +14,11 @@ const debug = debugFn('cypress:driver:command:type')
export default function (Commands, Cypress, cy, state, config) {
const { keyboard } = cy.devices
function type (subject, chars, options = {}) {
// Note: These "change type of `any` to X" comments are written instead of changing them directly
// because Cypress extends user-given options with Cypress internal options.
// These comments will be removed after removing `// @ts-nocheck` comments in `packages/driver`.
// TODO: change the type of `any` to `Partial<Cypress.TypeOptions>`
function type (subject, chars, options: any = {}) {
const userOptions = options
let updateTable
@@ -277,6 +280,13 @@ export default function (Commands, Cypress, cy, state, config) {
const type = (type) => $elements.isInputType(options.$el.get(0), type)
const sendClickEvent = type('button') || type('image') || type('submit') || type('reset')
const fireClickEvent = (el) => {
const ctor = $dom.getDocumentFromElement(el).defaultView!.PointerEvent
const event = new ctor('click')
el.dispatchEvent(event)
}
return keyboard.type({
$el: options.$el,
chars,
@@ -317,7 +327,28 @@ export default function (Commands, Cypress, cy, state, config) {
}
},
onEvent: updateTable || _.noop,
onEvent (id, key, event, value) {
if (updateTable) {
updateTable(id, key, event, value)
}
if (
// Firefox sends a click event when the Space key is pressed.
// We don't want send it twice.
!Cypress.isBrowser('firefox') &&
// Click event is sent after keyup event with space key.
event.type === 'keyup' && event.code === 'Space' &&
// Click events should be only sent to button-like elements.
// event.target is null when used with shadow DOM.
(event.target && $elements.isButtonLike(event.target)) &&
// When a space key is pressed for input radio elements, the click event is only fired when it's not checked.
!(event.target.tagName === 'INPUT' && event.target.type === 'radio' && event.target.checked === true) &&
// When event is prevented, the click event should not be emitted
!event.defaultPrevented
) {
fireClickEvent(event.target)
}
},
// fires only when the 'value'
// of input/text/contenteditable
@@ -365,10 +396,7 @@ export default function (Commands, Cypress, cy, state, config) {
if (sendClickEvent) {
// Firefox sends a click event automatically.
if (!Cypress.isBrowser('firefox')) {
const ctor = $dom.getDocumentFromElement(el).defaultView?.PointerEvent
const event = new ctor('click')
el.dispatchEvent(event)
fireClickEvent(el)
}
}
@@ -510,7 +538,8 @@ export default function (Commands, Cypress, cy, state, config) {
})
}
function clear (subject, options = {}) {
// TODO: change the type of `any` to `Partial<ClearOptions>`
function clear (subject, options: any = {}) {
const userOptions = options
options = _.defaults({}, userOptions, {
@@ -1,13 +1,11 @@
// @ts-nocheck
import _ from 'lodash'
import Promise from 'bluebird'
import $dom from '../../dom'
import $utils from '../../cypress/utils'
import $errUtils from '../../cypress/error_utils'
import $errUtils, { CypressError } from '../../cypress/error_utils'
const returnFalseIfThenable = (key, ...args) => {
const returnFalseIfThenable = (key, ...args): boolean => {
if ((key === 'then') && _.isFunction(args[0]) && _.isFunction(args[1])) {
// https://github.com/cypress-io/cypress/issues/111
// if we're inside of a promise then the promise lib will naturally
@@ -22,6 +20,8 @@ const returnFalseIfThenable = (key, ...args) => {
return false
}
return true
}
const primitiveToObject = (memo) => {
@@ -181,7 +181,7 @@ export default function (Commands, Cypress, cy, state) {
const invokeFn = (subject, userOptionsOrStr, ...args) => {
const userOptionsPassed = _.isObject(userOptionsOrStr) && !_.isFunction(userOptionsOrStr)
let userOptions = null
let userOptions: Record<string, any> | null = null
let str = null
if (!userOptionsPassed) {
@@ -219,7 +219,7 @@ export default function (Commands, Cypress, cy, state) {
const message = getMessage()
let traversalErr = null
let traversalErr: CypressError | null = null
// copy userOptions because _log is added below.
const options = _.extend({}, userOptions)
@@ -568,7 +568,7 @@ export default function (Commands, Cypress, cy, state) {
return ret
}
return thenFn(el, userOptions, callback, state)
return thenFn(el, userOptions, callback)
}
// generate a real array since bluebird is finicky and
@@ -586,9 +586,9 @@ export default function (Commands, Cypress, cy, state) {
// cy.resolve + cy.wrap are upgraded to handle
// promises
Commands.addAll({ prevSubject: 'optional' }, {
then () {
then (subject, userOptions, fn) {
// eslint-disable-next-line prefer-rest-params
return thenFn.apply(this, arguments)
return thenFn.apply(this, [subject, userOptions, fn])
},
})
+11 -8
View File
@@ -1,5 +1,3 @@
// @ts-nocheck
import _ from 'lodash'
import Promise from 'bluebird'
@@ -110,7 +108,7 @@ export default function (Commands, Cypress, cy, state, config) {
})
}
const getAndClear = (log, timeout, options = {}) => {
const getAndClear = (log?, timeout?, options = {}) => {
return automateCookies('get:cookies', options, log, timeout)
.then((resp) => {
// bail early if we got no cookies!
@@ -166,7 +164,8 @@ export default function (Commands, Cypress, cy, state, config) {
})
return Commands.addAll({
getCookie (name, options = {}) {
// TODO: change the type of `any` to `Partial<Cypress.Loggable & Cypress.Timeoutable>`
getCookie (name, options: any = {}) {
const userOptions = options
options = _.defaults({}, userOptions, {
@@ -212,7 +211,8 @@ export default function (Commands, Cypress, cy, state, config) {
.catch(handleBackendError('getCookie', 'reading the requested cookie from', onFail))
},
getCookies (options = {}) {
// TODO: change the type of `any` to `Partial<Cypress.Loggable & Cypress.Timeoutable>`
getCookies (options: any = {}) {
const userOptions = options
options = _.defaults({}, userOptions, {
@@ -250,7 +250,8 @@ export default function (Commands, Cypress, cy, state, config) {
.catch(handleBackendError('getCookies', 'reading cookies from', options._log))
},
setCookie (name, value, options = {}) {
// TODO: change the type of `any` to `Partial<Cypress.SetCookieOptions>`
setCookie (name, value, options: any = {}) {
const userOptions = options
options = _.defaults({}, userOptions, {
@@ -331,7 +332,8 @@ export default function (Commands, Cypress, cy, state, config) {
}).catch(handleBackendError('setCookie', 'setting the requested cookie in', onFail))
},
clearCookie (name, options = {}) {
// TODO: change the type of `any` to `Partial<Cypress.Loggable & Cypress.Timeoutable>`
clearCookie (name, options: any = {}) {
const userOptions = options
options = _.defaults({}, userOptions, {
@@ -380,7 +382,8 @@ export default function (Commands, Cypress, cy, state, config) {
.catch(handleBackendError('clearCookie', 'clearing the requested cookie in', onFail))
},
clearCookies (options = {}) {
// TODO: change the type of `any` to `Partial<Cypress.Loggable & Cypress.Timeoutable>`
clearCookies (options: any = {}) {
const userOptions = options
options = _.defaults({}, userOptions, {
+2 -3
View File
@@ -1,5 +1,3 @@
// @ts-nocheck
import _ from 'lodash'
import Promise from 'bluebird'
@@ -7,7 +5,8 @@ import $errUtils from '../../cypress/error_utils'
export default (Commands, Cypress, cy) => {
Commands.addAll({
exec (cmd, options = {}) {
// TODO: change the type of `any` to `Partical<Cypress.ExecOptions>`
exec (cmd, options: any = {}) {
const userOptions = options
options = _.defaults({}, userOptions, {
+4 -3
View File
@@ -1,4 +1,3 @@
// @ts-nocheck
import _ from 'lodash'
import { basename } from 'path'
@@ -6,7 +5,8 @@ import $errUtils from '../../cypress/error_utils'
export default (Commands, Cypress, cy, state) => {
Commands.addAll({
readFile (file, encoding, options = {}) {
// TODO: change the type of `any` to `Partial<Cypress.Loggable & Cypress.Timeoutable>`
readFile (file, encoding, options: any = {}) {
let userOptions = options
if (_.isObject(encoding)) {
@@ -109,7 +109,8 @@ export default (Commands, Cypress, cy, state) => {
return verifyAssertions()
},
writeFile (fileName, contents, encoding, options = {}) {
// TODO: change the type of `any` to `Partial<Cypress.WriteFileOPtions & Cypress.Timeoutable>`
writeFile (fileName, contents, encoding, options: any = {}) {
let userOptions = options
if (_.isObject(encoding)) {
+1 -3
View File
@@ -1,5 +1,3 @@
// @ts-nocheck
import _ from 'lodash'
import Promise from 'bluebird'
import { basename } from 'path'
@@ -44,7 +42,7 @@ export default (Commands, Cypress, cy, state, config) => {
return Promise.resolve(clone(resp))
}
let options = {}
let options: Record<string, any> = {}
if (_.isObject(args[0])) {
options = args[0]
+4 -4
View File
@@ -1,5 +1,3 @@
// @ts-nocheck
import _ from 'lodash'
import Promise from 'bluebird'
@@ -8,7 +6,8 @@ const { throwErrByPath } = $errUtils
export default (Commands, Cypress, cy) => {
Commands.addAll({
url (options = {}) {
// TODO: change the type of `any` to `Partial<Cypress.UrlOptions>`
url (options: any = {}) {
const userOptions = options
options = _.defaults({}, userOptions, { log: true })
@@ -39,7 +38,8 @@ export default (Commands, Cypress, cy) => {
return resolveHref()
},
hash (options = {}) {
// TODO: change the type of `any` to `Partial<Cypress.Loggable & Cypress.Timeoutable>`
hash (options: any = {}) {
const userOptions = options
options = _.defaults({}, userOptions, { log: true })
+2 -2
View File
@@ -1,4 +1,3 @@
// @ts-nocheck
import _ from 'lodash'
import Promise from 'bluebird'
@@ -50,7 +49,8 @@ export default (Commands, Cypress, cy, state) => {
return null
},
wrap (arg, options = {}) {
// TODO: change the type of `any` to `Partial<Cypress.Loggable & Cypress.Timeoutable>`
wrap (arg, options: any = {}) {
const userOptions = options
options = _.defaults({}, userOptions, {
+39 -27
View File
@@ -1,5 +1,3 @@
// @ts-nocheck
/* global cy, Cypress */
import _ from 'lodash'
import whatIsCircular from '@cypress/what-is-circular'
import UrlParse from 'url-parse'
@@ -15,10 +13,10 @@ import debugFn from 'debug'
const debug = debugFn('cypress:driver:navigation')
let id = null
let previousDomainVisited = null
let hasVisitedAboutBlank = null
let currentlyVisitingAboutBlank = null
let knownCommandCausedInstability = null
let previousDomainVisited: boolean = false
let hasVisitedAboutBlank: boolean = false
let currentlyVisitingAboutBlank: boolean = false
let knownCommandCausedInstability: boolean = false
const REQUEST_URL_OPTS = 'auth failOnStatusCode retryOnNetworkFailure retryOnStatusCodeFailure retryIntervals method body headers'
.split(' ')
@@ -27,7 +25,7 @@ const VISIT_OPTS = 'url log onBeforeLoad onLoad timeout requestTimeout'
.split(' ')
.concat(REQUEST_URL_OPTS)
const reset = (test = {}) => {
const reset = (test: any = {}) => {
knownCommandCausedInstability = false
// continuously reset this
@@ -62,7 +60,7 @@ const timedOutWaitingForPageLoad = (ms, log) => {
}
const cannotVisitDifferentOrigin = (origin, previousUrlVisited, remoteUrl, existingUrl, log) => {
const differences = []
const differences: string[] = []
if (remoteUrl.protocol !== existingUrl.protocol) {
differences.push('protocol')
@@ -171,7 +169,7 @@ const navigationChanged = (Cypress, cy, state, source, arg) => {
end: true,
snapshot: true,
consoleProps () {
const obj = {
const obj: Record<string, any> = {
'New Url': url,
}
@@ -265,7 +263,7 @@ const stabilityChanged = (Cypress, state, config, stable) => {
return
}
const options = {}
const options: Record<string, any> = {}
_.defaults(options, {
timeout: config('pageLoadTimeout'),
@@ -433,6 +431,14 @@ const normalizeTimeoutOptions = (options) => {
.value()
}
type NotOkResponseError = Error & {
gotResponse: boolean
}
type InvalidContentTypeError = Error & {
invalidContentType: boolean
}
export default (Commands, Cypress, cy, state, config) => {
reset()
@@ -449,7 +455,7 @@ export default (Commands, Cypress, cy, state, config) => {
Cypress.on('stability:changed', (bool, event) => {
// only send up page loading events when we're
// not stable!
stabilityChanged(Cypress, state, config, bool, event)
stabilityChanged(Cypress, state, config, bool)
})
Cypress.on('navigation:changed', (source, arg) => {
@@ -474,11 +480,11 @@ export default (Commands, Cypress, cy, state, config) => {
url,
normalizeTimeoutOptions(options),
)
.then((resp = {}) => {
.then((resp: any = {}) => {
if (!resp.isOkStatusCode) {
// if we didn't even get an OK response
// then immediately die
const err = new Error
const err: NotOkResponseError = new Error as any
err.gotResponse = true
_.extend(err, resp)
@@ -488,7 +494,7 @@ export default (Commands, Cypress, cy, state, config) => {
if (!resp.isHtml) {
// throw invalid contentType error
const err = new Error
const err: InvalidContentTypeError = new Error as any
err.invalidContentType = true
_.extend(err, resp)
@@ -554,7 +560,7 @@ export default (Commands, Cypress, cy, state, config) => {
// clear the current timeout
cy.clearTimeout('reload')
let cleanup = null
let cleanup: (() => any) | null = null
const options = _.defaults({}, userOptions, {
log: true,
timeout: config('pageLoadTimeout'),
@@ -608,7 +614,7 @@ export default (Commands, Cypress, cy, state, config) => {
},
go (numberOrString, userOptions = {}) {
const options = _.defaults({}, userOptions, {
const options: Record<string, any> = _.defaults({}, userOptions, {
log: true,
timeout: config('pageLoadTimeout'),
})
@@ -624,7 +630,7 @@ export default (Commands, Cypress, cy, state, config) => {
$errUtils.throwErrByPath('go.invalid_number', { onFail: options._log })
}
let cleanup = null
let cleanup: (() => any) | null = null
if (options._log) {
options._log.snapshot('before', { next: 'after' })
@@ -698,7 +704,7 @@ export default (Commands, Cypress, cy, state, config) => {
case 'forward': return goNumber(1)
case 'back': return goNumber(-1)
default:
$errUtils.throwErrByPath('go.invalid_direction', {
return $errUtils.throwErrByPath('go.invalid_direction', {
onFail: options._log,
args: { str },
})
@@ -713,10 +719,11 @@ export default (Commands, Cypress, cy, state, config) => {
return goString(numberOrString)
}
$errUtils.throwErrByPath('go.invalid_argument', { onFail: options._log })
return $errUtils.throwErrByPath('go.invalid_argument', { onFail: options._log })
},
visit (url, options = {}) {
// TODO: Change the type of `any` to `Partial<Cypress.VisitOptions>`.
visit (url, options: any = {}) {
if (options.url && url) {
$errUtils.throwErrByPath('visit.no_duplicate_url', { args: { optionsUrl: options.url, url } })
}
@@ -807,7 +814,7 @@ export default (Commands, Cypress, cy, state, config) => {
url = $Location.mergeUrlWithParams(url, qs)
}
let cleanup = null
let cleanup: (() => any) | null = null
// clear the current timeout
cy.clearTimeout('visit')
@@ -830,7 +837,7 @@ export default (Commands, Cypress, cy, state, config) => {
})
options.onBeforeLoad?.call(runnable.ctx, contentWindow)
} catch (err) {
} catch (err: any) {
err.isCallbackError = true
onBeforeLoadError = err
}
@@ -876,7 +883,10 @@ export default (Commands, Cypress, cy, state, config) => {
})
}
const onLoad = ({ runOnLoadCallback, totalTime }) => {
const onLoad = ({ runOnLoadCallback, totalTime }: {
runOnLoadCallback?: boolean
totalTime?: number
}) => {
// reset window on load
win = state('window')
@@ -884,7 +894,7 @@ export default (Commands, Cypress, cy, state, config) => {
if (runOnLoadCallback !== false) {
try {
options.onLoad?.call(runnable.ctx, win)
} catch (err) {
} catch (err: any) {
// mark these as user callback errors, so they're treated differently
// than Node.js errors when caught below
err.isCallbackError = true
@@ -959,7 +969,9 @@ export default (Commands, Cypress, cy, state, config) => {
}
return changeIframeSrc(remote.href, 'hashchange')
.then(onLoad)
.then(() => {
return onLoad({})
})
}
if (existingHash) {
@@ -974,7 +986,7 @@ export default (Commands, Cypress, cy, state, config) => {
}
return requestUrl(url, options)
.then((resp = {}) => {
.then((resp: any = {}) => {
let { url, originalUrl, cookies, redirects, filePath } = resp
// reapply the existing hash
@@ -1029,7 +1041,7 @@ export default (Commands, Cypress, cy, state, config) => {
// tell our backend we're changing domains
// TODO: add in other things we want to preserve
// state for like scrollTop
let s = {
let s: Record<string, any> = {
currentId: id,
tests: Cypress.runner.getTestsState(),
startTime: Cypress.runner.getStartTime(),
@@ -0,0 +1,70 @@
import _ from 'lodash'
import Promise from 'bluebird'
import $dom from '../../../dom'
export default (Commands, Cypress, cy, state) => {
Commands.addAll({
// TODO: any -> Partial<Cypress.Loggable & Cypress.Timeoutable>
focused (options: any = {}) {
const userOptions = options
options = _.defaults({}, userOptions, {
verify: true,
log: true,
})
if (options.log) {
options._log = Cypress.log({ timeout: options.timeout })
}
const log = ($el) => {
if (options.log === false) {
return
}
options._log.set({
$el,
consoleProps () {
const ret = $el ? $dom.getElements($el) : '--nothing--'
return {
Yielded: ret,
Elements: $el != null ? $el.length : 0,
}
},
})
}
const getFocused = () => {
const focused = cy.getFocused()
log(focused)
return focused
}
const resolveFocused = () => {
return Promise
.try(getFocused)
.then(($el) => {
if (options.verify === false) {
return $el
}
if (!$el) {
$el = $dom.wrap(null)
$el.selector = 'focused'
}
// pass in a null jquery object for assertions
return cy.verifyUpcomingAssertions($el, options, {
onRetry: resolveFocused,
})
})
}
return resolveFocused()
},
})
}
@@ -1,7 +1,11 @@
import * as Focused from './focused'
import * as Querying from './querying'
import * as Root from './root'
import * as Within from './within'
export {
Focused,
Querying,
Root,
Within,
}
@@ -9,68 +9,6 @@ import { getAliasedRequests, isDynamicAliasingPossible } from '../../net-stubbin
export default (Commands, Cypress, cy, state) => {
Commands.addAll({
// TODO: any -> Partial<Cypress.Loggable & Cypress.Timeoutable>
focused (options: any = {}) {
const userOptions = options
options = _.defaults({}, userOptions, {
verify: true,
log: true,
})
if (options.log) {
options._log = Cypress.log({ timeout: options.timeout })
}
const log = ($el) => {
if (options.log === false) {
return
}
options._log.set({
$el,
consoleProps () {
const ret = $el ? $dom.getElements($el) : '--nothing--'
return {
Yielded: ret,
Elements: $el != null ? $el.length : 0,
}
},
})
}
const getFocused = () => {
const focused = cy.getFocused()
log(focused)
return focused
}
const resolveFocused = () => {
return Promise
.try(getFocused)
.then(($el) => {
if (options.verify === false) {
return $el
}
if (!$el) {
$el = $dom.wrap(null)
$el.selector = 'focused'
}
// pass in a null jquery object for assertions
return cy.verifyUpcomingAssertions($el, options, {
onRetry: resolveFocused,
})
})
}
return resolveFocused()
},
// TODO: any -> Partial<Cypress.Loggable & Cypress.Timeoutable & Cypress.Withinable & Cypress.Shadow>
get (selector, options: any = {}) {
const userOptions = options
@@ -409,36 +347,6 @@ export default (Commands, Cypress, cy, state) => {
return resolveElements()
},
// TODO: any -> Partial<Cypress.Loggable & Cypress.Timeoutable>
root (options: any = {}) {
const userOptions = options
options = _.defaults({}, userOptions, { log: true })
if (options.log !== false) {
options._log = Cypress.log({
message: '',
timeout: options.timeout,
})
}
const log = ($el) => {
if (options.log) {
options._log.set({ $el })
}
return $el
}
const withinSubject = state('withinSubject')
if (withinSubject) {
return log(withinSubject)
}
return cy.now('get', 'html', { log: false }).then(log)
},
})
Commands.addAll({ prevSubject: ['optional', 'window', 'document', 'element'] }, {
@@ -0,0 +1,35 @@
import _ from 'lodash'
export default (Commands, Cypress, cy, state) => {
Commands.addAll({
// TODO: any -> Partial<Cypress.Loggable & Cypress.Timeoutable>
root (options: any = {}) {
const userOptions = options
options = _.defaults({}, userOptions, { log: true })
if (options.log !== false) {
options._log = Cypress.log({
message: '',
timeout: options.timeout,
})
}
const log = ($el) => {
if (options.log) {
options._log.set({ $el })
}
return $el
}
const withinSubject = state('withinSubject')
if (withinSubject) {
return log(withinSubject)
}
return cy.now('get', 'html', { log: false }).then(log)
},
})
}
+19 -12
View File
@@ -148,23 +148,30 @@ class $Cypress {
this.config = $SetterGetter.create(config, (config) => {
if (!window.top.__cySkipValidateConfig) {
validateNoReadOnlyConfig(config, (errProperty) => {
let errMessage
const errPath = this.state('runnable')
? 'config.invalid_cypress_config_override'
: 'config.invalid_test_config_override'
if (this.state('runnable')) {
errMessage = $errUtils.errByPath('config.invalid_cypress_config_override', {
errProperty,
})
} else {
errMessage = $errUtils.errByPath('config.invalid_test_config_override', {
errProperty,
})
}
const errMsg = $errUtils.errByPath(errPath, {
errProperty,
})
throw new this.state('specWindow').Error(errMessage)
throw new this.state('specWindow').Error(errMsg)
})
}
validate(config, (errMsg) => {
validate(config, (errResult) => {
const stringify = (str) => format(JSON.stringify(str))
const format = (str) => `\`${str}\``
// TODO: this does not use the @packages/error rewriting rules
// for stdout vs markdown - it always inserts backticks for markdown
// and those leak out into the stdout formatting.
const errMsg = _.isString(errResult)
? errResult
: `Expected ${format(errResult.key)} to be ${errResult.type}.\n\nInstead the value was: ${stringify(errResult.value)}\``
throw new this.state('specWindow').Error(errMsg)
})
})
+6 -3
View File
@@ -1,4 +1,3 @@
// @ts-nocheck
import _ from 'lodash'
import $utils from './utils'
import $errUtils from './error_utils'
@@ -36,12 +35,16 @@ const _isBrowser = (browser, matcher, errPrefix) => {
}
}
const isBrowser = (config, obj = '', errPrefix = '`Cypress.isBrowser()`') => {
// TODO: change the type of `any` to `IsBrowserMatcher`
const isBrowser = (config, obj: any = '', errPrefix: string = '`Cypress.isBrowser()`') => {
return _
.chain(obj)
.concat([])
.map((matcher) => _isBrowser(config.browser, matcher, errPrefix))
.reduce((a, b) => {
.reduce((
a: null | { isMatch: boolean, exclusive: boolean },
b: { isMatch: boolean, exclusive: boolean },
) => {
if (!a) return b
if (a.exclusive && b.exclusive) {
+6 -2
View File
@@ -1,4 +1,3 @@
// @ts-nocheck
import _ from 'lodash'
import $ from 'jquery'
import $dom from '../dom'
@@ -33,7 +32,12 @@ const maybeCastNumberToString = (num) => {
return _.isFinite(num) ? `${num}` : num
}
export const $chaiJquery = (chai, chaiUtils, callbacks = {}) => {
interface Callbacks {
onInvalid: (method, obj) => void
onError: (err, method, obj, negated) => void
}
export const $chaiJquery = (chai, chaiUtils, callbacks: Callbacks) => {
const { inspect, flag } = chaiUtils
const assertDom = (ctx, method, ...args) => {
+6 -8
View File
@@ -1,15 +1,13 @@
// @ts-nocheck
import _ from 'lodash'
import $errUtils from './error_utils'
import $stackUtils from './stack_utils'
import { allCommands } from '../cy/commands'
import { addCommand as addNetstubbingCommand } from '../cy/net-stubbing'
import { addCommands as addMultiDomainCommands } from '../cy/multi-domain'
import $errUtils from './error_utils'
import $stackUtils from './stack_utils'
const builtInCommands = [
// `default` is necessary if a file uses `export default` syntax.
// @ts-ignore
..._.toArray(allCommands).map((c) => c.default || c),
addNetstubbingCommand,
addMultiDomainCommands,
@@ -76,7 +74,7 @@ export default {
const overridden = _.clone(original)
overridden.fn = function (...args) {
args = [].concat(originalFn, args)
args = ([] as any).concat(originalFn, args)
return fn.apply(this, args)
}
@@ -142,7 +140,7 @@ export default {
errProps: {
appendToStack: {
title: 'From Cypress Internals',
content: $stackUtils.stackWithoutMessage((new Error('add command internal stack')).stack),
content: $stackUtils.stackWithoutMessage((new Error('add command internal stack')).stack || ''),
} },
})
}
+6 -6
View File
@@ -1,5 +1,3 @@
// @ts-nocheck
import _ from 'lodash'
import Cookies from 'js-cookie'
@@ -10,13 +8,13 @@ let isDebuggingVerbose = false
const preserved = {}
const defaults = {
const defaults: any = {
preserve: null,
}
const warnOnWhitelistRenamed = (obj, type) => {
if (obj.whitelist) {
return $errUtils.throwErrByPath('cookies.whitelist_renamed', { args: { type } })
$errUtils.throwErrByPath('cookies.whitelist_renamed', { args: { type } })
}
}
@@ -53,10 +51,12 @@ export const $Cookies = (namespace, domain) => {
if (preserved[name]) {
return delete preserved[name]
}
return false
}
const API = {
debug (bool = true, options = {}) {
debug (bool = true, options: any = {}) {
_.defaults(options, {
verbose: true,
})
@@ -82,7 +82,7 @@ export const $Cookies = (namespace, domain) => {
return console[m].apply(console, args)
},
getClearableCookies (cookies = []) {
getClearableCookies (cookies: any[] = []) {
return _.filter(cookies, (cookie) => {
return !isAllowed(cookie) && !removePreserved(cookie.name)
})
+34 -31
View File
@@ -1,14 +1,11 @@
// @ts-nocheck
// See: ./errorScenarios.md for details about error messages and stack traces
import _ from 'lodash'
import chai from 'chai'
import _ from 'lodash'
import $dom from '../dom'
import $utils from './utils'
import $stackUtils from './stack_utils'
import $errorMessages from './error_messages'
import $stackUtils, { StackAndCodeFrameIndex } from './stack_utils'
import $utils from './utils'
const ERROR_PROPS = 'message type name stack sourceMappedStack parsedStack fileName lineNumber columnNumber host uncaught actual expected showDiff isPending docsUrl codeFrame'.split(' ')
const ERR_PREPARED_FOR_SERIALIZATION = Symbol('ERR_PREPARED_FOR_SERIALIZATION')
@@ -17,9 +14,9 @@ const crossOriginScriptRe = /^script error/i
if (!Error.captureStackTrace) {
Error.captureStackTrace = (err, fn) => {
const stack = (new Error()).stack
const stack = (new Error()).stack;
err.stack = $stackUtils.stackWithLinesDroppedFromMarker(stack, fn.name)
(err as Error).stack = $stackUtils.stackWithLinesDroppedFromMarker(stack, fn?.name)
}
}
@@ -63,15 +60,15 @@ const wrapErr = (err) => {
return $utils.reduceProps(err, ERROR_PROPS)
}
const isAssertionErr = (err = {}) => {
const isAssertionErr = (err: Error) => {
return err.name === 'AssertionError'
}
const isChaiValidationErr = (err = {}) => {
const isChaiValidationErr = (err: Error) => {
return _.startsWith(err.message, 'Invalid Chai property')
}
const isCypressErr = (err = {}) => {
const isCypressErr = (err: Error): boolean => {
return err.name === 'CypressError'
}
@@ -79,7 +76,7 @@ const isSpecError = (spec, err) => {
return _.includes(err.stack, spec.relative)
}
const mergeErrProps = (origErr: Error, ...newProps) => {
const mergeErrProps = (origErr: Error, ...newProps): Error => {
return _.extend(origErr, ...newProps)
}
@@ -197,7 +194,7 @@ const makeErrFromObj = (obj) => {
return err2
}
const throwErr = (err, options = {}) => {
const makeErrFromErr = (err, options: any = {}) => {
if (_.isString(err)) {
err = cypressErr({ message: err })
}
@@ -205,12 +202,12 @@ const throwErr = (err, options = {}) => {
let { onFail, errProps } = options
// assume onFail is a command if
//# onFail is present and isn't a function
// onFail is present and isn't a function
if (onFail && !_.isFunction(onFail)) {
const command = onFail
//# redefine onFail and automatically
//# hook this into our command
// redefine onFail and automatically
// hook this into our command
onFail = (err) => {
return command.error(err)
}
@@ -224,10 +221,14 @@ const throwErr = (err, options = {}) => {
_.extend(err, errProps)
}
throw err
return err
}
const throwErrByPath = (errPath, options = {}) => {
const throwErr = (err, options: any = {}): never => {
throw makeErrFromErr(err, options)
}
const throwErrByPath = (errPath, options: any = {}): never => {
const err = errByPath(errPath, options.args)
if (options.stack) {
@@ -237,15 +238,16 @@ const throwErrByPath = (errPath, options = {}) => {
Error.captureStackTrace(err, throwErrByPath)
}
throwErr(err, options)
throw makeErrFromErr(err, options)
}
const warnByPath = (errPath, options = {}) => {
const warnByPath = (errPath, options: any = {}) => {
const errObj = errByPath(errPath, options.args)
let err = errObj.message
const docsUrl = (errObj as CypressError).docsUrl
if (errObj.docsUrl) {
err += `\n\n${errObj.docsUrl}`
if (docsUrl) {
err += `\n\n${docsUrl}`
}
$utils.warning(err)
@@ -266,6 +268,7 @@ export class InternalCypressError extends Error {
export class CypressError extends Error {
docsUrl?: string
retry?: boolean
userInvocationStack?: any
constructor (message) {
super(message)
@@ -297,10 +300,10 @@ const internalErr = (err): InternalCypressError => {
const cypressErr = (err): CypressError => {
const newErr = new CypressError(err.message)
return mergeErrProps(newErr, err)
return mergeErrProps(newErr, err) as CypressError
}
const cypressErrByPath = (errPath, options = {}) => {
const cypressErrByPath = (errPath, options: any = {}) => {
const errObj = errByPath(errPath, options.args)
return cypressErr(errObj)
@@ -376,7 +379,7 @@ const createUncaughtException = ({ frameType, handlerType, state, err }) => {
let uncaughtErr = errByPath(errPath, {
errMsg: err.message,
promiseAddendum: handlerType === 'unhandledrejection' ? ' It was caused by an unhandled promise rejection.' : '',
})
}) as CypressError
modifyErrMsg(err, uncaughtErr.message, () => uncaughtErr.message)
@@ -394,14 +397,14 @@ const createUncaughtException = ({ frameType, handlerType, state, err }) => {
// stacks from command failures and assertion failures have the right message
// but the stack points to cypress internals. here we replace the internal
// cypress stack with the invocation stack, which points to the user's code
const stackAndCodeFrameIndex = (err, userInvocationStack) => {
const stackAndCodeFrameIndex = (err, userInvocationStack): StackAndCodeFrameIndex => {
if (!userInvocationStack) return { stack: err.stack }
if (isCypressErr(err) || isChaiValidationErr(err)) {
return $stackUtils.stackWithUserInvocationStackSpliced(err, userInvocationStack)
}
return { stack: $stackUtils.replacedStack(err, userInvocationStack) }
return { stack: $stackUtils.replacedStack(err, userInvocationStack) || '' }
}
const preferredStackAndCodeFrameIndex = (err, userInvocationStack) => {
@@ -427,7 +430,7 @@ const enhanceStack = ({ err, userInvocationStack, projectRoot }) => {
// all errors flow through this function before they're finally thrown
// or used to reject promises
const processErr = (errObj = {}, config) => {
const processErr = (errObj: CypressError, config) => {
let docsUrl = errObj.docsUrl
if (config('isInteractive') || !docsUrl) {
@@ -482,7 +485,7 @@ const errorFromErrorEvent = (event): ErrorFromErrorEvent => {
// reset the message on a cross origin script error
// since no details are accessible
if (crossOriginScriptRe.test(message)) {
const crossOriginErr = errByPath('uncaught.cross_origin_script')
const crossOriginErr = errByPath('uncaught.cross_origin_script') as CypressError
message = crossOriginErr.message
docsUrl = crossOriginErr.docsUrl
@@ -490,9 +493,9 @@ const errorFromErrorEvent = (event): ErrorFromErrorEvent => {
// it's possible the error was thrown as a string (throw 'some error')
// so create it in the case it's not already an object
const err = _.isObject(error) ? error : convertErrorEventPropertiesToObject({
const err = (_.isObject(error) ? error : convertErrorEventPropertiesToObject({
message, filename, lineno, colno,
})
})) as CypressError
err.docsUrl = docsUrl
+4 -1
View File
@@ -1,4 +1,3 @@
// @ts-nocheck
// TODO:
// 1. test these method implementations using encoded characters
// look at the spec to figure out whether we SHOULD be decoding them
@@ -18,6 +17,8 @@ const reLocalHost = /^(localhost|0\.0\.0\.0|127\.0\.0\.1)/
const reQueryParam = /\?[^/]+/
export class $Location {
remote: UrlParse
constructor (remote) {
this.remote = new UrlParse(remote)
}
@@ -38,6 +39,8 @@ export class $Location {
password,
}
}
return
}
getHash () {
+16 -3
View File
@@ -7,7 +7,7 @@ import { codeFrameColumns } from '@babel/code-frame'
import $utils from './utils'
import $sourceMapUtils from './source_map_utils'
import { getStackLines, replacedStack, stackWithoutMessage, splitStack, unsplitStack } from '@packages/server/lib/util/stack_utils'
import { getStackLines, replacedStack, stackWithoutMessage, splitStack, unsplitStack } from '@packages/errors/src/stackUtils'
const whitespaceRegex = /^(\s*)*/
const stackLineRegex = /^\s*(at )?.*@?\(?.*\:\d+\:\d+\)?$/
@@ -66,7 +66,12 @@ const stackWithReplacementMarkerLineRemoved = (stack) => {
})
}
const stackWithUserInvocationStackSpliced = (err, userInvocationStack) => {
export type StackAndCodeFrameIndex = {
stack: string
index?: number
}
const stackWithUserInvocationStackSpliced = (err, userInvocationStack): StackAndCodeFrameIndex => {
const stack = _.trim(err.stack, '\n') // trim newlines from end
const [messageLines, stackLines] = splitStack(stack)
const userInvocationStackWithoutMessage = stackWithoutMessage(userInvocationStack)
@@ -139,13 +144,21 @@ const captureUserInvocationStack = (ErrorConstructor, userInvocationStack?) => {
if (!userInvocationStack) {
const newErr = new ErrorConstructor('userInvocationStack')
userInvocationStack = newErr.stack
// if browser natively supports Error.captureStackTrace, use it (chrome) (must be bound)
// otherwise use our polyfill on top.Error
const captureStackTrace = ErrorConstructor.captureStackTrace ? ErrorConstructor.captureStackTrace.bind(ErrorConstructor) : Error.captureStackTrace
captureStackTrace(newErr, captureUserInvocationStack)
userInvocationStack = newErr.stack
// On Chrome 99+, captureStackTrace strips away the whole stack,
// leaving nothing beyond the error message. If we get back a single line
// (just the error message with no stack trace), then use the original value
// instead of the trimmed one.
if (newErr.stack.match('\n')) {
userInvocationStack = newErr.stack
}
}
userInvocationStack = normalizedUserInvocationStack(userInvocationStack)
+2 -2
View File
@@ -98,7 +98,7 @@ export default {
throw new Error(`The switch/case value: '${value}' did not match any cases: ${keys.join(', ')}.`)
},
reduceProps (obj, props = []) {
reduceProps (obj, props: string[] = []) {
if (!obj) {
return null
}
@@ -355,7 +355,7 @@ export default {
// normalize more than {maxNewLines} new lines into
// exactly {replacementNumLines} new lines
normalizeNewLines (str, maxNewLines, replacementNumLines) {
normalizeNewLines (str, maxNewLines, replacementNumLines?) {
const moreThanMaxNewLinesRe = new RegExp(`\\n{${maxNewLines},}`)
const replacementWithNumLines = replacementNumLines ?? maxNewLines
+1 -1
View File
@@ -97,7 +97,7 @@ module.exports = {
debug('dest path %s', dest)
// make sure this path exists!
return fs.statAsync(appPath)
return fs.accessAsync(appPath)
.then(() => {
debug('appPath exists %s', appPath)
+5
View File
@@ -0,0 +1,5 @@
## @packages/errors
Error definitions and utilities for Cypress
See [Error Handling Guide](../../guides/error-handling.md) for more info
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Check your browser to continue logging in.<span style="color:#e6e6e6"></span></span>
</pre></body></html>
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Cypress was unable to open your installed browser. To continue logging in, please open this URL in your web browser:<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4ec4ff">https://dashboard.cypress.io/login<span style="color:#e05561"><span style="color:#e6e6e6"></span></span></span></span></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">The automation client disconnected. Cannot continue running tests.<span style="color:#e6e6e6"></span></span>
</pre></body></html>
@@ -0,0 +1,45 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Cypress detected policy settings on your computer that may cause issues.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">The following policies were detected that may prevent Cypress from automating Chrome:<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">HKEY_LOCAL_MACHINE\Software\Policies\Google\Chrome\ProxyServer<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">HKEY_CURRENT_USER\Software\Policies\Google\Chromium\ExtensionSettings<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">For more information, see https://on.cypress.io/bad-browser-policy<span style="color:#e6e6e6"></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Cypress detected policy settings on your computer that may cause issues with using this browser. For more information, see https://on.cypress.io/bad-browser-policy<span style="color:#e6e6e6"></span></span>
</pre></body></html>
@@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Can&#39;t run because you&#39;ve entered an invalid browser name.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">Browser: <span style="color:#e5e510">canary<span style="color:#e05561"> was not found on your system or is not supported by Cypress.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">Cypress supports the following browsers:<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">electron<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">chrome<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">chromium<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">chrome:canary<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">edge<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">firefox<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">You can also use a custom browser: https://on.cypress.io/customize-browsers<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">Available browsers found on your system are:<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">chrome<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">chromium<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">chrome:beta<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">chrome:canary<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">firefox<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">firefox:dev<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">firefox:nightly<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">edge<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">edge:canary<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">edge:beta<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">edge:dev<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">Note: In Cypress version 4.0.0, Canary must be launched as <span style="color:#de73ff">chrome:canary<span style="color:#e05561">, not <span style="color:#de73ff">canary<span style="color:#e05561">.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">See https://on.cypress.io/migration-guide for more information on breaking changes in 4.0.0.<span style="color:#e6e6e6"></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,63 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Can&#39;t run because you&#39;ve entered an invalid browser name.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">Browser: <span style="color:#e5e510">invalid-browser<span style="color:#e05561"> was not found on your system or is not supported by Cypress.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">Cypress supports the following browsers:<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">electron<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">chrome<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">chromium<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">chrome:canary<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">edge<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">firefox<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">You can also use a custom browser: https://on.cypress.io/customize-browsers<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">Available browsers found on your system are:<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">chrome<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">chromium<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">chrome:beta<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">chrome:canary<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">firefox<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">firefox:dev<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">firefox:nightly<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">edge<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">edge:canary<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">edge:beta<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> - <span style="color:#e05561"><span style="color:#4ec4ff">edge:dev<span style="color:#e05561"><span style="color:#e6e6e6"></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">We could not identify a known browser at the path you provided: <span style="color:#4ec4ff">/path/does/not/exist<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">The output from the command we ran was:<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#de73ff">fail whale<span style="color:#e05561"><span style="color:#e6e6e6"></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
+51
View File
@@ -0,0 +1,51 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Oops...we found an error preparing this test file:<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> &gt; <span style="color:#e05561"><span style="color:#4ec4ff">/path/to/file<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">The error was:<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e5e510">fail whale<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">This occurred while Cypress was compiling and bundling your test code. This is usually caused by:<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">- A missing file or dependency<span style="color:#e6e6e6">
<span style="color:#e05561">- A syntax error in the file or one of its dependencies<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">Fix the error in your code and re-run your tests.<span style="color:#e6e6e6"></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Cypress failed to verify that your server is running.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">Please start this server and then run Cypress again.<span style="color:#e6e6e6"></span></span></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561"><span style="color:#4f5666">We will try connecting to it 60 more times...<span style="color:#e05561"><span style="color:#e6e6e6"></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Cypress could not verify that this server is running:<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> &gt; <span style="color:#e05561"><span style="color:#4ec4ff">http://localhost:3000<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">We are verifying this server because it has been configured as your <span style="color:#e5e510">baseUrl<span style="color:#e05561">.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">Cypress automatically waits until your server is accessible before running tests.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666">We will try connecting to it 60 more times...<span style="color:#e05561"><span style="color:#e6e6e6"></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Cypress could not verify that this server is running:<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> &gt; <span style="color:#e05561"><span style="color:#4ec4ff">http://localhost:3000<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">This server has been configured as your <span style="color:#e5e510">baseUrl<span style="color:#e05561">, and tests will likely fail if it is not running.<span style="color:#e6e6e6"></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Can&#39;t create project&#39;s secret key.<span style="color:#e6e6e6"></span></span>
</pre></body></html>
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Can&#39;t find project&#39;s secret key.<span style="color:#e6e6e6"></span></span>
</pre></body></html>
@@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">You passed the <span style="color:#de73ff">--record<span style="color:#e05561"> flag but this project has not been setup to record.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">This project is missing the <span style="color:#e5e510">projectId<span style="color:#e05561"> inside of: <span style="color:#4ec4ff">/path/to/cypress.json<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">We cannot uniquely identify this project without this id.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">You need to setup this project to record. This will generate a unique projectId.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">Alternatively if you omit the <span style="color:#de73ff">--record<span style="color:#e05561"> flag this project will run without recording.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">https://on.cypress.io/recording-project-runs<span style="color:#e6e6e6"></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Warning: We failed to remove old browser profiles from previous runs.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">This error will not alter the exit code.<span style="color:#e6e6e6">
<span style="color:#c062de"><span style="color:#e6e6e6">
<span style="color:#c062de">Error: fail whale<span style="color:#e6e6e6">
<span style="color:#c062de"> at makeErr (cypress/packages/errors/test/unit/visualSnapshotErrors_spec.ts)<span style="color:#e6e6e6">
<span style="color:#c062de"> at CANNOT_REMOVE_OLD_BROWSER_PROFILES (cypress/packages/errors/test/unit/visualSnapshotErrors_spec.ts)<span style="color:#e6e6e6"></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Warning: We failed to trash the existing run results.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">This error will not alter the exit code.<span style="color:#e6e6e6">
<span style="color:#c062de"><span style="color:#e6e6e6">
<span style="color:#c062de">Error: fail whale<span style="color:#e6e6e6">
<span style="color:#c062de"> at makeErr (cypress/packages/errors/test/unit/visualSnapshotErrors_spec.ts)<span style="color:#e6e6e6">
<span style="color:#c062de"> at CANNOT_TRASH_ASSETS (cypress/packages/errors/test/unit/visualSnapshotErrors_spec.ts)<span style="color:#e6e6e6"></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Cypress failed to make a connection to the Chrome DevTools Protocol after retrying for 50 seconds.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">This usually indicates there was a problem opening the Chrome browser.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">The CDP port requested was <span style="color:#e5e510">2345<span style="color:#e05561">.<span style="color:#e6e6e6">
<span style="color:#c062de"><span style="color:#e6e6e6">
<span style="color:#c062de">Error: fail whale<span style="color:#e6e6e6">
<span style="color:#c062de"> at makeErr (cypress/packages/errors/test/unit/visualSnapshotErrors_spec.ts)<span style="color:#e6e6e6">
<span style="color:#c062de"> at CDP_COULD_NOT_CONNECT (cypress/packages/errors/test/unit/visualSnapshotErrors_spec.ts)<span style="color:#e6e6e6"></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">There was an error reconnecting to the Chrome DevTools protocol. Please restart the browser.<span style="color:#e6e6e6">
<span style="color:#c062de"><span style="color:#e6e6e6">
<span style="color:#c062de">Error: fail whale<span style="color:#e6e6e6">
<span style="color:#c062de"> at makeErr (cypress/packages/errors/test/unit/visualSnapshotErrors_spec.ts)<span style="color:#e6e6e6">
<span style="color:#c062de"> at CDP_COULD_NOT_RECONNECT (cypress/packages/errors/test/unit/visualSnapshotErrors_spec.ts)<span style="color:#e6e6e6"></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Still waiting to connect to Chrome, retrying in 1 second <span style="color:#4f5666">(attempt 1/62)<span style="color:#e05561"><span style="color:#e6e6e6"></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">A minimum CDP version of <span style="color:#e5e510">1.3<span style="color:#e05561"> is required, but the current browser has an older version.<span style="color:#e6e6e6"></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">A minimum CDP version of <span style="color:#e5e510">1.3<span style="color:#e05561"> is required, but the current browser has <span style="color:#e5e510">1.2<span style="color:#e05561">.<span style="color:#e6e6e6"></span></span></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Your project has set the configuration option: <span style="color:#e5e510">chromeWebSecurity<span style="color:#e05561"> to <span style="color:#4ec4ff">false<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">This option will not have an effect in Firefox. Tests that rely on web security being disabled will not run as expected.<span style="color:#e6e6e6"></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">There is both a <span style="color:#e5e510">cypress.config.js<span style="color:#e05561"> and a <span style="color:#e5e510">cypress.config.ts<span style="color:#e05561"> at the location below:<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#4f5666"> &gt; <span style="color:#e05561"><span style="color:#4ec4ff">/path/to/project/root<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">Cypress does not know which one to read for config. Please remove one of the two and try again.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6"></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Could not find a Cypress configuration file.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">We looked but did not find a <span style="color:#e5e510">cypress.json<span style="color:#e05561"> file in this folder: <span style="color:#4ec4ff">/path/to/project/root<span style="color:#e05561"><span style="color:#e6e6e6"></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>
@@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap" rel="stylesheet">
<style>
body {
font-family: "Courier Prime", Courier, monospace;
padding: 0 1em;
line-height: 1.4;
color: #eee;
background-color: #111;
}
pre {
padding: 0 0;
margin: 0 0;
font-family: "Courier Prime", Courier, monospace;
}
body {
margin: 5px;
padding: 0;
overflow: hidden;
}
pre {
white-space: pre-wrap;
word-break: break-word;
-webkit-font-smoothing: antialiased;
}
</style>
</head>
<body><pre><span style="color:#e05561">Your <span style="color:#e5e510">configFile<span style="color:#e05561"> set an invalid value from: <span style="color:#4ec4ff">cypress.json<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">Expected <span style="color:#e5e510">defaultCommandTimeout<span style="color:#e05561"> to be a number.<span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561">Instead the value was: <span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#de73ff">[<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#de73ff"> 1,<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#de73ff"> 2,<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#de73ff"> 3<span style="color:#e05561"><span style="color:#e6e6e6">
<span style="color:#e05561"><span style="color:#de73ff">]<span style="color:#e05561"><span style="color:#e6e6e6"></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
</pre></body></html>

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