11import { createServer } from "http" ;
22
33import fetch from "node-fetch" ;
4+ import express from "express" ;
45
56import { Webhooks , createNodeMiddleware , sign } from "../../src" ;
6- import { EmitterWebhookEvent } from "../../src/types" ;
77import { pushEventPayload } from "../fixtures" ;
88
99const signatureSha256 = sign (
@@ -12,10 +12,10 @@ const signatureSha256 = sign(
1212) ;
1313
1414describe ( "createNodeMiddleware(webhooks)" , ( ) => {
15- it ( "README example" , async ( ) => {
15+ test ( "README example" , async ( ) => {
1616 expect . assertions ( 3 ) ;
1717
18- const webhooks = new Webhooks < EmitterWebhookEvent > ( {
18+ const webhooks = new Webhooks ( {
1919 secret : "mySecret" ,
2020 } ) ;
2121
@@ -50,7 +50,7 @@ describe("createNodeMiddleware(webhooks)", () => {
5050 test ( "request.body already parsed (e.g. Lambda)" , async ( ) => {
5151 expect . assertions ( 3 ) ;
5252
53- const webhooks = new Webhooks < EmitterWebhookEvent > ( {
53+ const webhooks = new Webhooks ( {
5454 secret : "mySecret" ,
5555 } ) ;
5656 const dataChunks : any [ ] = [ ] ;
@@ -89,4 +89,230 @@ describe("createNodeMiddleware(webhooks)", () => {
8989
9090 server . close ( ) ;
9191 } ) ;
92+
93+ test ( "Handles invalid JSON" , async ( ) => {
94+ const webhooks = new Webhooks ( {
95+ secret : "mySecret" ,
96+ } ) ;
97+
98+ const server = createServer ( createNodeMiddleware ( webhooks ) ) . listen ( ) ;
99+
100+ // @ts -expect-error complains about { port } although it's included in returned AddressInfo interface
101+ const { port } = server . address ( ) ;
102+
103+ const response = await fetch (
104+ `http://localhost:${ port } /api/github/webhooks` ,
105+ {
106+ method : "POST" ,
107+ headers : {
108+ "X-GitHub-Delivery" : "123e4567-e89b-12d3-a456-426655440000" ,
109+ "X-GitHub-Event" : "push" ,
110+ "X-Hub-Signature-256" : signatureSha256 ,
111+ } ,
112+ body : "invalid" ,
113+ }
114+ ) ;
115+
116+ expect ( response . status ) . toEqual ( 400 ) ;
117+
118+ await expect ( response . text ( ) ) . resolves . toMatch ( / S y n t a x E r r o r : I n v a l i d J S O N / ) ;
119+
120+ server . close ( ) ;
121+ } ) ;
122+
123+ test ( "Handles non POST request" , async ( ) => {
124+ const webhooks = new Webhooks ( {
125+ secret : "mySecret" ,
126+ } ) ;
127+
128+ const server = createServer ( createNodeMiddleware ( webhooks ) ) . listen ( ) ;
129+
130+ // @ts -expect-error complains about { port } although it's included in returned AddressInfo interface
131+ const { port } = server . address ( ) ;
132+
133+ const response = await fetch (
134+ `http://localhost:${ port } /api/github/webhooks` ,
135+ {
136+ method : "PUT" ,
137+ headers : {
138+ "X-GitHub-Delivery" : "123e4567-e89b-12d3-a456-426655440000" ,
139+ "X-GitHub-Event" : "push" ,
140+ "X-Hub-Signature-256" : signatureSha256 ,
141+ } ,
142+ body : "invalid" ,
143+ }
144+ ) ;
145+
146+ expect ( response . status ) . toEqual ( 404 ) ;
147+
148+ await expect ( response . text ( ) ) . resolves . toMatch (
149+ / U n k n o w n r o u t e : P U T \/ a p i \/ g i t h u b \/ w e b h o o k s /
150+ ) ;
151+
152+ server . close ( ) ;
153+ } ) ;
154+
155+ test ( "Handles missing headers" , async ( ) => {
156+ const webhooks = new Webhooks ( {
157+ secret : "mySecret" ,
158+ } ) ;
159+
160+ const server = createServer ( createNodeMiddleware ( webhooks ) ) . listen ( ) ;
161+
162+ // @ts -expect-error complains about { port } although it's included in returned AddressInfo interface
163+ const { port } = server . address ( ) ;
164+
165+ const response = await fetch (
166+ `http://localhost:${ port } /api/github/webhooks` ,
167+ {
168+ method : "POST" ,
169+ headers : {
170+ "X-GitHub-Delivery" : "123e4567-e89b-12d3-a456-426655440000" ,
171+ // "X-GitHub-Event": "push",
172+ "X-Hub-Signature-256" : signatureSha256 ,
173+ } ,
174+ body : "invalid" ,
175+ }
176+ ) ;
177+
178+ expect ( response . status ) . toEqual ( 400 ) ;
179+
180+ await expect ( response . text ( ) ) . resolves . toMatch (
181+ / R e q u i r e d h e a d e r s m i s s i n g : x - g i t h u b - e v e n t /
182+ ) ;
183+
184+ server . close ( ) ;
185+ } ) ;
186+
187+ test ( "Handles non-request errors" , async ( ) => {
188+ const webhooks = new Webhooks ( {
189+ secret : "mySecret" ,
190+ } ) ;
191+
192+ webhooks . on ( "push" , ( ) => {
193+ throw new Error ( "boom" ) ;
194+ } ) ;
195+
196+ const server = createServer ( createNodeMiddleware ( webhooks ) ) . listen ( ) ;
197+
198+ // @ts -expect-error complains about { port } although it's included in returned AddressInfo interface
199+ const { port } = server . address ( ) ;
200+
201+ const response = await fetch (
202+ `http://localhost:${ port } /api/github/webhooks` ,
203+ {
204+ method : "POST" ,
205+ headers : {
206+ "X-GitHub-Delivery" : "123e4567-e89b-12d3-a456-426655440000" ,
207+ "X-GitHub-Event" : "push" ,
208+ "X-Hub-Signature-256" : signatureSha256 ,
209+ } ,
210+ body : JSON . stringify ( pushEventPayload ) ,
211+ }
212+ ) ;
213+
214+ await expect ( response . text ( ) ) . resolves . toMatch ( / b o o m / ) ;
215+ expect ( response . status ) . toEqual ( 500 ) ;
216+
217+ server . close ( ) ;
218+ } ) ;
219+
220+ test ( "Handles timeout" , async ( ) => {
221+ jest . useFakeTimers ( ) ;
222+
223+ const webhooks = new Webhooks ( {
224+ secret : "mySecret" ,
225+ } ) ;
226+
227+ webhooks . on ( "push" , async ( ) => {
228+ jest . advanceTimersByTime ( 10000 ) ;
229+ server . close ( ) ;
230+ } ) ;
231+
232+ const server = createServer ( createNodeMiddleware ( webhooks ) ) . listen ( ) ;
233+
234+ // @ts -expect-error complains about { port } although it's included in returned AddressInfo interface
235+ const { port } = server . address ( ) ;
236+
237+ const response = await fetch (
238+ `http://localhost:${ port } /api/github/webhooks` ,
239+ {
240+ method : "POST" ,
241+ headers : {
242+ "X-GitHub-Delivery" : "123e4567-e89b-12d3-a456-426655440000" ,
243+ "X-GitHub-Event" : "push" ,
244+ "X-Hub-Signature-256" : signatureSha256 ,
245+ } ,
246+ body : JSON . stringify ( pushEventPayload ) ,
247+ }
248+ ) ;
249+
250+ await expect ( response . text ( ) ) . resolves . toMatch ( / s t i l l p r o c e s s i n g / ) ;
251+ expect ( response . status ) . toEqual ( 202 ) ;
252+ } ) ;
253+
254+ test ( "Handles timeout with error" , async ( ) => {
255+ jest . useFakeTimers ( ) ;
256+
257+ const webhooks = new Webhooks ( {
258+ secret : "mySecret" ,
259+ } ) ;
260+
261+ webhooks . on ( "push" , async ( ) => {
262+ jest . advanceTimersByTime ( 10000 ) ;
263+ server . close ( ) ;
264+ throw new Error ( "oops" ) ;
265+ } ) ;
266+
267+ const server = createServer ( createNodeMiddleware ( webhooks ) ) . listen ( ) ;
268+
269+ // @ts -expect-error complains about { port } although it's included in returned AddressInfo interface
270+ const { port } = server . address ( ) ;
271+
272+ const response = await fetch (
273+ `http://localhost:${ port } /api/github/webhooks` ,
274+ {
275+ method : "POST" ,
276+ headers : {
277+ "X-GitHub-Delivery" : "123e4567-e89b-12d3-a456-426655440000" ,
278+ "X-GitHub-Event" : "push" ,
279+ "X-Hub-Signature-256" : signatureSha256 ,
280+ } ,
281+ body : JSON . stringify ( pushEventPayload ) ,
282+ }
283+ ) ;
284+
285+ await expect ( response . text ( ) ) . resolves . toMatch ( / s t i l l p r o c e s s i n g / ) ;
286+ expect ( response . status ) . toEqual ( 202 ) ;
287+ } ) ;
288+
289+ test ( "express middleware 404" , async ( ) => {
290+ const app = express ( ) ;
291+ const webhooks = new Webhooks ( {
292+ secret : "mySecret" ,
293+ } ) ;
294+
295+ app . post ( "/test" , createNodeMiddleware ( webhooks ) ) ;
296+ app . all ( "*" , ( ...[ , response ] ) => response . status ( 404 ) . send ( "Dafuq" ) ) ;
297+
298+ const server = app . listen ( ) ;
299+
300+ // @ts -expect-error complains about { port } although it's included in returned AddressInfo interface
301+ const { port } = server . address ( ) ;
302+
303+ const response = await fetch ( `http://localhost:${ port } /test` , {
304+ method : "POST" ,
305+ headers : {
306+ "X-GitHub-Delivery" : "123e4567-e89b-12d3-a456-426655440000" ,
307+ "X-GitHub-Event" : "push" ,
308+ "X-Hub-Signature-256" : signatureSha256 ,
309+ } ,
310+ body : JSON . stringify ( pushEventPayload ) ,
311+ } ) ;
312+
313+ await expect ( response . text ( ) ) . resolves . toBe ( "ok\n" ) ;
314+ expect ( response . status ) . toEqual ( 200 ) ;
315+
316+ server . close ( ) ;
317+ } ) ;
92318} ) ;
0 commit comments