Skip to content

Commit

Permalink
fix: map framework name to dependency that contains webpack (#22774)
Browse files Browse the repository at this point in the history
  • Loading branch information
ZachJW34 committed Jul 15, 2022
1 parent 97ec820 commit 7e0de0b
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 38 deletions.
2 changes: 1 addition & 1 deletion npm/webpack-dev-server/src/devServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export type WebpackDevServerConfig = {
webpackConfig?: unknown // Derived from the user's webpack
}

const ALL_FRAMEWORKS = ['create-react-app', 'nuxt', 'react', 'vue-cli', 'next', 'vue'] as const
export const ALL_FRAMEWORKS = ['create-react-app', 'nuxt', 'react', 'vue-cli', 'next', 'vue'] as const

/**
* @internal
Expand Down
25 changes: 22 additions & 3 deletions npm/webpack-dev-server/src/helpers/sourceRelativeWebpackModules.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Module from 'module'
import path from 'path'
import type { WebpackDevServerConfig } from '../devServer'
import type { WebpackDevServerConfig, ALL_FRAMEWORKS } from '../devServer'
import debugFn from 'debug'

const debug = debugFn('cypress:webpack-dev-server:sourceRelativeWebpackModules')
Expand Down Expand Up @@ -56,7 +56,18 @@ export const cypressWebpackPath = (config: WebpackDevServerConfig) => {
})
}

// Source the users framework from the provided projectRoot. The framework, if available, will server
type FrameworkWebpackMapper = { [Property in typeof ALL_FRAMEWORKS[number]]: string | undefined }

const frameworkWebpackMapper: FrameworkWebpackMapper = {
'create-react-app': 'react-scripts',
'vue-cli': '@vue/cli-service',
'nuxt': '@nuxt/webpack',
react: undefined,
vue: undefined,
next: 'next',
}

// Source the users framework from the provided projectRoot. The framework, if available, will serve
// 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)
Expand All @@ -66,10 +77,18 @@ export function sourceFramework (config: WebpackDevServerConfig): SourcedDepende
return null
}

const sourceOfWebpack = frameworkWebpackMapper[config.framework]

if (!sourceOfWebpack) {
debug('Not a higher-order framework so webpack dependencies should be resolvable from projectRoot')

return null
}

const framework = { } as SourcedDependency

try {
const frameworkJsonPath = require.resolve(`${config.framework}/package.json`, {
const frameworkJsonPath = require.resolve(`${sourceOfWebpack}/package.json`, {
paths: [config.cypressConfig.projectRoot],
})
const frameworkPathRoot = path.dirname(frameworkJsonPath)
Expand Down
18 changes: 15 additions & 3 deletions npm/webpack-dev-server/test/handlers/createReactAppHandler.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,45 +55,57 @@ describe('createReactAppHandler', function () {

process.chdir(projectRoot)

const { frameworkConfig: webpackConfig } = createReactAppHandler({
const { frameworkConfig: webpackConfig, sourceWebpackModulesResult } = createReactAppHandler({
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
framework: 'create-react-app',
} as WebpackDevServerConfig)

expect(webpackConfig.mode).eq('development')
expectEslintModifications(webpackConfig)
expectModuleSourceInPlaceModifications(webpackConfig, projectRoot)
expectBabelRuleModifications(webpackConfig, projectRoot)

expect(sourceWebpackModulesResult.framework?.importPath).to.include('react-scripts')
expect(sourceWebpackModulesResult.webpack.majorVersion).eq(4)
})

it('sources the config from react-scripts v5', async () => {
const projectRoot = await scaffoldMigrationProject('cra-5')

process.chdir(projectRoot)

const { frameworkConfig: webpackConfig } = createReactAppHandler({
const { frameworkConfig: webpackConfig, sourceWebpackModulesResult } = createReactAppHandler({
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
framework: 'create-react-app',
} as WebpackDevServerConfig)

expect(webpackConfig.mode).eq('development')
expectEslintModifications(webpackConfig)
expectModuleSourceInPlaceModifications(webpackConfig, projectRoot)
expectBabelRuleModifications(webpackConfig, projectRoot)
expectReactScriptsFiveModifications(webpackConfig)

expect(sourceWebpackModulesResult.framework?.importPath).to.include('react-scripts')
expect(sourceWebpackModulesResult.webpack.majorVersion).eq(5)
})

it('sources the config from ejected cra', async () => {
const projectRoot = await scaffoldMigrationProject('cra-ejected')

process.chdir(projectRoot)

const { frameworkConfig: webpackConfig } = createReactAppHandler({
const { frameworkConfig: webpackConfig, sourceWebpackModulesResult } = createReactAppHandler({
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
framework: 'create-react-app',
} as WebpackDevServerConfig)

expect(webpackConfig.mode).eq('development')
expectEslintModifications(webpackConfig)
expectModuleSourceInPlaceModifications(webpackConfig, projectRoot)
expectBabelRuleModifications(webpackConfig, projectRoot)
expectReactScriptsFiveModifications(webpackConfig)

expect(sourceWebpackModulesResult.framework).to.be.null
expect(sourceWebpackModulesResult.webpack.majorVersion).eq(5)
})
})
28 changes: 26 additions & 2 deletions npm/webpack-dev-server/test/handlers/nextHandler.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,53 @@ describe('nextHandler', function () {

process.chdir(projectRoot)

const { frameworkConfig: webpackConfig } = await nextHandler({
const { frameworkConfig: webpackConfig, sourceWebpackModulesResult } = await nextHandler({
framework: 'next',
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
} as WebpackDevServerConfig)

expectWatchOverrides(webpackConfig)
expectPagesDir(webpackConfig, projectRoot)
expectWebpackSpan(webpackConfig)

expect(sourceWebpackModulesResult.webpack.importPath).to.include('next')
expect(sourceWebpackModulesResult.webpack.majorVersion).eq(5)
})

it('sources from a next-11 project', async () => {
const projectRoot = await scaffoldMigrationProject('next-11')

process.chdir(projectRoot)

const { frameworkConfig: webpackConfig } = await nextHandler({
const { frameworkConfig: webpackConfig, sourceWebpackModulesResult } = await nextHandler({
framework: 'next',
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
} as WebpackDevServerConfig)

expectWatchOverrides(webpackConfig)
expectPagesDir(webpackConfig, projectRoot)
expectWebpackSpan(webpackConfig)

expect(sourceWebpackModulesResult.webpack.importPath).to.include('next')
expect(sourceWebpackModulesResult.webpack.majorVersion).eq(5)
})

it('sources from a next-11-webpack-4 project', async () => {
const projectRoot = await scaffoldMigrationProject('next-11-webpack-4')

process.chdir(projectRoot)

const { frameworkConfig: webpackConfig, sourceWebpackModulesResult } = await nextHandler({
framework: 'next',
cypressConfig: { projectRoot, cypressBinaryRoot: __dirname } as Cypress.PluginConfigOptions,
} as WebpackDevServerConfig)

expectWatchOverrides(webpackConfig)
expectPagesDir(webpackConfig, projectRoot)
expectWebpackSpan(webpackConfig)

expect(sourceWebpackModulesResult.webpack.importPath).to.include('next')
expect(sourceWebpackModulesResult.webpack.majorVersion).eq(4)
})

it('throws if nodeVersion is set to bundled', async () => {
Expand Down
6 changes: 5 additions & 1 deletion npm/webpack-dev-server/test/handlers/nuxtHandler.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ describe('nuxtHandler', function () {

process.chdir(projectRoot)

const { frameworkConfig: webpackConfig } = await nuxtHandler({
const { frameworkConfig: webpackConfig, sourceWebpackModulesResult } = await nuxtHandler({
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
framework: 'nuxt',
} as WebpackDevServerConfig)

// Verify it's a Vue-specific webpack config by seeing if VueLoader is present.
expect(webpackConfig.plugins.find((plug) => plug.constructor.name === 'VueLoader'))
expect(webpackConfig.performance).to.be.undefined

expect(sourceWebpackModulesResult.framework?.importPath).to.include('@nuxt/webpack')
expect(sourceWebpackModulesResult.webpack.majorVersion).eq(4)
})
})
12 changes: 10 additions & 2 deletions npm/webpack-dev-server/test/handlers/vueCliHandler.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,32 @@ describe('vueCliHandler', function () {

process.chdir(projectRoot)

const { frameworkConfig: webpackConfig } = vueCliHandler({
const { frameworkConfig: webpackConfig, sourceWebpackModulesResult } = vueCliHandler({
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
framework: 'vue-cli',
} as WebpackDevServerConfig)

// Verify it's a Vue-specific webpack config by seeing if VueLoader is present.
expect(webpackConfig.plugins.find((plug) => plug.constructor.name === 'VueLoader'))

expect(sourceWebpackModulesResult.framework?.importPath).to.include('@vue/cli-service')
expect(sourceWebpackModulesResult.webpack.majorVersion).eq(5)
})

it('sources from a @vue/cli-service@4.x project with Vue 2', async () => {
const projectRoot = await scaffoldMigrationProject('vuecli4-vue2')

process.chdir(projectRoot)

const { frameworkConfig: webpackConfig } = vueCliHandler({
const { frameworkConfig: webpackConfig, sourceWebpackModulesResult } = vueCliHandler({
cypressConfig: { projectRoot } as Cypress.PluginConfigOptions,
framework: 'vue-cli',
} as WebpackDevServerConfig)

// Verify it's a Vue-specific webpack config by seeing if VueLoader is present.
expect(webpackConfig.plugins.find((plug) => plug.constructor.name === 'VueLoader'))

expect(sourceWebpackModulesResult.framework?.importPath).to.include('@vue/cli-service')
expect(sourceWebpackModulesResult.webpack.majorVersion).eq(4)
})
})
37 changes: 12 additions & 25 deletions system-tests/__snapshots__/webpack_dev_server_fresh_spec.ts.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
exports['@cypress/webpack-dev-server react executes all of the tests for webpack4_wds3-react 1'] = `
ℹ 「wds」: Project is running at http://localhost:xxxx/webpack-dev-server/
ℹ 「wds」: webpack output is served from /__cypress/src
ℹ 「wds」: Content not from webpack is served from /foo/bar/.projects/webpack4_wds3-react
====================================================================================================
Expand All @@ -16,18 +19,7 @@ exports['@cypress/webpack-dev-server react executes all of the tests for webpack
────────────────────────────────────────────────────────────────────────────────────────────────────
Running: App.cy.jsx (1 of 4)
48 modules
ERROR in ./src/AppCompilationError.cy.jsx
Module build failed (from [..]):
SyntaxError: /foo/bar/.projects/webpack4_wds3-react/src/AppCompilationError.cy.jsx: Unexpected token, expected "," (9:0)
7 | cy.get('h1').contains('Hello World')
8 | }
> 9 | })
| ^
10 |
[stack trace lines]
ℹ 「wdm」: Failed to compile.
✓ renders hello world
Expand Down Expand Up @@ -459,6 +451,9 @@ When Cypress detects uncaught errors originating from your test code it will aut
`

exports['@cypress/webpack-dev-server react executes all of the tests for webpack5_wds3-react 1'] = `
ℹ 「wds」: Project is running at http://localhost:xxxx/webpack-dev-server/
ℹ 「wds」: webpack output is served from /__cypress/src
ℹ 「wds」: Content not from webpack is served from /foo/bar/.projects/webpack5_wds3-react
====================================================================================================
Expand All @@ -476,18 +471,7 @@ exports['@cypress/webpack-dev-server react executes all of the tests for webpack
────────────────────────────────────────────────────────────────────────────────────────────────────
Running: App.cy.jsx (1 of 4)
48 modules
ERROR in ./src/AppCompilationError.cy.jsx
Module build failed (from [..]):
SyntaxError: /foo/bar/.projects/webpack5_wds3-react/src/AppCompilationError.cy.jsx: Unexpected token, expected "," (9:0)
7 | cy.get('h1').contains('Hello World')
8 | }
> 9 | })
| ^
10 |
[stack trace lines]
ℹ 「wdm」: Failed to compile.
✓ renders hello world
Expand Down Expand Up @@ -706,7 +690,8 @@ exports['@cypress/webpack-dev-server react executes all of the tests for webpack
────────────────────────────────────────────────────────────────────────────────────────────────────
Running: App.cy.jsx (1 of 4)
48 modules
10 assets
58 modules
ERROR in ./src/AppCompilationError.cy.jsx
Module build failed (from [..]):
Expand All @@ -719,6 +704,8 @@ SyntaxError: /foo/bar/.projects/webpack5_wds4-react/src/AppCompilationError.cy.j
10 |
[stack trace lines]
webpack x.x.x compiled with x errors in xxx ms
✓ renders hello world
Expand Down
2 changes: 2 additions & 0 deletions system-tests/lib/system-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,8 @@ const systemTests = {
return stdout
.replace(/using description file: .* \(relative/g, 'using description file: [..] (relative')
.replace(/Module build failed \(from .*\)/g, 'Module build failed (from [..])')
.replace(/Project is running at http:\/\/localhost:\d+/g, 'Project is running at http://localhost:xxxx')
.replace(/webpack.*compiled with.*in \d+ ms/g, 'webpack x.x.x compiled with x errors in xxx ms')
},

normalizeRuns (runs) {
Expand Down
2 changes: 1 addition & 1 deletion system-tests/test/webpack_dev_server_fresh_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe('@cypress/webpack-dev-server', function () {
snapshot: true,
expectedExitCode: 3,
onStdout: (stdout) => {
return stripAnsi(systemTests.normalizeWebpackErrors(stdout))
return systemTests.normalizeWebpackErrors(stripAnsi(stdout))
},
})
})
Expand Down

4 comments on commit 7e0de0b

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 7e0de0b Jul 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.4.0/linux-x64/develop-7e0de0b0d085cc3e07b8f904ee9f0fa4cef6c1cf/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 7e0de0b Jul 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux arm64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.4.0/linux-arm64/develop-7e0de0b0d085cc3e07b8f904ee9f0fa4cef6c1cf/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 7e0de0b Jul 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.4.0/darwin-x64/develop-7e0de0b0d085cc3e07b8f904ee9f0fa4cef6c1cf/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 7e0de0b Jul 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the win32 x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.4.0/win32-x64/develop-7e0de0b0d085cc3e07b8f904ee9f0fa4cef6c1cf/cypress.tgz

Please sign in to comment.