Coverage for tests/test_places.py: 100%
78 statements
« prev ^ index » next coverage.py v7.6.0, created at 2024-07-28 10:16 -0400
« prev ^ index » next coverage.py v7.6.0, created at 2024-07-28 10:16 -0400
1from copy import deepcopy
2from typing import Any, Dict
3import pytest
4import pydantic
5from src.overturetoosm.places import (
6 process_place,
7)
8from src.overturetoosm.utils import process_geojson
9from src.overturetoosm.objects import ConfidenceError, UnmatchedError
12@pytest.fixture(name="clean_dict")
13def clean_fix() -> Dict[str, Any]:
14 return {
15 "name": "Primary Name",
16 "brand": "Brand Name",
17 "brand:wikidata": "Q123",
18 "addr:street_address": "123 Main St",
19 "addr:city": "City",
20 "addr:postcode": "12345",
21 "addr:state": "CA",
22 "addr:country": "Country",
23 "phone": "+1234567890",
24 "website": "https://example.com",
25 "source": "dataset1 via overturetoosm",
26 "office": "lawyer",
27 "lawyer": "notary",
28 "contact:facebook": "www.facebook.com/example",
29 }
32@pytest.fixture(name="geojson_dict")
33def geojson_fix() -> Dict[str, Any]:
34 return {
35 "type": "FeatureCollection",
36 "features": [
37 {
38 "type": "Feature",
39 "geometry": {"type": "Point", "coordinates": [-1, 1]},
40 "properties": {
41 "id": "123",
42 "version": 1,
43 "update_time": "2022-01-01T00:00:00Z",
44 "sources": [
45 {
46 "property": "property1",
47 "dataset": "dataset1",
48 "record_id": "record1",
49 "confidence": 0.8,
50 }
51 ],
52 "names": {
53 "primary": "Primary Name",
54 "common": "Common Name",
55 "rules": "Rules Name",
56 },
57 "brand": {
58 "wikidata": "Q123",
59 "names": {
60 "primary": "Brand Name",
61 "common": "Common Name",
62 "rules": "Rules Name",
63 },
64 },
65 "categories": {
66 "main": "notary_public",
67 "alternate": ["alternate_category1", "alternate_category2"],
68 },
69 "confidence": 0.8,
70 "websites": ["https://example.com"],
71 "socials": ["www.facebook.com/example"],
72 "phones": ["+1234567890"],
73 "addresses": [
74 {
75 "freeform": "123 Main St",
76 "locality": "City",
77 "postcode": "12345",
78 "region": "CA",
79 "country": "Country",
80 }
81 ],
82 },
83 }
84 ],
85 }
88@pytest.fixture(name="props_dict")
89def props_fix() -> Dict[str, Any]:
90 return {
91 "id": "123",
92 "version": 1,
93 "update_time": "2022-01-01T00:00:00Z",
94 "sources": [
95 {
96 "property": "property1",
97 "dataset": "dataset1",
98 "record_id": "record1",
99 "confidence": 0.8,
100 }
101 ],
102 "names": {
103 "primary": "Primary Name",
104 "common": "Common Name",
105 "rules": "Rules Name",
106 },
107 "brand": {
108 "wikidata": "Q123",
109 "names": {
110 "primary": "Brand Name",
111 "common": "Common Name",
112 "rules": "Rules Name",
113 },
114 },
115 "categories": {
116 "main": "notary_public",
117 "alternate": ["alternate_category1", "alternate_category2"],
118 },
119 "confidence": 0.8,
120 "websites": ["https://example.com"],
121 "socials": ["www.facebook.com/example"],
122 "phones": ["+1234567890"],
123 "addresses": [
124 {
125 "freeform": "123 Main St",
126 "locality": "City",
127 "postcode": "12345",
128 "region": "CA",
129 "country": "Country",
130 }
131 ],
132 }
135def test_place_props(props_dict: dict, clean_dict: dict):
136 """Test that all properties are processed correctly"""
137 new_props = process_place(props_dict)
138 assert new_props == clean_dict
141def test_place_props_no_brand(props_dict: dict, clean_dict: dict):
142 """Test that all properties are processed correctly"""
143 props_dict.pop("brand", None)
144 new_props = process_place(props_dict)
145 for i in ["brand", "brand:wikidata"]:
146 clean_dict.pop(i, None)
147 assert new_props == clean_dict
150def test_place_props_no_category(props_dict: dict, clean_dict: dict):
151 """Test that all properties are processed correctly"""
152 props_dict.pop("categories", None)
153 new_props = process_place(props_dict)
154 for i in ["office", "lawyer"]:
155 clean_dict.pop(i, None)
156 assert new_props == clean_dict
159def test_place_props_twitter(props_dict: dict, clean_dict: dict) -> None:
160 """Test that all properties are processed correctly"""
161 props_dict["socials"].append("https://twitter.com/example")
162 new_props = process_place(props_dict)
163 clean_dict["contact:twitter"] = "https://twitter.com/example"
164 assert new_props == clean_dict
167def test_low_confidence(props_dict):
168 """Test that properties with low confidence are not processed"""
169 with pytest.raises(ConfidenceError):
170 process_place(props_dict, confidence=0.9)
173def test_confidence(props_dict):
174 """Test that invalid properties are not processed"""
175 props_dict["confidence"] = -0.1
176 with pytest.raises(pydantic.ValidationError):
177 process_place(props_dict)
180def test_unmatched_error(props_dict):
181 """Test that invalid properties are not processed"""
182 props_dict["categories"]["main"] = "invalid_category"
183 with pytest.raises(UnmatchedError):
184 process_place(props_dict, unmatched="error")
187def test_unmatched_ignore(props_dict, clean_dict: dict):
188 """Test that invalid properties are not processed"""
189 props_dict["categories"]["main"] = "invalid_category"
190 for i in ["office", "lawyer"]:
191 clean_dict.pop(i, None)
192 assert process_place(props_dict, unmatched="ignore") == clean_dict
195def test_unmatched_force(props_dict, clean_dict: dict):
196 """Test that invalid properties are not processed"""
197 cat = "invalid_category"
198 props_dict["categories"]["main"] = cat
199 for i in ["office", "lawyer"]:
200 clean_dict.pop(i, None)
201 clean_dict["type"] = cat
202 assert process_place(props_dict, unmatched="force") == clean_dict
205def test_place_geojson(geojson_dict, clean_dict: dict):
206 """Test that all properties are processed correctly"""
207 assert process_geojson(geojson=geojson_dict, fx=process_place) == {
208 "type": "FeatureCollection",
209 "features": [
210 {
211 "type": "Feature",
212 "geometry": {"type": "Point", "coordinates": [-1, 1]},
213 "properties": clean_dict,
214 }
215 ],
216 }
219def test_place_geojson_error(geojson_dict):
220 """Test that all properties are processed correctly when error flag is set"""
221 copy = deepcopy(geojson_dict)
222 copy["features"][0]["properties"]["categories"]["main"] = "invalid_category"
223 assert process_geojson(
224 geojson=copy, fx=process_place, options={"unmatched": "error"}
225 ) == {
226 "type": "FeatureCollection",
227 "features": [],
228 }
231def test_place_geojson_force(geojson_dict, clean_dict: dict) -> None:
232 """Test that all properties are processed correctly when force flag is set"""
233 copy = deepcopy(geojson_dict)
234 copy["features"][0]["properties"]["categories"]["main"] = "invalid_category"
235 clean_dict["type"] = "invalid_category"
236 for i in ["office", "lawyer"]:
237 clean_dict.pop(i, None)
238 assert process_geojson(
239 geojson=copy, fx=process_place, options={"unmatched": "force"}
240 ) == {
241 "type": "FeatureCollection",
242 "features": [
243 {
244 "type": "Feature",
245 "geometry": {"type": "Point", "coordinates": [-1, 1]},
246 "properties": clean_dict,
247 }
248 ],
249 }
252def test_place_geojson_ignore(geojson_dict, clean_dict: dict) -> None:
253 """Test that all properties are processed correctly when ignore flag is set"""
254 copy = deepcopy(geojson_dict)
255 copy["features"][0]["properties"]["categories"]["main"] = "invalid_category"
256 for i in ["office", "lawyer"]:
257 clean_dict.pop(i, None)
258 assert process_geojson(
259 geojson=copy, fx=process_place, options={"unmatched": "ignore"}
260 ) == {
261 "type": "FeatureCollection",
262 "features": [
263 {
264 "type": "Feature",
265 "geometry": {"type": "Point", "coordinates": [-1, 1]},
266 "properties": clean_dict,
267 }
268 ],
269 }