@@ -17,10 +17,12 @@ import (
1717 "testing"
1818 "time"
1919
20+ "github.com/hashicorp/go-retryablehttp"
2021 "github.com/stretchr/testify/assert"
2122 "github.com/stretchr/testify/require"
2223
2324 "github.com/ory/herodot"
25+ "github.com/ory/kratos/driver"
2426 "github.com/ory/kratos/driver/config"
2527 "github.com/ory/kratos/pkg"
2628 "github.com/ory/kratos/selfservice/strategy/password"
@@ -30,6 +32,32 @@ import (
3032 "github.com/ory/x/httpx"
3133)
3234
35+ // testRegistry embeds RegistryDefault and overrides HTTPClient to inject a
36+ // controllable HTTP client for HIBP-related tests.
37+ type testRegistry struct {
38+ * driver.RegistryDefault
39+ cl * retryablehttp.Client
40+ }
41+
42+ func (r * testRegistry ) HTTPClient (_ context.Context , _ ... httpx.ResilientOptions ) * retryablehttp.Client {
43+ return r .cl
44+ }
45+
46+ // newTestValidator wires base with a fake HIBP HTTP client and returns the
47+ // validator along with the fake client for request assertions and stubbing.
48+ func newTestValidator (t * testing.T , base * driver.RegistryDefault , opts ... httpx.ResilientOptions ) (* password.DefaultPasswordValidator , * fakeHttpClient ) {
49+ t .Helper ()
50+ fakeClient := NewFakeHTTPClient ()
51+ cl := httpx .NewResilientClient (append ([]httpx.ResilientOptions {
52+ httpx .ResilientClientWithMaxRetry (1 ),
53+ httpx .ResilientClientWithConnectionTimeout (time .Millisecond ),
54+ }, opts ... )... )
55+ cl .HTTPClient = & fakeClient .Client
56+ s , err := password .NewDefaultPasswordValidatorStrategy (& testRegistry {RegistryDefault : base , cl : cl })
57+ require .NoError (t , err )
58+ return s , fakeClient
59+ }
60+
3361func TestDefaultPasswordValidationStrategy (t * testing.T ) {
3462 t .Parallel ()
3563
@@ -93,16 +121,8 @@ func TestDefaultPasswordValidationStrategy(t *testing.T) {
93121 t .Run ("failure cases" , func (t * testing.T ) {
94122 t .Parallel ()
95123
96- _ , reg := pkg .NewFastRegistryWithMocks (t )
97- s , err := password .NewDefaultPasswordValidatorStrategy (reg )
98- require .NoError (t , err )
99-
100- fakeClient := NewFakeHTTPClient ()
101- s .Client = httpx .NewResilientClient (
102- httpx .ResilientClientWithMaxRetry (1 ),
103- httpx .ResilientClientWithConnectionTimeout (time .Millisecond ),
104- httpx .ResilientClientWithMaxRetryWait (time .Millisecond ))
105- s .Client .HTTPClient = & fakeClient .Client
124+ _ , base := pkg .NewFastRegistryWithMocks (t )
125+ s , fakeClient := newTestValidator (t , base , httpx .ResilientClientWithMaxRetryWait (time .Millisecond ))
106126
107127 t .Run ("case=should send request to pwnedpasswords.com" , func (t * testing.T ) {
108128 ctx := contextx .WithConfigValue (t .Context (), config .ViperKeyIgnoreNetworkErrors , false )
@@ -139,12 +159,10 @@ func TestDefaultPasswordValidationStrategy(t *testing.T) {
139159 t .Parallel ()
140160
141161 const maxBreaches = 5
142- _ , reg := pkg .NewFastRegistryWithMocks (t , configx .WithValue (config .ViperKeyPasswordMaxBreaches , maxBreaches ))
143- s , err := password .NewDefaultPasswordValidatorStrategy (reg )
144- require .NoError (t , err )
162+ _ , base := pkg .NewFastRegistryWithMocks (t , configx .WithValue (config .ViperKeyPasswordMaxBreaches , maxBreaches ))
163+ s , fakeClient := newTestValidator (t , base )
145164
146165 hibpResp := make (chan string , 1 )
147- fakeClient := NewFakeHTTPClient ()
148166 fakeClient .responder = func (req * http.Request ) (* http.Response , error ) {
149167 buffer := bytes .NewBufferString (<- hibpResp )
150168 return & http.Response {
@@ -154,8 +172,6 @@ func TestDefaultPasswordValidationStrategy(t *testing.T) {
154172 Request : req ,
155173 }, nil
156174 }
157- s .Client = httpx .NewResilientClient (httpx .ResilientClientWithMaxRetry (1 ), httpx .ResilientClientWithConnectionTimeout (time .Millisecond ))
158- s .Client .HTTPClient = & fakeClient .Client
159175
160176 hashPw := func (t * testing.T , pw string ) string {
161177 //#nosec G401 -- sha1 is used for k-anonymity
@@ -271,13 +287,8 @@ func TestChangeHaveIBeenPwnedValidationHost(t *testing.T) {
271287 testServerURL , err := url .Parse (testServer .URL )
272288 require .NoError (t , err )
273289
274- _ , reg := pkg .NewFastRegistryWithMocks (t , configx .WithValue (config .ViperKeyPasswordHaveIBeenPwnedHost , testServerURL .Host ))
275- s , err := password .NewDefaultPasswordValidatorStrategy (reg )
276- require .NoError (t , err )
277-
278- fakeClient := NewFakeHTTPClient ()
279- s .Client = httpx .NewResilientClient (httpx .ResilientClientWithMaxRetry (1 ), httpx .ResilientClientWithConnectionTimeout (time .Millisecond ))
280- s .Client .HTTPClient = & fakeClient .Client
290+ _ , base := pkg .NewFastRegistryWithMocks (t , configx .WithValue (config .ViperKeyPasswordHaveIBeenPwnedHost , testServerURL .Host ))
291+ s , fakeClient := newTestValidator (t , base )
281292
282293 testServerExpectedCallURL := fmt .Sprintf ("https://%s/range/BCBA9" , testServerURL .Host )
283294
@@ -291,13 +302,8 @@ func TestChangeHaveIBeenPwnedValidationHost(t *testing.T) {
291302func TestDisableHaveIBeenPwnedValidationHost (t * testing.T ) {
292303 t .Parallel ()
293304
294- _ , reg := pkg .NewFastRegistryWithMocks (t , configx .WithValue (config .ViperKeyPasswordHaveIBeenPwnedEnabled , false ))
295- s , err := password .NewDefaultPasswordValidatorStrategy (reg )
296- require .NoError (t , err )
297-
298- fakeClient := NewFakeHTTPClient ()
299- s .Client = httpx .NewResilientClient (httpx .ResilientClientWithMaxRetry (1 ), httpx .ResilientClientWithConnectionTimeout (time .Millisecond ))
300- s .Client .HTTPClient = & fakeClient .Client
305+ _ , base := pkg .NewFastRegistryWithMocks (t , configx .WithValue (config .ViperKeyPasswordHaveIBeenPwnedEnabled , false ))
306+ s , fakeClient := newTestValidator (t , base )
301307
302308 t .Run ("case=should not send request to test server" , func (t * testing.T ) {
303309 require .NoError (t , s .Validate (t .Context (), "mohutdesub" , "damrumukuh" ))
0 commit comments