@@ -2,6 +2,7 @@ package config
22
33import (
44 "encoding/json"
5+ "errors"
56 "net/http"
67 "net/http/httptest"
78 "strings"
@@ -11,6 +12,26 @@ import (
1112 "github.com/stretchr/testify/require"
1213)
1314
15+ type cfgMockRT struct { handler http.Handler }
16+
17+ func (m * cfgMockRT ) RoundTrip (req * http.Request ) (* http.Response , error ) {
18+ rec := httptest .NewRecorder ()
19+ m .handler .ServeHTTP (rec , req )
20+ return rec .Result (), nil
21+ }
22+
23+ type cfgErrRT struct { err error }
24+
25+ func (e * cfgErrRT ) RoundTrip (* http.Request ) (* http.Response , error ) { return nil , e .err }
26+
27+ // withMockRemoteClient patches remoteHTTPClient for one test without binding ports.
28+ func withMockRemoteClient (t * testing.T , handler http.Handler ) {
29+ t .Helper ()
30+ orig := remoteHTTPClient
31+ remoteHTTPClient = & http.Client {Transport : & cfgMockRT {handler : handler }}
32+ t .Cleanup (func () { remoteHTTPClient = orig })
33+ }
34+
1435func TestGetPreset (t * testing.T ) {
1536 tests := []struct {
1637 name string
@@ -77,20 +98,13 @@ func TestFetchRemoteConfig_PublicConfig_NoToken(t *testing.T) {
7798 DotfilesRepo : "https://github.com/testuser/dotfiles" ,
7899 }
79100
80- server := httptest . NewServer ( http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
101+ withMockRemoteClient ( t , http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
81102 assert .Equal (t , "/testuser/myconfig/config" , r .URL .Path )
82103 assert .Empty (t , r .Header .Get ("Authorization" ))
83104
84105 w .WriteHeader (http .StatusOK )
85106 json .NewEncoder (w ).Encode (mockConfig ) //nolint:errcheck // test helper
86107 }))
87- defer server .Close ()
88-
89- originalClient := remoteHTTPClient
90- remoteHTTPClient = server .Client ()
91- defer func () { remoteHTTPClient = originalClient }()
92-
93- t .Setenv ("OPENBOOT_API_URL" , server .URL )
94108
95109 result , err := FetchRemoteConfig ("testuser/myconfig" , "" )
96110 require .NoError (t , err )
@@ -101,19 +115,12 @@ func TestFetchRemoteConfig_PublicConfig_NoToken(t *testing.T) {
101115}
102116
103117func TestFetchRemoteConfig_PrivateConfig_NoToken (t * testing.T ) {
104- server := httptest . NewServer ( http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
118+ withMockRemoteClient ( t , http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
105119 assert .Equal (t , "/testuser/private/config" , r .URL .Path )
106120 assert .Empty (t , r .Header .Get ("Authorization" ))
107121
108122 w .WriteHeader (http .StatusForbidden )
109123 }))
110- defer server .Close ()
111-
112- originalClient := remoteHTTPClient
113- remoteHTTPClient = server .Client ()
114- defer func () { remoteHTTPClient = originalClient }()
115-
116- t .Setenv ("OPENBOOT_API_URL" , server .URL )
117124
118125 result , err := FetchRemoteConfig ("testuser/private" , "" )
119126 assert .Error (t , err )
@@ -130,20 +137,13 @@ func TestFetchRemoteConfig_PrivateConfig_WithValidToken(t *testing.T) {
130137 Preset : "full" ,
131138 }
132139
133- server := httptest . NewServer ( http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
140+ withMockRemoteClient ( t , http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
134141 assert .Equal (t , "/testuser/private/config" , r .URL .Path )
135142 assert .Equal (t , "Bearer obt_valid_token" , r .Header .Get ("Authorization" ))
136143
137144 w .WriteHeader (http .StatusOK )
138145 json .NewEncoder (w ).Encode (mockConfig ) //nolint:errcheck // test helper
139146 }))
140- defer server .Close ()
141-
142- originalClient := remoteHTTPClient
143- remoteHTTPClient = server .Client ()
144- defer func () { remoteHTTPClient = originalClient }()
145-
146- t .Setenv ("OPENBOOT_API_URL" , server .URL )
147147
148148 result , err := FetchRemoteConfig ("testuser/private" , "obt_valid_token" )
149149 require .NoError (t , err )
@@ -153,19 +153,12 @@ func TestFetchRemoteConfig_PrivateConfig_WithValidToken(t *testing.T) {
153153}
154154
155155func TestFetchRemoteConfig_PrivateConfig_WithInvalidToken (t * testing.T ) {
156- server := httptest . NewServer ( http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
156+ withMockRemoteClient ( t , http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
157157 assert .Equal (t , "/testuser/private/config" , r .URL .Path )
158158 assert .Equal (t , "Bearer obt_invalid_token" , r .Header .Get ("Authorization" ))
159159
160160 w .WriteHeader (http .StatusForbidden )
161161 }))
162- defer server .Close ()
163-
164- originalClient := remoteHTTPClient
165- remoteHTTPClient = server .Client ()
166- defer func () { remoteHTTPClient = originalClient }()
167-
168- t .Setenv ("OPENBOOT_API_URL" , server .URL )
169162
170163 result , err := FetchRemoteConfig ("testuser/private" , "obt_invalid_token" )
171164 assert .Error (t , err )
@@ -175,17 +168,10 @@ func TestFetchRemoteConfig_PrivateConfig_WithInvalidToken(t *testing.T) {
175168}
176169
177170func TestFetchRemoteConfig_ConfigNotFound (t * testing.T ) {
178- server := httptest . NewServer ( http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
171+ withMockRemoteClient ( t , http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
179172 assert .Equal (t , "/testuser/nonexistent/config" , r .URL .Path )
180173 w .WriteHeader (http .StatusNotFound )
181174 }))
182- defer server .Close ()
183-
184- originalClient := remoteHTTPClient
185- remoteHTTPClient = server .Client ()
186- defer func () { remoteHTTPClient = originalClient }()
187-
188- t .Setenv ("OPENBOOT_API_URL" , server .URL )
189175
190176 result , err := FetchRemoteConfig ("testuser/nonexistent" , "" )
191177 assert .Error (t , err )
@@ -200,7 +186,7 @@ func TestFetchRemoteConfig_DefaultSlug(t *testing.T) {
200186 Name : "Default Config" ,
201187 }
202188
203- server := httptest . NewServer ( http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
189+ withMockRemoteClient ( t , http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
204190 switch r .URL .Path {
205191 case "/api/configs/alias/testuser" :
206192 w .WriteHeader (http .StatusNotFound )
@@ -212,13 +198,6 @@ func TestFetchRemoteConfig_DefaultSlug(t *testing.T) {
212198 w .WriteHeader (http .StatusNotFound )
213199 }
214200 }))
215- defer server .Close ()
216-
217- originalClient := remoteHTTPClient
218- remoteHTTPClient = server .Client ()
219- defer func () { remoteHTTPClient = originalClient }()
220-
221- t .Setenv ("OPENBOOT_API_URL" , server .URL )
222201
223202 result , err := FetchRemoteConfig ("testuser" , "" )
224203 require .NoError (t , err )
@@ -227,17 +206,10 @@ func TestFetchRemoteConfig_DefaultSlug(t *testing.T) {
227206}
228207
229208func TestFetchRemoteConfig_InvalidJSON (t * testing.T ) {
230- server := httptest . NewServer ( http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
209+ withMockRemoteClient ( t , http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
231210 w .WriteHeader (http .StatusOK )
232- w .Write ([]byte ("invalid json" ))
211+ w .Write ([]byte ("invalid json" )) //nolint:errcheck // test helper
233212 }))
234- defer server .Close ()
235-
236- originalClient := remoteHTTPClient
237- remoteHTTPClient = server .Client ()
238- defer func () { remoteHTTPClient = originalClient }()
239-
240- t .Setenv ("OPENBOOT_API_URL" , server .URL )
241213
242214 result , err := FetchRemoteConfig ("testuser/myconfig" , "" )
243215 assert .Error (t , err )
@@ -246,7 +218,9 @@ func TestFetchRemoteConfig_InvalidJSON(t *testing.T) {
246218}
247219
248220func TestFetchRemoteConfig_NetworkError (t * testing.T ) {
249- t .Setenv ("OPENBOOT_API_URL" , "http://localhost:9999" )
221+ orig := remoteHTTPClient
222+ remoteHTTPClient = & http.Client {Transport : & cfgErrRT {err : errors .New ("connection refused" )}}
223+ t .Cleanup (func () { remoteHTTPClient = orig })
250224
251225 result , err := FetchRemoteConfig ("testuser/myconfig" , "" )
252226 assert .Error (t , err )
@@ -262,7 +236,7 @@ func TestFetchRemoteConfig_AliasResolution(t *testing.T) {
262236 Preset : "developer" ,
263237 }
264238
265- server := httptest . NewServer ( http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
239+ withMockRemoteClient ( t , http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
266240 switch r .URL .Path {
267241 case "/api/configs/alias/testuser" :
268242 w .WriteHeader (http .StatusOK )
@@ -272,13 +246,6 @@ func TestFetchRemoteConfig_AliasResolution(t *testing.T) {
272246 w .WriteHeader (http .StatusNotFound )
273247 }
274248 }))
275- defer server .Close ()
276-
277- originalClient := remoteHTTPClient
278- remoteHTTPClient = server .Client ()
279- defer func () { remoteHTTPClient = originalClient }()
280-
281- t .Setenv ("OPENBOOT_API_URL" , server .URL )
282249
283250 result , err := FetchRemoteConfig ("testuser" , "" )
284251 require .NoError (t , err )
@@ -295,7 +262,7 @@ func TestFetchRemoteConfig_NoAliasFallsBackToDefault(t *testing.T) {
295262 Preset : "minimal" ,
296263 }
297264
298- server := httptest . NewServer ( http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
265+ withMockRemoteClient ( t , http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
299266 switch r .URL .Path {
300267 case "/api/configs/alias/testuser" :
301268 w .WriteHeader (http .StatusNotFound )
@@ -307,13 +274,6 @@ func TestFetchRemoteConfig_NoAliasFallsBackToDefault(t *testing.T) {
307274 w .WriteHeader (http .StatusNotFound )
308275 }
309276 }))
310- defer server .Close ()
311-
312- originalClient := remoteHTTPClient
313- remoteHTTPClient = server .Client ()
314- defer func () { remoteHTTPClient = originalClient }()
315-
316- t .Setenv ("OPENBOOT_API_URL" , server .URL )
317277
318278 result , err := FetchRemoteConfig ("testuser" , "" )
319279 require .NoError (t , err )
@@ -322,7 +282,7 @@ func TestFetchRemoteConfig_NoAliasFallsBackToDefault(t *testing.T) {
322282}
323283
324284func TestFetchRemoteConfig_NoAliasNoDefault (t * testing.T ) {
325- server := httptest . NewServer ( http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
285+ withMockRemoteClient ( t , http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
326286 switch r .URL .Path {
327287 case "/api/configs/alias/testuser" :
328288 w .WriteHeader (http .StatusNotFound )
@@ -332,13 +292,6 @@ func TestFetchRemoteConfig_NoAliasNoDefault(t *testing.T) {
332292 w .WriteHeader (http .StatusNotFound )
333293 }
334294 }))
335- defer server .Close ()
336-
337- originalClient := remoteHTTPClient
338- remoteHTTPClient = server .Client ()
339- defer func () { remoteHTTPClient = originalClient }()
340-
341- t .Setenv ("OPENBOOT_API_URL" , server .URL )
342295
343296 result , err := FetchRemoteConfig ("testuser" , "" )
344297 assert .Error (t , err )
@@ -510,17 +463,10 @@ func TestFetchRemoteConfig_ObjectArrayFormat(t *testing.T) {
510463 "dotfiles_repo" : "https://github.com/testuser/dotfiles" ,
511464 }
512465
513- server := httptest . NewServer ( http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
466+ withMockRemoteClient ( t , http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
514467 w .WriteHeader (http .StatusOK )
515468 json .NewEncoder (w ).Encode (mockConfig ) //nolint:errcheck // test helper
516469 }))
517- defer server .Close ()
518-
519- originalClient := remoteHTTPClient
520- remoteHTTPClient = server .Client ()
521- defer func () { remoteHTTPClient = originalClient }()
522-
523- t .Setenv ("OPENBOOT_API_URL" , server .URL )
524470
525471 result , err := FetchRemoteConfig ("testuser/myconfig" , "" )
526472 require .NoError (t , err )
@@ -643,17 +589,10 @@ func TestRemoteConfig_Validate_PostInstall(t *testing.T) {
643589}
644590
645591func TestFetchRemoteConfig_ExplicitSlugNoFallback (t * testing.T ) {
646- server := httptest . NewServer ( http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
592+ withMockRemoteClient ( t , http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
647593 assert .Equal (t , "/testuser/default/config" , r .URL .Path )
648594 w .WriteHeader (http .StatusNotFound )
649595 }))
650- defer server .Close ()
651-
652- originalClient := remoteHTTPClient
653- remoteHTTPClient = server .Client ()
654- defer func () { remoteHTTPClient = originalClient }()
655-
656- t .Setenv ("OPENBOOT_API_URL" , server .URL )
657596
658597 result , err := FetchRemoteConfig ("testuser/default" , "" )
659598 assert .Error (t , err )
0 commit comments