from django.contrib.auth import get_user_model from django.test import Client, TestCase from django.urls import reverse from contacts.models import Contact from contacts.services import ( addresses_match, find_matching_contact, phones_match, upsert_contact, ) from leads.models import Lead class ContactMatchHelpersTests(TestCase): def test_phones_match_ignores_formatting(self): self.assertTrue(phones_match("(630) 452-4443", "+1-630-452-4443")) self.assertFalse(phones_match("6304524443", "6304524444")) self.assertFalse(phones_match("4524443", "6304524443")) # too short def test_addresses_match_by_line1_and_zip(self): a = Contact.make_postal_address( line1="123 Main St.", city="Naperville", state="IL", zip_code="60540-1234", ) b = Contact.make_postal_address( line1="123 Main St", city="Elsewhere", state="IL", zip_code="60540", ) self.assertTrue(addresses_match(a, b)) def test_find_by_phone_then_address(self): existing = Contact.objects.create( email="one@example.com", phone="6305551212", first_name="Pat", postal_address=Contact.make_postal_address( line1="9 Oak Ave", city="Wheaton", state="IL", zip_code="60187", ), ) by_phone, reason = find_matching_contact( email="other@example.com", phone="(630) 555-1212", ) self.assertEqual(by_phone, existing) self.assertEqual(reason, "phone") by_addr, reason = find_matching_contact( email="third@example.com", phone="9995550000", postal_address=Contact.make_postal_address( line1="9 Oak Ave", city="Wheaton", state="IL", zip_code="60187", ), ) self.assertEqual(by_addr, existing) self.assertEqual(reason, "address") class UpsertContactMergeTests(TestCase): def test_merge_by_phone_keeps_one_contact(self): original = Contact.objects.create( email="ryan@example.com", phone="6305559999", first_name="Ryan", ) contact, created, reason = upsert_contact( email="ryan.alt@example.com", first_name="Ryan", last_name="Westfall", phone="630-555-9999", ) self.assertFalse(created) self.assertEqual(reason, "phone") self.assertEqual(contact.pk, original.pk) self.assertEqual(Contact.objects.count(), 1) contact.refresh_from_db() self.assertEqual(contact.email, "ryan@example.com") self.assertIn("ryan.alt@example.com", contact.notes) self.assertEqual(contact.last_name, "Westfall") def test_merge_by_address(self): original = Contact.objects.create( email="home@example.com", first_name="Sam", postal_address=Contact.make_postal_address( line1="100 Lake St", city="Naperville", state="IL", zip_code="60540", ), ) contact, created, reason = upsert_contact( email="new@example.com", first_name="Sam", postal_address=Contact.make_postal_address( line1="100 Lake St", city="Naperville", state="IL", zip_code="60540", ), ) self.assertFalse(created) self.assertEqual(reason, "address") self.assertEqual(contact.pk, original.pk) self.assertEqual(Contact.objects.count(), 1) class ContactFormMergeTests(TestCase): def setUp(self): self.client = Client() self.existing = Contact.objects.create( email="primary@example.com", phone="6301112222", first_name="Alex", postal_address=Contact.make_postal_address( line1="55 River Rd", city="Aurora", state="IL", zip_code="60505", ), ) def test_contact_form_merges_on_phone(self): url = reverse("public:contact") response = self.client.post( url, { "first_name": "Alex", "last_name": "Lee", "email": "alt@example.com", "phone": "(630) 111-2222", "address_line1": "55 River Rd", "address_city": "Aurora", "address_state": "IL", "address_zip": "60505", "interest": "general", "message": "Looking to buy", }, ) self.assertEqual(response.status_code, 302) self.assertEqual(Contact.objects.count(), 1) lead = Lead.objects.get() self.assertEqual(lead.contact_id, self.existing.pk) self.assertIn("alt@example.com", lead.message) self.assertIn("merged by phone", lead.message) class PortalCreateMatchPromptTests(TestCase): def setUp(self): User = get_user_model() self.user = User.objects.create_user( username="adder", password="test-pass-123" ) self.client = Client() self.client.login(username="adder", password="test-pass-123") self.existing = Contact.objects.create( email="primary@example.com", phone="6301112222", first_name="Alex", ) def test_phone_match_shows_prompt(self): url = reverse("contacts:create") response = self.client.post( url, { "first_name": "Alex", "email": "alt@example.com", "phone": "(630) 111-2222", "consent_email": "1", }, ) self.assertEqual(response.status_code, 200) self.assertContains(response, "Possible duplicate") self.assertContains(response, "Update existing") self.assertEqual(Contact.objects.count(), 1) def test_choose_create_new_keeps_both(self): url = reverse("contacts:create") response = self.client.post( url, { "first_name": "Alex", "email": "alt@example.com", "phone": "(630) 111-2222", "consent_email": "1", "resolve_match": "create", "match_id": str(self.existing.pk), }, ) self.assertEqual(response.status_code, 302) self.assertEqual(Contact.objects.count(), 2) def test_choose_update_merges(self): url = reverse("contacts:create") response = self.client.post( url, { "first_name": "Alexander", "email": "alt@example.com", "phone": "(630) 111-2222", "consent_email": "1", "resolve_match": "update", "match_id": str(self.existing.pk), }, ) self.assertEqual(response.status_code, 302) self.assertEqual(Contact.objects.count(), 1) self.existing.refresh_from_db() self.assertEqual(self.existing.first_name, "Alexander") self.assertIn("alt@example.com", self.existing.notes)