|
62 | 62 | feed_id="feed_id", |
63 | 63 | hosted_url="hosted_url", |
64 | 64 | note="note", |
65 | | - downloaded_at="downloaded_at", |
| 65 | + downloaded_at=datetime(2023, 1, 1, 0, 0, 0, tzinfo=ZoneInfo("UTC")), |
66 | 66 | hash="hash", |
67 | 67 | bounding_box="bounding_box", |
68 | 68 | service_date_range_start=datetime(2024, 1, 1, 0, 0, 0, tzinfo=ZoneInfo("Canada/Atlantic")), |
@@ -160,3 +160,97 @@ def test_from_orm_empty_fields(self): |
160 | 160 | def test_from_orm_none(self): |
161 | 161 | """Test the `from_orm` method with None.""" |
162 | 162 | assert FeedImpl.from_orm(None) is None |
| 163 | + |
| 164 | + def test_to_orm_from_dict_none(self): |
| 165 | + """to_orm_from_dict returns None when input is None or empty dict.""" |
| 166 | + assert FeedImpl.to_orm_from_dict(None) is None |
| 167 | + assert FeedImpl.to_orm_from_dict({}) is None |
| 168 | + |
| 169 | + def test_to_orm_from_dict_full_payload(self): |
| 170 | + """to_orm_from_dict maps primitives and nested collections; sorts externalids by associated_id.""" |
| 171 | + now = datetime(2024, 5, 1, 12, 30, 0) |
| 172 | + updated = datetime(2024, 6, 1, 8, 0, 0) |
| 173 | + payload = { |
| 174 | + "id": "feed-123", |
| 175 | + "stable_id": "stable-123", |
| 176 | + "data_type": "gtfs", |
| 177 | + "created_at": now, |
| 178 | + "provider": "Provider A", |
| 179 | + "feed_contact_email": "[email protected]", |
| 180 | + "producer_url": "https://producer.example.com", |
| 181 | + "authentication_type": 1, # should be converted to string |
| 182 | + "authentication_info_url": "https://auth.example.com", |
| 183 | + "api_key_parameter_name": "api_key", |
| 184 | + "license_url": "https://license.example.com", |
| 185 | + "status": "active", |
| 186 | + "official": True, |
| 187 | + "official_updated_at": updated, |
| 188 | + "feed_name": "Feed Name", |
| 189 | + "note": "Some note", |
| 190 | + # avoid DB-dependent fields: locations and redirectingids |
| 191 | + "externalids": [ |
| 192 | + {"external_id": "b-id", "source": "src"}, |
| 193 | + {"external_id": "a-id", "source": "src"}, |
| 194 | + ], |
| 195 | + "feedrelatedlinks": [ |
| 196 | + {"code": "docs", "url": "https://docs.example.com", "description": "Docs"}, |
| 197 | + {"code": "home", "url": "https://home.example.com", "description": "Home"}, |
| 198 | + ], |
| 199 | + } |
| 200 | + |
| 201 | + obj = FeedImpl.to_orm_from_dict(payload) |
| 202 | + |
| 203 | + # Basic type |
| 204 | + assert isinstance(obj, Feed) |
| 205 | + |
| 206 | + # Primitives |
| 207 | + assert obj.id == "feed-123" |
| 208 | + assert obj.stable_id == "stable-123" |
| 209 | + assert obj.data_type == "gtfs" |
| 210 | + assert obj.created_at == now |
| 211 | + assert obj.provider == "Provider A" |
| 212 | + assert obj. feed_contact_email == "[email protected]" |
| 213 | + assert obj.producer_url == "https://producer.example.com" |
| 214 | + # authentication_type coerced to string per implementation |
| 215 | + assert obj.authentication_type == "1" |
| 216 | + assert obj.authentication_info_url == "https://auth.example.com" |
| 217 | + assert obj.api_key_parameter_name == "api_key" |
| 218 | + assert obj.license_url == "https://license.example.com" |
| 219 | + assert obj.status == "active" |
| 220 | + assert obj.official is True |
| 221 | + assert obj.official_updated_at == updated |
| 222 | + assert obj.feed_name == "Feed Name" |
| 223 | + assert obj.note == "Some note" |
| 224 | + |
| 225 | + # Nested: externalids should be sorted by associated_id |
| 226 | + assert [type(e).__name__ for e in obj.externalids] == ["Externalid", "Externalid"] |
| 227 | + got_ext = [(e.source, e.associated_id) for e in obj.externalids] |
| 228 | + assert got_ext == [("src", "a-id"), ("src", "b-id")] |
| 229 | + |
| 230 | + # Nested: feedrelatedlinks preserved order (no explicit sort in impl) |
| 231 | + assert len(obj.feedrelatedlinks) == 2 |
| 232 | + codes = [feedrelatedlinks.code for feedrelatedlinks in obj.feedrelatedlinks] |
| 233 | + urls = [feedrelatedlinks.url for feedrelatedlinks in obj.feedrelatedlinks] |
| 234 | + assert codes == ["docs", "home"] |
| 235 | + assert urls == ["https://docs.example.com", "https://home.example.com"] |
| 236 | + |
| 237 | + # Relationships not provided should be empty lists |
| 238 | + assert obj.redirectingids == [] |
| 239 | + assert obj.locations == [] |
| 240 | + |
| 241 | + def test_to_orm_from_dict_empty_collections(self): |
| 242 | + """Explicit empty lists yield empty relationship collections in ORM object.""" |
| 243 | + payload = { |
| 244 | + "stable_id": "s", |
| 245 | + "data_type": "gtfs", |
| 246 | + "externalids": [], |
| 247 | + "feedrelatedlinks": [], |
| 248 | + "redirectingids": [], |
| 249 | + "locations": [], |
| 250 | + } |
| 251 | + obj = FeedImpl.to_orm_from_dict(payload) |
| 252 | + assert isinstance(obj, Feed) |
| 253 | + assert obj.externalids == [] |
| 254 | + assert obj.feedrelatedlinks == [] |
| 255 | + assert obj.redirectingids == [] |
| 256 | + assert obj.locations == [] |
0 commit comments