1
1
import { ProviderError } from "@smithy/property-provider" ;
2
- import { createServer } from "http" ;
3
- import nock from "nock" ;
4
- import { afterEach , beforeAll , describe , expect , test as it , vi } from "vitest" ;
2
+ import { afterEach , describe , expect , test as it , vi } from "vitest" ;
5
3
6
4
import { httpRequest } from "./httpRequest" ;
7
5
6
+ vi . mock ( "http" , async ( ) => {
7
+ const actual : any = vi . importActual ( "http" ) ;
8
+
9
+ const pkg = {
10
+ ...actual ,
11
+ request : vi . fn ( ) ,
12
+ } ;
13
+ return {
14
+ ...pkg ,
15
+ default : pkg ,
16
+ } ;
17
+ } ) ;
18
+
19
+ import EventEmitter from "events" ;
20
+ import { request } from "http" ;
21
+
8
22
describe ( "httpRequest" , ( ) => {
9
23
let port : number ;
10
24
const hostname = "localhost" ;
11
25
const path = "/" ;
12
26
13
- const getOpenPort = async ( candidatePort = 4321 ) : Promise < number > => {
14
- try {
15
- return new Promise < number > ( ( resolve , reject ) => {
16
- const server = createServer ( ) ;
17
- server . on ( "error" , ( ) => reject ( ) ) ;
18
- server . listen ( candidatePort ) ;
19
- server . close ( ( ) => resolve ( candidatePort ) ) ;
20
- } ) ;
21
- } catch ( e ) {
22
- return await getOpenPort ( candidatePort + 1 ) ;
23
- }
24
- } ;
25
-
26
- beforeAll ( async ( ) => {
27
- port = await getOpenPort ( ) ;
28
- } ) ;
29
-
30
27
afterEach ( ( ) => {
31
28
vi . clearAllMocks ( ) ;
32
29
} ) ;
33
30
31
+ function mockResponse ( { expectedResponse, statusCode = 200 } : any ) {
32
+ return vi . mocked ( request ) . mockImplementationOnce ( ( ( ) => {
33
+ const request = Object . assign ( new EventEmitter ( ) , {
34
+ destroy : vi . fn ( ) ,
35
+ end : vi . fn ( ) ,
36
+ } ) ;
37
+ const response = new EventEmitter ( ) as any ;
38
+ response . statusCode = statusCode ;
39
+ setTimeout ( ( ) => {
40
+ request . emit ( "response" , response ) ;
41
+ setTimeout ( ( ) => {
42
+ response . emit ( "data" , Buffer . from ( expectedResponse ) ) ;
43
+ response . emit ( "end" ) ;
44
+ } , 50 ) ;
45
+ } , 50 ) ;
46
+ return request ;
47
+ } ) as any ) ;
48
+ }
49
+
34
50
describe ( "returns response" , ( ) => {
35
51
it ( "defaults to method GET" , async ( ) => {
36
52
const expectedResponse = "expectedResponse" ;
37
- const scope = nock ( `http://${ hostname } :${ port } ` ) . get ( path ) . reply ( 200 , expectedResponse ) ;
53
+
54
+ mockResponse ( { expectedResponse } ) ;
38
55
39
56
const response = await httpRequest ( { hostname, path, port } ) ;
40
57
expect ( response . toString ( ) ) . toStrictEqual ( expectedResponse ) ;
41
-
42
- scope . done ( ) ;
43
58
} ) ;
44
59
45
60
it ( "uses method passed in options" , async ( ) => {
46
61
const method = "POST" ;
47
62
const expectedResponse = "expectedResponse" ;
48
- const scope = nock ( `http:// ${ hostname } : ${ port } ` ) . post ( path ) . reply ( 200 , expectedResponse ) ;
63
+ mockResponse ( { expectedResponse } ) ;
49
64
50
65
const response = await httpRequest ( { hostname, path, port, method } ) ;
51
66
expect ( response . toString ( ) ) . toStrictEqual ( expectedResponse ) ;
52
-
53
- scope . done ( ) ;
54
67
} ) ;
55
68
56
69
it ( "works with IPv6 hostname with encapsulated brackets" , async ( ) => {
57
70
const expectedResponse = "expectedResponse" ;
58
71
const encapsulatedIPv6Hostname = "[::1]" ;
59
- const scope = nock ( `http:// ${ encapsulatedIPv6Hostname } : ${ port } ` ) . get ( path ) . reply ( 200 , expectedResponse ) ;
72
+ mockResponse ( { expectedResponse } ) ;
60
73
61
74
const response = await httpRequest ( { hostname : encapsulatedIPv6Hostname , path, port } ) ;
62
75
expect ( response . toString ( ) ) . toStrictEqual ( expectedResponse ) ;
63
-
64
- scope . done ( ) ;
65
76
} ) ;
66
77
} ) ;
67
78
68
79
describe ( "throws error" , ( ) => {
69
80
const errorOnStatusCode = async ( statusCode : number ) => {
70
81
it ( `statusCode: ${ statusCode } ` , async ( ) => {
71
- const scope = nock ( `http://${ hostname } :${ port } ` ) . get ( path ) . reply ( statusCode , "continue" ) ;
82
+ mockResponse ( {
83
+ statusCode,
84
+ expectedResponse : "continue" ,
85
+ } ) ;
72
86
73
87
await expect ( httpRequest ( { hostname, path, port } ) ) . rejects . toStrictEqual (
74
88
Object . assign ( new ProviderError ( "Error response received from instance metadata service" ) , { statusCode } )
75
89
) ;
76
-
77
- scope . done ( ) ;
78
90
} ) ;
79
91
} ;
80
92
81
93
it ( "when request throws error" , async ( ) => {
82
- const scope = nock ( `http://${ hostname } :${ port } ` ) . get ( path ) . replyWithError ( "error" ) ;
94
+ vi . mocked ( request ) . mockImplementationOnce ( ( ( ) => {
95
+ const request = Object . assign ( new EventEmitter ( ) , {
96
+ destroy : vi . fn ( ) ,
97
+ end : vi . fn ( ) ,
98
+ } ) ;
99
+ setTimeout ( ( ) => {
100
+ request . emit ( "error" ) ;
101
+ } , 50 ) ;
102
+ return request ;
103
+ } ) as any ) ;
83
104
84
105
await expect ( httpRequest ( { hostname, path, port } ) ) . rejects . toStrictEqual (
85
106
new ProviderError ( "Unable to connect to instance metadata service" )
86
107
) ;
87
-
88
- scope . done ( ) ;
89
108
} ) ;
90
109
91
110
describe ( "when request returns with statusCode < 200" , ( ) => {
@@ -99,16 +118,21 @@ describe("httpRequest", () => {
99
118
100
119
it ( "timeout" , async ( ) => {
101
120
const timeout = 1000 ;
102
- const scope = nock ( `http://${ hostname } :${ port } ` )
103
- . get ( path )
104
- . delay ( timeout * 2 )
105
- . reply ( 200 , "expectedResponse" ) ;
121
+ vi . mocked ( request ) . mockImplementationOnce ( ( ( ) => {
122
+ const request = Object . assign ( new EventEmitter ( ) , {
123
+ destroy : vi . fn ( ) ,
124
+ end : vi . fn ( ) ,
125
+ } ) ;
126
+ const response = new EventEmitter ( ) as any ;
127
+ response . statusCode = 200 ;
128
+ setTimeout ( ( ) => {
129
+ request . emit ( "timeout" ) ;
130
+ } , 50 ) ;
131
+ return request ;
132
+ } ) as any ) ;
106
133
107
134
await expect ( httpRequest ( { hostname, path, port, timeout } ) ) . rejects . toStrictEqual (
108
135
new ProviderError ( "TimeoutError from instance metadata service" )
109
136
) ;
110
-
111
- nock . abortPendingRequests ( ) ;
112
- scope . done ( ) ;
113
137
} ) ;
114
138
} ) ;
0 commit comments