mirror of
https://github.com/cypress-io/cypress.git
synced 2026-03-09 10:09:52 -05:00
fix(component-testing): Fix webpack-dev-server deps validation crash (#15708)
Co-authored-by: Lachlan Miller <lachlan.miller.1990@outlook.com> Co-authored-by: ElevateBart <ledouxb@gmail.com> Co-authored-by: Barthélémy Ledoux <bart@cypress.io>
This commit is contained in:
committed by
GitHub
parent
cd66b05307
commit
254eb47d91
@@ -1,4 +1,4 @@
|
||||
export const MIN_SUPPORTED_VERSION = {
|
||||
'react-scripts': '^=3.x || ^=4.x',
|
||||
next: '^=9.x',
|
||||
next: '^=9.x || ^=10.x',
|
||||
}
|
||||
|
||||
@@ -51,16 +51,22 @@ async function askForComponentTesting () {
|
||||
return shouldSetupComponentTesting
|
||||
}
|
||||
|
||||
function printCypressCommandsHelper ({ useYarn }: { useYarn: boolean }) {
|
||||
const displayedCommand = useYarn ? 'yarn' : 'npx'
|
||||
function printCypressCommandsHelper (options: { shouldSetupComponentTesting: boolean, useYarn: boolean }) {
|
||||
const printCommand = (command: string, description: string) => {
|
||||
const displayedRunner = options.useYarn ? 'yarn' : 'npx'
|
||||
|
||||
console.log('Inside this directory, you can run several commands:')
|
||||
console.log()
|
||||
console.log(chalk.cyan(` ${displayedCommand} cypress open`))
|
||||
console.log(' Opens cypress local development app.')
|
||||
console.log()
|
||||
console.log(chalk.cyan(` ${displayedCommand} cypress run`))
|
||||
console.log(' Runs tests in headless mode.')
|
||||
console.log()
|
||||
console.log(chalk.cyan(` ${displayedRunner} ${command}`))
|
||||
console.log(` ${description}`)
|
||||
}
|
||||
|
||||
printCommand('cypress open', 'Opens cypress local development app.')
|
||||
printCommand('cypress run', 'Runs tests in headless mode.')
|
||||
|
||||
if (options.shouldSetupComponentTesting) {
|
||||
printCommand('cypress open-ct', 'Opens cypress component-testing web app.')
|
||||
printCommand('cypress run', 'Runs component testing in headless mode.')
|
||||
}
|
||||
}
|
||||
|
||||
export async function main ({ useNpm, ignoreTs, setupComponentTesting, ignoreExamples }: MainArgv) {
|
||||
@@ -92,7 +98,7 @@ export async function main ({ useNpm, ignoreTs, setupComponentTesting, ignoreExa
|
||||
}
|
||||
|
||||
console.log(`\n👍 Success! Cypress is installed and ready to run tests.`)
|
||||
printCypressCommandsHelper({ useYarn })
|
||||
printCypressCommandsHelper({ useYarn, shouldSetupComponentTesting })
|
||||
|
||||
console.log(`\nHappy testing with ${chalk.green('cypress.io')} 🌲\n`)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
/// <reference types="cypress" />
|
||||
import * as React from 'react'
|
||||
import RouterPage from '../../pages/router'
|
||||
import { createRouter } from 'next/router'
|
||||
import { RouterContext } from 'next/dist/next-server/lib/router-context'
|
||||
import { mount } from '@cypress/react'
|
||||
|
||||
@@ -22,6 +21,9 @@ describe('Component with router usage', () => {
|
||||
reload: cy.spy(),
|
||||
back: cy.spy(),
|
||||
prefetch: cy.spy(),
|
||||
isReady: true,
|
||||
isPreview: false,
|
||||
isLocaleDomain: false,
|
||||
beforePopState: cy.spy(),
|
||||
}
|
||||
|
||||
@@ -34,33 +36,6 @@ describe('Component with router usage', () => {
|
||||
cy.contains('Next.js route /testPath')
|
||||
})
|
||||
|
||||
it('renders the component that uses next.js with parsed query', () => {
|
||||
// alternatively you can use next's internal `createRouter` function to create a real instance of NextRouter
|
||||
const router = createRouter(
|
||||
'/testPath',
|
||||
{ param1: 'param1' },
|
||||
'/asTestPath',
|
||||
{
|
||||
subscription: cy.spy(),
|
||||
initialProps: {},
|
||||
App: cy.spy(),
|
||||
Component: cy.spy(),
|
||||
pageLoader: cy.spy(),
|
||||
initialStyleSheets: [],
|
||||
wrapApp: cy.spy(),
|
||||
isFallback: false,
|
||||
},
|
||||
)
|
||||
|
||||
mount(
|
||||
<RouterContext.Provider value={router}>
|
||||
<RouterPage />
|
||||
</RouterContext.Provider>,
|
||||
)
|
||||
|
||||
cy.contains('My query: {"param1":"param1"}')
|
||||
})
|
||||
|
||||
it('pushes the new route', () => {
|
||||
const router = {
|
||||
pathname: '/router',
|
||||
@@ -76,6 +51,9 @@ describe('Component with router usage', () => {
|
||||
reload: cy.spy(),
|
||||
back: cy.spy(),
|
||||
prefetch: cy.spy(),
|
||||
isReady: true,
|
||||
isPreview: false,
|
||||
isLocaleDomain: false,
|
||||
beforePopState: cy.spy(),
|
||||
}
|
||||
|
||||
|
||||
@@ -15,12 +15,11 @@
|
||||
"devDependencies": {
|
||||
"@cypress/react": "file:../../dist",
|
||||
"@mdx-js/loader": "^1.6.16",
|
||||
"@next/mdx": "10.0.7",
|
||||
"@next/mdx": "10.1.2",
|
||||
"@zeit/next-sass": "^1.0.1",
|
||||
"check-code-coverage": "1.9.2",
|
||||
"cypress-circleci-reporter": "0.2.0",
|
||||
"next": "10.0.7",
|
||||
"webpack": "^4.44.2"
|
||||
"next": "10.1.2"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -69,7 +69,7 @@
|
||||
"lodash": "4.17.15",
|
||||
"mobx": "6.0.0",
|
||||
"mobx-react-lite": "3.0.0",
|
||||
"next": "^9.5.3",
|
||||
"next": "^10.1.2",
|
||||
"pretty": "2.0.0",
|
||||
"prop-types": "15.7.2",
|
||||
"radioactive-state": "1.3.4",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// @ts-check
|
||||
/// <reference types="next" />
|
||||
const debug = require('debug')('@cypress/react')
|
||||
const loadConfig = require('next/dist/next-server/server/config').default
|
||||
const getNextJsBaseWebpackConfig = require('next/dist/build/webpack-config').default
|
||||
@@ -14,7 +15,7 @@ async function getNextWebpackConfig (config) {
|
||||
isServer: false,
|
||||
pagesDir: config.projectRoot,
|
||||
entrypoints: {},
|
||||
rewrites: [],
|
||||
rewrites: { fallback: [], afterFiles: [], beforeFiles: [] },
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
const { validatePeerDependencies } = require('./dist/errors')
|
||||
|
||||
validatePeerDependencies()
|
||||
|
||||
module.exports = require('./dist')
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@cypress/webpack-dev-server",
|
||||
"version": "0.0.0-development",
|
||||
"description": "Launches Webpack Dev Server for Component Testing",
|
||||
"main": "index.js",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"build-prod": "tsc",
|
||||
@@ -25,9 +25,9 @@
|
||||
"webpack-dev-server": "^3.11.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"html-webpack-plugin": "> 3",
|
||||
"webpack": "> 4",
|
||||
"webpack-dev-server": "> 3"
|
||||
"html-webpack-plugin": ">=4",
|
||||
"webpack": ">=4",
|
||||
"webpack-dev-server": ">=4"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
export interface MissingDependency {
|
||||
prettyName: string
|
||||
packageName: string
|
||||
}
|
||||
|
||||
const peerDeps: MissingDependency[] = [
|
||||
{
|
||||
prettyName: 'Webpack Dev Server',
|
||||
packageName: 'webpack-dev-server',
|
||||
},
|
||||
{
|
||||
prettyName: 'Html Webpack Plugin',
|
||||
packageName: 'html-webpack-plugin',
|
||||
},
|
||||
{
|
||||
prettyName: 'Webpack',
|
||||
packageName: 'webpack',
|
||||
},
|
||||
]
|
||||
|
||||
const makePrettyLibs = (libs) => {
|
||||
return libs.reduce((acc, curr, idx) => {
|
||||
acc.prettyNames.push(curr.prettyName)
|
||||
acc.packageNames.push(curr.packageName)
|
||||
|
||||
if (idx >= libs.length) return acc
|
||||
|
||||
return {
|
||||
prettyNames: acc.prettyNames.join(', '),
|
||||
packageNames: acc.packageNames.join(' '),
|
||||
}
|
||||
}, { prettyNames: [], packageNames: [] })
|
||||
}
|
||||
|
||||
export class MissingPeerDependency extends Error {
|
||||
private libs: { prettyNames: string[], packageNames: string[] }
|
||||
|
||||
constructor (message,
|
||||
libs: MissingDependency[]) {
|
||||
const prettyLibs = makePrettyLibs(libs)
|
||||
|
||||
super(`${message} ${prettyLibs.prettyNames}`)
|
||||
this.name = 'PeerDependencyMissing'
|
||||
this.libs = prettyLibs
|
||||
|
||||
Object.setPrototypeOf(this, MissingPeerDependency.prototype)
|
||||
}
|
||||
|
||||
get prettyMessage () {
|
||||
return `❌ Missing ${this.libs.prettyNames}. Please install them with npm or yarn.
|
||||
|
||||
npm i ${this.libs.packageNames} -D
|
||||
yarn add ${this.libs.packageNames} --dev
|
||||
|
||||
Updating webpack config is unnecessary
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
export function validatePeerDependencies () {
|
||||
const missingPeerDeps = peerDeps.filter((peerDep) => {
|
||||
try {
|
||||
require(peerDep.packageName)
|
||||
} catch (err) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
if (missingPeerDeps.length) {
|
||||
const error = new MissingPeerDependency(`@cypress/webpack-dev-server is missing peer dependencies`, missingPeerDeps)
|
||||
|
||||
console.error(error.prettyMessage) // eslint-disable-line
|
||||
|
||||
throw error
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
import { debug as debugFn } from 'debug'
|
||||
import { AddressInfo } from 'net'
|
||||
import { start as createDevServer } from './startServer'
|
||||
import { UserWebpackDevServerOptions } from './makeWebpackConfig'
|
||||
import { start as createDevServer, StartDevServer } from './startServer'
|
||||
|
||||
const debug = debugFn('cypress:webpack-dev-server:webpack')
|
||||
|
||||
@@ -12,12 +11,7 @@ export interface ResolvedDevServerConfig {
|
||||
close: (done?: DoneCallback) => void
|
||||
}
|
||||
|
||||
export interface StartDevServer extends UserWebpackDevServerOptions {
|
||||
/* this is the Cypress options object */
|
||||
options: Cypress.DevServerOptions
|
||||
/* support passing a path to the user's webpack config */
|
||||
webpackConfig?: Record<string, any>
|
||||
}
|
||||
export { StartDevServer }
|
||||
|
||||
export async function startDevServer (startDevServerArgs: StartDevServer, exitProcess = process.exit) {
|
||||
const webpackDevServer = await createDevServer(startDevServerArgs, exitProcess)
|
||||
|
||||
@@ -22,7 +22,7 @@ interface MakeWebpackConfigOptions extends CypressCTOptionsPluginOptions, UserWe
|
||||
isOpenMode: boolean
|
||||
}
|
||||
|
||||
const mergePublicPath = (baseValue: string, userValue = '/') => {
|
||||
const mergePublicPath = (baseValue = '/', userValue = '/') => {
|
||||
return path.join(baseValue, userValue, '/')
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
import Debug from 'debug'
|
||||
import webpack from 'webpack'
|
||||
import WebpackDevServer from 'webpack-dev-server'
|
||||
import { StartDevServer } from '.'
|
||||
import { makeWebpackConfig } from './makeWebpackConfig'
|
||||
import { makeWebpackConfig, UserWebpackDevServerOptions } from './makeWebpackConfig'
|
||||
|
||||
export interface StartDevServer extends UserWebpackDevServerOptions {
|
||||
/* this is the Cypress options object */
|
||||
options: Cypress.DevServerOptions
|
||||
/* support passing a path to the user's webpack config */
|
||||
webpackConfig?: Record<string, any>
|
||||
}
|
||||
|
||||
const debug = Debug('cypress:webpack-dev-server:start')
|
||||
|
||||
@@ -40,19 +46,6 @@ export async function start ({ webpackConfig: userWebpackConfig, options, ...use
|
||||
|
||||
debug('starting webpack dev server')
|
||||
|
||||
// TODO: write a test for how we are NOT modifying publicPath
|
||||
// here, and instead stripping it out of the cypress proxy layer
|
||||
//
|
||||
// ...this prevents a problem if users have a 'before' or 'after'
|
||||
// function defined in their webpack config, it does NOT
|
||||
// interfere with their routes... otherwise the public
|
||||
// path we are prefixing like /__cypress/src/ would be
|
||||
// prepended to req.url and cause their routing handlers to fail
|
||||
//
|
||||
// NOTE: we are merging in webpackConfig.devServer here so
|
||||
// that user values for the devServer get passed on correctly
|
||||
// since we are passing in the compiler directly, and these
|
||||
// devServer options would otherwise get ignored
|
||||
const webpackDevServerConfig = {
|
||||
...userWebpackConfig.devServer,
|
||||
hot: false,
|
||||
|
||||
@@ -14,6 +14,6 @@ module.exports = {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
},
|
||||
plugins: [new HtmlWebpackPlugin({
|
||||
template: path.join(__dirname, '../index-template.html'),
|
||||
template: path.resolve(__dirname, '..', 'index-template.html'),
|
||||
})],
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user