from django.core.exceptions import ValidationError
from django.template import Context, Template
from django.test import RequestFactory, TestCase
from apps.pages.maps import resolve_city
from apps.pages.models import MapMembership, MapPerson, MapPlacement, PeopleMap
class PeopleMapTests(TestCase):
def setUp(self):
self.world = PeopleMap.objects.create(title='Our global network')
self.person = MapPerson.objects.create(name='', institution='Institute')
def test_offline_city_and_country_resolution(self):
lat, lon = resolve_city('CA', 'Vancouver')
self.assertAlmostEqual(lat, 49.24966, places=2)
self.assertAlmostEqual(lon, -123.11934, places=2)
self.assertEqual(resolve_city('Canada', 'Vancouver'), (lat, lon))
def test_invalid_or_ambiguous_city_is_rejected(self):
for country, city in [('Canada', 'Not a real city'), ('Unknown country', 'Paris'), ('US', 'Springfield')]:
with self.subTest(country=country, city=city), self.assertRaises(ValidationError):
resolve_city(country, city)
def test_membership_saves_resolved_coordinates(self):
member = MapMembership.objects.create(people_map=self.world, person=self.person, country='CA', city='Vancouver')
self.assertLess(member.longitude, -120)
member.city = 'Toronto'
member.save()
member.refresh_from_db()
self.assertGreater(member.longitude, -80)
def test_explicit_coordinates_and_invalid_ranges(self):
member = MapMembership(people_map=self.world, person=self.person, location_method='coordinates', latitude=0, longitude=0)
member.full_clean()
for latitude, longitude in [(91, 0), (0, -181), (None, 0), (float('nan'), 0), (0, float('inf'))]:
member.latitude, member.longitude = latitude, longitude
with self.subTest(latitude=latitude, longitude=longitude), self.assertRaises(ValidationError):
member.full_clean()
def test_different_maps_can_have_different_members(self):
second = PeopleMap.objects.create(title='Other map')
MapMembership.objects.create(people_map=self.world, person=self.person, location_method='coordinates', latitude=0, longitude=0)
self.assertEqual(second.memberships.count(), 0)
with self.assertRaises(ValidationError):
MapMembership.objects.create(people_map=self.world, person=self.person, location_method='coordinates', latitude=1, longitude=1)
def test_placement_path_validation(self):
for path in ['https://example.com/', '//example.com/', '/about/?a=1', '/about/#x']:
with self.subTest(path=path), self.assertRaises(ValidationError):
MapPlacement(people_map=self.world, page_path=path).full_clean()
def render_maps(self, path, position='bottom'):
request = RequestFactory().get(path)
return Template('{% load people_maps %}{% people_maps position %}').render(Context({'request': request, 'position': position}))
def test_placement_filters_and_escaped_person_data(self):
MapPlacement.objects.create(people_map=self.world, page_path='/about/')
MapMembership.objects.create(people_map=self.world, person=self.person, location_method='coordinates', latitude=0, longitude=0)
html = self.render_maps('/about/')
self.assertIn('Our global network', html)
self.assertIn('<script>', html)
self.assertNotIn('