Files
cypress/npm/webpack-dev-server/test/devServer-e2e.spec.ts
Jess b326693879 chore: cutting over system-tests and Cypress to use the new CT Object API (#21079)
* removing vite-dev-server local dependency from react-vite-ts-configured system test

* moving some CRA examples over to use the object api for setup

* fixing issue where function API was broken by object API for cy config + devservers

* adding deeply nested react import to project-fixtures for cra

* finishes cutting over cypress/react for sys tests

* chore: adding circle for this feature branch

* chore: moving over many vue + vite system tests to use object API instead of function API (#21080)

* doing webpack-dev-server cutovers

* removing more webpack-dev-server refrences

* fixing snapshots

* bumping yarn.lock

* wip

* fix test

* fix assertion

Co-authored-by: Lachlan Miller <lachlan.miller.1990@outlook.com>

* feat: removing all references for "fresh" dev servers (webpack-dev-server-fresh and vite-dev-server-fresh) (#21094)

Co-authored-by: Lachlan Miller <lachlan.miller.1990@outlook.com>
Co-authored-by: Zachary Williams <ZachJW34@gmail.com>

* chore: add dev-servers as deps to server to be included in the binary (#21091)

* fix bad merge

* fix next types and webpack-dev-server- resolve

Co-authored-by: Lachlan Miller <lachlan.miller.1990@outlook.com>
Co-authored-by: Zachary Williams <ZachJW34@gmail.com>
2022-04-20 15:57:19 +10:00

281 lines
7.2 KiB
TypeScript

import path from 'path'
import sinon from 'sinon'
import { expect } from 'chai'
import { once, EventEmitter } from 'events'
import http from 'http'
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) => {
const opts = {
host: 'localhost',
port,
path: encodeURI(file),
}
const callback = (response: EventEmitter) => {
let str = ''
response.on('data', (chunk) => {
str += chunk
})
response.on('end', () => {
res(str)
})
}
http.request(opts, callback).end()
})
}
const root = path.join(__dirname, '..')
const webpackConfig = {
devServer: { static: { directory: root } },
}
const createSpecs = (name: string): Cypress.Cypress['spec'][] => {
return [
{
name: `${root}/test/fixtures/${name}`,
relative: `${root}/test/fixtures/${name}`,
absolute: `${root}/test/fixtures/${name}`,
},
]
}
const cypressConfig = {
projectRoot: root,
supportFile: '',
isTextTerminal: true,
devServerPublicPathRoute: root,
indexHtmlFile: path.join(__dirname, 'component-index.html'),
} as any as Cypress.PluginConfigOptions
describe('#devServer', () => {
beforeEach(() => {
delete require.cache
restoreLoadHook()
})
after(() => {
restoreLoadHook()
})
it('serves specs via a webpack dev server', async () => {
const { port, close } = await devServer({
cypressConfig,
webpackConfig,
specs: createSpecs('foo.spec.js'),
devServerEvents: new EventEmitter(),
})
const response = await requestSpecFile('/test/fixtures/foo.spec.js', port as number)
expect(response).to.eq('const foo = () => {}\n')
await new Promise<void>((resolve, reject) => {
close((err) => {
if (err) {
return reject(err)
}
resolve()
})
})
})
it('serves specs in directory with [] chars via a webpack dev server', async () => {
const { port, close } = await devServer({
cypressConfig,
webpackConfig,
specs: createSpecs('[foo]/bar.spec.js'),
devServerEvents: new EventEmitter(),
})
const response = await requestSpecFile('/test/fixtures/[foo]/bar.spec.js', port as number)
expect(response).to.eq(`it('this is a spec with a path containing []', () => {})\n`)
return new Promise((res) => {
close(() => res())
})
})
it('serves specs in directory with non English chars via a webpack dev server', async () => {
const { port, close } = await devServer({
webpackConfig,
cypressConfig,
specs: createSpecs('サイプレス.spec.js'),
devServerEvents: new EventEmitter(),
})
const response = await requestSpecFile('/test/fixtures/サイプレス.spec.js', port as number)
expect(response).to.eq(`it('サイプレス', () => {})\n`)
return new Promise((res) => {
close(() => res())
})
})
it('serves specs in directory with ... in the file name via a webpack dev server', async () => {
const { port, close } = await devServer({
webpackConfig,
cypressConfig,
specs: createSpecs('[...bar].spec.js'),
devServerEvents: new EventEmitter(),
})
const response = await requestSpecFile('/test/fixtures/[...bar].spec.js', port as number)
expect(response).to.eq(`it('...bar', () => {})\n`)
return new Promise((res) => {
close(() => res())
})
})
it('serves a file with spaces via a webpack dev server', async () => {
const { port, close } = await devServer({
webpackConfig,
cypressConfig,
specs: createSpecs('foo bar.spec.js'),
devServerEvents: new EventEmitter(),
})
const response = await requestSpecFile('/test/fixtures/foo bar.spec.js', port as number)
expect(response).to.eq(`it('this is a spec with a path containing a space', () => {})\n`)
return new Promise((res) => {
close(() => res())
})
})
it('emits dev-server:compile:success event on successful compilation', async () => {
const devServerEvents = new EventEmitter()
const { close } = await devServer({
webpackConfig,
cypressConfig,
specs: createSpecs('foo.spec.js'),
devServerEvents,
})
await once(devServerEvents, 'dev-server:compile:success')
await new Promise<void>((resolve, reject) => {
close((err) => {
if (err) {
return reject(err)
}
resolve()
})
})
})
it('emits dev-server:compile:error event on error compilation', async () => {
const devServerEvents = new EventEmitter()
const exitSpy = sinon.stub(process, 'exit')
const badSpec = `${root}/test/fixtures/compilation-fails.spec.js`
const { close } = await devServer({
webpackConfig,
cypressConfig,
specs: [
{
name: badSpec,
relative: badSpec,
absolute: badSpec,
},
],
devServerEvents,
})
const [err] = await once(devServerEvents, 'dev-server:compile:error')
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')
expect(exitSpy.calledOnce).to.be.true
await new Promise<void>((resolve, reject) => {
close((err) => {
if (err) {
return reject(err)
}
resolve()
})
})
})
it('touches browser.js when a spec file is added and recompile', async function () {
const devServerEvents = new EventEmitter()
const { close } = await devServer({
webpackConfig,
cypressConfig,
specs: createSpecs('foo.spec.js'),
devServerEvents,
})
const newSpec: Cypress.Cypress['spec'] = {
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
await once(devServerEvents, 'dev-server:compile:success')
devServerEvents.emit('dev-server:specs:changed', [newSpec])
await once(devServerEvents, 'dev-server:compile:success')
const updatedmtime = fs.statSync('./dist/browser.js').mtimeMs
expect(oldmtime).to.not.equal(updatedmtime)
await new Promise<void>((resolve, reject) => {
close((err) => {
if (err) {
return reject(err)
}
resolve()
})
})
})
it('accepts the devServer signature', async function () {
const devServerEvents = new EventEmitter()
const { port, close } = await devServer(
{
cypressConfig,
specs: createSpecs('foo.spec.js'),
devServerEvents,
webpackConfig,
},
)
const response = await requestSpecFile('/test/fixtures/foo.spec.js', port as number)
expect(response).to.eq('const foo = () => {}\n')
await new Promise<void>((resolve, reject) => {
close((err) => {
if (err) {
return reject(err)
}
resolve()
})
})
})
})
.timeout(5000)