@@ -2,11 +2,12 @@ import path from 'path'
2
2
import { expect } from 'chai'
3
3
import { once , EventEmitter } from 'events'
4
4
import http from 'http'
5
- import fs from 'fs'
5
+ import fs from 'fs-extra '
6
6
7
7
import { devServer } from '..'
8
8
import { restoreLoadHook } from '../src/helpers/sourceRelativeWebpackModules'
9
9
import './support'
10
+ import type { ConfigHandler } from '../src/devServer'
10
11
11
12
const requestSpecFile = ( file : string , port : number ) => {
12
13
return new Promise ( ( res ) => {
@@ -34,7 +35,7 @@ const requestSpecFile = (file: string, port: number) => {
34
35
35
36
const root = path . join ( __dirname , '..' )
36
37
37
- const webpackConfig = {
38
+ const webpackConfig : ConfigHandler = {
38
39
devServer : { static : { directory : root } } ,
39
40
}
40
41
@@ -48,6 +49,20 @@ const createSpecs = (name: string): Cypress.Cypress['spec'][] => {
48
49
]
49
50
}
50
51
52
+ type DevServerCloseFn = Awaited < ReturnType < typeof devServer > > [ 'close' ]
53
+
54
+ const closeServer = async ( closeFn : DevServerCloseFn ) => {
55
+ await new Promise < void > ( ( resolve , reject ) => {
56
+ closeFn ( ( err ?: Error ) => {
57
+ if ( err ) {
58
+ return reject ( err )
59
+ }
60
+
61
+ resolve ( )
62
+ } )
63
+ } )
64
+ }
65
+
51
66
const cypressConfig = {
52
67
projectRoot : root ,
53
68
supportFile : '' ,
@@ -78,15 +93,7 @@ describe('#devServer', () => {
78
93
79
94
expect ( response ) . to . eq ( 'const foo = () => {}\n' )
80
95
81
- await new Promise < void > ( ( resolve , reject ) => {
82
- close ( ( err ) => {
83
- if ( err ) {
84
- return reject ( err )
85
- }
86
-
87
- resolve ( )
88
- } )
89
- } )
96
+ await closeServer ( close )
90
97
} )
91
98
92
99
it ( 'serves specs in directory with [] chars via a webpack dev server' , async ( ) => {
@@ -101,9 +108,7 @@ describe('#devServer', () => {
101
108
102
109
expect ( response ) . to . eq ( `it('this is a spec with a path containing []', () => {})\n` )
103
110
104
- return new Promise ( ( res ) => {
105
- close ( ( ) => res ( ) )
106
- } )
111
+ return closeServer ( close )
107
112
} )
108
113
109
114
it ( 'serves specs in directory with non English chars via a webpack dev server' , async ( ) => {
@@ -118,9 +123,7 @@ describe('#devServer', () => {
118
123
119
124
expect ( response ) . to . eq ( `it('サイプレス', () => {})\n` )
120
125
121
- return new Promise ( ( res ) => {
122
- close ( ( ) => res ( ) )
123
- } )
126
+ return closeServer ( close )
124
127
} )
125
128
126
129
it ( 'serves specs in directory with ... in the file name via a webpack dev server' , async ( ) => {
@@ -135,9 +138,7 @@ describe('#devServer', () => {
135
138
136
139
expect ( response ) . to . eq ( `it('...bar', () => {})\n` )
137
140
138
- return new Promise ( ( res ) => {
139
- close ( ( ) => res ( ) )
140
- } )
141
+ return closeServer ( close )
141
142
} )
142
143
143
144
it ( 'serves a file with spaces via a webpack dev server' , async ( ) => {
@@ -152,9 +153,7 @@ describe('#devServer', () => {
152
153
153
154
expect ( response ) . to . eq ( `it('this is a spec with a path containing a space', () => {})\n` )
154
155
155
- return new Promise ( ( res ) => {
156
- close ( ( ) => res ( ) )
157
- } )
156
+ return closeServer ( close )
158
157
} )
159
158
160
159
it ( 'emits dev-server:compile:success event on successful compilation' , async ( ) => {
@@ -167,18 +166,13 @@ describe('#devServer', () => {
167
166
} )
168
167
169
168
await once ( devServerEvents , 'dev-server:compile:success' )
170
- await new Promise < void > ( ( resolve , reject ) => {
171
- close ( ( err ) => {
172
- if ( err ) {
173
- return reject ( err )
174
- }
175
169
176
- resolve ( )
177
- } )
178
- } )
170
+ await closeServer ( close )
179
171
} )
180
172
181
173
it ( 'touches browser.js when a spec file is added and recompile' , async function ( ) {
174
+ // File watching only enabled when running in `open` mode
175
+ cypressConfig . isTextTerminal = false
182
176
const devServerEvents = new EventEmitter ( )
183
177
const { close } = await devServer ( {
184
178
webpackConfig,
@@ -203,14 +197,58 @@ describe('#devServer', () => {
203
197
204
198
expect ( oldmtime ) . to . not . equal ( updatedmtime )
205
199
206
- await new Promise < void > ( ( resolve , reject ) => {
207
- close ( ( err ) => {
208
- if ( err ) {
209
- return reject ( err )
200
+ await closeServer ( close )
201
+ } )
202
+
203
+ ; [ {
204
+ title : 'does not watch/recompile files in `run` mode' ,
205
+ isRunMode : true ,
206
+ updateExpected : false ,
207
+ message : 'Files should not be watched in `run` mode' ,
208
+ } , {
209
+ title : 'watches and recompiles files on change in `open` mode' ,
210
+ isRunMode : false ,
211
+ updateExpected : true ,
212
+ message : 'Files should be watched and automatically rebuild on update in `open` mode' ,
213
+ } ] . forEach ( ( { title, isRunMode, updateExpected, message } ) => {
214
+ it ( title , async ( ) => {
215
+ const originalContent = await fs . readFile ( `./test/fixtures/dependency.js` )
216
+
217
+ try {
218
+ cypressConfig . devServerPublicPathRoute = '/__cypress/src'
219
+ cypressConfig . isTextTerminal = isRunMode
220
+ const devServerEvents = new EventEmitter ( )
221
+ const { close, port } = await devServer ( {
222
+ webpackConfig : { } ,
223
+ cypressConfig,
224
+ specs : createSpecs ( 'bar.spec.js' ) ,
225
+ devServerEvents,
226
+ } )
227
+
228
+ // Wait for initial "ready" from server
229
+ await once ( devServerEvents , 'dev-server:compile:success' )
230
+
231
+ // Get the initial version of the bundled spec
232
+ const original = await requestSpecFile ( '/__cypress/src/spec-0.js' , port )
233
+
234
+ // Update a dependency of the spec
235
+ await fs . writeFile ( './test/fixtures/dependency.js' , `window.TEST = true;${ originalContent } ` )
236
+ // Brief wait to give server time to detect changes
237
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 500 ) )
238
+
239
+ // Re-fetch the spec
240
+ const updated = await requestSpecFile ( '/__cypress/src/spec-0.js' , port )
241
+
242
+ if ( updateExpected ) {
243
+ expect ( original , message ) . not . to . equal ( updated )
244
+ } else {
245
+ expect ( original , message ) . to . equal ( updated )
210
246
}
211
247
212
- resolve ( )
213
- } )
248
+ await closeServer ( close )
249
+ } finally {
250
+ fs . writeFile ( './test/fixtures/dependency.js' , originalContent )
251
+ }
214
252
} )
215
253
} )
216
254
@@ -229,15 +267,7 @@ describe('#devServer', () => {
229
267
230
268
expect ( response ) . to . eq ( 'const foo = () => {}\n' )
231
269
232
- await new Promise < void > ( ( resolve , reject ) => {
233
- close ( ( err ) => {
234
- if ( err ) {
235
- return reject ( err )
236
- }
237
-
238
- resolve ( )
239
- } )
240
- } )
270
+ await closeServer ( close )
241
271
} )
242
272
} )
243
273
. timeout ( 5000 )
0 commit comments