chore: merge in develop to unified-desktop-gui (#18103)

* merge in develop

* remove accidentally merged file

* update types
This commit is contained in:
Lachlan Miller
2021-09-15 16:24:28 +10:00
committed by GitHub
parent 563a8a2fc8
commit 8bda0a9d02
35 changed files with 654 additions and 707 deletions

View File

@@ -2,8 +2,7 @@ branches:
only:
- master
- develop
- issue-17944-remove-source-files
- windows-code-signing
- fix-test-other-projects
- /win*/
# https://www.appveyor.com/docs/lang/nodejs-iojs/

View File

@@ -8,7 +8,7 @@ macBuildFilters: &macBuildFilters
branches:
only:
- develop
- issue-17944-remove-source-files
- fix-test-other-projects
defaults: &defaults
parallelism: 1
@@ -42,7 +42,7 @@ onlyMainBranches: &onlyMainBranches
branches:
only:
- develop
- issue-17944-remove-source-files
- fix-test-other-projects
requires:
- create-build-artifacts
@@ -1504,7 +1504,7 @@ jobs:
- run:
name: Check current branch to persist artifacts
command: |
if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "issue-17944-remove-source-files" ]]; then
if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "fix-test-other-projects" ]]; then
echo "Not uploading artifacts or posting install comment for this branch."
circleci-agent step halt
fi
@@ -2142,7 +2142,7 @@ linux-workflow: &linux-workflow
branches:
only:
- develop
- issue-17944-remove-source-files
- fix-test-other-projects
requires:
- build
- test-kitchensink:
@@ -2154,7 +2154,7 @@ linux-workflow: &linux-workflow
branches:
only:
- develop
- issue-17944-remove-source-files
- fix-test-other-projects
requires:
- build
- create-build-artifacts:
@@ -2204,7 +2204,7 @@ linux-workflow: &linux-workflow
branches:
only:
- develop
- issue-17944-remove-source-files
- fix-test-other-projects
requires:
- create-build-artifacts
- test-npm-module-and-verify-binary:
@@ -2212,7 +2212,7 @@ linux-workflow: &linux-workflow
branches:
only:
- develop
- issue-17944-remove-source-files
- fix-test-other-projects
requires:
- create-build-artifacts
- test-binary-against-staging:
@@ -2221,7 +2221,7 @@ linux-workflow: &linux-workflow
branches:
only:
- develop
- issue-17944-remove-source-files
- fix-test-other-projects
requires:
- create-build-artifacts
@@ -2246,7 +2246,7 @@ linux-workflow: &linux-workflow
branches:
only:
- develop
- issue-17944-remove-source-files
- fix-test-other-projects
requires:
- create-build-artifacts
@@ -2318,7 +2318,7 @@ mac-workflow: &mac-workflow
branches:
only:
- develop
- issue-17944-remove-source-files
- fix-test-other-projects
requires:
- darwin-create-build-artifacts
@@ -2330,7 +2330,7 @@ mac-workflow: &mac-workflow
branches:
only:
- develop
- issue-17944-remove-source-files
- fix-test-other-projects
requires:
- darwin-create-build-artifacts

View File

@@ -22,6 +22,19 @@ declare namespace Cypress {
password: string
}
interface RemoteState {
auth?: {
username: string
password: string
}
domainName: string
strategy: 'file' | 'http'
origin: string
fileServer: string
props: Record<string, any>
visiting: string
}
interface Backend {
/**
* Firefox only: Force Cypress to run garbage collection routines.
@@ -2856,19 +2869,15 @@ declare namespace Cypress {
projectName: string
projectRoot: string
proxyUrl: string
remote: RemoteState
report: boolean
reporterRoute: string
reporterUrl: string
socketId: null | string
socketIoCookie: string
socketIoRoute: string
spec: {
absolute: string
name: string
relative: string
specFilter: null | string
specType: 'integration' | 'component'
}
spec: Cypress['spec']
specs: Array<Cypress['spec']>
xhrRoute: string
xhrUrl: string
}

View File

@@ -1,3 +1,10 @@
# [@cypress/schematic-v1.5.1](https://github.com/cypress-io/cypress/compare/@cypress/schematic-v1.5.0...@cypress/schematic-v1.5.1) (2021-09-10)
### Bug Fixes
* **cypress/schematic:** add edge to list of allowed browsers ([#17637](https://github.com/cypress-io/cypress/issues/17637)) ([49de24f](https://github.com/cypress-io/cypress/commit/49de24f6178e0ef7bfd654c3efc0bfa8008e962e))
# [@cypress/schematic-v1.5.0](https://github.com/cypress-io/cypress/compare/@cypress/schematic-v1.4.2...@cypress/schematic-v1.5.0) (2021-07-20)

View File

@@ -1,3 +1,10 @@
# [@cypress/react-v5.10.0](https://github.com/cypress-io/cypress/compare/@cypress/react-v5.9.4...@cypress/react-v5.10.0) (2021-09-10)
### Features
* allow usage of @react/plugins with cypress.config.js ([#17738](https://github.com/cypress-io/cypress/issues/17738)) ([da4b1e0](https://github.com/cypress-io/cypress/commit/da4b1e06ce33945aabddda0e6e175dc0e1b488a5))
# [@cypress/react-v5.9.4](https://github.com/cypress-io/cypress/compare/@cypress/react-v5.9.3...@cypress/react-v5.9.4) (2021-08-10)

View File

@@ -4,16 +4,19 @@
"description": "Test React components using Cypress",
"main": "dist/cypress-react.cjs.js",
"scripts": {
"build": "rimraf dist && yarn rollup -c rollup.config.js",
"build": "rimraf dist && yarn transpile-plugins && yarn rollup -c rollup.config.js",
"build-prod": "yarn build",
"cy:open": "node ../../scripts/cypress.js open-ct",
"cy:open:debug": "node --inspect-brk ../../scripts/start.js --component-testing --run-project ${PWD}",
"cy:run": "node ../../scripts/cypress.js run-ct",
"cy:run:debug": "node --inspect-brk ../../scripts/start.js --component-testing --run-project ${PWD}",
"pretest": "yarn transpile",
"test": "yarn cy:run",
"test": "yarn test-unit && yarn test-component",
"test-unit": "mocha -r @packages/ts/register test/**/*.spec.*",
"test-component": "yarn cy:run",
"test-ci": "node ../../scripts/run-ct-examples.js --examplesList=./examples.env",
"transpile": "tsc",
"transpile-plugins": "yarn transpile --project ./plugins",
"watch": "yarn build --watch --watch.exclude ./dist/**/*"
},
"dependencies": {

View File

@@ -2,6 +2,7 @@
/// <reference types="next" />
const debug = require('debug')('@cypress/react')
const getNextJsBaseWebpackConfig = require('next/dist/build/webpack-config').default
const { findPagesDir } = require('../../dist/next/findPagesDir')
async function getNextWebpackConfig (config) {
let loadConfig
@@ -26,7 +27,7 @@ async function getNextWebpackConfig (config) {
config: nextConfig,
dev: true,
isServer: false,
pagesDir: config.projectRoot,
pagesDir: findPagesDir(config.projectRoot),
entrypoints: {},
rewrites: { fallback: [], afterFiles: [], beforeFiles: [] },
},

View File

@@ -0,0 +1,33 @@
import * as fs from 'fs'
import * as path from 'path'
const existsSync = (file: string) => {
try {
fs.accessSync(file, fs.constants.F_OK)
return true
} catch (_) {
return false
}
}
/**
* Next allows the `pages` directory to be located at either
* `${projectRoot}/pages` or `${projectRoot}/src/pages`.
* If neither is found, return projectRoot
*/
export function findPagesDir (projectRoot: string) {
// prioritize ./pages over ./src/pages
let pagesDir = path.join(projectRoot, 'pages')
if (existsSync(pagesDir)) {
return pagesDir
}
pagesDir = path.join(projectRoot, 'src/pages')
if (existsSync(pagesDir)) {
return pagesDir
}
return projectRoot
}

View File

@@ -0,0 +1,11 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"rootDir": "./",
"types": [
"cypress",
"node"
]
},
"include": ["./**/*.ts"]
}

View File

@@ -0,0 +1,19 @@
import { expect } from 'chai'
import * as path from 'path'
import { findPagesDir } from '../../plugins/next/findPagesDir'
describe('Next.js findPagesDir', () => {
it('should find the correct pagesDir', () => {
const nextPluginFixturePath = path.join(__dirname, '../fixtures/next-plugin')
let projectRoot = nextPluginFixturePath
expect(findPagesDir(projectRoot)).to.equal(projectRoot)
projectRoot = path.join(nextPluginFixturePath, 'next-project-one')
expect(findPagesDir(projectRoot)).to.equal(path.join(projectRoot, 'pages'))
projectRoot = path.join(nextPluginFixturePath, 'next-project-two')
expect(findPagesDir(projectRoot)).to.equal(path.join(projectRoot, 'src/pages'))
})
})

View File

