mirror of
https://github.com/cypress-io/cypress.git
synced 2026-03-09 10:09:52 -05:00
feat: add next preset to webpack-dev-server-fresh (#21069)
Co-authored-by: Tim Griesser <tgriesser10@gmail.com>
This commit is contained in:
74
npm/webpack-dev-server-fresh/cypress/e2e/next.cy.ts
Normal file
74
npm/webpack-dev-server-fresh/cypress/e2e/next.cy.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
// <reference types="cypress" />
|
||||
/// <reference path="../support/e2e.ts" />
|
||||
import type { ProjectFixtureDir } from '@tooling/system-tests/lib/fixtureDirs'
|
||||
|
||||
const WEBPACK_REACT: ProjectFixtureDir[] = ['next-11', 'next-12', 'next-11-webpack-4']
|
||||
|
||||
// Add to this list to focus on a particular permutation
|
||||
const ONLY_PROJECTS: ProjectFixtureDir[] = []
|
||||
|
||||
for (const project of WEBPACK_REACT) {
|
||||
if (ONLY_PROJECTS.length && !ONLY_PROJECTS.includes(project)) {
|
||||
continue
|
||||
}
|
||||
|
||||
describe(`Working with ${project}`, () => {
|
||||
beforeEach(() => {
|
||||
cy.scaffoldProject(project)
|
||||
cy.openProject(project)
|
||||
cy.startAppServer('component')
|
||||
})
|
||||
|
||||
it('should mount a passing test', () => {
|
||||
cy.visitApp()
|
||||
cy.contains('index.cy.js').click()
|
||||
cy.get('.passed > .num').should('contain', 1)
|
||||
})
|
||||
|
||||
it('should live-reload on src changes', () => {
|
||||
cy.visitApp()
|
||||
|
||||
cy.contains('index.cy.js').click()
|
||||
cy.get('.passed > .num').should('contain', 1)
|
||||
|
||||
cy.withCtx(async (ctx) => {
|
||||
const indexPath = ctx.path.join('pages', 'index.js')
|
||||
|
||||
await ctx.actions.file.writeFileInProject(
|
||||
indexPath,
|
||||
(await ctx.file.readFileInProject(indexPath)).replace('Welcome to', 'Hello from'),
|
||||
)
|
||||
})
|
||||
|
||||
cy.get('.failed > .num', { timeout: 10000 }).should('contain', 1)
|
||||
|
||||
cy.withCtx(async (ctx) => {
|
||||
const indexTestPath = ctx.path.join('pages', 'index.cy.js')
|
||||
|
||||
await ctx.actions.file.writeFileInProject(
|
||||
indexTestPath,
|
||||
(await ctx.file.readFileInProject(indexTestPath)).replace('Welcome to', 'Hello from'),
|
||||
)
|
||||
})
|
||||
|
||||
cy.get('.passed > .num').should('contain', 1)
|
||||
})
|
||||
|
||||
it('should detect new spec', () => {
|
||||
cy.visitApp()
|
||||
|
||||
cy.withCtx(async (ctx) => {
|
||||
const newTestPath = ctx.path.join('pages', 'New.cy.js')
|
||||
const indexTestPath = ctx.path.join('pages', 'index.cy.js')
|
||||
|
||||
await ctx.actions.file.writeFileInProject(
|
||||
newTestPath,
|
||||
await ctx.file.readFileInProject(indexTestPath),
|
||||
)
|
||||
})
|
||||
|
||||
cy.contains('New.cy.js').click()
|
||||
cy.get('.passed > .num').should('contain', 1)
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -4,13 +4,14 @@ import type WebpackDevServer from 'webpack-dev-server'
|
||||
import type { Compiler, Configuration } from 'webpack'
|
||||
|
||||
import { createWebpackDevServer } from './createWebpackDevServer'
|
||||
import { sourceRelativeWebpackModules } from './helpers/sourceRelativeWebpackModules'
|
||||
import type { AddressInfo } from 'net'
|
||||
import debugLib from 'debug'
|
||||
import type { Server } from 'http'
|
||||
import { vueCliHandler } from './helpers/vueCliHandler'
|
||||
import { nuxtHandler } from './helpers/nuxtHandler'
|
||||
import { createReactAppHandler } from './helpers/createReactAppHandler'
|
||||
import { nextHandler } from './helpers/nextHandler'
|
||||
import { sourceDefaultWebpackDependencies, SourceRelativeWebpackResult } from './helpers/sourceRelativeWebpackModules'
|
||||
|
||||
const debug = debugLib('cypress:webpack-dev-server-fresh:devServer')
|
||||
|
||||
@@ -23,7 +24,7 @@ export type WebpackDevServerConfig = {
|
||||
webpackConfig?: unknown // Derived from the user's webpack
|
||||
}
|
||||
|
||||
const ALL_FRAMEWORKS = ['create-react-app', 'nuxt', 'react', 'vue-cli'] as const
|
||||
const ALL_FRAMEWORKS = ['create-react-app', 'nuxt', 'react', 'vue-cli', 'next', 'vue'] as const
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@@ -111,6 +112,31 @@ export function devServer (devServerConfig: WebpackDevServerConfig): Promise<Cyp
|
||||
})
|
||||
}
|
||||
|
||||
export type PresetHandlerResult = { frameworkConfig?: Configuration, sourceWebpackModulesResult: SourceRelativeWebpackResult }
|
||||
|
||||
async function getPreset (devServerConfig: WebpackDevServerConfig): Promise<PresetHandlerResult> {
|
||||
switch (devServerConfig.framework) {
|
||||
case 'create-react-app':
|
||||
return createReactAppHandler(devServerConfig)
|
||||
case 'nuxt':
|
||||
return await nuxtHandler(devServerConfig)
|
||||
|
||||
case 'vue-cli':
|
||||
return vueCliHandler(devServerConfig)
|
||||
|
||||
case 'next':
|
||||
return await nextHandler(devServerConfig)
|
||||
|
||||
case 'react':
|
||||
case 'vue':
|
||||
case undefined:
|
||||
return { sourceWebpackModulesResult: sourceDefaultWebpackDependencies(devServerConfig) }
|
||||
|
||||
default:
|
||||
throw new Error(`Unexpected framework ${devServerConfig.framework}, expected one of ${ALL_FRAMEWORKS.join(', ')}`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously create the webpack server instance, without starting.
|
||||
* Useful for testing
|
||||
@@ -118,29 +144,7 @@ export function devServer (devServerConfig: WebpackDevServerConfig): Promise<Cyp
|
||||
* @internal
|
||||
*/
|
||||
devServer.create = async function (devServerConfig: WebpackDevServerConfig) {
|
||||
const sourceWebpackModulesResult = sourceRelativeWebpackModules(devServerConfig)
|
||||
|
||||
let frameworkConfig: Configuration | undefined
|
||||
|
||||
// If we have a framework specified, source the associated config
|
||||
if (typeof devServerConfig.framework === 'string') {
|
||||
switch (devServerConfig.framework) {
|
||||
case 'create-react-app':
|
||||
frameworkConfig = createReactAppHandler({ devServerConfig, sourceWebpackModulesResult })
|
||||
break
|
||||
case 'react':
|
||||
break
|
||||
case 'nuxt':
|
||||
frameworkConfig = await nuxtHandler({ devServerConfig, sourceWebpackModulesResult })
|
||||
break
|
||||
|
||||
case 'vue-cli':
|
||||
frameworkConfig = vueCliHandler({ devServerConfig, sourceWebpackModulesResult })
|
||||
break
|
||||
default:
|
||||
throw new Error(`Unexpected framework ${devServerConfig.framework}, expected one of ${ALL_FRAMEWORKS.join(', ')}`)
|
||||
}
|
||||
}
|
||||
const { frameworkConfig, sourceWebpackModulesResult } = await getPreset(devServerConfig)
|
||||
|
||||
const { server, compiler } = createWebpackDevServer({
|
||||
devServerConfig,
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
import type { CreateFinalWebpackConfig } from '../createWebpackDevServer'
|
||||
import debugLib from 'debug'
|
||||
import type { Configuration, ResolvePluginInstance, RuleSetRule } from 'webpack'
|
||||
import path from 'path'
|
||||
|
||||
type PresetHandlerOptions = Omit<CreateFinalWebpackConfig, 'frameworkConfig'>
|
||||
import type { PresetHandlerResult, WebpackDevServerConfig } from '../devServer'
|
||||
import { sourceDefaultWebpackDependencies } from './sourceRelativeWebpackModules'
|
||||
|
||||
const debug = debugLib('cypress:webpack-dev-server-fresh:create-react-app')
|
||||
|
||||
/**
|
||||
* Sourcing the config for create-react-app
|
||||
*/
|
||||
export function createReactAppHandler (presetHandler: PresetHandlerOptions) {
|
||||
const { devServerConfig, sourceWebpackModulesResult } = presetHandler
|
||||
export function createReactAppHandler (devServerConfig: WebpackDevServerConfig): PresetHandlerResult {
|
||||
const sourceWebpackModulesResult = sourceDefaultWebpackDependencies(devServerConfig)
|
||||
|
||||
// this is required because
|
||||
// 1) we use our own HMR and we don't need react-refresh transpiling overhead
|
||||
// 2) it doesn't work with process.env=test @see https://github.com/cypress-io/cypress-realworld-app/pull/832
|
||||
process.env.FAST_REFRESH = 'false'
|
||||
const webpackConfig = loadWebpackConfig(presetHandler)
|
||||
const webpackConfig = loadWebpackConfig(devServerConfig)
|
||||
|
||||
addCypressToWebpackEslintRulesInPlace(webpackConfig)
|
||||
|
||||
@@ -32,10 +31,13 @@ export function createReactAppHandler (presetHandler: PresetHandlerOptions) {
|
||||
reactScriptsFiveModifications(webpackConfig)
|
||||
}
|
||||
|
||||
return webpackConfig
|
||||
return {
|
||||
frameworkConfig: webpackConfig,
|
||||
sourceWebpackModulesResult,
|
||||
}
|
||||
}
|
||||
|
||||
function loadWebpackConfig ({ devServerConfig }: PresetHandlerOptions): Configuration {
|
||||
function loadWebpackConfig (devServerConfig: WebpackDevServerConfig): Configuration {
|
||||
let webpackConfigPath: string
|
||||
|
||||
const envName = 'test'
|
||||
|
||||
250
npm/webpack-dev-server-fresh/src/helpers/nextHandler.ts
Normal file
250
npm/webpack-dev-server-fresh/src/helpers/nextHandler.ts
Normal file
@@ -0,0 +1,250 @@
|
||||
import debugLib from 'debug'
|
||||
import Module from 'module'
|
||||
import type { Configuration } from 'webpack'
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import type { PresetHandlerResult, WebpackDevServerConfig } from '../devServer'
|
||||
import { cypressWebpackPath, getMajorVersion, ModuleClass, SourcedDependency, SourcedWebpack, sourceFramework, sourceHtmlWebpackPlugin, sourceWebpackDevServer } from './sourceRelativeWebpackModules'
|
||||
|
||||
const debug = debugLib('cypress:webpack-dev-server-fresh:nextHandler')
|
||||
|
||||
export async function nextHandler (devServerConfig: WebpackDevServerConfig): Promise<PresetHandlerResult> {
|
||||
const webpackConfig = await loadWebpackConfig(devServerConfig)
|
||||
|
||||
debug('resolved next.js webpack config %o', webpackConfig)
|
||||
|
||||
checkSWC(webpackConfig, devServerConfig.cypressConfig)
|
||||
|
||||
// Next webpack compiler ignored watching any node_modules changes, but we need to watch
|
||||
// for changes to 'dist/browser.js' in order to detect new specs that have been added
|
||||
if (webpackConfig.watchOptions && Array.isArray(webpackConfig.watchOptions.ignored)) {
|
||||
webpackConfig.watchOptions = {
|
||||
...webpackConfig.watchOptions,
|
||||
ignored: [...webpackConfig.watchOptions.ignored.filter((pattern: string) => !/node_modules/.test(pattern)), '**/node_modules/!(@cypress/webpack-dev-server/dist/browser.js)**'],
|
||||
}
|
||||
|
||||
debug('found options next.js watchOptions.ignored %O', webpackConfig.watchOptions.ignored)
|
||||
}
|
||||
|
||||
return { frameworkConfig: webpackConfig, sourceWebpackModulesResult: sourceNextWebpackDeps(devServerConfig) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquire the modules needed to load the Next webpack config. We are using Next's APIs to grab the webpackConfig
|
||||
* but since this is in the binary, we have to `require.resolve` them from the projectRoot
|
||||
* `loadConfig` acquires the next.config.js
|
||||
* `getNextJsBaseWebpackConfig` acquires the webpackConfig dependent on the next.config.js
|
||||
*/
|
||||
function getNextJsPackages (devServerConfig: WebpackDevServerConfig) {
|
||||
const resolvePaths = { paths: [devServerConfig.cypressConfig.projectRoot] }
|
||||
const packages = {} as { loadConfig: Function, getNextJsBaseWebpackConfig: Function }
|
||||
|
||||
try {
|
||||
const loadConfigPath = require.resolve('next/dist/server/config', resolvePaths)
|
||||
|
||||
packages.loadConfig = require(loadConfigPath).default
|
||||
} catch (e: any) {
|
||||
throw new Error(`Failed to load "next/dist/server/config" with error: ${e.message ?? e}`)
|
||||
}
|
||||
|
||||
try {
|
||||
const getNextJsBaseWebpackConfigPath = require.resolve('next/dist/build/webpack-config', resolvePaths)
|
||||
|
||||
packages.getNextJsBaseWebpackConfig = require(getNextJsBaseWebpackConfigPath).default
|
||||
} catch (e: any) {
|
||||
throw new Error(`Failed to load "next/dist/build/webpack-config" with error: ${ e.message ?? e}`)
|
||||
}
|
||||
|
||||
return packages
|
||||
}
|
||||
|
||||
async function loadWebpackConfig (devServerConfig: WebpackDevServerConfig): Promise<Configuration> {
|
||||
const { loadConfig, getNextJsBaseWebpackConfig } = getNextJsPackages(devServerConfig)
|
||||
|
||||
const nextConfig = await loadConfig('development', devServerConfig.cypressConfig.projectRoot)
|
||||
const runWebpackSpan = await getRunWebpackSpan()
|
||||
const webpackConfig = await getNextJsBaseWebpackConfig(
|
||||
devServerConfig.cypressConfig.projectRoot,
|
||||
{
|
||||
buildId: `@cypress/react-${Math.random().toString()}`,
|
||||
config: nextConfig,
|
||||
dev: true,
|
||||
isServer: false,
|
||||
pagesDir: findPagesDir(devServerConfig.cypressConfig.projectRoot),
|
||||
entrypoints: {},
|
||||
rewrites: { fallback: [], afterFiles: [], beforeFiles: [] },
|
||||
...runWebpackSpan,
|
||||
},
|
||||
)
|
||||
|
||||
return webpackConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if Next is using the SWC compiler. Compilation will fail if user has `nodeVersion: "bundled"` set
|
||||
* due to SWC certificate issues.
|
||||
*/
|
||||
function checkSWC (
|
||||
webpackConfig: Configuration,
|
||||
cypressConfig: Cypress.PluginConfigOptions,
|
||||
) {
|
||||
const hasSWCLoader = webpackConfig.module?.rules?.some((rule) => {
|
||||
return typeof rule !== 'string' && rule.oneOf?.some(
|
||||
(oneOf) => (oneOf.use as any)?.loader === 'next-swc-loader',
|
||||
)
|
||||
})
|
||||
|
||||
// "resolvedNodePath" is only set when using the user's Node.js, which is required to compile Next.js with SWC optimizations
|
||||
// If it is not set, they have either explicitly set "nodeVersion" to "bundled" or are are using Cypress < 9.0.0 where it was set to "bundled" by default
|
||||
if (hasSWCLoader && cypressConfig.nodeVersion === 'bundled') {
|
||||
throw new Error(`Cypress cannot compile your Next.js application when "nodeVersion" is set to "bundled". Please remove this option from your Cypress configuration file.`)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
||||
// Starting with v11.1.1, a trace is required.
|
||||
// 'next/dist/telemetry/trace/trace' only exists since v10.0.9
|
||||
// and our peerDeps support back to v8 so try-catch this import
|
||||
// Starting from 12.0 trace is now located in 'next/dist/trace/trace'
|
||||
async function getRunWebpackSpan (): Promise<{ runWebpackSpan?: any }> {
|
||||
let trace: (name: string) => any
|
||||
|
||||
try {
|
||||
try {
|
||||
trace = await import('next/dist/telemetry/trace/trace').then((m) => m.trace)
|
||||
|
||||
return { runWebpackSpan: trace('cypress') }
|
||||
} catch (_) {
|
||||
// @ts-ignore
|
||||
trace = await import('next/dist/trace/trace').then((m) => m.trace)
|
||||
|
||||
return { runWebpackSpan: trace('cypress') }
|
||||
}
|
||||
} catch (_) {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
const originalModuleLoad = (Module as ModuleClass)._load
|
||||
|
||||
function sourceNextWebpackDeps (devServerConfig: WebpackDevServerConfig) {
|
||||
const framework = sourceFramework(devServerConfig)!
|
||||
const webpack = sourceNextWebpack(devServerConfig, framework)
|
||||
const webpackDevServer = sourceWebpackDevServer(devServerConfig, framework)
|
||||
const htmlWebpackPlugin = sourceHtmlWebpackPlugin(devServerConfig, framework, webpack)
|
||||
|
||||
return {
|
||||
framework,
|
||||
webpack,
|
||||
webpackDevServer,
|
||||
htmlWebpackPlugin,
|
||||
}
|
||||
}
|
||||
|
||||
function sourceNextWebpack (devServerConfig: WebpackDevServerConfig, framework: SourcedDependency) {
|
||||
const searchRoot = framework.importPath
|
||||
|
||||
debug('NextWebpack: Attempting to load NextWebpack from %s', searchRoot)
|
||||
|
||||
let webpackJsonPath: string
|
||||
const webpack = {} as SourcedWebpack
|
||||
|
||||
try {
|
||||
webpackJsonPath = require.resolve('next/dist/compiled/webpack/package.json', {
|
||||
paths: [searchRoot],
|
||||
})
|
||||
} catch (e) {
|
||||
debug('NextWebpack: Failed to load NextWebpack - %s', e)
|
||||
throw e
|
||||
}
|
||||
|
||||
// Next 11 allows the choice of webpack@4 or webpack@5, depending on the "webpack5" property in their next.config.js
|
||||
// The webpackModule.init" for Next 11 returns a webpack@4 or webpack@4 compiler instance based on this boolean
|
||||
let webpack5 = true
|
||||
const importPath = path.join(path.dirname(webpackJsonPath), 'webpack.js')
|
||||
const webpackModule = require(importPath)
|
||||
|
||||
try {
|
||||
const nextConfig = require(path.resolve(devServerConfig.cypressConfig.projectRoot, 'next.config.js'))
|
||||
|
||||
debug('NextWebpack: next.config.js found - %o', nextConfig)
|
||||
|
||||
if (nextConfig.webpack5 === false) {
|
||||
webpack5 = false
|
||||
}
|
||||
} catch (e) {
|
||||
// No next.config.js, assume webpack 5
|
||||
}
|
||||
|
||||
debug('NextWebpack: webpack5 - %s', webpack5)
|
||||
webpackModule.init(webpack5)
|
||||
|
||||
const packageJson = require(webpackJsonPath)
|
||||
|
||||
webpack.importPath = importPath
|
||||
// The package.json of "next/dist/compiled/webpack/package.json" has no version so we supply the version for later use
|
||||
webpack.packageJson = { ...packageJson, version: webpack5 ? '5' : '4' }
|
||||
webpack.module = webpackModule.webpack
|
||||
webpack.majorVersion = getMajorVersion(webpack.packageJson, [4, 5])
|
||||
|
||||
debug('NextWebpack: Successfully loaded NextWebpack - %o', webpack)
|
||||
|
||||
;(Module as ModuleClass)._load = function (request, parent, isMain) {
|
||||
// Next with webpack@4 doesn't ship certain dependencies that HtmlWebpackPlugin requires, so we patch the resolution through to our bundled version
|
||||
if ((request === 'webpack' || request.startsWith('webpack/')) && webpack.majorVersion === 4) {
|
||||
const resolvePath = require.resolve(request, {
|
||||
paths: [cypressWebpackPath],
|
||||
})
|
||||
|
||||
debug('NextWebpack: Module._load for webpack@4 - %s', resolvePath)
|
||||
|
||||
return originalModuleLoad(resolvePath, parent, isMain)
|
||||
}
|
||||
|
||||
if (request === 'webpack' || request.startsWith('webpack/')) {
|
||||
const resolvePath = require.resolve(request, {
|
||||
paths: [framework.importPath],
|
||||
})
|
||||
|
||||
debug('NextWebpack: Module._load - %s', resolvePath)
|
||||
|
||||
return originalModuleLoad(resolvePath, parent, isMain)
|
||||
}
|
||||
|
||||
return originalModuleLoad(request, parent, isMain)
|
||||
}
|
||||
|
||||
return webpack
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
import type { CreateFinalWebpackConfig } from '../createWebpackDevServer'
|
||||
import debugLib from 'debug'
|
||||
import type { Configuration } from 'webpack'
|
||||
|
||||
type PresetHandler = Omit<CreateFinalWebpackConfig, 'frameworkConfig'>
|
||||
import type { PresetHandlerResult, WebpackDevServerConfig } from '../devServer'
|
||||
import { sourceDefaultWebpackDependencies } from './sourceRelativeWebpackModules'
|
||||
|
||||
const debug = debugLib('cypress:webpack-dev-server-fresh:nuxtHandler')
|
||||
|
||||
export async function nuxtHandler ({ devServerConfig }: PresetHandler): Promise<Configuration> {
|
||||
export async function nuxtHandler (devServerConfig: WebpackDevServerConfig): Promise<PresetHandlerResult> {
|
||||
const sourceWebpackModulesResult = sourceDefaultWebpackDependencies(devServerConfig)
|
||||
|
||||
try {
|
||||
const nuxt = require.resolve('nuxt', {
|
||||
paths: [devServerConfig.cypressConfig.projectRoot],
|
||||
@@ -22,7 +22,7 @@ export async function nuxtHandler ({ devServerConfig }: PresetHandler): Promise<
|
||||
|
||||
debug('webpack config %o', webpackConfig)
|
||||
|
||||
return webpackConfig
|
||||
return { frameworkConfig: webpackConfig, sourceWebpackModulesResult }
|
||||
} catch (e) {
|
||||
console.error(e) // eslint-disable-line no-console
|
||||
throw Error(`Error loading nuxt. Looked in ${require.resolve.paths(devServerConfig.cypressConfig.projectRoot)}`)
|
||||
|
||||
@@ -5,7 +5,7 @@ import debugFn from 'debug'
|
||||
|
||||
const debug = debugFn('cypress:webpack-dev-server-fresh:sourceRelativeWebpackModules')
|
||||
|
||||
type ModuleClass = typeof Module & {
|
||||
export type ModuleClass = typeof Module & {
|
||||
_load(id: string, parent: Module, isMain: boolean): any
|
||||
_resolveFilename(request: string, parent: Module, isMain: boolean, options?: { paths: string[] }): string
|
||||
_cache: Record<string, Module>
|
||||
@@ -16,97 +16,89 @@ export interface PackageJson {
|
||||
version: string
|
||||
}
|
||||
|
||||
export interface SourcedDependency {
|
||||
importPath: string
|
||||
packageJson: PackageJson
|
||||
}
|
||||
|
||||
export interface SourcedWebpack extends SourcedDependency {
|
||||
module: Function
|
||||
majorVersion: 4 | 5
|
||||
}
|
||||
|
||||
export interface SourcedWebpackDevServer extends SourcedDependency {
|
||||
module: {
|
||||
new (...args: unknown[]): unknown
|
||||
}
|
||||
majorVersion: 3 | 4
|
||||
}
|
||||
|
||||
export interface SourcedHtmlWebpackPlugin extends SourcedDependency {
|
||||
module: unknown
|
||||
majorVersion: 4 | 5
|
||||
}
|
||||
|
||||
export interface SourceRelativeWebpackResult {
|
||||
framework?: {
|
||||
importPath: string
|
||||
packageJson: PackageJson
|
||||
}
|
||||
/**
|
||||
* The webpack module instance
|
||||
*/
|
||||
webpack: {
|
||||
importPath: string
|
||||
module: Function
|
||||
packageJson: PackageJson
|
||||
majorVersion: 4 | 5
|
||||
}
|
||||
/**
|
||||
* The webpack dev-server instance
|
||||
*/
|
||||
webpackDevServer: {
|
||||
importPath: string
|
||||
module: {
|
||||
new (...args: unknown[]): unknown
|
||||
}
|
||||
packageJson: PackageJson
|
||||
majorVersion: 3 | 4
|
||||
}
|
||||
/**
|
||||
* html-webpack-plugin
|
||||
*/
|
||||
htmlWebpackPlugin: {
|
||||
importPath: string
|
||||
module: unknown
|
||||
packageJson: PackageJson
|
||||
majorVersion: 4 | 5
|
||||
}
|
||||
framework: SourcedDependency | null
|
||||
webpack: SourcedWebpack
|
||||
webpackDevServer: SourcedWebpackDevServer
|
||||
htmlWebpackPlugin: SourcedHtmlWebpackPlugin
|
||||
}
|
||||
|
||||
const originalModuleLoad = (Module as ModuleClass)._load
|
||||
const originalModuleResolveFilename = (Module as ModuleClass)._resolveFilename
|
||||
|
||||
/**
|
||||
* Based on the current project config, we look for the closest webpack,
|
||||
* webpack-dev-server, and html-webpack-plugin for a user's project
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function sourceRelativeWebpackModules (config: WebpackDevServerConfig) {
|
||||
let searchRoot = config.cypressConfig.projectRoot
|
||||
const result = {
|
||||
webpackDevServer: {},
|
||||
webpack: {},
|
||||
htmlWebpackPlugin: {},
|
||||
} as SourceRelativeWebpackResult
|
||||
// We ship webpack@4 as part of '@cypress/webpack-batteries-included-preprocessor'. The path to this module
|
||||
// serves as our fallback.
|
||||
export const cypressWebpackPath = require.resolve('@cypress/webpack-batteries-included-preprocessor', {
|
||||
paths: [__dirname],
|
||||
})
|
||||
|
||||
// First, we source the framework, ensuring it's sourced from the user's project and not the
|
||||
// Cypress binary. This is the path we use to relative-resolve the
|
||||
// This is generally used for Create React App and Vue CLI and other packages
|
||||
// that ship webpack as a dependency. e.g. your-project/node_modules/react-scripts/node_modules/webpack
|
||||
// So what we do, is we grab the framework's path, and try and find webpack relative to that framework.
|
||||
if (config.framework) {
|
||||
try {
|
||||
const frameworkJsonPath = require.resolve(`${config.framework}/package.json`, {
|
||||
paths: [searchRoot],
|
||||
})
|
||||
// Source the users framework from the provided projectRoot. The framework, if available, will server
|
||||
// as the resolve base for webpack dependency resolution.
|
||||
export function sourceFramework (config: WebpackDevServerConfig): SourcedDependency | null {
|
||||
debug('Framework: Attempting to source framework for %s', config.cypressConfig.projectRoot)
|
||||
if (!config.framework) {
|
||||
debug('Framework: No framework provided')
|
||||
|
||||
debug('Framework JSON path is %s', frameworkJsonPath)
|
||||
const frameworkPathRoot = path.dirname(frameworkJsonPath)
|
||||
|
||||
debug('Framework JSON path root is %s', frameworkPathRoot)
|
||||
|
||||
// Want to make sure we're sourcing this from the user's code. Otherwise we can
|
||||
// warn and tell them they don't have their dependencies installed
|
||||
if (!frameworkPathRoot.includes(config.cypressConfig.cypressBinaryRoot)) {
|
||||
result.framework = {
|
||||
importPath: frameworkPathRoot,
|
||||
packageJson: require(frameworkJsonPath),
|
||||
}
|
||||
|
||||
searchRoot = frameworkPathRoot
|
||||
}
|
||||
} catch (e) {
|
||||
debug('Error %o', e)
|
||||
// TODO
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// Webpack:
|
||||
// At this point, we know where we're looking for webpack!
|
||||
// We've made accommodations for certain frameworks that bundle it in (e.g. react-scripts)
|
||||
let webpackJsonPath: string
|
||||
const framework = { } as SourcedDependency
|
||||
|
||||
debug('search root is %s', searchRoot)
|
||||
try {
|
||||
const frameworkJsonPath = require.resolve(`${config.framework}/package.json`, {
|
||||
paths: [config.cypressConfig.projectRoot],
|
||||
})
|
||||
const frameworkPathRoot = path.dirname(frameworkJsonPath)
|
||||
|
||||
// Want to make sure we're sourcing this from the user's code. Otherwise we can
|
||||
// warn and tell them they don't have their dependencies installed
|
||||
framework.importPath = frameworkPathRoot
|
||||
framework.packageJson = require(frameworkJsonPath)
|
||||
|
||||
debug('Framework: Successfully sourced framework - %o', framework)
|
||||
|
||||
return framework
|
||||
} catch (e) {
|
||||
debug('Framework: Failed to source framework - %s', e)
|
||||
|
||||
// TODO
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// Source the webpack module from the provided framework or projectRoot. We override the module resolution
|
||||
// so that other packages that import webpack resolve to the version we found.
|
||||
// If none is found, we fallback to the bundled version in '@cypress/webpack-batteries-included-preprocessor'.
|
||||
export function sourceWebpack (config: WebpackDevServerConfig, framework: SourcedDependency | null): SourcedWebpack {
|
||||
const searchRoot = framework?.importPath ?? config.cypressConfig.projectRoot
|
||||
|
||||
debug('Webpack: Attempting to source webpack from %s', searchRoot)
|
||||
|
||||
const webpack = { } as SourcedWebpack
|
||||
|
||||
let webpackJsonPath: string
|
||||
|
||||
try {
|
||||
webpackJsonPath = require.resolve('webpack/package.json', {
|
||||
@@ -114,53 +106,63 @@ export function sourceRelativeWebpackModules (config: WebpackDevServerConfig) {
|
||||
})
|
||||
} catch (e) {
|
||||
if ((e as {code?: string}).code !== 'MODULE_NOT_FOUND') {
|
||||
debug('Webpack: Failed to source webpack - %s', e)
|
||||
throw e
|
||||
}
|
||||
|
||||
webpackJsonPath = require.resolve('webpack/package.json', {
|
||||
paths: [
|
||||
require.resolve('@cypress/webpack-batteries-included-preprocessor', {
|
||||
paths: [__dirname],
|
||||
}),
|
||||
],
|
||||
})
|
||||
debug('Webpack: Falling back to bundled version')
|
||||
|
||||
debug('using webpack-batteries-included %s', webpackJsonPath)
|
||||
webpackJsonPath = require.resolve('webpack/package.json', {
|
||||
paths: [cypressWebpackPath],
|
||||
})
|
||||
}
|
||||
|
||||
result.webpack.importPath = path.dirname(webpackJsonPath)
|
||||
result.webpack.packageJson = require(webpackJsonPath)
|
||||
result.webpack.module = require(result.webpack.importPath)
|
||||
result.webpack.majorVersion = getMajorVersion(result.webpack.packageJson, [4, 5])
|
||||
webpack.importPath = path.dirname(webpackJsonPath)
|
||||
webpack.packageJson = require(webpackJsonPath)
|
||||
webpack.module = require(webpack.importPath)
|
||||
webpack.majorVersion = getMajorVersion(webpack.packageJson, [4, 5])
|
||||
|
||||
const webpackImportPath = result.webpack.importPath
|
||||
debug('Webpack: Successfully sourced webpack - %o', webpack)
|
||||
|
||||
;(Module as ModuleClass)._load = function (request, parent, isMain) {
|
||||
if (request === 'webpack' || request.startsWith('webpack/')) {
|
||||
const resolvePath = require.resolve(request, {
|
||||
paths: [webpackImportPath],
|
||||
paths: [webpack.importPath],
|
||||
})
|
||||
|
||||
debug('Resolve path %s', resolvePath)
|
||||
debug('Webpack: Module._load resolvePath - %s', resolvePath)
|
||||
|
||||
return originalModuleLoad(resolvePath, parent, isMain)
|
||||
}
|
||||
|
||||
return originalModuleLoad(request, parent, isMain)
|
||||
};
|
||||
}
|
||||
|
||||
(Module as ModuleClass)._resolveFilename = function (request, parent, isMain, options) {
|
||||
;(Module as ModuleClass)._resolveFilename = function (request, parent, isMain, options) {
|
||||
if (request === 'webpack' || request.startsWith('webpack/') && !options?.paths) {
|
||||
return originalModuleResolveFilename(request, parent, isMain, {
|
||||
paths: [webpackImportPath],
|
||||
const resolveFilename = originalModuleResolveFilename(request, parent, isMain, {
|
||||
paths: [webpack.importPath],
|
||||
})
|
||||
|
||||
debug('Webpack: Module._resolveFilename resolveFilename - %s', resolveFilename)
|
||||
|
||||
return resolveFilename
|
||||
}
|
||||
|
||||
return originalModuleResolveFilename(request, parent, isMain, options)
|
||||
}
|
||||
|
||||
// Webpack dev server:
|
||||
return webpack
|
||||
}
|
||||
|
||||
// Source the webpack-dev-server module from the provided framework or projectRoot.
|
||||
// If none is found, we fallback to the version bundled with this package.
|
||||
export function sourceWebpackDevServer (config: WebpackDevServerConfig, framework?: SourcedDependency | null): SourcedWebpackDevServer {
|
||||
const searchRoot = framework?.importPath ?? config.cypressConfig.projectRoot
|
||||
|
||||
debug('WebpackDevServer: Attempting to source webpack-dev-server from %s', searchRoot)
|
||||
|
||||
const webpackDevServer = { } as SourcedWebpackDevServer
|
||||
let webpackDevServerJsonPath: string
|
||||
|
||||
try {
|
||||
@@ -169,23 +171,36 @@ export function sourceRelativeWebpackModules (config: WebpackDevServerConfig) {
|
||||
})
|
||||
} catch (e) {
|
||||
if ((e as {code?: string}).code !== 'MODULE_NOT_FOUND') {
|
||||
debug('WebpackDevServer: Failed to source webpack-dev-server - %s', e)
|
||||
throw e
|
||||
}
|
||||
|
||||
debug('WebpackDevServer: Falling back to bundled version')
|
||||
|
||||
webpackDevServerJsonPath = require.resolve('webpack-dev-server/package.json', {
|
||||
paths: [
|
||||
__dirname,
|
||||
],
|
||||
paths: [cypressWebpackPath],
|
||||
})
|
||||
}
|
||||
|
||||
result.webpackDevServer.importPath = path.dirname(webpackDevServerJsonPath)
|
||||
result.webpackDevServer.packageJson = require(webpackDevServerJsonPath)
|
||||
result.webpackDevServer.module = require(result.webpackDevServer.importPath)
|
||||
result.webpackDevServer.majorVersion = getMajorVersion(result.webpackDevServer.packageJson, [3, 4])
|
||||
webpackDevServer.importPath = path.dirname(webpackDevServerJsonPath)
|
||||
webpackDevServer.packageJson = require(webpackDevServerJsonPath)
|
||||
webpackDevServer.module = require(webpackDevServer.importPath)
|
||||
webpackDevServer.majorVersion = getMajorVersion(webpackDevServer.packageJson, [3, 4])
|
||||
|
||||
// Webpack HTML Plugin:
|
||||
debug('WebpackDevServer: Successfully sourced webpack-dev-server - %o', webpackDevServer)
|
||||
|
||||
return webpackDevServer
|
||||
}
|
||||
|
||||
// Source the html-webpack-plugin module from the provided framework or projectRoot.
|
||||
// If none is found, we fallback to the version bundled with this package dependent on the major version of webpack.
|
||||
// We ship both v4 and v5 of 'html-webpack-plugin' by aliasing the package with the major version (check package.json).
|
||||
export function sourceHtmlWebpackPlugin (config: WebpackDevServerConfig, framework: SourcedDependency | null, webpack: SourcedWebpack): SourcedHtmlWebpackPlugin {
|
||||
const searchRoot = framework?.importPath ?? config.cypressConfig.projectRoot
|
||||
|
||||
debug('HtmlWebpackPlugin: Attempting to source html-webpack-plugin from %s', searchRoot)
|
||||
|
||||
const htmlWebpackPlugin = { } as SourcedHtmlWebpackPlugin
|
||||
let htmlWebpackPluginJsonPath: string
|
||||
|
||||
try {
|
||||
@@ -193,18 +208,21 @@ export function sourceRelativeWebpackModules (config: WebpackDevServerConfig) {
|
||||
paths: [searchRoot],
|
||||
})
|
||||
|
||||
result.htmlWebpackPlugin.packageJson = require(htmlWebpackPluginJsonPath)
|
||||
htmlWebpackPlugin.packageJson = require(htmlWebpackPluginJsonPath)
|
||||
// Check that they're not using v3 of html-webpack-plugin. Since we should be the only consumer of it,
|
||||
// we shouldn't be concerned with using our own copy if they've shipped w/ an earlier version
|
||||
result.htmlWebpackPlugin.majorVersion = getMajorVersion(result.htmlWebpackPlugin.packageJson, [4, 5])
|
||||
htmlWebpackPlugin.majorVersion = getMajorVersion(htmlWebpackPlugin.packageJson, [4, 5])
|
||||
} catch (e) {
|
||||
const err = e as Error & {code?: string}
|
||||
|
||||
if (err.code !== 'MODULE_NOT_FOUND' && !err.message.includes('Unexpected major version')) {
|
||||
debug('HtmlWebpackPlugin: Failed to source html-webpack-plugin - %s', e)
|
||||
throw e
|
||||
}
|
||||
|
||||
const htmlWebpack = `html-webpack-plugin-${result.webpack.majorVersion}`
|
||||
const htmlWebpack = `html-webpack-plugin-${webpack.majorVersion}`
|
||||
|
||||
debug('HtmlWebpackPlugin: Falling back to bundled version %s', htmlWebpack)
|
||||
|
||||
htmlWebpackPluginJsonPath = require.resolve(`${htmlWebpack}/package.json`, {
|
||||
paths: [
|
||||
@@ -213,15 +231,32 @@ export function sourceRelativeWebpackModules (config: WebpackDevServerConfig) {
|
||||
})
|
||||
}
|
||||
|
||||
result.htmlWebpackPlugin.importPath = path.dirname(htmlWebpackPluginJsonPath)
|
||||
result.htmlWebpackPlugin.packageJson = require(htmlWebpackPluginJsonPath)
|
||||
result.htmlWebpackPlugin.module = require(result.htmlWebpackPlugin.importPath)
|
||||
result.htmlWebpackPlugin.majorVersion = getMajorVersion(result.htmlWebpackPlugin.packageJson, [4, 5])
|
||||
htmlWebpackPlugin.importPath = path.dirname(htmlWebpackPluginJsonPath),
|
||||
htmlWebpackPlugin.packageJson = require(htmlWebpackPluginJsonPath),
|
||||
htmlWebpackPlugin.module = require(htmlWebpackPlugin.importPath),
|
||||
htmlWebpackPlugin.majorVersion = getMajorVersion(htmlWebpackPlugin.packageJson, [4, 5])
|
||||
|
||||
return result
|
||||
debug('HtmlWebpackPlugin: Successfully sourced html-webpack-plugin - %o', htmlWebpackPlugin)
|
||||
|
||||
return htmlWebpackPlugin
|
||||
}
|
||||
|
||||
function getMajorVersion <T extends number> (json: PackageJson, acceptedVersions: T[]): T {
|
||||
// Most frameworks follow a similar path for sourcing webpack dependencies so this is a utility to handle all the sourcing.
|
||||
export function sourceDefaultWebpackDependencies (config: WebpackDevServerConfig): SourceRelativeWebpackResult {
|
||||
const framework = sourceFramework(config)
|
||||
const webpack = sourceWebpack(config, framework)
|
||||
const webpackDevServer = sourceWebpackDevServer(config, framework)
|
||||
const htmlWebpackPlugin = sourceHtmlWebpackPlugin(config, framework, webpack)
|
||||
|
||||
return {
|
||||
framework,
|
||||
webpack,
|
||||
webpackDevServer,
|
||||
htmlWebpackPlugin,
|
||||
}
|
||||
}
|
||||
|
||||
export function getMajorVersion <T extends number> (json: PackageJson, acceptedVersions: T[]): T {
|
||||
const major = Number(json.version.split('.')[0])
|
||||
|
||||
if (!acceptedVersions.includes(major as T)) {
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
import type { CreateFinalWebpackConfig } from '../createWebpackDevServer'
|
||||
import debugLib from 'debug'
|
||||
import type { Configuration } from 'webpack'
|
||||
|
||||
type PresetHandler = Omit<CreateFinalWebpackConfig, 'frameworkConfig'>
|
||||
import type { PresetHandlerResult, WebpackDevServerConfig } from '../devServer'
|
||||
import { sourceDefaultWebpackDependencies } from './sourceRelativeWebpackModules'
|
||||
|
||||
const debug = debugLib('cypress:webpack-dev-server-fresh:vueCliHandler')
|
||||
|
||||
export function vueCliHandler ({ devServerConfig }: PresetHandler): Configuration {
|
||||
export function vueCliHandler (devServerConfig: WebpackDevServerConfig): PresetHandlerResult {
|
||||
const sourceWebpackModulesResult = sourceDefaultWebpackDependencies(devServerConfig)
|
||||
|
||||
try {
|
||||
const config = require.resolve('@vue/cli-service/webpack.config', {
|
||||
paths: [devServerConfig.cypressConfig.projectRoot],
|
||||
})
|
||||
|
||||
const webpackConfig = require(config)
|
||||
const webpackConfig = require(config) as Configuration
|
||||
|
||||
debug('webpack config %o', webpackConfig)
|
||||
|
||||
return webpackConfig
|
||||
return { frameworkConfig: webpackConfig, sourceWebpackModulesResult }
|
||||
} catch (e) {
|
||||
console.error(e) // eslint-disable-line no-console
|
||||
throw Error(`Error loading @vue/cli-service/webpack.config.js. Looked in ${require.resolve.paths(devServerConfig.cypressConfig.projectRoot)}`)
|
||||
|
||||
@@ -7,6 +7,7 @@ import fs from 'fs'
|
||||
|
||||
import { devServer } from '..'
|
||||
import { restoreLoadHook } from '../src/helpers/sourceRelativeWebpackModules'
|
||||
import './support'
|
||||
|
||||
const requestSpecFile = (file: string, port: number) => {
|
||||
return new Promise((res) => {
|
||||
|
||||
@@ -17,7 +17,7 @@ describe('devServer', function () {
|
||||
it('creates a new devServer webpack4, webpackDevServer3', async () => {
|
||||
const { devServer } = proxyquire('../src/devServer', {
|
||||
'./helpers/sourceRelativeWebpackModules': {
|
||||
sourceRelativeWebpackModules: () => {
|
||||
sourceDefaultWebpackDependencies: () => {
|
||||
return createModuleMatrixResult({
|
||||
webpack: 4,
|
||||
webpackDevServer: 3,
|
||||
@@ -38,7 +38,7 @@ describe('devServer', function () {
|
||||
it('creates a new devServer webpack4, webpackDevServer4', async () => {
|
||||
const { devServer } = proxyquire('../src/devServer', {
|
||||
'./helpers/sourceRelativeWebpackModules': {
|
||||
sourceRelativeWebpackModules: () => {
|
||||
sourceDefaultWebpackDependencies: () => {
|
||||
return createModuleMatrixResult({
|
||||
webpack: 4,
|
||||
webpackDevServer: 4,
|
||||
@@ -59,7 +59,7 @@ describe('devServer', function () {
|
||||
it('creates a new devServer webpack5, webpackDevServer4', async () => {
|
||||
const { devServer } = proxyquire('../src/devServer', {
|
||||
'./helpers/sourceRelativeWebpackModules': {
|
||||
sourceRelativeWebpackModules: () => {
|
||||
sourceDefaultWebpackDependencies: () => {
|
||||
return createModuleMatrixResult({
|
||||
webpack: 5,
|
||||
webpackDevServer: 4,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { scaffoldMigrationProject } from '../test-helpers/scaffoldProject'
|
||||
import { expect } from 'chai'
|
||||
import { createReactAppHandler, cypressGlobals } from '../../src/helpers/createReactAppHandler'
|
||||
import { SourceRelativeWebpackResult } from '../../src/helpers/sourceRelativeWebpackModules'
|
||||
import { WebpackDevServerConfig } from '../../src/devServer'
|
||||
import { Configuration } from 'webpack'
|
||||
import * as path from 'path'
|
||||
import '../support'
|
||||
|
||||
const expectEslintModifications = (webpackConfig: Configuration) => {
|
||||
const eslintPlugin: any = webpackConfig.plugins?.find((plugin) => plugin.constructor.name === 'ESLintWebpackPlugin')
|
||||
@@ -55,12 +55,9 @@ describe('createReactAppHandler', function () {
|
||||
|
||||
process.chdir(projectRoot)
|
||||
|
||||
const webpackConfig = createReactAppHandler({
|
||||
devServerConfig: {
|
||||
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
|
||||
} as WebpackDevServerConfig,
|
||||
sourceWebpackModulesResult: { webpack: { majorVersion: 4 } } as SourceRelativeWebpackResult,
|
||||
})
|
||||
const { frameworkConfig: webpackConfig } = createReactAppHandler({
|
||||
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
|
||||
} as WebpackDevServerConfig)
|
||||
|
||||
expect(webpackConfig.mode).eq('development')
|
||||
expectEslintModifications(webpackConfig)
|
||||
@@ -73,12 +70,9 @@ describe('createReactAppHandler', function () {
|
||||
|
||||
process.chdir(projectRoot)
|
||||
|
||||
const webpackConfig = createReactAppHandler({
|
||||
devServerConfig: {
|
||||
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
|
||||
} as WebpackDevServerConfig,
|
||||
sourceWebpackModulesResult: { webpack: { majorVersion: 5 } } as SourceRelativeWebpackResult,
|
||||
})
|
||||
const { frameworkConfig: webpackConfig } = createReactAppHandler({
|
||||
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
|
||||
} as WebpackDevServerConfig)
|
||||
|
||||
expect(webpackConfig.mode).eq('development')
|
||||
expectEslintModifications(webpackConfig)
|
||||
@@ -88,16 +82,13 @@ describe('createReactAppHandler', function () {
|
||||
})
|
||||
|
||||
it('sources the config from ejected cra', async () => {
|
||||
const projectRoot = await scaffoldMigrationProject('cra-5')
|
||||
const projectRoot = await scaffoldMigrationProject('cra-ejected')
|
||||
|
||||
process.chdir(projectRoot)
|
||||
|
||||
const webpackConfig = createReactAppHandler({
|
||||
devServerConfig: {
|
||||
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
|
||||
} as WebpackDevServerConfig,
|
||||
sourceWebpackModulesResult: { webpack: { majorVersion: 5 } } as SourceRelativeWebpackResult,
|
||||
})
|
||||
const { frameworkConfig: webpackConfig } = createReactAppHandler({
|
||||
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
|
||||
} as WebpackDevServerConfig)
|
||||
|
||||
expect(webpackConfig.mode).eq('development')
|
||||
expectEslintModifications(webpackConfig)
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import { scaffoldMigrationProject } from '../test-helpers/scaffoldProject'
|
||||
import { expect } from 'chai'
|
||||
import { nextHandler } from '../../src/helpers/nextHandler'
|
||||
import type { Configuration } from 'webpack'
|
||||
import * as path from 'path'
|
||||
import { WebpackDevServerConfig } from '../../src/devServer'
|
||||
import '../support'
|
||||
|
||||
const expectWatchOverrides = (webpackConfig: Configuration) => {
|
||||
expect(webpackConfig.watchOptions.ignored).to.contain('**/node_modules/!(@cypress/webpack-dev-server/dist/browser.js)**')
|
||||
}
|
||||
|
||||
const expectPagesDir = (webpackConfig: Configuration, projectRoot: string) => {
|
||||
const ReactLoadablePlugin: any = webpackConfig.plugins.find((plugin) => plugin.constructor.name === 'ReactLoadablePlugin')
|
||||
|
||||
expect(ReactLoadablePlugin.pagesDir).eq(path.join(projectRoot, 'pages'))
|
||||
}
|
||||
|
||||
const expectWebpackSpan = (webpackConfig: Configuration) => {
|
||||
const ProfilingPlugin: any = webpackConfig.plugins.find((plugin) => plugin.constructor.name === 'ProfilingPlugin')
|
||||
|
||||
expect(ProfilingPlugin.runWebpackSpan).to.exist
|
||||
}
|
||||
|
||||
describe('nextHandler', function () {
|
||||
// can take a while since we install node_modules
|
||||
this.timeout(1000 * 60)
|
||||
|
||||
it('sources from a next-12 project', async () => {
|
||||
const projectRoot = await scaffoldMigrationProject('next-12')
|
||||
|
||||
process.chdir(projectRoot)
|
||||
|
||||
const { frameworkConfig: webpackConfig } = await nextHandler({
|
||||
framework: 'next',
|
||||
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
|
||||
} as WebpackDevServerConfig)
|
||||
|
||||
expectWatchOverrides(webpackConfig)
|
||||
expectPagesDir(webpackConfig, projectRoot)
|
||||
expectWebpackSpan(webpackConfig)
|
||||
})
|
||||
|
||||
it('sources from a next-11 project', async () => {
|
||||
const projectRoot = await scaffoldMigrationProject('next-11')
|
||||
|
||||
process.chdir(projectRoot)
|
||||
|
||||
const { frameworkConfig: webpackConfig } = await nextHandler({
|
||||
framework: 'next',
|
||||
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
|
||||
} as WebpackDevServerConfig)
|
||||
|
||||
expectWatchOverrides(webpackConfig)
|
||||
expectPagesDir(webpackConfig, projectRoot)
|
||||
expectWebpackSpan(webpackConfig)
|
||||
})
|
||||
|
||||
it('throws if nodeVersion is set to bundled', async () => {
|
||||
const projectRoot = await scaffoldMigrationProject('next-12')
|
||||
|
||||
process.chdir(projectRoot)
|
||||
|
||||
let err
|
||||
|
||||
try {
|
||||
await nextHandler({
|
||||
|
||||
framework: 'next', cypressConfig: { projectRoot, nodeVersion: 'bundled' } as Cypress.PluginConfigOptions,
|
||||
} as WebpackDevServerConfig)
|
||||
} catch (e) {
|
||||
err = e
|
||||
}
|
||||
|
||||
expect(err.message).to.contain('Cypress cannot compile your Next.js application when "nodeVersion" is set to "bundled".')
|
||||
})
|
||||
})
|
||||
@@ -1,6 +1,8 @@
|
||||
import { scaffoldMigrationProject } from '../test-helpers/scaffoldProject'
|
||||
import { expect } from 'chai'
|
||||
import { nuxtHandler } from '../../src/helpers/nuxtHandler'
|
||||
import { WebpackDevServerConfig } from '../../src/devServer'
|
||||
import '../support'
|
||||
|
||||
describe('nuxtHandler', function () {
|
||||
// can take a while since we install node_modules
|
||||
@@ -11,14 +13,12 @@ describe('nuxtHandler', function () {
|
||||
|
||||
process.chdir(projectRoot)
|
||||
|
||||
const config = await nuxtHandler({
|
||||
devServerConfig: {
|
||||
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
|
||||
},
|
||||
} as any)
|
||||
const { frameworkConfig: webpackConfig } = await nuxtHandler({
|
||||
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
|
||||
} as WebpackDevServerConfig)
|
||||
|
||||
// Verify it's a Vue-specific webpack config by seeing if VueLoader is present.
|
||||
expect(config.plugins.find((plug) => plug.constructor.name === 'VueLoader'))
|
||||
expect(config.performance).to.be.undefined
|
||||
expect(webpackConfig.plugins.find((plug) => plug.constructor.name === 'VueLoader'))
|
||||
expect(webpackConfig.performance).to.be.undefined
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { scaffoldMigrationProject } from '../test-helpers/scaffoldProject'
|
||||
import { expect } from 'chai'
|
||||
import { vueCliHandler } from '../../src/helpers/vueCliHandler'
|
||||
import { WebpackDevServerConfig } from '../../src/devServer'
|
||||
import '../support'
|
||||
|
||||
describe('vueCliHandler', function () {
|
||||
// can take a while since we install node_modules
|
||||
@@ -11,14 +13,12 @@ describe('vueCliHandler', function () {
|
||||
|
||||
process.chdir(projectRoot)
|
||||
|
||||
const config = vueCliHandler({
|
||||
devServerConfig: {
|
||||
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
|
||||
},
|
||||
} as any)
|
||||
const { frameworkConfig: webpackConfig } = vueCliHandler({
|
||||
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
|
||||
} as WebpackDevServerConfig)
|
||||
|
||||
// Verify it's a Vue-specific webpack config by seeing if VueLoader is present.
|
||||
expect(config.plugins.find((plug) => plug.constructor.name === 'VueLoader'))
|
||||
expect(webpackConfig.plugins.find((plug) => plug.constructor.name === 'VueLoader'))
|
||||
})
|
||||
|
||||
it('sources from a @vue/cli-service@4.x project with Vue 2', async () => {
|
||||
@@ -26,13 +26,11 @@ describe('vueCliHandler', function () {
|
||||
|
||||
process.chdir(projectRoot)
|
||||
|
||||
const config = vueCliHandler({
|
||||
devServerConfig: {
|
||||
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
|
||||
},
|
||||
} as any)
|
||||
const { frameworkConfig: webpackConfig } = vueCliHandler({
|
||||
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
|
||||
} as WebpackDevServerConfig)
|
||||
|
||||
// Verify it's a Vue-specific webpack config by seeing if VueLoader is present.
|
||||
expect(config.plugins.find((plug) => plug.constructor.name === 'VueLoader'))
|
||||
expect(webpackConfig.plugins.find((plug) => plug.constructor.name === 'VueLoader'))
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,7 +2,7 @@ import { expect } from 'chai'
|
||||
import EventEmitter from 'events'
|
||||
import snapshot from 'snap-shot-it'
|
||||
import { WebpackDevServerConfig } from '../src/devServer'
|
||||
import { sourceRelativeWebpackModules } from '../src/helpers/sourceRelativeWebpackModules'
|
||||
import { sourceDefaultWebpackDependencies } from '../src/helpers/sourceRelativeWebpackModules'
|
||||
import { makeWebpackConfig } from '../src/makeWebpackConfig'
|
||||
|
||||
describe('makeWebpackConfig', () => {
|
||||
@@ -24,7 +24,7 @@ describe('makeWebpackConfig', () => {
|
||||
}
|
||||
const actual = await makeWebpackConfig({
|
||||
devServerConfig,
|
||||
sourceWebpackModulesResult: sourceRelativeWebpackModules(devServerConfig),
|
||||
sourceWebpackModulesResult: sourceDefaultWebpackDependencies(devServerConfig),
|
||||
})
|
||||
|
||||
// plugins contain circular deps which cannot be serialized in a snapshot.
|
||||
|
||||
@@ -5,8 +5,9 @@ import { expect } from 'chai'
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
|
||||
import { restoreLoadHook, sourceRelativeWebpackModules } from '../src/helpers/sourceRelativeWebpackModules'
|
||||
import { sourceDefaultWebpackDependencies } from '../src/helpers/sourceRelativeWebpackModules'
|
||||
import { WebpackDevServerConfig } from '../src/devServer'
|
||||
import './support'
|
||||
|
||||
type ProjectDirs = typeof fixtureDirs
|
||||
|
||||
@@ -45,7 +46,7 @@ async function sourceModulesForProject (fixture: ProjectDirs[number]) {
|
||||
|
||||
await FixturesScaffold.scaffoldProjectNodeModules(fixture)
|
||||
|
||||
const result = sourceRelativeWebpackModules({
|
||||
const result = sourceDefaultWebpackDependencies({
|
||||
cypressConfig: {
|
||||
projectRoot,
|
||||
},
|
||||
@@ -56,16 +57,7 @@ async function sourceModulesForProject (fixture: ProjectDirs[number]) {
|
||||
|
||||
// Ensures that we are properly sourcing the webpacks from the node_modules in the given project,
|
||||
// rather than from the node_modules in the project root
|
||||
describe('sourceRelativeWebpackModules', () => {
|
||||
beforeEach(() => {
|
||||
delete require.cache
|
||||
restoreLoadHook()
|
||||
})
|
||||
|
||||
after(() => {
|
||||
restoreLoadHook()
|
||||
})
|
||||
|
||||
describe('sourceDefaultWebpackDependencies', () => {
|
||||
for (const [fixture, versionsToMatch] of Object.entries(WEBPACK_REACT)) {
|
||||
describe(fixture, () => {
|
||||
it(`sources the correct webpack versions for ${fixture}`, async () => {
|
||||
|
||||
10
npm/webpack-dev-server-fresh/test/support.ts
Normal file
10
npm/webpack-dev-server-fresh/test/support.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { restoreLoadHook } from '../src/helpers/sourceRelativeWebpackModules'
|
||||
|
||||
beforeEach(() => {
|
||||
delete require.cache
|
||||
restoreLoadHook()
|
||||
})
|
||||
|
||||
after(() => {
|
||||
restoreLoadHook()
|
||||
})
|
||||
18
system-tests/project-fixtures/next/cypress.config.js
Normal file
18
system-tests/project-fixtures/next/cypress.config.js
Normal file
@@ -0,0 +1,18 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
component: {
|
||||
devServer: {
|
||||
framework: 'next',
|
||||
bundler: 'webpack',
|
||||
// Necessary due to cypress/react resolving from cypress/node_modules rather than the project root
|
||||
webpackConfig: {
|
||||
resolve: {
|
||||
alias: {
|
||||
'react': path.resolve(__dirname, './node_modules/react'),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<title>Components App</title>
|
||||
<div id="__next_css__DO_NOT_USE__"></div>
|
||||
</head>
|
||||
<body>
|
||||
<div data-cy-root></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
//
|
||||
7
system-tests/project-fixtures/next/pages/_app.js
Normal file
7
system-tests/project-fixtures/next/pages/_app.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import '../styles/globals.css'
|
||||
|
||||
function MyApp({ Component, pageProps }) {
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
|
||||
export default MyApp
|
||||
5
system-tests/project-fixtures/next/pages/api/hello.js
Normal file
5
system-tests/project-fixtures/next/pages/api/hello.js
Normal file
@@ -0,0 +1,5 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
|
||||
export default function handler(req, res) {
|
||||
res.status(200).json({ name: 'John Doe' })
|
||||
}
|
||||
9
system-tests/project-fixtures/next/pages/index.cy.js
Normal file
9
system-tests/project-fixtures/next/pages/index.cy.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import { mount } from "cypress/react"
|
||||
import Index from "./index.js"
|
||||
|
||||
describe('<Index />', () => {
|
||||
it('renders', () => {
|
||||
mount(<Index />)
|
||||
cy.contains('h1', 'Welcome to Next.js!')
|
||||
})
|
||||
})
|
||||
69
system-tests/project-fixtures/next/pages/index.js
Normal file
69
system-tests/project-fixtures/next/pages/index.js
Normal file
@@ -0,0 +1,69 @@
|
||||
import Head from 'next/head'
|
||||
import Image from 'next/image'
|
||||
import styles from '../styles/Home.module.css'
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<Head>
|
||||
<title>Create Next App</title>
|
||||
<meta name="description" content="Generated by create next app" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
|
||||
<main className={styles.main}>
|
||||
<h1 className={styles.title}>
|
||||
Welcome to <a href="https://nextjs.org">Next.js!</a>
|
||||
</h1>
|
||||
|
||||
<p className={styles.description}>
|
||||
Get started by editing{' '}
|
||||
<code className={styles.code}>pages/index.js</code>
|
||||
</p>
|
||||
|
||||
<div className={styles.grid}>
|
||||
<a href="https://nextjs.org/docs" className={styles.card}>
|
||||
<h2>Documentation →</h2>
|
||||
<p>Find in-depth information about Next.js features and API.</p>
|
||||
</a>
|
||||
|
||||
<a href="https://nextjs.org/learn" className={styles.card}>
|
||||
<h2>Learn →</h2>
|
||||
<p>Learn about Next.js in an interactive course with quizzes!</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://github.com/vercel/next.js/tree/master/examples"
|
||||
className={styles.card}
|
||||
>
|
||||
<h2>Examples →</h2>
|
||||
<p>Discover and deploy boilerplate example Next.js projects.</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
|
||||
className={styles.card}
|
||||
>
|
||||
<h2>Deploy →</h2>
|
||||
<p>
|
||||
Instantly deploy your Next.js site to a public URL with Vercel.
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer className={styles.footer}>
|
||||
<a
|
||||
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Powered by{' '}
|
||||
<span className={styles.logo}>
|
||||
<Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
|
||||
</span>
|
||||
</a>
|
||||
</footer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
BIN
system-tests/project-fixtures/next/public/favicon.ico
Normal file
BIN
system-tests/project-fixtures/next/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
4
system-tests/project-fixtures/next/public/vercel.svg
Normal file
4
system-tests/project-fixtures/next/public/vercel.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="283" height="64" viewBox="0 0 283 64" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M141.04 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.46 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM248.72 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.45 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM200.24 34c0 6 3.92 10 10 10 4.12 0 7.21-1.87 8.8-4.92l7.68 4.43c-3.18 5.3-9.14 8.49-16.48 8.49-11.05 0-19-7.2-19-18s7.96-18 19-18c7.34 0 13.29 3.19 16.48 8.49l-7.68 4.43c-1.59-3.05-4.68-4.92-8.8-4.92-6.07 0-10 4-10 10zm82.48-29v46h-9V5h9zM36.95 0L73.9 64H0L36.95 0zm92.38 5l-27.71 48L73.91 5H84.3l17.32 30 17.32-30h10.39zm58.91 12v9.69c-1-.29-2.06-.49-3.2-.49-5.81 0-10 4-10 10V51h-9V17h9v9.2c0-5.08 5.91-9.2 13.2-9.2z" fill="#000"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
121
system-tests/project-fixtures/next/styles/Home.module.css
Normal file
121
system-tests/project-fixtures/next/styles/Home.module.css
Normal file
@@ -0,0 +1,121 @@
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
padding: 0 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.main {
|
||||
padding: 5rem 0;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
border-top: 1px solid #eaeaea;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.footer a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.title a {
|
||||
color: #0070f3;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.title a:hover,
|
||||
.title a:focus,
|
||||
.title a:active {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 0;
|
||||
line-height: 1.15;
|
||||
font-size: 4rem;
|
||||
}
|
||||
|
||||
.title,
|
||||
.description {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.description {
|
||||
line-height: 1.5;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.code {
|
||||
background: #fafafa;
|
||||
border-radius: 5px;
|
||||
padding: 0.75rem;
|
||||
font-size: 1.1rem;
|
||||
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
|
||||
Bitstream Vera Sans Mono, Courier New, monospace;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
max-width: 800px;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.card {
|
||||
margin: 1rem;
|
||||
padding: 1.5rem;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
border: 1px solid #eaeaea;
|
||||
border-radius: 10px;
|
||||
transition: color 0.15s ease, border-color 0.15s ease;
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
.card:hover,
|
||||
.card:focus,
|
||||
.card:active {
|
||||
color: #0070f3;
|
||||
border-color: #0070f3;
|
||||
}
|
||||
|
||||
.card h2 {
|
||||
margin: 0 0 1rem 0;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.card p {
|
||||
margin: 0;
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 1em;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.grid {
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
16
system-tests/project-fixtures/next/styles/globals.css
Normal file
16
system-tests/project-fixtures/next/styles/globals.css
Normal file
@@ -0,0 +1,16 @@
|
||||
html,
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
3
system-tests/projects/next-11-webpack-4/next.config.js
Normal file
3
system-tests/projects/next-11-webpack-4/next.config.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
webpack5: false,
|
||||
}
|
||||
17
system-tests/projects/next-11-webpack-4/package.json
Normal file
17
system-tests/projects/next-11-webpack-4/package.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "^11.0.0",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2"
|
||||
},
|
||||
"projectFixtureDirectory": "next"
|
||||
}
|
||||
3537
system-tests/projects/next-11-webpack-4/yarn.lock
Normal file
3537
system-tests/projects/next-11-webpack-4/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
17
system-tests/projects/next-11/package.json
Normal file
17
system-tests/projects/next-11/package.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "^11.0.0",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2"
|
||||
},
|
||||
"projectFixtureDirectory": "next"
|
||||
}
|
||||
1961
system-tests/projects/next-11/yarn.lock
Normal file
1961
system-tests/projects/next-11/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
17
system-tests/projects/next-12/package.json
Normal file
17
system-tests/projects/next-12/package.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "12.1.4",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2"
|
||||
},
|
||||
"projectFixtureDirectory": "next"
|
||||
}
|
||||
167
system-tests/projects/next-12/yarn.lock
Normal file
167
system-tests/projects/next-12/yarn.lock
Normal file
@@ -0,0 +1,167 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@next/env@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.1.4.tgz#5af629b43075281ecd7f87938802b7cf5b67e94b"
|
||||
integrity sha512-7gQwotJDKnfMxxXd8xJ2vsX5AzyDxO3zou0+QOXX8/unypA6icw5+wf6A62yKZ6qQ4UZHHxS68pb6UV+wNneXg==
|
||||
|
||||
"@next/swc-android-arm-eabi@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.1.4.tgz#c3dae178b7c15ad627d2e9b8dfb38caecb5c4ac7"
|
||||
integrity sha512-FJg/6a3s2YrUaqZ+/DJZzeZqfxbbWrynQMT1C5wlIEq9aDLXCFpPM/PiOyJh0ahxc0XPmi6uo38Poq+GJTuKWw==
|
||||
|
||||
"@next/swc-android-arm64@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.1.4.tgz#f320d60639e19ecffa1f9034829f2d95502a9a51"
|
||||
integrity sha512-LXraazvQQFBgxIg3Htny6G5V5he9EK7oS4jWtMdTGIikmD/OGByOv8ZjLuVLZLtVm3UIvaAiGtlQSLecxJoJDw==
|
||||
|
||||
"@next/swc-darwin-arm64@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.4.tgz#fd578278312613eddcf3aee26910100509941b63"
|
||||
integrity sha512-SSST/dBymecllZxcqTCcSTCu5o1NKk9I+xcvhn/O9nH6GWjgvGgGkNqLbCarCa0jJ1ukvlBA138FagyrmZ/4rQ==
|
||||
|
||||
"@next/swc-darwin-x64@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.1.4.tgz#ace5f80d8c8348efe194f6d7074c6213c52b3944"
|
||||
integrity sha512-p1lwdX0TVjaoDXQVuAkjtxVBbCL/urgxiMCBwuPDO7TikpXtSRivi+mIzBj5q7ypgICFmIAOW3TyupXeoPRAnA==
|
||||
|
||||
"@next/swc-linux-arm-gnueabihf@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.1.4.tgz#2bf2c83863635f19c71c226a2df936e001cce29c"
|
||||
integrity sha512-67PZlgkCn3TDxacdVft0xqDCL7Io1/C4xbAs0+oSQ0xzp6OzN2RNpuKjHJrJgKd0DsE1XZ9sCP27Qv0591yfyg==
|
||||
|
||||
"@next/swc-linux-arm64-gnu@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.1.4.tgz#d577190f641c9b4b463719dd6b8953b6ba9be8d9"
|
||||
integrity sha512-OnOWixhhw7aU22TQdQLYrgpgFq0oA1wGgnjAiHJ+St7MLj82KTDyM9UcymAMbGYy6nG/TFOOHdTmRMtCRNOw0g==
|
||||
|
||||
"@next/swc-linux-arm64-musl@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.1.4.tgz#e70ffe70393d8f9242deecdb282ce5a8fd588b14"
|
||||
integrity sha512-UoRMzPZnsAavdWtVylYxH8DNC7Uy0i6RrvNwT4PyQVdfANBn2omsUkcH5lgS2O7oaz0nAYLk1vqyZDO7+tJotA==
|
||||
|
||||
"@next/swc-linux-x64-gnu@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.4.tgz#91498a130387fb1961902f2bee55863f8e910cff"
|
||||
integrity sha512-nM+MA/frxlTLUKLJKorctdI20/ugfHRjVEEkcLp/58LGG7slNaP1E5d5dRA1yX6ISjPcQAkywas5VlGCg+uTvA==
|
||||
|
||||
"@next/swc-linux-x64-musl@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.4.tgz#78057b03c148c121553d41521ad38f6c732762ff"
|
||||
integrity sha512-GoRHxkuW4u4yKw734B9SzxJwVdyEJosaZ62P7ifOwcujTxhgBt3y76V2nNUrsSuopcKI2ZTDjaa+2wd5zyeXbA==
|
||||
|
||||
"@next/swc-win32-arm64-msvc@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.1.4.tgz#05bbaabacac23b8edf6caa99eb86b17550a09051"
|
||||
integrity sha512-6TQkQze0ievXwHJcVUrIULwCYVe3ccX6T0JgZ1SiMeXpHxISN7VJF/O8uSCw1JvXZYZ6ud0CJ7nfC5HXivgfPg==
|
||||
|
||||
"@next/swc-win32-ia32-msvc@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.1.4.tgz#8fd2fb48f04a2802e51fc320878bf6b411c1c866"
|
||||
integrity sha512-CsbX/IXuZ5VSmWCpSetG2HD6VO5FTsO39WNp2IR2Ut/uom9XtLDJAZqjQEnbUTLGHuwDKFjrIO3LkhtROXLE/g==
|
||||
|
||||
"@next/swc-win32-x64-msvc@12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.4.tgz#a72ed44c9b1f850986a30fe36c59e01f8a79b5f3"
|
||||
integrity sha512-JtYuWzKXKLDMgE/xTcFtCm1MiCIRaAc5XYZfYX3n/ZWSI1SJS/GMm+Su0SAHJgRFavJh6U/p998YwO/iGTIgqQ==
|
||||
|
||||
caniuse-lite@^1.0.30001283:
|
||||
version "1.0.30001328"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001328.tgz#0ed7a2ca65ec45872c613630201644237ba1e329"
|
||||
integrity sha512-Ue55jHkR/s4r00FLNiX+hGMMuwml/QGqqzVeMQ5thUewznU2EdULFvI3JR7JJid6OrjJNfFvHY2G2dIjmRaDDQ==
|
||||
|
||||
"js-tokens@^3.0.0 || ^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
||||
loose-envify@^1.1.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||
dependencies:
|
||||
js-tokens "^3.0.0 || ^4.0.0"
|
||||
|
||||
nanoid@^3.1.30:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.2.tgz#c89622fafb4381cd221421c69ec58547a1eec557"
|
||||
integrity sha512-CuHBogktKwpm5g2sRgv83jEy2ijFzBwMoYA60orPDR7ynsLijJDqgsi4RDGj3OJpy3Ieb+LYwiRmIOGyytgITA==
|
||||
|
||||
next@12.1.4:
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-12.1.4.tgz#597a9bdec7aec778b442c4f6d41afd2c64a54b23"
|
||||
integrity sha512-DA4g97BM4Z0nKtDvCTm58RxdvoQyYzeg0AeVbh0N4Y/D8ELrNu47lQeEgRGF8hV4eQ+Sal90zxrJQQG/mPQ8CQ==
|
||||
dependencies:
|
||||
"@next/env" "12.1.4"
|
||||
caniuse-lite "^1.0.30001283"
|
||||
postcss "8.4.5"
|
||||
styled-jsx "5.0.1"
|
||||
optionalDependencies:
|
||||
"@next/swc-android-arm-eabi" "12.1.4"
|
||||
"@next/swc-android-arm64" "12.1.4"
|
||||
"@next/swc-darwin-arm64" "12.1.4"
|
||||
"@next/swc-darwin-x64" "12.1.4"
|
||||
"@next/swc-linux-arm-gnueabihf" "12.1.4"
|
||||
"@next/swc-linux-arm64-gnu" "12.1.4"
|
||||
"@next/swc-linux-arm64-musl" "12.1.4"
|
||||
"@next/swc-linux-x64-gnu" "12.1.4"
|
||||
"@next/swc-linux-x64-musl" "12.1.4"
|
||||
"@next/swc-win32-arm64-msvc" "12.1.4"
|
||||
"@next/swc-win32-ia32-msvc" "12.1.4"
|
||||
"@next/swc-win32-x64-msvc" "12.1.4"
|
||||
|
||||
object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
|
||||
picocolors@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
||||
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
|
||||
|
||||
postcss@8.4.5:
|
||||
version "8.4.5"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95"
|
||||
integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==
|
||||
dependencies:
|
||||
nanoid "^3.1.30"
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.1"
|
||||
|
||||
react-dom@17.0.2:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
|
||||
integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
scheduler "^0.20.2"
|
||||
|
||||
react@17.0.2:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
|
||||
integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
scheduler@^0.20.2:
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
|
||||
integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
source-map-js@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
||||
|
||||
styled-jsx@5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.1.tgz#78fecbbad2bf95ce6cd981a08918ce4696f5fc80"
|
||||
integrity sha512-+PIZ/6Uk40mphiQJJI1202b+/dYeTVd9ZnMPR80pgiWbjIwvN2zIp4r9et0BgqBuShh48I0gttPlAXA7WVvBxw==
|
||||
Reference in New Issue
Block a user