44from typer .testing import CliRunner
55
66from datafog .client import app
7+ from datafog .models .annotator import AnnotationResult , AnnotatorMetadata
8+ from datafog .models .anonymizer import (
9+ AnonymizationResult ,
10+ Anonymizer ,
11+ AnonymizerType ,
12+ HashType ,
13+ )
14+ from datafog .models .common import EntityTypes
715
816runner = CliRunner ()
917
@@ -14,6 +22,38 @@ def mock_datafog():
1422 yield mock
1523
1624
25+ @pytest .fixture
26+ def sample_text ():
27+ return "Jeff Smith works at DigiCorp Incorporated in Paris."
28+
29+
30+ @pytest .fixture
31+ def sample_annotations ():
32+ return [
33+ AnnotationResult (
34+ start = 0 ,
35+ end = 9 ,
36+ score = 1.0 ,
37+ entity_type = EntityTypes .PERSON ,
38+ recognition_metadata = AnnotatorMetadata (),
39+ ),
40+ AnnotationResult (
41+ start = 20 ,
42+ end = 42 ,
43+ score = 1.0 ,
44+ entity_type = EntityTypes .ORGANIZATION ,
45+ recognition_metadata = AnnotatorMetadata (),
46+ ),
47+ AnnotationResult (
48+ start = 46 ,
49+ end = 51 ,
50+ score = 1.0 ,
51+ entity_type = EntityTypes .LOCATION ,
52+ recognition_metadata = AnnotatorMetadata (),
53+ ),
54+ ]
55+
56+
1757def test_scan_image_no_urls ():
1858 result = runner .invoke (app , ["scan-image" ])
1959 assert result .exit_code == 1
@@ -101,3 +141,140 @@ def test_list_entities(mock_spacy_annotator):
101141 result = runner .invoke (app , ["list-entities" ])
102142 assert result .exit_code == 0
103143 assert "['PERSON', 'ORG']" in result .stdout
144+
145+
146+ @patch ("datafog.client.SpacyAnnotator" )
147+ @patch ("datafog.client.Anonymizer" )
148+ def test_redact_text (mock_anonymizer , mock_spacy_annotator , sample_annotations ):
149+ mock_annotator = mock_spacy_annotator .return_value
150+ mock_anonymizer_instance = mock_anonymizer .return_value
151+
152+ sample_text = "John Doe works at Acme Corp"
153+ sample_annotations = [
154+ AnnotationResult (
155+ start = 0 ,
156+ end = 8 ,
157+ score = 1.0 ,
158+ entity_type = EntityTypes .PERSON ,
159+ recognition_metadata = AnnotatorMetadata (),
160+ ),
161+ AnnotationResult (
162+ start = 18 ,
163+ end = 27 ,
164+ score = 1.0 ,
165+ entity_type = EntityTypes .ORGANIZATION ,
166+ recognition_metadata = AnnotatorMetadata (),
167+ ),
168+ ]
169+ mock_annotator .annotate_text .return_value = sample_annotations
170+
171+ mock_anonymizer_instance .anonymize .return_value = AnonymizationResult (
172+ anonymized_text = "[REDACTED] works at [REDACTED]" , anonymized_entities = []
173+ )
174+
175+ result = runner .invoke (app , ["redact-text" , sample_text ])
176+
177+ assert result .exit_code == 0
178+ assert "[REDACTED] works at [REDACTED]" in result .stdout
179+ mock_spacy_annotator .assert_called_once ()
180+ mock_anonymizer .assert_called_once_with (anonymizer_type = AnonymizerType .REDACT )
181+ mock_annotator .annotate_text .assert_called_once_with (sample_text )
182+ mock_anonymizer_instance .anonymize .assert_called_once_with (
183+ sample_text , sample_annotations
184+ )
185+
186+
187+ @patch ("datafog.client.SpacyAnnotator" )
188+ @patch ("datafog.client.Anonymizer" )
189+ def test_replace_text (mock_anonymizer , mock_spacy_annotator ):
190+ mock_annotator = mock_spacy_annotator .return_value
191+ mock_anonymizer_instance = mock_anonymizer .return_value
192+
193+ sample_text = "John Doe works at Acme Corp"
194+ sample_annotations = [
195+ AnnotationResult (
196+ start = 0 ,
197+ end = 8 ,
198+ score = 1.0 ,
199+ entity_type = EntityTypes .PERSON ,
200+ recognition_metadata = AnnotatorMetadata (),
201+ ),
202+ AnnotationResult (
203+ start = 18 ,
204+ end = 27 ,
205+ score = 1.0 ,
206+ entity_type = EntityTypes .ORGANIZATION ,
207+ recognition_metadata = AnnotatorMetadata (),
208+ ),
209+ ]
210+ mock_annotator .annotate_text .return_value = sample_annotations
211+
212+ mock_anonymizer_instance .anonymize .return_value = AnonymizationResult (
213+ anonymized_text = "Jane Smith works at TechCo Inc" , anonymized_entities = []
214+ )
215+
216+ result = runner .invoke (app , ["replace-text" , sample_text ])
217+
218+ assert result .exit_code == 0
219+ assert "Jane Smith works at TechCo Inc" in result .stdout
220+ mock_spacy_annotator .assert_called_once ()
221+ mock_anonymizer .assert_called_once_with (anonymizer_type = AnonymizerType .REPLACE )
222+ mock_annotator .annotate_text .assert_called_once_with (sample_text )
223+ mock_anonymizer_instance .anonymize .assert_called_once_with (
224+ sample_text , sample_annotations
225+ )
226+
227+
228+ @patch ("datafog.client.SpacyAnnotator" )
229+ @patch ("datafog.client.Anonymizer" )
230+ def test_hash_text (mock_anonymizer , mock_spacy_annotator ):
231+ mock_annotator = mock_spacy_annotator .return_value
232+ mock_anonymizer_instance = mock_anonymizer .return_value
233+
234+ sample_text = "John Doe works at Acme Corp"
235+ sample_annotations = [
236+ AnnotationResult (
237+ start = 0 ,
238+ end = 8 ,
239+ score = 1.0 ,
240+ entity_type = EntityTypes .PERSON ,
241+ recognition_metadata = AnnotatorMetadata (),
242+ ),
243+ AnnotationResult (
244+ start = 18 ,
245+ end = 27 ,
246+ score = 1.0 ,
247+ entity_type = EntityTypes .ORGANIZATION ,
248+ recognition_metadata = AnnotatorMetadata (),
249+ ),
250+ ]
251+ mock_annotator .annotate_text .return_value = sample_annotations
252+
253+ mock_anonymizer_instance .anonymize .return_value = AnonymizationResult (
254+ anonymized_text = "5ab5c95f works at 7b23f032" , anonymized_entities = []
255+ )
256+
257+ result = runner .invoke (app , ["hash-text" , sample_text ])
258+
259+ assert result .exit_code == 0
260+ assert "5ab5c95f works at 7b23f032" in result .stdout
261+ mock_spacy_annotator .assert_called_once ()
262+ mock_anonymizer .assert_called_once_with (
263+ anonymizer_type = AnonymizerType .HASH , hash_type = HashType .SHA256
264+ )
265+ mock_annotator .annotate_text .assert_called_once_with (sample_text )
266+ mock_anonymizer_instance .anonymize .assert_called_once_with (
267+ sample_text , sample_annotations
268+ )
269+
270+ # Test with custom hash type
271+ result = runner .invoke (app , ["hash-text" , sample_text , "--hash-type" , "md5" ])
272+
273+ print (f"Exit code: { result .exit_code } " )
274+ print (f"Output: { result .stdout } " )
275+ print (f"Exception: { result .exception } " )
276+
277+ assert result .exit_code == 0
278+ mock_anonymizer .assert_called_with (
279+ anonymizer_type = AnonymizerType .HASH , hash_type = HashType .MD5
280+ )
0 commit comments