@@ -1,3 +1,10 @@
# [@cypress/vite-dev-server-v2.1.0](https://github.com/cypress-io/cypress/compare/@cypress/vite-dev-server-v2.0.8...@cypress/vite-dev-server-v2.1.0) (2021-09-10)
### Features
* allow usage of @react/plugins with cypress.config.js ([#17738](https://github.com/cypress-io/cypress/issues/17738)) ([da4b1e0](https://github.com/cypress-io/cypress/commit/da4b1e06ce33945aabddda0e6e175dc0e1b488a5))
# [@cypress/vite-dev-server-v2.0.8](https://github.com/cypress-io/cypress/compare/@cypress/vite-dev-server-v2.0.7...@cypress/vite-dev-server-v2.0.8) (2021-08-30)

View File

@@ -1,3 +1,10 @@
# [@cypress/webpack-dev-server-v1.6.0](https://github.com/cypress-io/cypress/compare/@cypress/webpack-dev-server-v1.5.0...@cypress/webpack-dev-server-v1.6.0) (2021-09-10)
### Features
* allow usage of @react/plugins with cypress.config.js ([#17738](https://github.com/cypress-io/cypress/issues/17738)) ([da4b1e0](https://github.com/cypress-io/cypress/commit/da4b1e06ce33945aabddda0e6e175dc0e1b488a5))
# [@cypress/webpack-dev-server-v1.5.0](https://github.com/cypress-io/cypress/compare/@cypress/webpack-dev-server-v1.4.0...@cypress/webpack-dev-server-v1.5.0) (2021-08-30)

View File

@@ -1,6 +1,6 @@
{
"name": "cypress",
"version": "8.3.1",
"version": "8.4.0",
"description": "Cypress.io end to end testing tool",
"private": true,
"scripts": {
@@ -162,7 +162,7 @@
"lint-staged": "11.0.0",
"listr2": "3.8.3",
"lodash": "4.17.21",
"make-empty-github-commit": "1.2.0",
"make-empty-github-commit": "cypress-io/make-empty-github-commit#4a592aedb776ba2f4cc88979055315a53eec42ee",
"minimist": "1.2.5",
"mocha": "3.5.3",
"mocha-banner": "1.1.2",

View File

@@ -1,5 +1,4 @@
import _ from 'lodash'
import type CyServer from '@packages/server'
import { blocked, cors } from '@packages/network'
import { InterceptRequest } from '@packages/net-stubbing'
import debugModule from 'debug'
@@ -126,7 +125,7 @@ const StripUnsupportedAcceptEncoding: RequestMiddleware = function () {
this.next()
}
function reqNeedsBasicAuthHeaders (req, { auth, origin }: CyServer.RemoteState) {
function reqNeedsBasicAuthHeaders (req, { auth, origin }: Cypress.RemoteState) {
//if we have auth headers, this request matches our origin, protection space, and the user has not supplied auth headers
return auth && !req.headers['authorization'] && cors.urlMatchesOriginProtectionSpace(req.proxiedUrl, origin)
}

View File

@@ -2,7 +2,9 @@ import path from 'path'
let fs: typeof import('fs-extra')
type FoldersWithDist = 'static' | 'runner' | 'runner-ct' | 'driver'
export type RunnerPkg = 'runner' | 'runner-ct'
type FoldersWithDist = 'static' | 'driver' | RunnerPkg
export const getPathToDist = (folder: FoldersWithDist, ...args: string[]) => {
return path.join(...[__dirname, '..', '..', folder, 'dist', ...args])
@@ -14,7 +16,7 @@ export const getRunnerInjectionContents = () => {
return fs.readFile(getPathToDist('runner', 'injection.js'))
}
export const getPathToIndex = (pkg: 'runner' | 'runner-ct') => {
export const getPathToIndex = (pkg: RunnerPkg) => {
return getPathToDist(pkg, 'index.html')
}

View File

@@ -14,7 +14,7 @@
// types for the `server` package
export namespace CyServer {
export type getRemoteState = () => RemoteState
export type getRemoteState = () => Cypress.RemoteState
// TODO: pull this from main types
export interface Config {
@@ -28,18 +28,6 @@ export namespace CyServer {
responseTimeout: number
}
export interface RemoteState {
auth?: {
username: string
password: string
}
domainName: string
strategy: 'file' | 'http'
origin: string
fileServer: string
visiting: string
}
export interface Socket {
toDriver: (eventName: string, ...args: any) => void
}

View File

@@ -0,0 +1,56 @@
import type { Request, Response } from 'express'
import type httpProxy from 'http-proxy'
import Debug from 'debug'
import files from './files'
import type { Cfg } from '../project-base'
const debug = Debug('cypress:server:iframes')
interface IFramesController {
config: Cfg
}
interface E2E extends IFramesController {
getRemoteState: () => any
getSpec: () => Cypress.Cypress['spec'] | null
}
interface CT extends IFramesController {
nodeProxy: httpProxy
}
export const iframesController = {
e2e: ({ getSpec, getRemoteState, config }: E2E, req: Request, res: Response) => {
const extraOptions = {
specFilter: getSpec()?.specFilter,
specType: 'integration',
}
debug('handling iframe for project spec %o', {
spec: getSpec(),
extraOptions,
})
files.handleIframe(req, res, config, getRemoteState, extraOptions)
},
component: ({ config, nodeProxy }: CT, req: Request, res: Response) => {
// always proxy to the index.html file
// attach header data for webservers
// to properly intercept and serve assets from the correct src root
// TODO: define a contract for dev-server plugins to configure this behavior
req.headers.__cypress_spec_path = req.params[0]
req.url = `${config.devServerPublicPathRoute}/index.html`
// user the node proxy here instead of the network proxy
// to avoid the user accidentally intercepting and modifying
// our internal index.html handler
nodeProxy.web(req, res, {}, (e) => {
if (e) {
// eslint-disable-next-line
debug('Proxy request error. This is likely the socket hangup issue, we can basically ignore this because the stream will automatically continue once the asset will be available', e)
}
})
},
}

View File

@@ -1,65 +0,0 @@
const _ = require('lodash')
const send = require('send')
const os = require('os')
const { fs } = require('../util/fs')
const path = require('path')
const debug = require('debug')('cypress:server:runner')
const pkg = require('@packages/root')
/**
* @type {import('@packages/resolve-dist')}
*/
const { getPathToDist, getPathToIndex } = require('@packages/resolve-dist')
const PATH_TO_NON_PROXIED_ERROR = path.join(__dirname, '..', 'html', 'non_proxied_error.html')
const _serveNonProxiedError = (res) => {
return fs.readFile(PATH_TO_NON_PROXIED_ERROR)
.then((html) => {
return res.type('html').end(html)
})
}
module.exports = {
serve (req, res, options = {}) {
if (req.proxiedUrl.startsWith('/')) {
debug('request was not proxied via Cypress, erroring %o', _.pick(req, 'proxiedUrl'))
return _serveNonProxiedError(res)
}
let { config, getRemoteState, getCurrentBrowser, getSpec, specsStore } = options
config = _.clone(config)
config.remote = getRemoteState()
config.version = pkg.version
config.platform = os.platform()
config.arch = os.arch()
config.spec = getSpec()
config.specs = specsStore.specFiles
config.browser = getCurrentBrowser()
debug('serving runner index.html with config %o',
_.pick(config, 'version', 'platform', 'arch', 'projectName'))
// log the env object's keys without values to avoid leaking sensitive info
debug('env object has the following keys: %s', _.keys(config.env).join(', '))
// base64 before embedding so user-supplied contents can't break out of <script>
// https://github.com/cypress-io/cypress/issues/4952
const base64Config = Buffer.from(JSON.stringify(config)).toString('base64')
const runnerPath = process.env.CYPRESS_INTERNAL_RUNNER_PATH || getPathToIndex('runner')
return res.render(runnerPath, {
base64Config,
projectName: config.projectName,
})
},
handle (req, res) {
const pathToFile = getPathToDist('runner', req.params[0])
return send(req, pathToFile)
.pipe(res)
},
}

View File

@@ -0,0 +1,91 @@
import _ from 'lodash'
import type { Response } from 'express'
import send from 'send'
import os from 'os'
import { fs } from '../util/fs'
import path from 'path'
import Debug from 'debug'
import pkg from '@packages/root'
import { getPathToDist, getPathToIndex, RunnerPkg } from '@packages/resolve-dist'
import type { InitializeRoutes } from '../routes'
import type { PlatformName } from '@packages/types'
import type { Cfg } from '../project-base'
const debug = Debug('cypress:server:runner')
const PATH_TO_NON_PROXIED_ERROR = path.join(__dirname, '..', 'html', 'non_proxied_error.html')
const _serveNonProxiedError = (res: Response) => {
return fs.readFile(PATH_TO_NON_PROXIED_ERROR)
.then((html) => {
return res.type('html').end(html)
})
}
export interface ServeOptions extends Pick<InitializeRoutes, 'getSpec' | 'config' | 'getCurrentBrowser' | 'getRemoteState' | 'specsStore'> {
testingType: Cypress.TestingType
}
export const serveRunner = (runnerPkg: RunnerPkg, config: Cfg, res: Response) => {
// base64 before embedding so user-supplied contents can't break out of <script>
// https://github.com/cypress-io/cypress/issues/4952
const base64Config = Buffer.from(JSON.stringify(config)).toString('base64')
const runnerPath = process.env.CYPRESS_INTERNAL_RUNNER_PATH || getPathToIndex(runnerPkg)
return res.render(runnerPath, {
base64Config,
projectName: config.projectName,
})
}
export const runner = {
serve (req, res, runnerPkg: RunnerPkg, options: ServeOptions) {
if (req.proxiedUrl.startsWith('/')) {
debug('request was not proxied via Cypress, erroring %o', _.pick(req, 'proxiedUrl'))
return _serveNonProxiedError(res)
}
let { config, getRemoteState, getCurrentBrowser, getSpec, specsStore } = options
config = _.clone(config)
// at any given point, rather than just arbitrarily modifying it.
// @ts-ignore
config.testingType = options.testingType
// TODO #1: bug. Passing `remote.domainName` breaks CT for unknown reasons.
// If you pass a remote object with a domainName key, we get cross-origin
// iframe access errors.
// repro:
// {
// "domainName": "localhost"
// }
// TODO: Find out what the problem.
if (options.testingType === 'e2e') {
config.remote = getRemoteState()
}
config.version = pkg.version
config.platform = os.platform() as PlatformName
config.arch = os.arch()
config.spec = getSpec() ?? undefined
config.specs = specsStore.specFiles
config.browser = getCurrentBrowser()
debug('serving runner index.html with config %o',
_.pick(config, 'version', 'platform', 'arch', 'projectName'))
// log the env object's keys without values to avoid leaking sensitive info
debug('env object has the following keys: %s', _.keys(config.env).join(', '))
return serveRunner(runnerPkg, config, res)
},
handle (testingType, req, res) {
const pathToFile = getPathToDist(testingType === 'e2e' ? 'runner' : 'runner-ct', req.params[0])
return send(req, pathToFile)
.pipe(res)
},
}

View File

@@ -1,14 +0,0 @@
const send = require('send')
/**
* @type {import('@packages/resolve-dist')}
*/
const { getPathToDist } = require('@packages/resolve-dist')
module.exports = {
handle (req, res) {
const pathToFile = getPathToDist('static', req.params[0])
return send(req, pathToFile)
.pipe(res)
},
}

View File

@@ -0,0 +1,12 @@
import send from 'send'
import type { Request, Response } from 'express'
import { getPathToDist } from '@packages/resolve-dist'
export const staticCtrl = {
handle (req: Request, res: Response) {
const pathToFile = getPathToDist('static', req.params[0])
return send(req, pathToFile)
.pipe(res)
},
}

View File

@@ -1,17 +1,17 @@
const human = require('human-interval')
const _ = require('lodash')
const Debug = require('debug')
const { getBrowsers } = require('../browsers/utils')
const errors = require('../errors')
const browsers = require('../browsers')
const { openProject } = require('../open_project')
const Updater = require('../updater')
import Debug from 'debug'
import _ from 'lodash'
import browserUtils from '../browsers/utils'
import human from 'human-interval'
import browsers from '../browsers'
import { openProject } from '../open_project'
import type { LaunchArgs } from '@packages/types'
import * as Updater from '../updater'
import * as errors from '../errors'
const debug = Debug('cypress:server:interactive-ct')
const registerCheckForUpdates = () => {
const checkForUpdates = (initialLaunch) => {
const checkForUpdates = (initialLaunch: boolean) => {
Updater.check({
initialLaunch,
testingType: 'component',
@@ -24,10 +24,7 @@ const registerCheckForUpdates = () => {
checkForUpdates(true)
}
// Partial because there are probably other options that are not included in this type.
// projectRoot: string
// args: LaunchArgs
const start = async (projectRoot, args) => {
const start = async (projectRoot: string, args: LaunchArgs) => {
if (process.env['CYPRESS_INTERNAL_ENV'] === 'production') {
registerCheckForUpdates()
}
@@ -36,13 +33,13 @@ const start = async (projectRoot, args) => {
// add chrome as a default browser if none has been specified
return browsers.ensureAndGetByNameOrPath(args.browser)
.then((browser) => {
.then((browser: Cypress.Browser) => {
const spec = {
name: 'All Specs',
absolute: '__all',
relative: '__all',
specType: 'component',
}
} as const
const options = {
browsers: [browser],
@@ -51,7 +48,7 @@ const start = async (projectRoot, args) => {
debug('create project')
return openProject.create(projectRoot, args, options)
.then((project) => {
.then(() => {
debug('launch project')
return openProject.launch(browser, spec, {
@@ -65,9 +62,12 @@ const start = async (projectRoot, args) => {
})
}
const browsersForCtInteractive = ['chrome', 'chromium', 'edge', 'electron', 'firefox']
export const browsersForCtInteractive = ['chrome', 'chromium', 'edge', 'electron', 'firefox'] as const
const returnDefaultBrowser = (browsersByPriority, installedBrowsers) => {
export const returnDefaultBrowser = (
browsersByPriority: typeof browsersForCtInteractive,
installedBrowsers: any[],
) => {
const browserMap = installedBrowsers.reduce((acc, curr) => {
acc[curr.name] = true
@@ -79,14 +79,16 @@ const returnDefaultBrowser = (browsersByPriority, installedBrowsers) => {
return browser
}
}
return undefined
}
const run = async (options) => {
const installedBrowsers = await getBrowsers()
export const run = async (options: LaunchArgs) => {
const installedBrowsers = await browserUtils.getBrowsers()
options.browser = options.browser || returnDefaultBrowser(browsersForCtInteractive, installedBrowsers)
return start(options.projectRoot, options).catch((e) => {
return start(options.projectRoot, options).catch((e: Error) => {
// Usually this kind of error management is doen inside cypress.js start
// But here we bypassed this since we don't use the window of the gui
// Handle errors here to avoid multiple errors appearing.
@@ -95,9 +97,3 @@ const run = async (options) => {
})
})
}
module.exports = {
run,
returnDefaultBrowser,
browsersForCtInteractive,
}

View File

@@ -31,18 +31,15 @@ import Watchers from './watchers'
import devServer from './plugins/dev-server'
import preprocessor from './plugins/preprocessor'
import { SpecsStore } from './specs-store'
import { createRoutes as createE2ERoutes } from './routes'
import { createRoutes as createCTRoutes } from './routes-ct'
import { checkSupportFile } from './project_utils'
import type { FoundBrowser, OpenProjectLaunchOptions, ResolvedConfigurationOptions } from '@packages/types'
// Cannot just use RuntimeConfigOptions as is because some types are not complete.
// Instead, this is an interface of values that have been manually validated to exist
// and are required when creating a project.
// TODO: Figure out how to type this better.
type ReceivedCypressOptions =
Partial<Pick<Cypress.RuntimeConfigOptions, 'hosts' | 'projectName' | 'clientRoute' | 'devServerPublicPathRoute' | 'namespace' | 'report' | 'socketIoCookie' | 'configFile' | 'isTextTerminal' | 'isNewProject' | 'proxyUrl' | 'browsers' | 'browserUrl' | 'socketIoRoute'>>
& Partial<Pick<Cypress.ResolvedConfigOptions, 'chromeWebSecurity' | 'supportFolder' | 'experimentalSourceRewriting' | 'fixturesFolder' | 'reporter' | 'reporterOptions' | 'screenshotsFolder' | 'pluginsFile' | 'supportFile' | 'integrationFolder' | 'baseUrl' | 'viewportHeight' | 'viewportWidth' | 'port' | 'experimentalInteractiveRunEvents' | 'componentFolder' | 'userAgent' | 'downloadsFolder'>>
Partial<Pick<Cypress.RuntimeConfigOptions, 'hosts' | 'projectName' | 'clientRoute' | 'devServerPublicPathRoute' | 'namespace' | 'report' | 'socketIoCookie' | 'configFile' | 'isTextTerminal' | 'isNewProject' | 'proxyUrl' | 'browsers' | 'browserUrl' | 'socketIoRoute' | 'arch' | 'platform' | 'spec' | 'specs' | 'browser' | 'version' | 'remote'>>
& Partial<Pick<Cypress.ResolvedConfigOptions, 'chromeWebSecurity' | 'supportFolder' | 'experimentalSourceRewriting' | 'fixturesFolder' | 'reporter' | 'reporterOptions' | 'screenshotsFolder' | 'pluginsFile' | 'supportFile' | 'integrationFolder' | 'baseUrl' | 'viewportHeight' | 'viewportWidth' | 'port' | 'experimentalInteractiveRunEvents' | 'componentFolder' | 'userAgent' | 'downloadsFolder' | 'env'>>// TODO: Figure out how to type this better.
export interface Cfg extends ReceivedCypressOptions {
projectRoot: string
@@ -208,7 +205,6 @@ export class ProjectBase<TServer extends Server> extends EE {
shouldCorrelatePreRequests: this.shouldCorrelatePreRequests,
testingType: this.testingType,
SocketCtor: this.testingType === 'e2e' ? SocketE2E : SocketCt,
createRoutes: this.testingType === 'e2e' ? createE2ERoutes : createCTRoutes,
specsStore,
})

View File

@@ -1,39 +1,32 @@
import Debug from 'debug'
import type { ErrorRequestHandler, Express } from 'express'
import httpProxy from 'http-proxy'
import send from 'send'
import type { NetworkProxy } from '@packages/proxy'
import { handle, serve, makeServeConfig, serveChunk } from './runner-ct'
import xhrs from './controllers/xhrs'
import type { SpecsStore } from './specs-store'
import type { Cfg } from './project-base'
import { handle, makeServeConfig } from './runner-ct'
import { Request, Response, Router } from 'express'
import { getPathToDist } from '@packages/resolve-dist'
import type { Browser } from './browsers/types'
import { runner } from './controllers/runner'
import type { InitializeRoutes } from './routes'
const debug = Debug('cypress:server:routes')
const debug = Debug('cypress:server:routes-ct')
export interface InitializeRoutes {
app: Express
specsStore: SpecsStore
config: Cfg
getSpec: () => Cypress.Cypress['spec'] | null
getCurrentBrowser: () => Browser
nodeProxy: httpProxy
networkProxy: NetworkProxy
getRemoteState: () => any
testingType: Cypress.TestingType
onError: (...args: unknown[]) => any
const serveChunk = (req: Request, res: Response, clientRoute: string) => {
let pathToFile = getPathToDist('runner-ct', req.originalUrl.replace(clientRoute, ''))
return send(req, pathToFile).pipe(res)
}
export const createRoutes = ({
app,
export const createRoutesCT = ({
config,
specsStore,
nodeProxy,
networkProxy,
getCurrentBrowser,
testingType,
getSpec,
getRemoteState,
}: InitializeRoutes) => {
const routesCt = Router()
// If development
const myProxy = httpProxy.createProxyServer({
target: 'http://localhost:3333/',
@@ -41,7 +34,7 @@ export const createRoutes = ({
// TODO If prod, serve the build app files from app/dist
app.get('/__/api', (req, res) => {
routesCt.get('/__/api', (req, res) => {
const options = makeServeConfig({
config,
getCurrentBrowser,
@@ -53,21 +46,21 @@ export const createRoutes = ({
// TODO: can namespace this onto a "unified" route like __app-unified__
// make sure to update the generated routes inside of vite.config.ts
app.get('/__vite__/*', (req, res) => {
routesCt.get('/__vite__/*', (req, res) => {
myProxy.web(req, res, {}, (e) => {
})
})
app.get('/__cypress/runner/*', handle)
routesCt.get('/__cypress/runner/*', handle)
app.get('/__cypress/static/*', (req, res) => {
routesCt.get('/__cypress/static/*', (req, res) => {
const pathToFile = getPathToDist('static', req.params[0])
return send(req, pathToFile)
.pipe(res)
})
app.get('/__cypress/iframes/*', (req, res) => {
routesCt.get('/__cypress/iframes/*', (req, res) => {
// always proxy to the index.html file
// attach header data for webservers
// to properly intercept and serve assets from the correct src root
@@ -89,7 +82,7 @@ export const createRoutes = ({
// user app code + spec code
// default mounted to /__cypress/src/*
app.get(`${config.devServerPublicPathRoute}*`, (req, res) => {
routesCt.get(`${config.devServerPublicPathRoute}*`, (req, res) => {
// user the node proxy here instead of the network proxy
// to avoid the user accidentally intercepting and modifying
// their own app.js files + spec.js files
@@ -107,49 +100,28 @@ export const createRoutes = ({
throw Error(`clientRoute is required. Received ${clientRoute}`)
}
app.all('/__cypress/xhrs/*', (req, res, next) => {
xhrs.handle(req, res, config, next)
})
app.get(clientRoute, (req, res) => {
routesCt.get(clientRoute, (req, res) => {
debug('Serving Cypress front-end by requested URL:', req.url)
serve(req, res, {
runner.serve(req, res, 'runner-ct', {
config,
testingType,
getSpec,
getCurrentBrowser,
getRemoteState,
specsStore,
})
})
// enables runner-ct to make a dynamic import
app.get(`${clientRoute}ctChunk-*`, (req, res) => {
routesCt.get([
`${clientRoute}ctChunk-*`,
`${clientRoute}vendors~ctChunk-*`,
], (req, res) => {
debug('Serving Cypress front-end chunk by requested URL:', req.url)
serveChunk(req, res, { config })
serveChunk(req, res, clientRoute)
})
app.get(`${clientRoute}vendors~ctChunk-*`, (req, res) => {
debug('Serving Cypress front-end vendor chunk by requested URL:', req.url)
serveChunk(req, res, { config })
})
app.all('*', (req, res) => {
networkProxy.handleHttpRequest(req, res)
})
// when we experience uncaught errors
// during routing just log them out to
// the console and send 500 status
// and report to raygun (in production)
const errorHandlingMiddleware: ErrorRequestHandler = (err, req, res) => {
console.log(err.stack) // eslint-disable-line no-console
res.set('x-cypress-error', err.message)
res.set('x-cypress-stack', JSON.stringify(err.stack))
res.sendStatus(500)
}
app.use(errorHandlingMiddleware)
return routesCt
}

View File

@@ -0,0 +1,156 @@
import path from 'path'
import la from 'lazy-ass'
import check from 'check-more-types'
import Debug from 'debug'
import { Router } from 'express'
import AppData from './util/app_data'
import CacheBuster from './util/cache_buster'
import specController from './controllers/spec'
import reporter from './controllers/reporter'
import { runner } from './controllers/runner'
import client from './controllers/client'
import files from './controllers/files'
import type { InitializeRoutes } from './routes'
const debug = Debug('cypress:server:routes-e2e')
export const createRoutesE2E = ({
config,
specsStore,
getRemoteState,
networkProxy,
getSpec,
getCurrentBrowser,
onError,
testingType,
}: InitializeRoutes) => {
const routesE2E = Router()
// routing for the actual specs which are processed automatically
// this could be just a regular .js file or a .coffee file
routesE2E.get('/__cypress/tests', (req, res, next) => {
// slice out the cache buster
const test = CacheBuster.strip(req.query.p)
specController.handle(test, req, res, config, next, onError)
})
routesE2E.get('/__cypress/socket.io.js', (req, res) => {
client.handle(req, res)
})
routesE2E.get('/__cypress/reporter/*', (req, res) => {
reporter.handle(req, res)
})
routesE2E.get('/__cypress/automation/getLocalStorage', (req, res) => {
// gathers and sends localStorage and sessionStorage via postMessage to the Cypress frame
// detect existence of local/session storage with JSON.stringify(...).length since localStorage.length may not be accurate
res.send(`<html><body><script>(${(function () {
const _localStorageStr = JSON.stringify(window.localStorage)
const _localStorage = _localStorageStr.length > 2 && JSON.parse(_localStorageStr)
const _sessionStorageStr = JSON.stringify(window.sessionStorage)
const _sessionStorage = _sessionStorageStr.length > 2 && JSON.parse(JSON.stringify(window.sessionStorage))
const value = {} as any
if (_localStorage) {
value.localStorage = _localStorage
}
if (_sessionStorage) {
value.sessionStorage = _sessionStorage
}
window.parent.postMessage({
value,
type: 'localStorage',
}, '*')
}).toString()})()</script></body></html>`)
})
/* eslint-disable no-undef */
routesE2E.get('/__cypress/automation/setLocalStorage', (req, res) => {
const origin = req.originalUrl.slice(req.originalUrl.indexOf('?') + 1)
networkProxy.http.getRenderedHTMLOrigins()[origin] = true
res.send(`<html><body><script>(${(function () {
window.onmessage = function (event) {
const msg = event.data
if (msg.type === 'set:storage:data') {
const { data } = msg
const setData = (storageData, type) => {
if (!storageData) return
const { clear, value } = storageData
if (clear) {
// @ts-ignore
window[type].clear()
}
if (value) {
Object.keys(value).forEach((key) => {
// @ts-ignore
window[type].setItem(key, value[key])
})
}
}
setData(data.localStorage, 'localStorage')
setData(data.sessionStorage, 'sessionStorage')
window.parent.postMessage({ type: 'set:storage:complete' }, '*')
}
}
window.parent.postMessage({ type: 'set:storage:load' }, '*')
}).toString()})()</script></body></html>`)
})
/* eslint-enable no-undef */
// routing for /files JSON endpoint
routesE2E.get('/__cypress/files', (req, res) => {
files.handleFiles(req, res, config)
})
routesE2E.get('/__cypress/source-maps/:id.map', (req, res) => {
networkProxy.handleSourceMapRequest(req, res)
})
// special fallback - serve local files from the project's root folder
routesE2E.get('/__root/*', (req, res) => {
const file = path.join(config.projectRoot, req.params[0])
res.sendFile(file, { etag: false })
})
// special fallback - serve dist'd (bundled/static) files from the project path folder
routesE2E.get('/__cypress/bundled/*', (req, res) => {
const file = AppData.getBundledFilePath(config.projectRoot, path.join('src', req.params[0]))
debug(`Serving dist'd bundle at file path: %o`, { path: file, url: req.url })
res.sendFile(file, { etag: false })
})
la(check.unemptyString(config.clientRoute), 'missing client route in config', config)
routesE2E.get(`${config.clientRoute}`, (req, res) => {
debug('Serving Cypress front-end by requested URL:', req.url)
runner.serve(req, res, 'runner', {
config,
testingType,
getSpec,
getCurrentBrowser,
getRemoteState,
specsStore,
})
})
return routesE2E
}

View File

@@ -1,185 +1,60 @@
import path from 'path'
import la from 'lazy-ass'
import check from 'check-more-types'
import Debug from 'debug'
import type httpProxy from 'http-proxy'
import { ErrorRequestHandler, Router } from 'express'
import type { InitializeRoutes } from './routes-ct'
import AppData from './util/app_data'
import CacheBuster from './util/cache_buster'
import specController from './controllers/spec'
import reporter from './controllers/reporter'
import runner from './controllers/runner'
import type { SpecsStore } from './specs-store'
import { staticCtrl } from './controllers/static'
import type { Browser } from './browsers/types'
import type { NetworkProxy } from '@packages/proxy'
import type { Cfg } from './project-base'
import xhrs from './controllers/xhrs'
import client from './controllers/client'
import files from './controllers/files'
import staticCtrl from './controllers/static'
import { runner } from './controllers/runner'
import { iframesController } from './controllers/iframes'
const debug = Debug('cypress:server:routes')
export interface InitializeRoutes {
specsStore: SpecsStore
config: Cfg
getSpec: () => Cypress.Spec | null
getCurrentBrowser: () => Browser
nodeProxy: httpProxy
networkProxy: NetworkProxy
getRemoteState: () => Cypress.RemoteState
onError: (...args: unknown[]) => any
testingType: Cypress.TestingType
}
export const createRoutes = ({
app,
export const createCommonRoutes = ({
config,
specsStore,
getRemoteState,
networkProxy,
getSpec,
getCurrentBrowser,
onError,
testingType,
getSpec,
getRemoteState,
nodeProxy,
}: InitializeRoutes) => {
// routing for the actual specs which are processed automatically
// this could be just a regular .js file or a .coffee file
app.get('/__cypress/tests', (req, res, next) => {
// slice out the cache buster
const test = CacheBuster.strip(req.query.p)
const router = Router()
specController.handle(test, req, res, config, next, onError)
router.get('/__cypress/runner/*', (req, res) => {
runner.handle(testingType, req, res)
})
app.get('/__cypress/socket.io.js', (req, res) => {
client.handle(req, res)
})
app.get('/__cypress/reporter/*', (req, res) => {
reporter.handle(req, res)
})
app.get('/__cypress/runner/*', (req, res) => {
runner.handle(req, res)
})
app.get('/__cypress/automation/getLocalStorage', (req, res) => {
// gathers and sends localStorage and sessionStorage via postMessage to the Cypress frame
// detect existence of local/session storage with JSON.stringify(...).length since localStorage.length may not be accurate
res.send(`<html><body><script>(${(function () {
const _localStorageStr = JSON.stringify(window.localStorage)
const _localStorage = _localStorageStr.length > 2 && JSON.parse(_localStorageStr)
const _sessionStorageStr = JSON.stringify(window.sessionStorage)
const _sessionStorage = _sessionStorageStr.length > 2 && JSON.parse(JSON.stringify(window.sessionStorage))
const value = {} as any
if (_localStorage) {
value.localStorage = _localStorage
}
if (_sessionStorage) {
value.sessionStorage = _sessionStorage
}
window.parent.postMessage({
value,
type: 'localStorage',
}, '*')
}).toString()})()</script></body></html>`)
})
/* eslint-disable no-undef */
app.get('/__cypress/automation/setLocalStorage', (req, res) => {
const origin = req.originalUrl.slice(req.originalUrl.indexOf('?') + 1)
networkProxy.http.getRenderedHTMLOrigins()[origin] = true
res.send(`<html><body><script>(${(function () {
window.onmessage = function (event) {
const msg = event.data
if (msg.type === 'set:storage:data') {
const { data } = msg
const setData = (storageData, type) => {
if (!storageData) return
const { clear, value } = storageData
if (clear) {
// @ts-ignore
window[type].clear()
}
if (value) {
Object.keys(value).forEach((key) => {
// @ts-ignore
window[type].setItem(key, value[key])
})
}
}
setData(data.localStorage, 'localStorage')
setData(data.sessionStorage, 'sessionStorage')
window.parent.postMessage({ type: 'set:storage:complete' }, '*')
}
}
window.parent.postMessage({ type: 'set:storage:load' }, '*')
}).toString()})()</script></body></html>`)
})
/* eslint-enable no-undef */
app.get('/__cypress/static/*', (req, res) => {
staticCtrl.handle(req, res)
})
// routing for /files JSON endpoint
app.get('/__cypress/files', (req, res) => {
files.handleFiles(req, res, config)
})
// routing for the dynamic iframe html
app.get('/__cypress/iframes/*', (req, res) => {
const extraOptions = {
specFilter: getSpec()?.specFilter,
specType: 'integration',
}
debug('handling iframe for project spec %o', {
spec: getSpec(),
extraOptions,
})
files.handleIframe(req, res, config, getRemoteState, extraOptions)
})
app.all('/__cypress/xhrs/*', (req, res, next) => {
router.all('/__cypress/xhrs/*', (req, res, next) => {
xhrs.handle(req, res, config, next)
})
app.get('/__cypress/source-maps/:id.map', (req, res) => {
networkProxy.handleSourceMapRequest(req, res)
router.get('/__cypress/static/*', (req, res) => {
staticCtrl.handle(req, res)
})
// special fallback - serve local files from the project's root folder
app.get('/__root/*', (req, res) => {
const file = path.join(config.projectRoot, req.params[0])
router.get('/__cypress/iframes/*', (req, res) => {
if (testingType === 'e2e') {
iframesController.e2e({ config, getSpec, getRemoteState }, req, res)
}
res.sendFile(file, { etag: false })
if (testingType === 'component') {
iframesController.component({ config, nodeProxy }, req, res)
}
})
// special fallback - serve dist'd (bundled/static) files from the project path folder
app.get('/__cypress/bundled/*', (req, res) => {
const file = AppData.getBundledFilePath(config.projectRoot, path.join('src', req.params[0]))
debug(`Serving dist'd bundle at file path: %o`, { path: file, url: req.url })
res.sendFile(file, { etag: false })
})
la(check.unemptyString(config.clientRoute), 'missing client route in config', config)
app.get(`${config.clientRoute}`, (req, res) => {
debug('Serving Cypress front-end by requested URL:', req.url)
runner.serve(req, res, {
// testingType should be passed below to send `testingType` to the client
config: { ...config, testingType },
getSpec,
getCurrentBrowser,
getRemoteState,
specsStore,
})
})
app.all('*', (req, res) => {
router.all('*', (req, res) => {
networkProxy.handleHttpRequest(req, res)
})
@@ -187,19 +62,16 @@ export const createRoutes = ({
// during routing just log them out to
// the console and send 500 status
// and report to raygun (in production)
app.use((err, req, res) => {
// TODO: Figure out if types are wrong, or if this code is wrong
// and we just have no tests around it.
// @ts-ignore
const errorHandlingMiddleware: ErrorRequestHandler = (err, req, res) => {
console.log(err.stack) // eslint-disable-line no-console
// @ts-ignore
res.set('x-cypress-error', err.message)
// @ts-ignore
res.set('x-cypress-stack', JSON.stringify(err.stack))
// @ts-ignore
res.sendStatus(500)
})
}
router.use(errorHandlingMiddleware)
return router
}

View File

@@ -53,10 +53,3 @@ export const serve = (req, res, options: ServeOptions) => {
return res.render(runnerPath, config)
}
export const serveChunk = (req, res, options) => {
let { config } = options
let pathToFile = getPathToDist('runner-ct', req.originalUrl.replace(config.clientRoute, ''))
return send(req, pathToFile).pipe(res)
}

View File

@@ -26,9 +26,11 @@ import { allowDestroy, DestroyableHttpServer } from './util/server_destroy'
import { SocketAllowed } from './util/socket_allowed'
import { createInitialWorkers } from '@packages/rewriter'
import type { SpecsStore } from './specs-store'
import type { InitializeRoutes } from './routes-ct'
import type { Cfg } from './project-base'
import type { Browser } from '@packages/server/lib/browsers/types'
import { InitializeRoutes, createCommonRoutes } from './routes'
import { createRoutesE2E } from './routes-e2e'
import { createRoutesCT } from './routes-ct'
const ALLOWED_PROXY_BYPASS_URLS = [
'/',
@@ -100,7 +102,6 @@ export interface OpenServerOptions {
getCurrentBrowser: () => Browser
getSpec: () => Cypress.Cypress['spec'] | null
shouldCorrelatePreRequests: () => boolean
createRoutes: (args: InitializeRoutes) => any
}
export abstract class ServerBase<TSocket extends SocketE2E | SocketCt> {
@@ -174,7 +175,6 @@ export abstract class ServerBase<TSocket extends SocketE2E | SocketCt> {
onWarning,
shouldCorrelatePreRequests,
specsStore,
createRoutes,
testingType,
SocketCtor,
}: OpenServerOptions) {
@@ -210,8 +210,7 @@ export abstract class ServerBase<TSocket extends SocketE2E | SocketCt> {
this.createHosts(config.hosts)
createRoutes({
app,
const routeOptions: InitializeRoutes = {
config,
specsStore,
getRemoteState,
@@ -221,7 +220,14 @@ export abstract class ServerBase<TSocket extends SocketE2E | SocketCt> {
getSpec,
getCurrentBrowser,
testingType,
})
}
const runnerSpecificRouter = testingType === 'e2e'
? createRoutesE2E(routeOptions)
: createRoutesCT(routeOptions)
app.use(runnerSpecificRouter)
app.use(createCommonRoutes(routeOptions))
return this.createServer(app, config, onWarning)
}
@@ -397,7 +403,7 @@ export abstract class ServerBase<TSocket extends SocketE2E | SocketCt> {
})
}
_getRemoteState () {
_getRemoteState (): Cypress.RemoteState {
// {
// origin: "http://localhost:2020"
// fileServer:
@@ -425,7 +431,7 @@ export abstract class ServerBase<TSocket extends SocketE2E | SocketCt> {
visiting: this._remoteVisitingUrl,
domainName: this._remoteDomainName,
fileServer: this._remoteFileServer,
})
}) as Cypress.RemoteState
debug('Getting remote state: %o', props)

View File

@@ -1,182 +0,0 @@
import Chai from 'chai'
import Bluebird from 'bluebird'
import http from 'http'
import sinon from 'sinon'
import { Express } from 'express'
import { Cfg } from '../../lib/project-base'
import { ServerBase, WarningErr } from '../../lib/server-base'
import { SocketE2E } from '../../lib/socket-e2e'
import SinonChai from 'sinon-chai'
import { SpecsStore } from '../../lib/specs-store'
const expect = Chai.expect
Chai.use(SinonChai)
const browser = {
name: 'chrome',
family: 'chromium',
displayName: 'chrome',
path: '/usr/chrome.app',
channel: 'canary',
version: '90',
majorVersion: null,
isHeaded: true,
isHeadless: false,
} as const
class ServerTest extends ServerBase<SocketE2E> {
createServer (
app: Express,
config: Cfg,
onWarning: unknown,
): Bluebird<[number, WarningErr?]> {
return Bluebird.try(() => {
return [1111]
})
}
}
describe('ServerBase', () => {
it('smoke test', () => {
new ServerTest()
})
describe('#createExpressApp', () => {
beforeEach(() => {
sinon.restore()
})
it('removes x-powered-by header', (done) => {
const server = new ServerTest()
const app = server.createExpressApp({ morgan: true })
app.get('/test', (req, res) => res.end('OK'))
const srv = app.listen(3344, () => {
http.request('http://localhost:3344/test,', (res) => {
expect(res.headers['x-powered-by']).to.be.undefined
srv.close(done)
}).end()
})
})
it('does not use morgan when morgan: false', () => {
const useMorgan = sinon.stub(ServerTest.prototype, 'useMorgan').returns(() => {})
const server = new ServerTest()
server.createExpressApp({ morgan: false })
expect(useMorgan).not.to.have.been.called
})
it('does use morgan when morgan: true', () => {
const useMorgan = sinon.stub(ServerTest.prototype, 'useMorgan').returns(() => {})
const server = new ServerTest()
server.createExpressApp({ morgan: true })
expect(useMorgan).to.have.been.called
})
it('uses middleware if provided', (done) => {
const server = new ServerTest()
const middleware = sinon.stub()
server.__setMiddleware(middleware)
server.createExpressApp({})
const app = server.createExpressApp({})
app.get('/test', (req, res) => res.end('OK'))
const srv = app.listen(3344, () => {
http.request('http://localhost:3344/test,', (res) => {
expect(middleware).to.have.been.called
srv.close(done)
}).end()
})
})
})
describe('#open', () => {
beforeEach(() => {
sinon.restore()
})
const cfg = { projectRoot: '/foo/bar' }
const noop = (...args: any[]) => ({} as any)
const defaults = {
getSpec: noop,
getCurrentBrowser: () => browser,
onError: noop,
onWarning: noop,
shouldCorrelatePreRequests: () => false,
specsStore: new SpecsStore({}, 'e2e'),
createRoutes: () => {},
testingType: 'e2e',
SocketCtor: SocketE2E,
} as const
it('smoke test', async () => {
const server = new ServerTest()
await server.open(cfg, defaults)
})
it('errors when using component testing without config.baseUrl', () => {
const server = new ServerTest()
try {
server.open({ ...cfg, baseUrl: undefined }, { ...defaults, testingType: 'component' })
} catch (e) {
expect(e.message).to.eq('ServerCt#open called without config.baseUrl.')
}
})
it('assigns socket', async () => {
const server = new ServerTest()
await server.open(cfg, defaults)
expect(server.socket).not.to.be.undefined
})
it('calls createNetworkProxy, assigns `_networkProxy`', async () => {
const server = new ServerTest()
await server.open(cfg, defaults)
expect(server.networkProxy).not.to.be.undefined
})
it('calls createHosts with config.hosts', async () => {
const hosts = ['/host']
const createHostsStub = sinon.stub(ServerTest.prototype, 'createHosts')
const server = new ServerTest()
await server.open({ ...cfg, hosts }, defaults)
expect(createHostsStub).to.have.been.calledWith(hosts)
})
it('calls createRoutes with correct params', async () => {
const server = new ServerTest()
const createRoutesStub = sinon.stub()
await server.open(cfg, { ...defaults, createRoutes: createRoutesStub })
expect(createRoutesStub).to.have.been.calledWithMatch({
config: cfg,
specsStore: defaults.specsStore,
onError: defaults.onError,
getSpec: defaults.getSpec,
getCurrentBrowser: defaults.getCurrentBrowser,
})
const args = createRoutesStub.getCalls()[0].args[0]
expect(args.networkProxy).to.eq(server.networkProxy)
expect(args.nodeProxy).to.eq(server.nodeProxy)
expect(args.app).not.to.be.undefined
})
})
})

View File

@@ -115,7 +115,7 @@ index 0ef9f80..4cd787e 100644
catch (e) {
return false;
diff --git a/node_modules/socket.io-parser/dist/is-binary.js b/node_modules/socket.io-parser/dist/is-binary.js
index 4b7c234..e444014 100644
index 4b7c234..f588141 100644
--- a/node_modules/socket.io-parser/dist/is-binary.js
+++ b/node_modules/socket.io-parser/dist/is-binary.js
@@ -1,6 +1,7 @@
@@ -126,10 +126,11 @@ index 4b7c234..e444014 100644
const withNativeArrayBuffer = typeof ArrayBuffer === "function";
const isView = (obj) => {
return typeof ArrayBuffer.isView === "function"
@@ -15,23 +16,37 @@ const withNativeFile = typeof File === "function" ||
@@ -14,24 +15,38 @@ const withNativeBlob = typeof Blob === "function" ||
const withNativeFile = typeof File === "function" ||
(typeof File !== "undefined" &&
toString.call(File) === "[object FileConstructor]");
/**
+/**
+ * Returns true if obj is an ArrayBuffer.
+ * This extra check is made because the "instanceof ArrayBuffer" check does not work
+ * across different execution contexts.
@@ -138,7 +139,7 @@ index 4b7c234..e444014 100644
+function isArrayBuffer(obj) {
+ return typeof obj === 'object' && obj !== null && toString.call(obj) === '[object ArrayBuffer]';
+}
+/**
/**
* Returns true if obj is a Buffer, an ArrayBuffer, a Blob or a File.
*
* @private
@@ -153,7 +154,7 @@ index 4b7c234..e444014 100644
}
exports.isBinary = isBinary;
-function hasBinary(obj, toJSON) {
+function hasBinary(obj, known = []) {
+function hasBinary(obj, known = [], toJSON = false) {
if (!obj || typeof obj !== "object") {
return false;
}
@@ -168,12 +169,14 @@ index 4b7c234..e444014 100644
return true;
}
}
@@ -43,10 +58,10 @@ function hasBinary(obj, toJSON) {
@@ -42,11 +57,11 @@ function hasBinary(obj, toJSON) {
}
if (obj.toJSON &&
typeof obj.toJSON === "function" &&
arguments.length === 1) {
- arguments.length === 1) {
- return hasBinary(obj.toJSON(), true);
+ return hasBinary(obj.toJSON(), known);
+ arguments.length === 2) {
+ return hasBinary(obj.toJSON(), known, true);
}
for (const key in obj) {
- if (Object.prototype.hasOwnProperty.call(obj, key) && hasBinary(obj[key])) {

View File

@@ -3,6 +3,7 @@ const path = require('path')
const server = require('socket.io')
const client = require('socket.io-client')
const parser = require('socket.io-parser')
const { hasBinary } = require('socket.io-parser/dist/is-binary')
const expect = require('chai').expect
const pkg = require('../package.json')
const lib = require('../index')
@@ -217,4 +218,18 @@ describe('Socket', function () {
}
})
})
context('hasBinary', () => {
it('hasBinary handles binary data in toJSON()', () => {
const x = {
toJSON () {
return Buffer.from('123', 'utf8')
},
}
const data = ['a', x]
expect(hasBinary(data)).to.be.true
})
})
})

View File

@@ -25,7 +25,7 @@ const isRightBranch = () => {
process.env.APPVEYOR_REPO_COMMIT_MESSAGE || ''
).includes('[build binary]')
const branchesToBuildBinary = ['develop', 'windows-code-signing']
const branchesToBuildBinary = ['develop', 'fix-test-other-projects']
return branchesToBuildBinary.includes(branch) || shouldForceBinaryBuild
}

174
yarn.lock
View File

@@ -5687,16 +5687,17 @@
dependencies:
"@octokit/types" "^6.0.3"
"@octokit/core@^3.2.3":
version "3.2.5"
resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.2.5.tgz#57becbd5fd789b0592b915840855f3a5f233d554"
integrity sha512-+DCtPykGnvXKWWQI0E1XD+CCeWSBhB6kwItXqfFmNBlIlhczuDPbg+P6BtLnVBaRJDAjv+1mrUJuRsFSjktopg==
"@octokit/core@^3.5.1":
version "3.5.1"
resolved "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz#8601ceeb1ec0e1b1b8217b960a413ed8e947809b"
integrity sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==
dependencies:
"@octokit/auth-token" "^2.4.4"
"@octokit/graphql" "^4.5.8"
"@octokit/request" "^5.4.12"
"@octokit/request" "^5.6.0"
"@octokit/request-error" "^2.0.5"
"@octokit/types" "^6.0.3"
before-after-hook "^2.1.0"
before-after-hook "^2.2.0"
universal-user-agent "^6.0.0"
"@octokit/endpoint@^3.2.0":
@@ -5727,10 +5728,10 @@
"@octokit/types" "^6.0.3"
universal-user-agent "^6.0.0"
"@octokit/openapi-types@^5.3.0":
version "5.3.1"
resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-5.3.1.tgz#a49d119a1b9e47b7a9f5133ab14be2d8afaa183d"
integrity sha512-TvVk2QuIA0lQZcIMd6xbdGaGDVeNYIOa3l1ZVagAIk5K3t/WMYbcg4BISNDhzdVhm/TgQB26frAgd/GV81aHJA==
"@octokit/openapi-types@^10.1.4":
version "10.1.5"
resolved "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-10.1.5.tgz#deafbec805896ae963d7d3846e70b18003cafda1"
integrity sha512-OoShNYzhAU8p8JbGHe1rRs1GIErRtmN2230AQCJAjL5lc0AUU5OhppVe6693HIZ2eCBLUhoLPhnnnmQ5ASH7Wg==
"@octokit/plugin-enterprise-rest@^3.6.1":
version "3.6.2"
@@ -5744,17 +5745,17 @@
dependencies:
"@octokit/types" "^2.0.1"
"@octokit/plugin-paginate-rest@^2.6.2":
version "2.11.0"
resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.11.0.tgz#3568c43896a3355f4a0bbb3a64f443b2abdc760d"
integrity sha512-7L9xQank2G3r1dGqrVPo1z62V5utbykOUzlmNHPz87Pww/JpZQ9KyG5CHtUzgmB4n5iDRKYNK/86A8D98HP0yA==
"@octokit/plugin-paginate-rest@^2.16.0":
version "2.16.1"
resolved "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.16.1.tgz#699ea5c4d0274626bd7c4b896b4789c21ea3540e"
integrity sha512-53RGhlRNhQVepZq063YCoIssZkAYjIU1kWQi9m7Qjdq/1IiuZOB9iSHdjDQmKtHWDRSqNwbtsX+tlJNhP1DHEQ==
dependencies:
"@octokit/types" "^6.11.0"
"@octokit/types" "^6.27.1"
"@octokit/plugin-request-log@^1.0.0", "@octokit/plugin-request-log@^1.0.2":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.3.tgz#70a62be213e1edc04bb8897ee48c311482f9700d"
integrity sha512-4RFU4li238jMJAzLgAwkBAw+4Loile5haQMQr+uhFq27BmyJXcXSKvoQKqh0agsZEiUlW6iSv3FAgvmGkur7OQ==
"@octokit/plugin-request-log@^1.0.0", "@octokit/plugin-request-log@^1.0.4":
version "1.0.4"
resolved "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85"
integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==
"@octokit/plugin-rest-endpoint-methods@2.4.0":
version "2.4.0"
@@ -5764,12 +5765,12 @@
"@octokit/types" "^2.0.1"
deprecation "^2.3.1"
"@octokit/plugin-rest-endpoint-methods@4.13.4":
version "4.13.4"
resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.13.4.tgz#093b130d558760f6bc912c6f622ce502522410af"
integrity sha512-MGxptzVfiP8O+aydC/riheYzS/yJ9P16M29OuvtZep/sF5sKuOCQP8Wf83YCKXRsQF+ZpYfke2snbPPSIMZKzg==
"@octokit/plugin-rest-endpoint-methods@^5.9.0":
version "5.10.2"
resolved "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.10.2.tgz#84ae65ae3f40b2d8a25bf7db7c1054a15d9383b6"
integrity sha512-Q1QdPqA1HuKbXBuUnyNEImp948htcxgOVwUFTbUbRUsWSJPhabDe3Imd+C8vZg2czpBkl9uR8zx71WE1CP9TxA==
dependencies:
"@octokit/types" "^6.12.0"
"@octokit/types" "^6.27.1"
deprecation "^2.3.1"
"@octokit/request-error@^1.0.2":
@@ -5781,10 +5782,10 @@
deprecation "^2.0.0"
once "^1.4.0"
"@octokit/request-error@^2.0.0":
version "2.0.5"
resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.0.5.tgz#72cc91edc870281ad583a42619256b380c600143"
integrity sha512-T/2wcCFyM7SkXzNoyVNWjyVlUwBvW3igM3Btr/eKYiPmucXTtkxt2RBsf6gn3LTzaLSLTQtNmvg+dGsOxQrjZg==
"@octokit/request-error@^2.0.5", "@octokit/request-error@^2.1.0":
version "2.1.0"
resolved "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz#9e150357831bfc788d13a4fd4b1913d60c74d677"
integrity sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==
dependencies:
"@octokit/types" "^6.0.3"
deprecation "^2.0.0"
@@ -5802,18 +5803,16 @@
once "^1.4.0"
universal-user-agent "^2.0.1"
"@octokit/request@^5.2.0", "@octokit/request@^5.3.0", "@octokit/request@^5.4.12":
version "5.4.14"
resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.14.tgz#ec5f96f78333bb2af390afa5ff66f114b063bc96"
integrity sha512-VkmtacOIQp9daSnBmDI92xNIeLuSRDOIuplp/CJomkvzt7M18NXgG044Cx/LFKLgjKt9T2tZR6AtJayba9GTSA==
"@octokit/request@^5.2.0", "@octokit/request@^5.3.0", "@octokit/request@^5.6.0":
version "5.6.1"
resolved "https://registry.npmjs.org/@octokit/request/-/request-5.6.1.tgz#f97aff075c37ab1d427c49082fefeef0dba2d8ce"
integrity sha512-Ls2cfs1OfXaOKzkcxnqw5MR6drMA/zWX/LIS/p8Yjdz7QKTPQLMsB3R+OvoxE6XnXeXEE2X7xe4G4l4X0gRiKQ==
dependencies:
"@octokit/endpoint" "^6.0.1"
"@octokit/request-error" "^2.0.0"
"@octokit/types" "^6.7.1"
deprecation "^2.0.0"
"@octokit/request-error" "^2.1.0"
"@octokit/types" "^6.16.1"
is-plain-object "^5.0.0"
node-fetch "^2.6.1"
once "^1.4.0"
universal-user-agent "^6.0.0"
"@octokit/rest@16.23.2":
@@ -5834,6 +5833,16 @@
universal-user-agent "^2.0.0"
url-template "^2.0.8"
"@octokit/rest@18.10.0", "@octokit/rest@^18.0.0":
version "18.10.0"
resolved "https://registry.npmjs.org/@octokit/rest/-/rest-18.10.0.tgz#8a0add9611253e0e31d3ed5b4bc941a3795a7648"
integrity sha512-esHR5OKy38bccL/sajHqZudZCvmv4yjovMJzyXlphaUo7xykmtOdILGJ3aAm0mFHmMLmPFmDMJXf39cAjNJsrw==
dependencies:
"@octokit/core" "^3.5.1"
"@octokit/plugin-paginate-rest" "^2.16.0"
"@octokit/plugin-request-log" "^1.0.4"
"@octokit/plugin-rest-endpoint-methods" "^5.9.0"
"@octokit/rest@^16.28.4":
version "16.43.2"
resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.43.2.tgz#c53426f1e1d1044dee967023e3279c50993dd91b"
@@ -5856,16 +5865,6 @@
once "^1.4.0"
universal-user-agent "^4.0.0"
"@octokit/rest@^18.0.0":
version "18.3.4"
resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.3.4.tgz#8e7ab02cd509e2fe7e71917a54254a8f8b827f20"
integrity sha512-NES0pHbwyFB1D0jrLkdnIXgEmze/gLE0JoSNgfAe4vwD77/qaQGO/lRWNuPPsoBVBjiW6mmA9CU5cYHujJTKQA==
dependencies:
"@octokit/core" "^3.2.3"
"@octokit/plugin-paginate-rest" "^2.6.2"
"@octokit/plugin-request-log" "^1.0.2"
"@octokit/plugin-rest-endpoint-methods" "4.13.4"
"@octokit/types@^2.0.0", "@octokit/types@^2.0.1":
version "2.16.2"
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-2.16.2.tgz#4c5f8da3c6fecf3da1811aef678fda03edac35d2"
@@ -5873,12 +5872,12 @@
dependencies:
"@types/node" ">= 8"
"@octokit/types@^6.0.3", "@octokit/types@^6.11.0", "@octokit/types@^6.12.0", "@octokit/types@^6.7.1":
version "6.12.0"
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.12.0.tgz#8376fd60edfd5d1eebfeedb994c6bcb5b862c7a1"
integrity sha512-KwOf16soD7aDEEi/PgNeJlHzjZPfrmmNy+7WezSdrpnqZ7YImBJcNnX9+5RUHt1MnA4h8oISRHTqaZDGsX9DRQ==
"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.27.1":
version "6.27.1"
resolved "https://registry.npmjs.org/@octokit/types/-/types-6.27.1.tgz#88ec25f0cff5fb637c475cf420a0a2e35ba564c7"
integrity sha512-p8VR2OTO1ozxqdAvPeCDDMNmcBzkOL6sPogy2MaEQCapbeWcWNDbwZnqMT3VTZ0DLBBAO0PyHYzU8bA99zd1Fg==
dependencies:
"@octokit/openapi-types" "^5.3.0"
"@octokit/openapi-types" "^10.1.4"
"@opentelemetry/api@0.14.0":
version "0.14.0"
@@ -10461,14 +10460,6 @@ after@0.8.2:
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=
agent-base@2:
version "2.1.1"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-2.1.1.tgz#d6de10d5af6132d5bd692427d46fc538539094c7"
integrity sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=
dependencies:
extend "~3.0.0"
semver "~5.0.1"
agent-base@4, agent-base@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
@@ -12941,10 +12932,10 @@ before-after-hook@^1.4.0:
resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-1.4.0.tgz#2b6bf23dca4f32e628fd2747c10a37c74a4b484d"
integrity sha512-l5r9ir56nda3qu14nAXIlyq1MmUSs0meCIaFAh8HwkFwP1F8eToOuS3ah2VAHHcY04jaYD7FpJC5JTXHYRbkzg==
before-after-hook@^2.0.0, before-after-hook@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.0.tgz#09c40d92e936c64777aa385c4e9b904f8147eaf0"
integrity sha512-jH6rKQIfroBbhEXVmI7XmXe3ix5S/PgJqpzdDPnR8JGLHWNYLsYZ6tK5iWOF/Ra3oqEX0NobXGlzbiylIzVphQ==
before-after-hook@^2.0.0, before-after-hook@^2.2.0:
version "2.2.2"
resolved "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz#a6e8ca41028d90ee2c24222f201c90956091613e"
integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==
better-opn@^2.1.1:
version "2.1.1"
@@ -19619,7 +19610,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2:
assign-symbols "^1.0.0"
is-extendable "^1.0.1"
extend@3, extend@^3.0.0, extend@~3.0.0, extend@~3.0.2:
extend@^3.0.0, extend@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
@@ -20463,14 +20454,6 @@ folktale@2.3.2:
resolved "https://registry.yarnpkg.com/folktale/-/folktale-2.3.2.tgz#38231b039e5ef36989920cbf805bf6b227bf4fd4"
integrity sha512-+8GbtQBwEqutP0v3uajDDoN64K2ehmHd0cjlghhxh0WpcfPzAIjPA03e1VvHlxL02FVGR0A6lwXsNQKn3H1RNQ==
follow-redirects@0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-0.0.7.tgz#34b90bab2a911aa347571da90f22bd36ecd8a919"
integrity sha1-NLkLqyqRGqNHVx2pDyK9NuzYqRk=
dependencies:
debug "^2.2.0"
stream-consume "^0.1.0"
follow-redirects@1.5.10:
version "1.5.10"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
@@ -21286,16 +21269,6 @@ github-slugger@^1.0.0:
dependencies:
emoji-regex ">=6.0.0 <=6.1.1"
github@11.0.0:
version "11.0.0"
resolved "https://registry.yarnpkg.com/github/-/github-11.0.0.tgz#edb32df5efb33cad004ebf0bdd2a4b30bb63a854"
integrity sha1-7bMt9e+zPK0ATr8L3SpLMLtjqFQ=
dependencies:
follow-redirects "0.0.7"
https-proxy-agent "^1.0.0"
mime "^1.2.11"
netrc "^0.1.4"
glob-base@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
@@ -22876,15 +22849,6 @@ https-proxy-agent@5.0.0, https-proxy-agent@^5.0.0:
agent-base "6"
debug "4"
https-proxy-agent@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz#35f7da6c48ce4ddbfa264891ac593ee5ff8671e6"
integrity sha1-NffabEjOTdv6JkiRrFk+5f+GceY=
dependencies:
agent-base "2"
debug "2"
extend "3"
https-proxy-agent@^2.2.3:
version "2.2.4"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
@@ -27358,14 +27322,13 @@ make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0:
dependencies:
semver "^6.0.0"
make-empty-github-commit@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/make-empty-github-commit/-/make-empty-github-commit-1.2.0.tgz#5cf1402b12d509933fb2b66355a1434c8dbeec17"
integrity sha512-Rkme2QetJ4+C0eV32wHGW8myhYM12NL0ComCWIJhhr9fgxcHyCBpaC5Ljb2cdsi44ck20IugyUmlzBqoONtrDg==
make-empty-github-commit@cypress-io/make-empty-github-commit#4a592aedb776ba2f4cc88979055315a53eec42ee:
version "0.0.0-development"
resolved "https://codeload.github.com/cypress-io/make-empty-github-commit/tar.gz/4a592aedb776ba2f4cc88979055315a53eec42ee"
dependencies:
"@octokit/rest" "18.10.0"
debug "3.1.0"
github "11.0.0"
minimist "1.2.0"
minimist "1.2.5"
parse-github-repo-url "1.4.1"
make-error@^1, make-error@^1.1.1:
@@ -27928,7 +27891,7 @@ mime-types@^2.1.12, mime-types@^2.1.18, mime-types@^2.1.21, mime-types@^2.1.27,
dependencies:
mime-db "1.49.0"
mime@1.6.0, mime@^1.2.11, mime@^1.3.4, mime@^1.4.1, mime@^1.6.0:
mime@1.6.0, mime@^1.3.4, mime@^1.4.1, mime@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
@@ -28975,11 +28938,6 @@ nested-error-stacks@^2.0.0, nested-error-stacks@^2.1.0:
resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz#0fbdcf3e13fe4994781280524f8b96b0cdff9c61"
integrity sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==
netrc@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/netrc/-/netrc-0.1.4.tgz#6be94fcaca8d77ade0a9670dc460914c94472444"
integrity sha1-a+lPysqNd63gqWcNxGCRTJRHJEQ=
next-tick@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
@@ -36185,11 +36143,6 @@ semver@~2.3.1:
resolved "https://registry.yarnpkg.com/semver/-/semver-2.3.2.tgz#b9848f25d6cf36333073ec9ef8856d42f1233e52"
integrity sha1-uYSPJdbPNjMwc+ye+IVtQvEjPlI=
semver@~5.0.1:
version "5.0.3"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.0.3.tgz#77466de589cd5d3c95f138aa78bc569a3cb5d27a"
integrity sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=
send@0.17.1:
version "0.17.1"
resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
@@ -37642,11 +37595,6 @@ stream-combiner@~0.0.4:
dependencies:
duplexer "~0.1.1"
stream-consume@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/stream-consume/-/stream-consume-0.1.1.tgz#d3bdb598c2bd0ae82b8cac7ac50b1107a7996c48"
integrity sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==
stream-each@^1.1.0:
version "1.2.3"
resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae"