11"use strict" ;
22
33const path = require ( "node:path" ) ;
4+ const [ devServerVersion ] = require ( "webpack-dev-server/package.json" ) . version ;
45const {
56 getFreePort,
67 normalizeStderr,
@@ -10,6 +11,8 @@ const {
1011
1112const testPath = path . resolve ( __dirname ) ;
1213
14+ const describeDevServer6 = devServerVersion === "5" ? describe . skip : describe ;
15+
1316const normalStdKillOptions = {
1417 stdoutKillStr : / w e b p a c k \d + \. \d + \. \d / ,
1518 stderrKillStr : / C o n t e n t n o t f r o m w e b p a c k i s s e r v e d f r o m / ,
@@ -95,21 +98,64 @@ describe("basic serve usage", () => {
9598 expect ( stdout ) . toContain ( "second-output/main.js" ) ;
9699 } ) ;
97100
98- // TODO need fix in future, edge case
99- // eslint-disable-next-line jest/no-disabled-tests
100- it . skip ( "should work in multi compiler mode with multiple dev servers" , async ( ) => {
101- const { stderr, stdout } = await runWatch (
102- __dirname ,
103- [ "serve" , "--config" , "multi-dev-server.config.js" ] ,
104- normalStdKillOptions ,
105- ) ;
101+ // TODO in the next major release, remove the condition, only dev servers with plugin support
102+ // select distinct ports for configurations without them
103+ describeDevServer6 ( "with multiple dev servers" , ( ) => {
104+ it ( "should work in multi compiler mode without ports" , async ( ) => {
105+ const ports = [ ] ;
106+ const responses = { } ;
107+ const { exitCode, stdout } = await runWatch (
108+ __dirname ,
109+ [ "serve" , "--config" , "multi-dev-server.config.js" , "--watch-options-stdin" ] ,
110+ {
111+ // Automatic ports start from the base one
112+ env : { WEBPACK_DEV_SERVER_BASE_PORT : String ( port ) } ,
113+ handler : ( proc ) => {
114+ let output = "" ;
115+
116+ proc . stderr . on ( "data" , ( chunk ) => {
117+ output += chunk . toString ( ) ;
118+
119+ if ( ports . length > 0 ) {
120+ return ;
121+ }
122+
123+ const found = [ ...output . matchAll ( / L o o p b a c k : h t t p : \/ \/ l o c a l h o s t : ( \d + ) \/ / g) ] . map (
124+ ( [ , found ] ) => found ,
125+ ) ;
126+
127+ if ( found . length < 2 ) {
128+ return ;
129+ }
130+
131+ ports . push ( ...found ) ;
132+
133+ // Every dev server serves all compilers
134+ Promise . all (
135+ ports . flatMap ( ( port ) =>
136+ [ "first-output" , "second-output" ] . map ( ( directory ) =>
137+ fetch (
138+ `http://127.0.0.1:${ port } /dev-server-my-public-path/${ directory } /main.js` ,
139+ ) . then ( ( response ) => {
140+ responses [ `${ port } :${ directory } ` ] = response . status ;
141+ } ) ,
142+ ) ,
143+ ) ,
144+ ) . finally ( ( ) => {
145+ proc . stdin . end ( ) ;
146+ } ) ;
147+ } ) ;
148+ } ,
149+ } ,
150+ ) ;
106151
107- expect ( normalizeStderr ( stderr ) ) . toMatchSnapshot ( "stderr" ) ;
108- expect ( stdout ) . toContain ( "HotModuleReplacementPlugin" ) ;
109- expect ( stdout ) . toContain ( "one" ) ;
110- expect ( stdout ) . toContain ( "first-output/main.js" ) ;
111- expect ( stdout ) . toContain ( "two" ) ;
112- expect ( stdout ) . toContain ( "second-output/main.js" ) ;
152+ expect ( exitCode ) . toBe ( 0 ) ;
153+ expect ( new Set ( ports ) . size ) . toBe ( 2 ) ;
154+ expect ( Object . values ( responses ) ) . toEqual ( [ 200 , 200 , 200 , 200 ] ) ;
155+ expect ( stdout ) . toContain ( "HotModuleReplacementPlugin" ) ;
156+ expect ( stdout ) . toContain ( "first-output/main.js" ) ;
157+ expect ( stdout ) . toContain ( "second-output/main.js" ) ;
158+ } ) ;
113159 } ) ;
114160
115161 it ( 'should work with the "--mode" option' , async ( ) => {
0 commit comments