1
1
import * as http from "http"
2
+ import { logger } from "@coder/logger"
3
+ import { AddressInfo } from "net"
2
4
import * as path from "path"
3
5
import { SettingsProvider , UpdateSettings } from "../../../src/node/settings"
4
6
import { LatestResponse , UpdateProvider } from "../../../src/node/update"
5
- import { clean , mockLogger , tmpdir } from "../../utils/helpers"
7
+ import { clean , isAddressInfo , mockLogger , tmpdir } from "../../utils/helpers"
6
8
7
9
describe ( "update" , ( ) => {
8
10
let version = "1.0.0"
@@ -23,6 +25,46 @@ describe("update", () => {
23
25
return response . end ( JSON . stringify ( latest ) )
24
26
}
25
27
28
+ if ( request . url === "/reject-status-code" ) {
29
+ response . writeHead ( 500 )
30
+ return response . end ( "rejected status code test" )
31
+ }
32
+
33
+ if ( request . url === "/no-location-header" ) {
34
+ response . writeHead ( 301 , "testing" , {
35
+ location : "" ,
36
+ } )
37
+ return response . end ( "rejected status code test" )
38
+ }
39
+
40
+ if ( request . url === "/with-location-header" ) {
41
+ response . writeHead ( 301 , "testing" , {
42
+ location : "/latest" ,
43
+ } )
44
+
45
+ return response . end ( )
46
+ }
47
+
48
+ // Checks if url matches /redirect/${number}
49
+ // with optional trailing slash
50
+ const match = request . url . match ( / \/ r e d i r e c t \/ ( [ 0 - 9 ] + ) \/ ? $ / )
51
+ if ( match ) {
52
+ if ( request . url === "/redirect/0" ) {
53
+ response . writeHead ( 200 )
54
+ return response . end ( "done" )
55
+ }
56
+
57
+ // Subtract 1 from the current redirect number
58
+ // i.e. /redirect/10 -> /redirect/9 -> /redirect/8
59
+ const currentRedirectNumber = parseInt ( match [ 1 ] )
60
+ const newRedirectNumber = currentRedirectNumber - 1
61
+
62
+ response . writeHead ( 302 , "testing" , {
63
+ location : `/redirect/${ String ( newRedirectNumber ) } ` ,
64
+ } )
65
+ return response . end ( "" )
66
+ }
67
+
26
68
// Anything else is a 404.
27
69
response . writeHead ( 404 )
28
70
response . end ( "not found" )
@@ -37,6 +79,7 @@ describe("update", () => {
37
79
}
38
80
39
81
let _provider : UpdateProvider | undefined
82
+ let _address : string | AddressInfo | null
40
83
const provider = ( ) : UpdateProvider => {
41
84
if ( ! _provider ) {
42
85
throw new Error ( "Update provider has not been created" )
@@ -62,19 +105,20 @@ describe("update", () => {
62
105
} )
63
106
} )
64
107
65
- const address = server . address ( )
66
- if ( ! address || typeof address === "string" || ! address . port ) {
108
+ _address = server . address ( )
109
+ if ( ! isAddressInfo ( _address ) ) {
67
110
throw new Error ( "unexpected address" )
68
111
}
69
112
70
- _provider = new UpdateProvider ( `http://${ address . address } :${ address . port } /latest` , _settings )
113
+ _provider = new UpdateProvider ( `http://${ _address ? .address } :${ _address ? .port } /latest` , _settings )
71
114
} )
72
115
73
116
afterAll ( ( ) => {
74
117
server . close ( )
75
118
} )
76
119
77
120
beforeEach ( ( ) => {
121
+ jest . clearAllMocks ( )
78
122
spy = [ ]
79
123
} )
80
124
@@ -170,4 +214,61 @@ describe("update", () => {
170
214
expect ( update . checked < Date . now ( ) && update . checked >= now ) . toEqual ( true )
171
215
expect ( update . version ) . toStrictEqual ( "unknown" )
172
216
} )
217
+
218
+ it ( "should reject if response has status code 500" , async ( ) => {
219
+ if ( isAddressInfo ( _address ) ) {
220
+ const mockURL = `http://${ _address . address } :${ _address . port } /reject-status-code`
221
+ let provider = new UpdateProvider ( mockURL , settings ( ) )
222
+ let update = await provider . getUpdate ( true )
223
+
224
+ expect ( update . version ) . toBe ( "unknown" )
225
+ expect ( logger . error ) . toHaveBeenCalled ( )
226
+ expect ( logger . error ) . toHaveBeenCalledWith ( "Failed to get latest version" , {
227
+ identifier : "error" ,
228
+ value : `${ mockURL } : 500` ,
229
+ } )
230
+ }
231
+ } )
232
+
233
+ it ( "should reject if no location header provided" , async ( ) => {
234
+ if ( isAddressInfo ( _address ) ) {
235
+ const mockURL = `http://${ _address . address } :${ _address . port } /no-location-header`
236
+ let provider = new UpdateProvider ( mockURL , settings ( ) )
237
+ let update = await provider . getUpdate ( true )
238
+
239
+ expect ( update . version ) . toBe ( "unknown" )
240
+ expect ( logger . error ) . toHaveBeenCalled ( )
241
+ expect ( logger . error ) . toHaveBeenCalledWith ( "Failed to get latest version" , {
242
+ identifier : "error" ,
243
+ value : `received redirect with no location header` ,
244
+ } )
245
+ }
246
+ } )
247
+
248
+ it ( "should resolve the request with response.headers.location" , async ( ) => {
249
+ version = "4.1.1"
250
+ if ( isAddressInfo ( _address ) ) {
251
+ const mockURL = `http://${ _address . address } :${ _address . port } /with-location-header`
252
+ let provider = new UpdateProvider ( mockURL , settings ( ) )
253
+ let update = await provider . getUpdate ( true )
254
+
255
+ expect ( logger . error ) . not . toHaveBeenCalled ( )
256
+ expect ( update . version ) . toBe ( "4.1.1" )
257
+ }
258
+ } )
259
+
260
+ it ( "should reject if more than 10 redirects" , async ( ) => {
261
+ if ( isAddressInfo ( _address ) ) {
262
+ const mockURL = `http://${ _address . address } :${ _address . port } /redirect/11`
263
+ let provider = new UpdateProvider ( mockURL , settings ( ) )
264
+ let update = await provider . getUpdate ( true )
265
+
266
+ expect ( update . version ) . toBe ( "unknown" )
267
+ expect ( logger . error ) . toHaveBeenCalled ( )
268
+ expect ( logger . error ) . toHaveBeenCalledWith ( "Failed to get latest version" , {
269
+ identifier : "error" ,
270
+ value : `reached max redirects` ,
271
+ } )
272
+ }
273
+ } )
173
274
} )
0 commit comments