@@ -16,19 +16,25 @@ func TestUserMapper(t *testing.T) {
1616 createdAt := time .Date (2026 , 7 , 21 , 19 , 41 , 41 , 0 , time .UTC )
1717 updatedAt := time .Date (2026 , 7 , 22 , 8 , 12 , 3 , 0 , time .UTC )
1818
19- newModel := func (email string ) * models.User {
20- return & models.User {
21- ID : id ,
22- Email : storage .NullString (email ),
23- CreatedAt : createdAt ,
24- UpdatedAt : updatedAt ,
19+ newModel := func (email string , claims map [string ]interface {}) models.ProvisionedUser {
20+ in := models.ProvisionedUser {
21+ User : & models.User {
22+ ID : id ,
23+ Email : storage .NullString (email ),
24+ CreatedAt : createdAt ,
25+ UpdatedAt : updatedAt ,
26+ },
2527 }
28+ if claims != nil {
29+ in .Identity = & models.Identity {IdentityData : claims }
30+ }
31+ return in
2632 }
2733
2834 mapper := NewUserMapper ("http://localhost:9999/scim/v2" )
2935
3036 t .Run ("maps a user onto the core User resource" , func (t * testing.T ) {
31- user := mapper .MapFrom (newModel ("bjensen@example.com" ))
37+ user := mapper .MapFrom (newModel ("bjensen@example.com" , nil ))
3238
3339 require .Equal (t , []core.SchemaURI {core .SchemaUser }, user .Schemas )
3440 require .Equal (t , id .String (), user .ID )
@@ -38,20 +44,20 @@ func TestUserMapper(t *testing.T) {
3844 })
3945
4046 t .Run ("omits emails when the user has no email" , func (t * testing.T ) {
41- user := mapper .MapFrom (newModel ("" ))
47+ user := mapper .MapFrom (newModel ("" , nil ))
4248
4349 require .Empty (t , user .UserName )
4450 require .Nil (t , user .Emails )
4551 })
4652
4753 t .Run ("builds the location from the base URL" , func (t * testing.T ) {
48- user := NewUserMapper ("https://auth.example.com/scim/v2" ).MapFrom (newModel ("bjensen@example.com" ))
54+ user := NewUserMapper ("https://auth.example.com/scim/v2" ).MapFrom (newModel ("bjensen@example.com" , nil ))
4955
5056 require .Equal (t , "https://auth.example.com/scim/v2/Users/" + id .String (), user .Meta .Location )
5157 })
5258
5359 t .Run ("normalizes the timestamps to UTC" , func (t * testing.T ) {
54- model := newModel ("bjensen@example.com" )
60+ model := newModel ("bjensen@example.com" , nil )
5561 model .CreatedAt = createdAt .In (time .FixedZone ("MDT" , - 6 * 60 * 60 ))
5662
5763 user := mapper .MapFrom (model )
@@ -61,7 +67,69 @@ func TestUserMapper(t *testing.T) {
6167 require .Equal (t , updatedAt , user .Meta .LastModified )
6268 })
6369
70+ t .Run ("prefers the email the provider supplied over the user record" , func (t * testing.T ) {
71+ user := mapper .MapFrom (newModel ("stale@example.com" , map [string ]interface {}{
72+ "email" : "bjensen@example.com" ,
73+ }))
74+
75+ require .Equal (t , "bjensen@example.com" , user .UserName )
76+ require .Equal (t , []core.Email {{Value : "bjensen@example.com" , Primary : true }}, user .Emails )
77+ })
78+
79+ t .Run ("falls back to the user record when the provider supplied no email" , func (t * testing.T ) {
80+ user := mapper .MapFrom (newModel ("bjensen@example.com" , map [string ]interface {}{
81+ "sub" : id .String (),
82+ }))
83+
84+ require .Equal (t , "bjensen@example.com" , user .UserName )
85+ require .Equal (t , []core.Email {{Value : "bjensen@example.com" , Primary : true }}, user .Emails )
86+ })
87+
88+ t .Run ("prefers preferred_username for the userName" , func (t * testing.T ) {
89+ user := mapper .MapFrom (newModel ("" , map [string ]interface {}{
90+ "preferred_username" : "bjensen" ,
91+ "email" : "bjensen@example.com" ,
92+ }))
93+
94+ require .Equal (t , "bjensen" , user .UserName )
95+ require .Equal (t , []core.Email {{Value : "bjensen@example.com" , Primary : true }}, user .Emails )
96+ })
97+
98+ t .Run ("maps the name components the provider supplied" , func (t * testing.T ) {
99+ user := mapper .MapFrom (newModel ("" , map [string ]interface {}{
100+ "name" : "Ms. Barbara Jane Jensen, III" ,
101+ "family_name" : "Jensen" ,
102+ "given_name" : "Barbara" ,
103+ "middle_name" : "Jane" ,
104+ }))
105+
106+ require .Equal (t , & core.Name {
107+ Formatted : "Ms. Barbara Jane Jensen, III" ,
108+ FamilyName : "Jensen" ,
109+ GivenName : "Barbara" ,
110+ MiddleName : "Jane" ,
111+ }, user .Name )
112+ })
113+
114+ t .Run ("omits the name when the provider supplied no components" , func (t * testing.T ) {
115+ require .Nil (t , mapper .MapFrom (newModel ("bjensen@example.com" , nil )).Name )
116+ require .Nil (t , mapper .MapFrom (newModel ("bjensen@example.com" , map [string ]interface {}{
117+ "sub" : id .String (),
118+ })).Name )
119+ })
120+
121+ t .Run ("ignores claims that are not strings" , func (t * testing.T ) {
122+ user := mapper .MapFrom (newModel ("bjensen@example.com" , map [string ]interface {}{
123+ "email" : 12345 ,
124+ "given_name" : []string {"Barbara" },
125+ "family_name" : "Jensen" ,
126+ }))
127+
128+ require .Equal (t , "bjensen@example.com" , user .UserName )
129+ require .Equal (t , & core.Name {FamilyName : "Jensen" }, user .Name )
130+ })
131+
64132 t .Run ("satisfies the Mapper interface" , func (t * testing.T ) {
65- var _ Mapper [* models.User , * core.User ] = NewUserMapper ("" )
133+ var _ Mapper [models.ProvisionedUser , * core.User ] = NewUserMapper ("" )
66134 })
67135}
0 commit comments