|
1 | 1 | import datetime |
2 | 2 |
|
| 3 | +import pytest |
| 4 | +from pydantic import ValidationError |
| 5 | + |
3 | 6 | from scim2_models import Address |
4 | 7 | from scim2_models import Email |
5 | 8 | from scim2_models import Im |
6 | 9 | from scim2_models import PhoneNumber |
7 | 10 | from scim2_models import Photo |
8 | 11 | from scim2_models import Reference |
9 | 12 | from scim2_models import User |
| 13 | +from scim2_models.context import Context |
10 | 14 |
|
11 | 15 |
|
12 | 16 | def test_minimal_user(load_sample): |
@@ -124,3 +128,67 @@ def test_full_user(load_sample): |
124 | 128 | obj.meta.location |
125 | 129 | == "https://example.com/v2/Users/2819c223-7f76-453a-919d-413861904646" |
126 | 130 | ) |
| 131 | + |
| 132 | + |
| 133 | +def test_multiple_emails_without_primary_is_valid(): |
| 134 | + """Test that multiple emails without any primary attribute is valid.""" |
| 135 | + user_data = { |
| 136 | + "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], |
| 137 | + "userName": "testuser", |
| 138 | + "emails": [ |
| 139 | + {"value": "test1@example.com", "type": "work"}, |
| 140 | + {"value": "test2@example.com", "type": "home"}, |
| 141 | + ], |
| 142 | + } |
| 143 | + user = User.model_validate(user_data, scim_ctx=Context.RESOURCE_CREATION_REQUEST) |
| 144 | + assert user.user_name == "testuser" |
| 145 | + |
| 146 | + |
| 147 | +def test_single_primary_email_is_valid(): |
| 148 | + """Test that exactly one primary email is valid per RFC 7643.""" |
| 149 | + user_data = { |
| 150 | + "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], |
| 151 | + "userName": "testuser", |
| 152 | + "emails": [ |
| 153 | + {"value": "primary@example.com", "type": "work", "primary": True}, |
| 154 | + {"value": "secondary@example.com", "type": "home", "primary": False}, |
| 155 | + ], |
| 156 | + } |
| 157 | + user = User.model_validate(user_data, scim_ctx=Context.RESOURCE_CREATION_REQUEST) |
| 158 | + assert user.emails[0].primary is True |
| 159 | + assert user.emails[1].primary is False |
| 160 | + |
| 161 | + |
| 162 | +def test_multiple_primary_emails_rejected(): |
| 163 | + """Test that multiple primary emails are rejected per RFC 7643.""" |
| 164 | + user_data = { |
| 165 | + "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], |
| 166 | + "userName": "testuser", |
| 167 | + "emails": [ |
| 168 | + {"value": "primary1@example.com", "primary": True}, |
| 169 | + {"value": "primary2@example.com", "primary": True}, |
| 170 | + ], |
| 171 | + } |
| 172 | + |
| 173 | + with pytest.raises(ValidationError) as exc_info: |
| 174 | + User.model_validate(user_data, scim_ctx=Context.RESOURCE_CREATION_REQUEST) |
| 175 | + |
| 176 | + error = exc_info.value.errors()[0] |
| 177 | + assert error["type"] == "primary_uniqueness_error" |
| 178 | + assert "emails" in error["ctx"]["field_name"] |
| 179 | + assert error["ctx"]["count"] == 2 |
| 180 | + |
| 181 | + |
| 182 | +@pytest.mark.parametrize("scim_ctx", [None, Context.DEFAULT]) |
| 183 | +def test_multiple_primary_validation_skipped_without_strict_context(scim_ctx): |
| 184 | + """Test that primary validation is skipped when no strict SCIM context is provided.""" |
| 185 | + user_data = { |
| 186 | + "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], |
| 187 | + "userName": "testuser", |
| 188 | + "emails": [ |
| 189 | + {"value": "primary1@example.com", "primary": True}, |
| 190 | + {"value": "primary2@example.com", "primary": True}, |
| 191 | + ], |
| 192 | + } |
| 193 | + user = User.model_validate(user_data, scim_ctx=scim_ctx) |
| 194 | + assert len(user.emails) == 2 |
0 commit comments