Skip to content

Commit 711737f

Browse files
committed
test: replace httptest.NewServer with in-memory RoundTripper across 7 packages
All packages that previously bound real TCP ports (auth, config, httputil, search, shell, system, updater) now use a mockRoundTripper that dispatches to the handler via httptest.NewRecorder — zero network binding. Production changes: - shell.go: add omzHTTPClient var (replaces http.DefaultClient injection) - system.go: add brewHTTPClient var (replaces http.DefaultClient injection)
1 parent bc440c1 commit 711737f

9 files changed

Lines changed: 318 additions & 645 deletions

File tree

internal/auth/login_test.go

Lines changed: 106 additions & 387 deletions
Large diffs are not rendered by default.

internal/config/config_test.go

Lines changed: 37 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package config
22

33
import (
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+
1435
func 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

103117
func 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

155155
func 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

177170
func 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

229208
func 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

248220
func 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

324284
func 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

645591
func 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

Comments
 (0)