Skip to content

Commit

Permalink
fix: detect newly added specs in dev-server compilation (#17950)
Browse files Browse the repository at this point in the history
Co-authored-by: Lachlan Miller <lachlan.miller.1990@outlook.com>
  • Loading branch information
ZachJW34 and lmiller1990 committed Feb 8, 2022
1 parent f1fb88a commit f9ce67c
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 64 deletions.
2 changes: 1 addition & 1 deletion npm/webpack-dev-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"scripts": {
"build": "tsc",
"build-prod": "tsc",
"test": "node ./test-wds-3.js",
"test": "node ./test-deps.js",
"test-all": "tsc && mocha -r @packages/ts/register test/**/*.spec.ts test/*.spec.ts --exit",
"watch": "tsc -w"
},
Expand Down
1 change: 1 addition & 0 deletions npm/webpack-dev-server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export async function startDevServer (startDevServerArgs: StartDevServer, exitPr

return new Promise<ResolvedDevServerConfig>(async (resolve, reject) => {
if (webpackDevServerFacts.isV3()) {
// @ts-ignore
const server: Server = webpackDevServer.listen(0, '127.0.0.1', () => {
// FIXME: handle address returning a string
const port = (server.address() as AddressInfo).port
Expand Down
7 changes: 6 additions & 1 deletion npm/webpack-dev-server/src/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import debugFn from 'debug'
import * as path from 'path'
import { CypressCTWebpackContext } from './plugin'
const debug = debugFn('cypress:webpack-dev-server:webpack')
import type { LoaderContext } from 'webpack'

/**
* @param {ComponentSpec} file spec to create import string from.
Expand Down Expand Up @@ -49,7 +50,11 @@ function buildSpecs (projectRoot: string, files: Cypress.Cypress['spec'][] = [])
}

// Runs the tests inside the iframe
export default function loader (this: CypressCTWebpackContext) {
export default function loader (this: CypressCTWebpackContext & LoaderContext<void>) {
// In Webpack 5, a spec added after the dev-server is created won't
// be included in the compilation. Disabling the caching of this loader ensures
// we regenerate our specs and include any new ones in the compilation.
this.cacheable(false)
const { files, projectRoot, supportFile } = this._cypress

const supportFileAbsolutePath = supportFile ? JSON.stringify(path.resolve(projectRoot, supportFile)) : undefined
Expand Down
2 changes: 1 addition & 1 deletion npm/webpack-dev-server/src/startServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export async function start ({ webpackConfig: userWebpackConfig, template, optio
hot: false,
}

// @ts-expect-error Webpack types are clashing between Webpack and WebpackDevServer
// @ts-ignore Webpack types are clashing between Webpack and WebpackDevServer
return new WebpackDevServer(webpackDevServerConfig, compiler)
}

Expand Down
79 changes: 79 additions & 0 deletions npm/webpack-dev-server/test-deps.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
const execa = require('execa')
const pkg = require('./package.json')
const fs = require('fs')

/**
* This file installs dependencies that we support but don't have coverage for.
* We read package.json, update the dependency, then re-run yarn install.
* After it finishes, pass or fail,
* we revert the package.json back to the original state.
*/
const main = async () => {
const depsToTest = [
[
{
name: 'webpack-dev-server',
version: '3.11.0',
type: 'devDependencies',
},
],
[
{ name: 'webpack', version: '5.53.0', type: 'devDependencies' },
{
name: 'html-webpack-plugin',
version: '5.3.2',
type: 'devDependencies',
},
],
]
const originalPkg = JSON.stringify(pkg, null, 2)

const install = () => execa('yarn', ['install', '--ignore-scripts'], { stdio: 'inherit' })

const exit = async (exitCode) => {
fs.writeFileSync('package.json', originalPkg, 'utf8')
await install()
process.exit(exitCode)
}

for (const deps of depsToTest) {
const pkg = JSON.parse(originalPkg)
const depsInfo = JSON.stringify(deps)

deps.forEach(({ type, name, version }) => (pkg[type][name] = version))

// eslint-disable-next-line no-console
console.log('[@cypress/webpack-dev-server]: updating package.json...')
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2), 'utf8')

// eslint-disable-next-line no-console
console.log('[@cypress/webpack-dev-server]: install dependencies...')
await install()

// eslint-disable-next-line no-console
console.log(
`[@cypress/webpack-dev-server]: Testing with deps: ${depsInfo}`,
)

const { exitCode } = await execa('yarn', ['test-all'], {
stdio: 'inherit',
})

if (typeof exitCode !== 'number') {
// eslint-disable-next-line no-console
console.error(
`Testing with deps: ${depsInfo} finished with missing exit code from execa (received ${exitCode})`,
)
}

if (exitCode !== 0) {
exit(exitCode)
}
}
exit(0)
}

// execute main function if called from command line
if (require.main === module) {
main()
}
49 changes: 0 additions & 49 deletions npm/webpack-dev-server/test-wds-3.js

This file was deleted.

31 changes: 21 additions & 10 deletions npm/webpack-dev-server/test/e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,10 @@ describe('#startDevServer', () => {

return new Promise((res) => {
devServerEvents.on('dev-server:compile:error', (err: string) => {
expect(err).to.contain('./test/fixtures/compilation-fails.spec.js 1:5')
if (webpackDevServerFacts.isV3()) {
expect(err).to.contain('./test/fixtures/compilation-fails.spec.js 1:5')
}

expect(err).to.contain('Module parse failed: Unexpected token (1:5)')
expect(err).to.contain('You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders')
expect(err).to.contain('> this is an invalid spec file')
Expand All @@ -128,7 +131,7 @@ describe('#startDevServer', () => {
})
})

it('touches browser.js when a spec file is added', async function () {
it('touches browser.js when a spec file is added and recompile', async function () {
const devServerEvents = new EventEmitter()
const { close } = await startDevServer({
webpackConfig,
Expand All @@ -140,19 +143,27 @@ describe('#startDevServer', () => {
})

const newSpec: Cypress.Cypress['spec'] = {
name: './some-newly-created-spec.js',
relative: './some-newly-created-spec.js',
absolute: '/some-newly-created-spec.js',
name: `${root}/test/fixtures/bar.spec.js`,
relative: `${root}/test/fixtures/bar.spec.js`,
absolute: `${root}/test/fixtures/bar.spec.js`,
}

const oldmtime = fs.statSync('./dist/browser.js').mtimeMs

return new Promise((res) => {
devServerEvents.emit('dev-server:specs:changed', [newSpec])
const updatedmtime = fs.statSync('./dist/browser.js').mtimeMs
let firstCompile = true

expect(oldmtime).to.not.equal(updatedmtime)
close(() => res())
return new Promise((res) => {
devServerEvents.on('dev-server:compile:success', () => {
if (firstCompile) {
firstCompile = false
devServerEvents.emit('dev-server:specs:changed', [newSpec])
const updatedmtime = fs.statSync('./dist/browser.js').mtimeMs

expect(oldmtime).to.not.equal(updatedmtime)
} else {
close(() => res())
}
})
})
})

Expand Down
1 change: 1 addition & 0 deletions npm/webpack-dev-server/test/fixtures/bar.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const bar = () => {}
6 changes: 4 additions & 2 deletions npm/webpack-preprocessor/test-webpack-5.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ const fs = require('fs')
const main = async () => {
const originalPkg = JSON.stringify(pkg, null, 2)

const install = () => execa('yarn', ['install', '--ignore-scripts'], { stdio: 'inherit' })

const resetPkg = async () => {
fs.writeFileSync('package.json', originalPkg, 'utf8')
await execa('yarn', ['install'], { stdio: 'inherit' })
await install()
}

const checkExit = async ({ exitCode, step }) => {
Expand All @@ -40,7 +42,7 @@ const main = async () => {

// eslint-disable-next-line no-console
console.log('[@cypress/webpack-preprocessor]: install dependencies...')
await execa('yarn', ['install'], { stdio: 'inherit' })
await install()

const unit = await execa('yarn', ['test-unit'], { stdio: 'inherit' })

Expand Down

0 comments on commit f9ce67c

Please sign in to comment.