1
- import { spawn } from "child_process" ;
1
+ import { fork } from "child_process" ;
2
2
import * as path from "path" ;
3
3
import type { ChildProcess } from "child_process" ;
4
4
import { describe , expect , it , beforeAll , afterAll , beforeEach } from "vitest" ;
@@ -18,48 +18,63 @@ const waitUntilReady = async (url: string): Promise<Response> => {
18
18
return response as Response ;
19
19
} ;
20
20
21
- const isWindows = process . platform === "win32" ;
21
+ type WranglerInstance = {
22
+ dirName : string ;
23
+ childProcess : ChildProcess ;
24
+ ip : string ;
25
+ port : string ;
26
+ } ;
22
27
23
28
describe ( "Pages Functions" , ( ) => {
24
- let wranglerProcess : ChildProcess ;
29
+ let wranglerInstances : WranglerInstance [ ] = [ ] ;
30
+ let pagesAppPort : string ;
25
31
26
- beforeAll ( ( ) => {
27
- wranglerProcess = spawn ( "npm" , [ "run" , "dev" ] , {
28
- shell : isWindows ,
29
- cwd : path . resolve ( __dirname , "../" ) ,
30
- env : { BROWSER : "none" , ...process . env } ,
31
- } ) ;
32
- wranglerProcess . stdout ?. on ( "data" , ( chunk ) => {
33
- console . log ( chunk . toString ( ) ) ;
34
- } ) ;
35
- wranglerProcess . stderr ?. on ( "data" , ( chunk ) => {
36
- console . log ( chunk . toString ( ) ) ;
37
- } ) ;
32
+ beforeAll ( async ( ) => {
33
+ wranglerInstances = await Promise . all (
34
+ [
35
+ {
36
+ dirName : "module-worker-a" ,
37
+ } ,
38
+ {
39
+ dirName : "module-worker-b" ,
40
+ } ,
41
+ {
42
+ dirName : "service-worker-a" ,
43
+ } ,
44
+ {
45
+ dirName : "module-worker-c" ,
46
+ extraArgs : [ "--env=staging" ] ,
47
+ } ,
48
+ {
49
+ dirName : "module-worker-d" ,
50
+ extraArgs : [ "--env=production" ] ,
51
+ } ,
52
+ {
53
+ pages : true ,
54
+ dirName : "pages-functions-app" ,
55
+ extraArgs : [
56
+ "--service=MODULE_A_SERVICE=module-worker-a" ,
57
+ "--service=MODULE_B_SERVICE=module-worker-b" ,
58
+ "--service=SERVICE_A_SERVICE=service-worker-a" ,
59
+ "--service=STAGING_MODULE_C_SERVICE=module-worker-c@staging" ,
60
+ "--service=STAGING_MODULE_D_SERVICE=module-worker-d@staging" ,
61
+ ] ,
62
+ } ,
63
+ ] . map ( getWranglerInstance )
64
+ ) ;
65
+ pagesAppPort =
66
+ wranglerInstances . find ( ( { dirName } ) => dirName === "pages-functions-app" )
67
+ ?. port ?? "0" ;
38
68
} ) ;
39
69
40
70
afterAll ( async ( ) => {
41
- await new Promise ( ( resolve , reject ) => {
42
- wranglerProcess . once ( "exit" , ( code ) => {
43
- if ( ! code ) {
44
- resolve ( code ) ;
45
- } else {
46
- reject ( code ) ;
47
- }
48
- } ) ;
49
- wranglerProcess . kill ( "SIGTERM" ) ;
50
- } ) ;
51
- } ) ;
52
-
53
- beforeEach ( async ( ) => {
54
- await Promise . all (
55
- [ 8500 , 8501 , 8502 , 8503 , 8504 , 8505 ] . map ( ( port ) =>
56
- waitUntilReady ( `http://localhost:${ port } ` )
57
- )
58
- ) ;
71
+ await Promise . allSettled ( wranglerInstances . map ( terminateWranglerInstance ) ) ;
59
72
} ) ;
60
73
61
74
it ( "connects up Workers (both module and service ones) and fetches from them" , async ( ) => {
62
- const combinedResponse = await waitUntilReady ( "http://localhost:8505/" ) ;
75
+ const combinedResponse = await waitUntilReady (
76
+ `http://localhost:${ pagesAppPort } /`
77
+ ) ;
63
78
const json = await combinedResponse . json ( ) ;
64
79
expect ( json ) . toMatchInlineSnapshot ( `
65
80
{
@@ -71,7 +86,9 @@ describe("Pages Functions", () => {
71
86
} ) ;
72
87
73
88
it ( "respects the environments specified for the service bindings (and doesn't connect if the env doesn't match)" , async ( ) => {
74
- const combinedResponse = await waitUntilReady ( "http://localhost:8505/env" ) ;
89
+ const combinedResponse = await waitUntilReady (
90
+ `http://localhost:${ pagesAppPort } /env`
91
+ ) ;
75
92
const json = await combinedResponse . json ( ) ;
76
93
expect ( json ) . toMatchInlineSnapshot ( `
77
94
{
@@ -81,3 +98,55 @@ describe("Pages Functions", () => {
81
98
` ) ;
82
99
} ) ;
83
100
} ) ;
101
+
102
+ async function getWranglerInstance ( {
103
+ pages = false ,
104
+ dirName,
105
+ extraArgs = [ ] ,
106
+ } : {
107
+ pages ?: boolean ;
108
+ dirName : string ;
109
+ extraArgs ?: string [ ] ;
110
+ } ) : Promise < WranglerInstance > {
111
+ return new Promise ( ( resolve ) => {
112
+ const childProcess = fork (
113
+ path . join ( ".." , ".." , ".." , "packages" , "wrangler" , "bin" , "wrangler.js" ) ,
114
+ [
115
+ ...( pages ? [ "pages" ] : [ ] ) ,
116
+ "dev" ,
117
+ ...( pages ? [ "public" ] : [ "index.ts" ] ) ,
118
+ "--local" ,
119
+ `--port=0` ,
120
+ ...extraArgs ,
121
+ ] ,
122
+ {
123
+ cwd : path . resolve ( __dirname , ".." , dirName ) ,
124
+ env : { BROWSER : "none" , ...process . env } ,
125
+ stdio : [ "ignore" , "ignore" , "ignore" , "ipc" ] ,
126
+ }
127
+ ) . on ( "message" , ( message ) => {
128
+ const parsedMessage = JSON . parse ( message . toString ( ) ) ;
129
+ resolve ( {
130
+ dirName,
131
+ childProcess,
132
+ ip : parsedMessage . ip ,
133
+ port : parsedMessage . port ,
134
+ } ) ;
135
+ } ) ;
136
+ } ) ;
137
+ }
138
+
139
+ function terminateWranglerInstance ( {
140
+ childProcess,
141
+ } : WranglerInstance ) : Promise < unknown > {
142
+ return new Promise ( ( resolve , reject ) => {
143
+ childProcess . once ( "exit" , ( code ) => {
144
+ if ( ! code ) {
145
+ resolve ( code ) ;
146
+ } else {
147
+ reject ( code ) ;
148
+ }
149
+ } ) ;
150
+ childProcess . kill ( "SIGTERM" ) ;
151
+ } ) ;
152
+ }
0 commit comments