@@ -49,6 +49,11 @@ type fakeAuth0Users struct {
4949 // created tracks users passed to Create.
5050 created []* management.User
5151
52+ // updateErr is returned by Update.
53+ updateErr error
54+ // updated tracks (id, user) pairs passed to Update.
55+ updated []* management.User
56+
5257 // linkErr is returned by Link.
5358 linkErr error
5459 // linked tracks (primaryID, provider, userID) tuples.
@@ -94,7 +99,11 @@ func (f *fakeAuth0Users) Create(_ context.Context, u *management.User, _ ...mana
9499 return nil
95100}
96101
97- func (f * fakeAuth0Users ) Update (_ context.Context , _ string , _ * management.User , _ ... management.RequestOption ) error {
102+ func (f * fakeAuth0Users ) Update (_ context.Context , _ string , u * management.User , _ ... management.RequestOption ) error {
103+ if f .updateErr != nil {
104+ return f .updateErr
105+ }
106+ f .updated = append (f .updated , u )
98107 return nil
99108}
100109
@@ -145,10 +154,13 @@ func TestLinkEmailIdentity(t *testing.T) {
145154 cleanup := setupLinkTest (t , fake )
146155 defer cleanup ()
147156
148- err := linkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
157+ linked , err := linkEmailIdentity (context .Background (), fake . users [ "auth0|primary" ] , "alt@example.com" )
149158 if err != nil {
150159 t .Fatalf ("unexpected error: %v" , err )
151160 }
161+ if ! linked {
162+ t .Error ("expected linked=true for happy path" )
163+ }
152164 if len (fake .created ) != 1 {
153165 t .Fatalf ("expected 1 create call, got %d" , len (fake .created ))
154166 }
@@ -174,10 +186,94 @@ func TestLinkEmailIdentity(t *testing.T) {
174186 cleanup := setupLinkTest (t , fake )
175187 defer cleanup ()
176188
177- err := linkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
189+ linked , err := linkEmailIdentity (context .Background (), fake .users ["auth0|primary" ], "alt@example.com" )
190+ if err != nil {
191+ t .Fatalf ("unexpected error: %v" , err )
192+ }
193+ if ! linked {
194+ t .Error ("expected linked=true for already-linked idempotent case" )
195+ }
196+ if len (fake .created ) != 0 {
197+ t .Errorf ("expected no create calls, got %d" , len (fake .created ))
198+ }
199+ if len (fake .linked ) != 0 {
200+ t .Errorf ("expected no link calls, got %d" , len (fake .linked ))
201+ }
202+ })
203+
204+ t .Run ("email matches primary account's own email is skipped" , func (t * testing.T ) {
205+ fake := & fakeAuth0Users {
206+ users : map [string ]* management.User {
207+ "auth0|primary" : {
208+ ID : auth0 .String ("auth0|primary" ),
209+ Email : auth0 .String ("alt@example.com" ),
210+ },
211+ },
212+ }
213+ cleanup := setupLinkTest (t , fake )
214+ defer cleanup ()
215+
216+ linked , err := linkEmailIdentity (context .Background (), fake .users ["auth0|primary" ], "alt@example.com" )
217+ if err != nil {
218+ t .Fatalf ("unexpected error: %v" , err )
219+ }
220+ if linked {
221+ t .Error ("expected linked=false when email matches primary" )
222+ }
223+ if len (fake .created ) != 0 {
224+ t .Errorf ("expected no create calls, got %d" , len (fake .created ))
225+ }
226+ if len (fake .linked ) != 0 {
227+ t .Errorf ("expected no link calls, got %d" , len (fake .linked ))
228+ }
229+ })
230+
231+ t .Run ("email matches primary account's own email case-insensitive is skipped" , func (t * testing.T ) {
232+ fake := & fakeAuth0Users {
233+ users : map [string ]* management.User {
234+ "auth0|primary" : {
235+ ID : auth0 .String ("auth0|primary" ),
236+ Email : auth0 .String ("Alt@Example.COM" ),
237+ },
238+ },
239+ }
240+ cleanup := setupLinkTest (t , fake )
241+ defer cleanup ()
242+
243+ linked , err := linkEmailIdentity (context .Background (), fake .users ["auth0|primary" ], "alt@example.com" )
178244 if err != nil {
179245 t .Fatalf ("unexpected error: %v" , err )
180246 }
247+ if linked {
248+ t .Error ("expected linked=false when email matches primary (case-insensitive)" )
249+ }
250+ if len (fake .created ) != 0 {
251+ t .Errorf ("expected no create calls, got %d" , len (fake .created ))
252+ }
253+ if len (fake .linked ) != 0 {
254+ t .Errorf ("expected no link calls, got %d" , len (fake .linked ))
255+ }
256+ })
257+
258+ t .Run ("blocked primary account is skipped" , func (t * testing.T ) {
259+ fake := & fakeAuth0Users {
260+ users : map [string ]* management.User {
261+ "auth0|primary" : {
262+ ID : auth0 .String ("auth0|primary" ),
263+ Blocked : auth0 .Bool (true ),
264+ },
265+ },
266+ }
267+ cleanup := setupLinkTest (t , fake )
268+ defer cleanup ()
269+
270+ linked , err := linkEmailIdentity (context .Background (), fake .users ["auth0|primary" ], "alt@example.com" )
271+ if err != nil {
272+ t .Fatalf ("unexpected error: %v" , err )
273+ }
274+ if linked {
275+ t .Error ("expected linked=false for blocked account" )
276+ }
181277 if len (fake .created ) != 0 {
182278 t .Errorf ("expected no create calls, got %d" , len (fake .created ))
183279 }
@@ -200,10 +296,13 @@ func TestLinkEmailIdentity(t *testing.T) {
200296 cleanup := setupLinkTest (t , fake )
201297 defer cleanup ()
202298
203- err := linkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
299+ linked , err := linkEmailIdentity (context .Background (), fake . users [ "auth0|primary" ] , "alt@example.com" )
204300 if err != nil {
205301 t .Fatalf ("unexpected error: %v" , err )
206302 }
303+ if ! linked {
304+ t .Error ("expected linked=true for already-linked case-insensitive match" )
305+ }
207306 if len (fake .created ) != 0 {
208307 t .Errorf ("expected no create calls for case-insensitive match" )
209308 }
@@ -228,10 +327,13 @@ func TestLinkEmailIdentity(t *testing.T) {
228327 cleanup := setupLinkTest (t , fake )
229328 defer cleanup ()
230329
231- err := linkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
330+ linked , err := linkEmailIdentity (context .Background (), fake . users [ "auth0|primary" ] , "alt@example.com" )
232331 if err != nil {
233332 t .Fatalf ("unexpected error: %v" , err )
234333 }
334+ if ! linked {
335+ t .Error ("expected linked=true when email is already linked (idempotent)" )
336+ }
235337 if len (fake .created ) != 0 {
236338 t .Errorf ("should not create when email is linked to another user" )
237339 }
@@ -265,10 +367,13 @@ func TestLinkEmailIdentity(t *testing.T) {
265367 cleanup := setupLinkTest (t , fake )
266368 defer cleanup ()
267369
268- err := linkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
370+ linked , err := linkEmailIdentity (context .Background (), fake . users [ "auth0|primary" ] , "alt@example.com" )
269371 if err != nil {
270372 t .Fatalf ("unexpected error: %v" , err )
271373 }
374+ if ! linked {
375+ t .Error ("expected linked=true when only non-email identities match" )
376+ }
272377 if len (fake .created ) != 1 {
273378 t .Errorf ("should proceed to create when only non-email identities match, got %d creates" , len (fake .created ))
274379 }
@@ -291,10 +396,13 @@ func TestLinkEmailIdentity(t *testing.T) {
291396 cleanup := setupLinkTest (t , fake )
292397 defer cleanup ()
293398
294- err := linkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
399+ linked , err := linkEmailIdentity (context .Background (), fake . users [ "auth0|primary" ] , "alt@example.com" )
295400 if err != nil {
296401 t .Fatalf ("unexpected error: %v" , err )
297402 }
403+ if ! linked {
404+ t .Error ("expected linked=true for case-insensitive collision (idempotent)" )
405+ }
298406 if len (fake .created ) != 0 {
299407 t .Errorf ("case-insensitive collision should still abort the link" )
300408 }
@@ -310,8 +418,7 @@ func TestLinkEmailIdentity(t *testing.T) {
310418 cleanup := setupLinkTest (t , fake )
311419 defer cleanup ()
312420
313- err := linkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
314- if err == nil {
421+ if _ , err := linkEmailIdentity (context .Background (), fake .users ["auth0|primary" ], "alt@example.com" ); err == nil {
315422 t .Fatal ("expected Lucene search error to propagate" )
316423 }
317424 })
@@ -331,10 +438,13 @@ func TestLinkEmailIdentity(t *testing.T) {
331438 cleanup := setupLinkTest (t , fake )
332439 defer cleanup ()
333440
334- err := linkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
441+ linked , err := linkEmailIdentity (context .Background (), fake . users [ "auth0|primary" ] , "alt@example.com" )
335442 if err != nil {
336443 t .Fatalf ("unexpected error: %v" , err )
337444 }
445+ if ! linked {
446+ t .Error ("expected linked=true for 409+resolve path" )
447+ }
338448 if len (fake .linked ) != 1 {
339449 t .Fatalf ("expected 1 link call, got %d" , len (fake .linked ))
340450 }
@@ -356,8 +466,7 @@ func TestLinkEmailIdentity(t *testing.T) {
356466 cleanup := setupLinkTest (t , fake )
357467 defer cleanup ()
358468
359- err := linkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
360- if err == nil {
469+ if _ , err := linkEmailIdentity (context .Background (), fake .users ["auth0|primary" ], "alt@example.com" ); err == nil {
361470 t .Fatal ("expected error when 409 but no email| user found" )
362471 }
363472 })
@@ -373,10 +482,13 @@ func TestLinkEmailIdentity(t *testing.T) {
373482 cleanup := setupLinkTest (t , fake )
374483 defer cleanup ()
375484
376- err := linkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
485+ linked , err := linkEmailIdentity (context .Background (), fake . users [ "auth0|primary" ] , "alt@example.com" )
377486 if err != nil {
378487 t .Fatalf ("link 409 should be treated as success, got: %v" , err )
379488 }
489+ if ! linked {
490+ t .Error ("expected linked=true for link 409 idempotent case" )
491+ }
380492 })
381493
382494 t .Run ("link wrapped 409 is still idempotent (errors.As unwraps)" , func (t * testing.T ) {
@@ -390,10 +502,13 @@ func TestLinkEmailIdentity(t *testing.T) {
390502 cleanup := setupLinkTest (t , fake )
391503 defer cleanup ()
392504
393- err := linkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
505+ linked , err := linkEmailIdentity (context .Background (), fake . users [ "auth0|primary" ] , "alt@example.com" )
394506 if err != nil {
395507 t .Fatalf ("wrapped 409 should unwrap and be treated as success, got: %v" , err )
396508 }
509+ if ! linked {
510+ t .Error ("expected linked=true for wrapped link 409 idempotent case" )
511+ }
397512 })
398513
399514 t .Run ("create wrapped 409 unwraps and resolves existing user" , func (t * testing.T ) {
@@ -411,10 +526,13 @@ func TestLinkEmailIdentity(t *testing.T) {
411526 cleanup := setupLinkTest (t , fake )
412527 defer cleanup ()
413528
414- err := linkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
529+ linked , err := linkEmailIdentity (context .Background (), fake . users [ "auth0|primary" ] , "alt@example.com" )
415530 if err != nil {
416531 t .Fatalf ("wrapped create 409 should unwrap and proceed to link, got: %v" , err )
417532 }
533+ if ! linked {
534+ t .Error ("expected linked=true for wrapped create 409 path" )
535+ }
418536 if len (fake .linked ) != 1 {
419537 t .Fatalf ("expected 1 link call, got %d" , len (fake .linked ))
420538 }
@@ -431,8 +549,7 @@ func TestLinkEmailIdentity(t *testing.T) {
431549 cleanup := setupLinkTest (t , fake )
432550 defer cleanup ()
433551
434- err := linkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
435- if err == nil {
552+ if _ , err := linkEmailIdentity (context .Background (), fake .users ["auth0|primary" ], "alt@example.com" ); err == nil {
436553 t .Fatal ("expected error to propagate" )
437554 }
438555 })
@@ -453,7 +570,7 @@ func TestUnlinkEmailIdentity(t *testing.T) {
453570 cleanup := setupLinkTest (t , fake )
454571 defer cleanup ()
455572
456- err := unlinkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
573+ err := unlinkEmailIdentity (context .Background (), fake . users [ "auth0|primary" ] , "alt@example.com" )
457574 if err != nil {
458575 t .Fatalf ("unexpected error: %v" , err )
459576 }
@@ -474,7 +591,7 @@ func TestUnlinkEmailIdentity(t *testing.T) {
474591 cleanup := setupLinkTest (t , fake )
475592 defer cleanup ()
476593
477- err := unlinkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
594+ err := unlinkEmailIdentity (context .Background (), fake . users [ "auth0|primary" ] , "alt@example.com" )
478595 if err != nil {
479596 t .Fatalf ("unexpected error: %v" , err )
480597 }
@@ -498,7 +615,7 @@ func TestUnlinkEmailIdentity(t *testing.T) {
498615 cleanup := setupLinkTest (t , fake )
499616 defer cleanup ()
500617
501- err := unlinkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
618+ err := unlinkEmailIdentity (context .Background (), fake . users [ "auth0|primary" ] , "alt@example.com" )
502619 if err != nil {
503620 t .Fatalf ("unlink 404 should be treated as success, got: %v" , err )
504621 }
@@ -519,7 +636,7 @@ func TestUnlinkEmailIdentity(t *testing.T) {
519636 cleanup := setupLinkTest (t , fake )
520637 defer cleanup ()
521638
522- err := unlinkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
639+ err := unlinkEmailIdentity (context .Background (), fake . users [ "auth0|primary" ] , "alt@example.com" )
523640 if err != nil {
524641 t .Fatalf ("wrapped 404 should unwrap and be treated as success, got: %v" , err )
525642 }
@@ -540,7 +657,7 @@ func TestUnlinkEmailIdentity(t *testing.T) {
540657 cleanup := setupLinkTest (t , fake )
541658 defer cleanup ()
542659
543- err := unlinkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
660+ err := unlinkEmailIdentity (context .Background (), fake . users [ "auth0|primary" ] , "alt@example.com" )
544661 if err == nil {
545662 t .Fatal ("expected error to propagate" )
546663 }
@@ -560,7 +677,7 @@ func TestUnlinkEmailIdentity(t *testing.T) {
560677 cleanup := setupLinkTest (t , fake )
561678 defer cleanup ()
562679
563- err := unlinkEmailIdentity (context .Background (), "auth0|primary" , "alt@example.com" )
680+ err := unlinkEmailIdentity (context .Background (), fake . users [ "auth0|primary" ] , "alt@example.com" )
564681 if err != nil {
565682 t .Fatalf ("unexpected error: %v" , err )
566683 }
0 commit comments