Compare commits
	
		
			32 Commits
		
	
	
		
			0.1.2
			...
			e77edf18ac
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| e77edf18ac | |||
| 3780aa6cf1 | |||
| 21124ec2ad | |||
| 0ee5fc59d3 | |||
| b8dfef691e | |||
| a1886b0b60 | |||
| e1002b5315 | |||
| fed90d4f7b | |||
| dcfb329c5a | |||
| b8a21a8baa | |||
| 7f73035b02 | |||
| 317437fedc | |||
| 26286984c2 | |||
| 9ae31c0146 | |||
| 87fd8fa96f | |||
| c3401e732f | |||
| 4ee7373b3f | |||
| 64c0c5f8e6 | |||
| 18a597c726 | |||
|  | baca596603 | ||
| d993387216 | |||
| aed2856df3 | |||
| c78858c152 | |||
| f49581259e | |||
| f5bf642cd6 | |||
| 7687acb366 | |||
| e655e1598a | |||
| 64ed38332f | |||
| d438303aec | |||
| 38b3736951 | |||
| 6be060ea40 | |||
| 5c5756150f | 
							
								
								
									
										6
									
								
								Pipfile
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								Pipfile
									
									
									
									
									
								
							| @@ -11,6 +11,7 @@ pipenv = "*" | ||||
| wheel = "*" | ||||
| twine = "*" | ||||
| pandoc ="*" | ||||
| pylint-django ="*" | ||||
|  | ||||
| [packages] | ||||
| django = "*" | ||||
| @@ -18,6 +19,7 @@ easy-thumbnails = "*" | ||||
| image = "*" | ||||
| django-widget-tweaks = "*" | ||||
| django-taggit = "*" | ||||
|  | ||||
| # Commented out to not explicitly specify Python 3 subversion. | ||||
| # [requires] | ||||
| # python_version = "3.8" | ||||
| [requires] | ||||
| python_version = "3.7" | ||||
|   | ||||
| @@ -6,15 +6,15 @@ | ||||
| from django.contrib import admin | ||||
| from django.contrib.auth import get_user_model | ||||
| from django.contrib.auth.admin import UserAdmin | ||||
| from .models import * | ||||
| from lostplaces_app.models import * | ||||
|  | ||||
| from .forms import ExplorerCreationForm, ExplorerChangeForm | ||||
| from lostplaces_app.forms import ExplorerCreationForm, ExplorerChangeForm | ||||
|  | ||||
| # Register your models here. | ||||
|  | ||||
| class VoucherAdmin(admin.ModelAdmin): | ||||
|     fields = ['code', 'expires', 'created'] | ||||
|     readonly_fields = ['created'] | ||||
|     fields = ['code', 'expires_when', 'created_when'] | ||||
|     readonly_fields = ['created_when'] | ||||
|  | ||||
| admin.site.register(Explorer) | ||||
| admin.site.register(Voucher, VoucherAdmin) | ||||
|   | ||||
| @@ -9,6 +9,7 @@ database. | ||||
| import os | ||||
| import uuid | ||||
|  | ||||
| from django.urls import reverse | ||||
| from django.db import models | ||||
| from django.contrib.auth.models import User | ||||
| from django.db.models.signals import post_save | ||||
| @@ -19,6 +20,31 @@ from taggit.managers import TaggableManager | ||||
|  | ||||
| # Create your models here. | ||||
|  | ||||
| class Taggable(models.Model): | ||||
|      | ||||
|     class Meta: | ||||
|         abstract = True | ||||
|          | ||||
|     tags = TaggableManager(blank=True) | ||||
|      | ||||
| class MapablePoint(models.Model): | ||||
|     class Meta: | ||||
|         abstract = True | ||||
|          | ||||
|     name = models.CharField(max_length=50) | ||||
|      | ||||
|     latitude = models.FloatField( | ||||
|         validators=[ | ||||
|             MinValueValidator(-90), | ||||
|             MaxValueValidator(90) | ||||
|         ] | ||||
|     ) | ||||
|     longitude = models.FloatField( | ||||
|         validators=[ | ||||
|             MinValueValidator(-180), | ||||
|             MaxValueValidator(180) | ||||
|         ] | ||||
|     ) | ||||
|  | ||||
| class Explorer(models.Model): | ||||
|     """ | ||||
| @@ -33,7 +59,7 @@ class Explorer(models.Model): | ||||
|     ) | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.user.name | ||||
|         return self.user.username | ||||
|          | ||||
| @receiver(post_save, sender=User) | ||||
| def create_user_profile(sender, instance, created, **kwargs): | ||||
| @@ -54,19 +80,18 @@ class Voucher(models.Model): | ||||
|     """ | ||||
|  | ||||
|     code = models.CharField(unique=True, max_length=30) | ||||
|     created = models.DateTimeField(auto_now_add=True) | ||||
|     expires = models.DateField() | ||||
|     created_when = models.DateTimeField(auto_now_add=True) | ||||
|     expires_when = models.DateTimeField() | ||||
|  | ||||
|     def __str__(self): | ||||
|         return "Voucher " + str(self.pk) | ||||
|         return "Voucher " + str(self.code) | ||||
|  | ||||
|  | ||||
| class Place (models.Model): | ||||
| class Place(Taggable, MapablePoint): | ||||
|     """ | ||||
|     Place defines a lost place (location, name, description etc.). | ||||
|     """ | ||||
|      | ||||
|     name = models.CharField(max_length=50) | ||||
|     submitted_when = models.DateTimeField(auto_now_add=True, null=True) | ||||
|     submitted_by = models.ForeignKey( | ||||
|         Explorer, | ||||
| @@ -76,24 +101,15 @@ class Place (models.Model): | ||||
|         related_name='places' | ||||
|     ) | ||||
|     location = models.CharField(max_length=50) | ||||
|     latitude = models.FloatField( | ||||
|         validators=[ | ||||
|             MinValueValidator(-90), | ||||
|             MaxValueValidator(90) | ||||
|         ] | ||||
|     ) | ||||
|     longitude = models.FloatField( | ||||
|         validators=[ | ||||
|             MinValueValidator(-180), | ||||
|             MaxValueValidator(180) | ||||
|         ] | ||||
|     ) | ||||
|     description = models.TextField() | ||||
|  | ||||
|     tags = TaggableManager(blank=True) | ||||
|     def get_absolute_url(self): | ||||
|         return reverse('place_detail', kwargs={'pk': self.pk}) | ||||
|      | ||||
|  | ||||
|     @classmethod | ||||
|     # Get center position of LP-geocoordinates. | ||||
|     def average_latlon(place_list): | ||||
|     def average_latlon(cls, place_list): | ||||
|         amount = len(place_list) | ||||
|         # Init fill values to prevent None | ||||
|         longitude = 0 | ||||
| @@ -103,9 +119,9 @@ class Place (models.Model): | ||||
|             for place in place_list: | ||||
|                 longitude += place.longitude | ||||
|                 latitude += place.latitude | ||||
|             return (latitude / amount, longitude / amount) | ||||
|             return {'latitude':latitude / amount, 'longitude': longitude / amount} | ||||
|  | ||||
|         return (latitude, longitude) | ||||
|         return {'latitude': latitude, 'longitude': longitude} | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.name | ||||
|   | ||||
| @@ -2,8 +2,8 @@ | ||||
|  | ||||
| {% load static %} | ||||
| {% block additional_head %} | ||||
|     <link rel="stylesheet" href="{% static 'maps/ol.css' %}" type="text/css"> | ||||
|     <script src="{% static 'maps/ol.js' %}"></script> | ||||
| <link rel="stylesheet" href="{% static 'maps/ol.css' %}" type="text/css"> | ||||
| <script src="{% static 'maps/ol.js' %}"></script> | ||||
| {% endblock additional_head %} | ||||
|  | ||||
| # {% block title %}Start{% endblock %} | ||||
| @@ -14,7 +14,7 @@ | ||||
| <article class="LP-TextSection"> | ||||
| </article> | ||||
|  | ||||
| {% include 'partials/osm_map.html' %} | ||||
| {% include 'partials/osm_map.html' with config=map_config %} | ||||
| <div class="LP-PlaceGrid"> | ||||
|     <h1 class="LP-Headline LP-Headline">Explore the latest locations</h1> | ||||
|     <ul class="LP-PlaceGrid__Grid"> | ||||
|   | ||||
| @@ -11,20 +11,20 @@ | ||||
|                 }), | ||||
|             ], | ||||
|             view: new ol.View({ | ||||
|                 center: ol.proj.fromLonLat([{{place_map_center|last}}, {{place_map_center|first}}]), | ||||
|                 center: ol.proj.fromLonLat([{{config.map_center.longitude}}, {{config.map_center.latitude}}]), | ||||
|                 zoom: 9 | ||||
|             }) | ||||
|             }); | ||||
|  | ||||
|             var vectorSource = new ol.source.Vector({ | ||||
|                 features: [ | ||||
|                     {% for place in place_list %} | ||||
|                     {% for point in config.point_list %} | ||||
|                         new ol.Feature({ | ||||
|                             geometry: new ol.geom.Point( | ||||
|                                 ol.proj.fromLonLat([{{place.longitude}},{{place.latitude}}]) | ||||
|                                 ol.proj.fromLonLat([{{point.longitude}},{{point.latitude}}]) | ||||
|                             ), | ||||
|                             url: '{% url 'place_detail' pk=place.pk %}', | ||||
|                             name: '{{place.name}}' | ||||
|                             url: '{{point.get_absolute_url}}', | ||||
|                             name: '  {{point.name}}' | ||||
|                         }), | ||||
|                     {% endfor %} | ||||
|                 ] | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| <div class="LP-TagList"> | ||||
|     <ul class="LP-TagList__List"> | ||||
|         {% for tag in tag_list %} | ||||
|         {% for tag in config.tagged_item.tags.all %} | ||||
|         <li class="LP-TagList__Item"> | ||||
|             <div class="LP-Tag"> | ||||
|                 <a href="#" class="LP-Link"> | ||||
| @@ -23,7 +23,7 @@ | ||||
|     </ul> | ||||
| </div> | ||||
|  | ||||
| <form id="id_tag_submit_form" class="LP-Form LP-Form--inline LP-Form--tagging" method="POST" action="{{config.submit_url}}"> | ||||
| <form id="id_tag_submit_form" class="LP-Form LP-Form--inline LP-Form--tagging" method="POST" action="{% url config.submit_url_name tagged_id=config.tagged_item.id%}"> | ||||
|     <fieldset class="LP-Form__Fieldset"> | ||||
|         <legend class="LP-Form__Legend">Tags hinzufügen</legend> | ||||
|         {% csrf_token %} | ||||
| @@ -46,14 +46,10 @@ | ||||
|     submit_form.onsubmit = () => false | ||||
|  | ||||
|     const tagify = new Tagify(input, { | ||||
|         'whitelist': [{ | ||||
|                 % | ||||
|                 for tag in all_tags % | ||||
|             } | ||||
| 		'whitelist': [ | ||||
| 			{% for tag in config.tagged_item.tags.all %} | ||||
|             '{{tag}}', | ||||
|             { | ||||
|                 % endfor % | ||||
|             } | ||||
|             {% endfor %} | ||||
|         ] | ||||
|     }) | ||||
|  | ||||
|   | ||||
| @@ -37,13 +37,13 @@ | ||||
|     <section class="LP-Section"> | ||||
|  | ||||
|         {% url 'place_tag_submit' place_id=place.id as tag_submit_url%} | ||||
|         {% include 'partials/tagging.html' with tag_list=place.tags.all config=tagging_config all_tags=all_tags %} | ||||
|         {% include 'partials/tagging.html' with config=tagging_config %} | ||||
|  | ||||
|     </section> | ||||
|  | ||||
|     <section class="LP-Section"> | ||||
|         <h1 class="LP-Headline">Map-Links</h1> | ||||
|         {% include 'partials/osm_map.html' %} | ||||
|         {% include 'partials/osm_map.html' with config=map_config%} | ||||
|         <div class="LP-LinkList"> | ||||
|             <ul class="LP-LinkList__Container"> | ||||
|                 <li class="LP-LinkList__Item"><a target="_blank" href="https://www.google.com/maps?q={{place.latitude}},{{place.longitude}}" class="LP-Link"><span class="LP-Text">Google Maps</span></a></li> | ||||
|   | ||||
| @@ -2,54 +2,54 @@ | ||||
| {% load static %} | ||||
|  | ||||
| {% block additional_head %} | ||||
|     <link rel="stylesheet" href="{% static 'maps/ol.css' %}" type="text/css"> | ||||
|     <script src="{% static 'maps/ol.js' %}"></script> | ||||
| <link rel="stylesheet" href="{% static 'maps/ol.css' %}" type="text/css"> | ||||
| <script src="{% static 'maps/ol.js' %}"></script> | ||||
| {% endblock additional_head %} | ||||
|  | ||||
| {% block title %}Lost Places{% endblock %} | ||||
|  | ||||
| {% block maincontent %} | ||||
|  | ||||
| {% include 'partials/osm_map.html' %} | ||||
| {% include 'partials/osm_map.html' with config=map_config %} | ||||
| <div class="LP-PlaceList"> | ||||
|     <h1 class="LP-Headline">Listing our places</h1> | ||||
|     <ul class="LP-PlaceList__List"> | ||||
|         {% for place in place_list %} | ||||
|             <li class="LP-PlaceList__Item"> | ||||
|                 <a href="{% url 'place_detail' pk=place.pk %}" class="LP-Link"> | ||||
|                     <article class="LP-PlaceTeaser LP-PlaceTeaser--extended"> | ||||
|                         <div class="LP-PlaceTeaser__Image"> | ||||
|                             <img class="LP-Image" src="{{ place.images.first.filename.thumbnail.url }}" /> | ||||
|         <li class="LP-PlaceList__Item"> | ||||
|             <a href="{% url 'place_detail' pk=place.pk %}" class="LP-Link"> | ||||
|                 <article class="LP-PlaceTeaser LP-PlaceTeaser--extended"> | ||||
|                     <div class="LP-PlaceTeaser__Image"> | ||||
|                         <img class="LP-Image" src="{{ place.images.first.filename.thumbnail.url }}" /> | ||||
|                     </div> | ||||
|                     <div class="LP-PlaceTeaser__Meta"> | ||||
|                         <div class="LP-PlaceTeaser__Info"> | ||||
|                             <span class="LP-PlaceTeaser__Title"> | ||||
|                                 <h2 class="LP-Headline LP-Headline--teaser">{{place.name}}</h2> | ||||
|                             </span> | ||||
|                             <span class="LP-PlaceTeaser__Detail"> | ||||
|                                 <p class="LP-Paragraph">{{place.location}}</p> | ||||
|                             </span> | ||||
|                         </div> | ||||
|                         <div class="LP-PlaceTeaser__Meta"> | ||||
|                             <div class="LP-PlaceTeaser__Info"> | ||||
|                                 <span class="LP-PlaceTeaser__Title"> | ||||
|                                     <h2 class="LP-Headline LP-Headline--teaser">{{place.name}}</h2> | ||||
|                                 </span> | ||||
|                                 <span class="LP-PlaceTeaser__Detail"> | ||||
|                                     <p class="LP-Paragraph">{{place.location}}</p> | ||||
|                                 </span> | ||||
|                             </div> | ||||
|                             <div class="LP-PlaceTeaser__Description"> | ||||
|                                 <p class="LP-Paragraph"> | ||||
|                                     {% if place.description|length > 210 %} | ||||
|                                         {{place.description|truncatechars:210|truncatewords:-1}} | ||||
|                                     {% else %} | ||||
|                                         {{place.description}} | ||||
|                                     {% endif %} | ||||
|                                 </p> | ||||
|                             </div> | ||||
|                             <div class="LP-PlaceTeaser__Icons"> | ||||
|                                 <ul class="LP-Icon__List"> | ||||
|                                     <li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/favourite.svg' %}" /></li> | ||||
|                         <div class="LP-PlaceTeaser__Description"> | ||||
|                             <p class="LP-Paragraph"> | ||||
|                                 {% if place.description|length > 210 %} | ||||
|                                 {{place.description|truncatechars:210|truncatewords:-1}} | ||||
|                                 {% else %} | ||||
|                                 {{place.description}} | ||||
|                                 {% endif %} | ||||
|                             </p> | ||||
|                         </div> | ||||
|                         <div class="LP-PlaceTeaser__Icons"> | ||||
|                             <ul class="LP-Icon__List"> | ||||
|                                 <li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/favourite.svg' %}" /></li> | ||||
|                                 <li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/location.svg' %}" /></li> | ||||
|                                 <li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/flag.svg' %}" /></li> | ||||
|                                 </ul> | ||||
|                             </div> | ||||
|                             </ul> | ||||
|                         </div> | ||||
|                     </article> | ||||
|                 </a> | ||||
|             </li> | ||||
|                     </div> | ||||
|                 </article> | ||||
|             </a> | ||||
|         </li> | ||||
|         {% endfor %} | ||||
|     </ul> | ||||
|  | ||||
|   | ||||
| @@ -1,13 +1,2 @@ | ||||
| from django.db import models as django_models | ||||
| from django.test import TestCase | ||||
| from django.contrib.auth.models import User | ||||
|  | ||||
|  | ||||
| def mock_user(): | ||||
|     explorer_list =  User.objects.all() | ||||
|     if len(explorer_list) <= 0: | ||||
|         return User.objects.create_user( | ||||
|             username='testpeter', | ||||
|             password='Develop123' | ||||
|         ) | ||||
|     else: | ||||
|         return explorer_list[0] | ||||
| @@ -1,58 +1,107 @@ | ||||
| from django.db import models | ||||
| from django.contrib.auth.models import User | ||||
| from django.core.exceptions import FieldDoesNotExist | ||||
| from django.test import TestCase | ||||
|  | ||||
| class TestModel: | ||||
| # Creating a test user | ||||
|  | ||||
| class ModelTestCase: | ||||
|     ''' | ||||
|     Base class for Lostplaces models | ||||
|     Base class for ModelTests | ||||
|     ''' | ||||
|     model = None | ||||
|     model_name = None | ||||
|  | ||||
|     def _test_field(self, field_name, field_class): | ||||
|     def setUp(self): | ||||
|         if not self.model._meta.abstract: | ||||
|             self.object = self.model.objects.get(id=1) | ||||
|         self.model_name = self.model.__name__ | ||||
|  | ||||
|     def _test_field(self, field_name, field_class, must_have={}, must_not_have={}): | ||||
|         ''' | ||||
|         Tests if a field exists under the given name and | ||||
|         if the field is of the right type | ||||
|         if the field is of the right type. | ||||
|         Also checks if the field has the given must_have attributes | ||||
|         and does not have any of the must_not_have attributes. If you | ||||
|         dont care about the value of the attribute you can just set it to  | ||||
|         something that fullfills value == False (i.e. '' or 0) | ||||
|         ''' | ||||
|         field = self.object._meta.get_field(field_name) | ||||
|         self.assertTrue( | ||||
|             field, | ||||
|             msg="%s has no field named '%s'" % ( | ||||
|                 self.model_name, | ||||
|                 field_name | ||||
|         try: | ||||
|             field = self.model._meta.get_field(field_name) | ||||
|         except FieldDoesNotExist: | ||||
|             self.fail( | ||||
|                 'Expecting %s to have a field named \'%s\'' % ( | ||||
|                     self.model_name, | ||||
|                     field_name | ||||
|                 ) | ||||
|             ) | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             type(field), field_class, | ||||
|             msg='%s.%s name field is no CharField' % ( | ||||
|             msg='Expecting type of %s.%s to be %s' % ( | ||||
|                 self.model_name, | ||||
|                 field_name | ||||
|                 field_name, | ||||
|                 field_class.__name__ | ||||
|             ) | ||||
|         ) | ||||
|  | ||||
|         for key, value in must_have.items(): | ||||
|             if value: | ||||
|                 self.assertEqual(getattr(field, key), value, | ||||
|                     msg='Expeting %s.%s.%s to be \'%s\'' % ( | ||||
|                         self.model_name, | ||||
|                         field_name, | ||||
|                         key, | ||||
|                         value | ||||
|                     ) | ||||
|                 ) | ||||
|             else: | ||||
|                 self.assertTrue(hasattr(field, key), | ||||
|                     msg='Expeting %s.%s to have \'%s\'' % ( | ||||
|                         self.model_name, | ||||
|                         field_name, | ||||
|                         key | ||||
|                     ) | ||||
|                 ) | ||||
|  | ||||
|         for key, value in must_not_have.items(): | ||||
|             if value: | ||||
|                 self.assertTrue(getattr(field, key) != value, | ||||
|                     msg='Expeting %s.%s.%s to not be \'%s\'' % ( | ||||
|                         self.model_name, | ||||
|                         field_name, | ||||
|                         key, | ||||
|                         value | ||||
|                     ) | ||||
|                 ) | ||||
|             else: | ||||
|                 self.assertFalse(hasattr(field, value), | ||||
|                     msg='Expeting %s.%s to not have \'%s\'' % ( | ||||
|                         self.model_name, | ||||
|                         field_name, | ||||
|                         key | ||||
|                     ) | ||||
|                 ) | ||||
|  | ||||
|         return field | ||||
|  | ||||
|  | ||||
|     def _test_char_field(self, field_name, min_length, max_length): | ||||
|     def _test_char_field(self, field_name, min_length, max_length, must_have={}, must_hot_have={}): | ||||
|         ''' | ||||
|         Tests if the given field is a char field and if its max_length | ||||
|         is in min_length and max_legth | ||||
|         ''' | ||||
|         field = self._test_field(field_name, models.CharField) | ||||
|         self.assertEqual( | ||||
|             type(field), models.CharField,  | ||||
|             msg='%s.%s name field is no CharField' % ( | ||||
|                 self.model_name, | ||||
|                 field_name | ||||
|             ) | ||||
|         ) | ||||
|         field = self._test_field( | ||||
|             field_name, models.CharField, must_have, must_hot_have) | ||||
|         self.assertTrue( | ||||
|             field.max_length in range(min_length, max_length), | ||||
|             msg='%s.%s field max_length not in range of %d and %d' % ( | ||||
|             msg='Expeting %s.%s field max_length to be in the range of %d and %d' % ( | ||||
|                 self.model_name, | ||||
|                 field_name, | ||||
|                 min_length, | ||||
|                 max_length | ||||
|                 ) | ||||
|             ) | ||||
|         ) | ||||
|  | ||||
|     def _test_float_field(self, field_name, min_value=None, max_value=None): | ||||
|     def _test_float_field(self, field_name, min_value=None, max_value=None, must_have={}, must_hot_have={}): | ||||
|         ''' | ||||
|         Tests if the field is a floatfield. If min_value and/or max_value are passed, | ||||
|         the validators of the field are also checked. The validator list of the field should | ||||
| @@ -61,21 +110,23 @@ class TestModel: | ||||
|         [MinValueValidator] if only min_value is passed, | ||||
|         [MaxValueValidator] if only max_value is passed | ||||
|         ''' | ||||
|         field = self._test_field(field_name, models.FloatField) | ||||
|         field = self._test_field( | ||||
|             field_name, models.FloatField, must_have, must_hot_have) | ||||
|         if min_value: | ||||
|             self.assertTrue( | ||||
|                 len(field.validators) >= 1, | ||||
|                 msg='%s.%s first validator should check minimum' % ( | ||||
|                 msg='Expecting the first valiator of %s.%s to check the minimum' % ( | ||||
|                     self.model_name, | ||||
|                     field_name | ||||
|                     ) | ||||
|                 ) | ||||
|             ) | ||||
|             self.assertEqual( | ||||
|                 field.validators[0].limit_value, | ||||
|                 min_value, | ||||
|                 msg='%s.%s min value missmatch' % ( | ||||
|                 msg='Expecting the min value of %s.%s min to be at least %d' % ( | ||||
|                     self.model_name, | ||||
|                     field_name | ||||
|                     field_name, | ||||
|                     min_value | ||||
|                 ) | ||||
|             ) | ||||
|         if max_value: | ||||
| @@ -84,38 +135,41 @@ class TestModel: | ||||
|                 index += 1 | ||||
|             self.assertTrue( | ||||
|                 len(field.validators) >= index+1, | ||||
|                 msg='%s.%s second validator should check maximum' % ( | ||||
|                     self.model_name, | ||||
|                     field_name | ||||
|                     ) | ||||
|             ) | ||||
|             self.assertEqual( | ||||
|                 field.validators[1].limit_value, | ||||
|                 max_value, | ||||
|                 msg='%s.%s max value missmatch' % ( | ||||
|                 msg='Expecting the second valiator of %s.%s to check the maximum' % ( | ||||
|                     self.model_name, | ||||
|                     field_name | ||||
|                 ) | ||||
|             ) | ||||
|             self.assertEqual( | ||||
|                 field.validators[1].limit_value, | ||||
|                 max_value, | ||||
|                 msg='Expecting the max value of %s.%s min to be at most %d' % ( | ||||
|                     self.model_name, | ||||
|                     field_name, | ||||
|                     max_value | ||||
|                 ) | ||||
|             ) | ||||
|  | ||||
| class TestSubmittable(TestModel): | ||||
|     model_name='<Class>' | ||||
|  | ||||
| class SubmittableTestCase(ModelTestCase): | ||||
|     model_name = '<Class>' | ||||
|     related_name = None | ||||
|     nullable = False | ||||
|  | ||||
|     def test_submitted_when(self): | ||||
|         submitted_when = self._test_field('submitted_when', models.DateTimeField) | ||||
|         self.assertTrue(submitted_when.auto_now_add,  | ||||
|             msg='%s.submitted_when should be auto_now_add' % ( | ||||
|                 self.model_name | ||||
|             ) | ||||
|         submitted_when = self._test_field( | ||||
|             'submitted_when', | ||||
|             models.DateTimeField, | ||||
|             must_have={'auto_now_add': True} | ||||
|         ) | ||||
|  | ||||
|     def test_submitted_by(self): | ||||
|         submitted_by = self._test_field('submitted_by',models.ForeignKey) | ||||
|         submitted_by = self._test_field('submitted_by', models.ForeignKey) | ||||
|         if self.related_name: | ||||
|             self.assertEqual(submitted_by.remote_field.related_name, self.related_name) | ||||
|             self.assertEqual( | ||||
|                 submitted_by.remote_field.related_name, self.related_name) | ||||
|         if self.nullable: | ||||
|             self.assertTrue(submitted_by.null,) | ||||
|             self.assertTrue(submitted_by.blank) | ||||
|             self.assertEqual(submitted_by.remote_field.on_delete, models.SET_NULL) | ||||
|             self.assertEqual( | ||||
|                 submitted_by.remote_field.on_delete, models.SET_NULL) | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								lostplaces/lostplaces_app/tests/models/im_a_image.jpeg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								lostplaces/lostplaces_app/tests/models/im_a_image.jpeg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 81 KiB | 
| @@ -0,0 +1,44 @@ | ||||
| import datetime | ||||
|  | ||||
| from django.test import TestCase | ||||
| from django.db import models | ||||
| from django.contrib.auth.models import User | ||||
|  | ||||
| from lostplaces_app.models import Place, Taggable, MapablePoint | ||||
| from lostplaces_app.tests.models import ModelTestCase | ||||
|  | ||||
| from taggit.managers import TaggableManager | ||||
|  | ||||
|  | ||||
| class TaggableTestCase(ModelTestCase, TestCase): | ||||
|  | ||||
|     model = Taggable | ||||
|  | ||||
|     def test_tags(self): | ||||
|         self._test_field('tags', TaggableManager) | ||||
|  | ||||
|  | ||||
| class MapablePointTestCase(ModelTestCase, TestCase): | ||||
|  | ||||
|     model = MapablePoint | ||||
|  | ||||
|     def test_name(self): | ||||
|         self._test_char_field( | ||||
|             field_name='name', | ||||
|             min_length=10, | ||||
|             max_length=100 | ||||
|         ) | ||||
|  | ||||
|     def test_latitude(self): | ||||
|         self._test_float_field( | ||||
|             field_name='latitude', | ||||
|             min_value=-90, | ||||
|             max_value=90 | ||||
|         ) | ||||
|  | ||||
|     def test_longitude(self): | ||||
|         self._test_float_field( | ||||
|             field_name='longitude', | ||||
|             min_value=-180, | ||||
|             max_value=180 | ||||
|         ) | ||||
| @@ -0,0 +1,58 @@ | ||||
| from django.test import TestCase | ||||
| from django.db import models | ||||
| from django.contrib.auth.models import User | ||||
|  | ||||
| from lostplaces_app.models import Explorer | ||||
|  | ||||
| class ExplorerTestCase(TestCase): | ||||
|  | ||||
|     @classmethod | ||||
|     def setUpTestData(self): | ||||
|         User.objects.create_user( | ||||
|             username='testpeter', | ||||
|             password='Develop123' | ||||
|         ) | ||||
|  | ||||
|     def test_epxlorer_creation(self): | ||||
|         ''' | ||||
|         Tests if the explorer profile will be automticly | ||||
|         created when a user is created | ||||
|         ''' | ||||
|          | ||||
|         user = User.objects.get(id=1) | ||||
|         explorer_list = Explorer.objects.all() | ||||
|         self.assertTrue(len(explorer_list) > 0, | ||||
|             msg='Expecting at least one Exlorer object, none found' | ||||
|         ) | ||||
|         self.assertTrue(hasattr(user, 'explorer'), | ||||
|             msg='''Expecting the User instance to have an \'explorer\' attribute.  | ||||
|             Check the Explorer model and the related name.''' | ||||
|         ) | ||||
|          | ||||
|         explorer = Explorer.objects.get(id=1) | ||||
|         self.assertEqual(explorer, user.explorer, | ||||
|             msg='''The Explorer object of the User did not match. | ||||
|             Expecting User with id 1 to have Explorer with id 1''' | ||||
|         ) | ||||
|          | ||||
|         explorer = Explorer.objects.get(id=1) | ||||
|         self.assertEqual(explorer.user, user, | ||||
|             msg='''The User object of the Explorer did not match. | ||||
|             Expecting Explorer with id 1 to have User with id 1''' | ||||
|         ) | ||||
|          | ||||
|     def test_explorer_deletion(self): | ||||
|         ''' | ||||
|         Tests if the Explorer objects get's deleted when the User instance is deleted | ||||
|         ''' | ||||
|          | ||||
|         user = User.objects.get(username='testpeter') | ||||
|         explorer_id = user.explorer.id | ||||
|         user.delete() | ||||
|         with self.assertRaises(models.ObjectDoesNotExist, | ||||
|             msg='Expecting explorer objec to be deleted when the corresponding User object is deleted' | ||||
|             ): | ||||
|             Explorer.objects.get(id=explorer_id) | ||||
|          | ||||
|          | ||||
|      | ||||
| @@ -1,32 +1,63 @@ | ||||
| import datetime | ||||
| import os | ||||
| import shutil | ||||
| from unittest import mock | ||||
|  | ||||
| from django.test import TestCase | ||||
| from django.db import models | ||||
| from django.core.files import File | ||||
| from django.conf import settings | ||||
| from django.contrib.auth.models import User | ||||
|  | ||||
| from lostplaces_app.models import PlaceImage | ||||
| from lostplaces_app.tests.models import TestSubmittable | ||||
| from lostplaces_app.tests import mock_user | ||||
| from lostplaces_app.tests.models import TestModel | ||||
| from lostplaces_app.tests.models.test_place_model import mock_place | ||||
| from lostplaces_app.models import PlaceImage, Place | ||||
| from lostplaces_app.tests.models import SubmittableTestCase | ||||
|  | ||||
| from easy_thumbnails.fields import ThumbnailerImageField | ||||
|  | ||||
| def mock_place_image(): | ||||
|     return PlaceImage( | ||||
|         description='Im a description', | ||||
|         filename=mock.MagicMock(spec=File, name='FileMock'), | ||||
|         place=mock_place(), | ||||
|         submitted_when=datetime.datetime.now(), | ||||
|         submitted_by=mock_user().explorer | ||||
|     ) | ||||
| class TestPlaceImage(SubmittableTestCase, TestCase): | ||||
|     model = PlaceImage | ||||
|  | ||||
| class TestPlaceImage(TestSubmittable, TestCase): | ||||
|     model_name = 'PlaceImage' | ||||
|     @classmethod | ||||
|     def setUpTestData(cls): | ||||
|         user = User.objects.create_user( | ||||
|             username='testpeter', | ||||
|             password='Develop123' | ||||
|         ) | ||||
|          | ||||
|     def setUp(self): | ||||
|         self.object = mock_place_image() | ||||
|         place = Place.objects.create( | ||||
|             name='Im a place', | ||||
|             submitted_when=datetime.datetime.now(), | ||||
|             submitted_by=User.objects.get(username='testpeter').explorer, | ||||
|             location='Testtown', | ||||
|             latitude=50.5, | ||||
|             longitude=7.0, | ||||
|             description='This is just a test, do not worry' | ||||
|         ) | ||||
|         place.tags.add('I a tag', 'testlocation') | ||||
|         place.save() | ||||
|  | ||||
|         if not os.path.isdir(settings.MEDIA_ROOT): | ||||
|             os.mkdir(settings.MEDIA_ROOT) | ||||
|  | ||||
|         current_dir = os.path.dirname(os.path.abspath(__file__)) | ||||
|         if not os.path.isfile(os.path.join(settings.MEDIA_ROOT, 'im_a_image_copy.jpeg')): | ||||
|             shutil.copyfile( | ||||
|                 os.path.join(current_dir, 'im_a_image.jpeg'), | ||||
|                 os.path.join(settings.MEDIA_ROOT, 'im_a_image_copy.jpeg') | ||||
|             ) | ||||
|              | ||||
|             shutil.copyfile( | ||||
|                 os.path.join(current_dir, 'im_a_image.jpeg'), | ||||
|                 os.path.join(settings.MEDIA_ROOT, 'im_a_image_changed.jpeg') | ||||
|             ) | ||||
|              | ||||
|         PlaceImage.objects.create( | ||||
|             description='Im a description', | ||||
|             filename=os.path.join(settings.MEDIA_ROOT, 'im_a_image_copy.jpeg'), | ||||
|             place=place, | ||||
|             submitted_when=datetime.datetime.now(), | ||||
|             submitted_by=user.explorer | ||||
|         ) | ||||
|  | ||||
|     def test_description(self): | ||||
|         self._test_field('description', models.TextField) | ||||
| @@ -51,5 +82,26 @@ class TestPlaceImage(TestSubmittable, TestCase): | ||||
|         ) | ||||
|  | ||||
|     def test_str(self): | ||||
|         place_image = mock_place_image() | ||||
|         self.assertEqual(str(place_image), ' '.join([place_image.place.name, str(place_image.pk)])) | ||||
|         place_image = self.object | ||||
|         self.assertTrue(place_image.place.name.lower() in str(place_image).lower(), | ||||
|             msg='Expecting %s.__str__ to contain  the name of the place' % ( | ||||
|                 self.model_name | ||||
|             ) | ||||
|         ) | ||||
|          | ||||
|     def test_change_filename(self): | ||||
|         path = self.object.filename.path | ||||
|         self.object.filename = os.path.join(settings.MEDIA_ROOT, 'im_a_image_changed.jpeg') | ||||
|         self.object.save() | ||||
|         self.assertFalse( | ||||
|             os.path.isfile(path), | ||||
|             msg='Expecting the old file of an place_image to be deleteed when an place_image file is changed' | ||||
|         ) | ||||
|          | ||||
|     def test_deletion(self): | ||||
|         path = self.object.filename.path | ||||
|         self.object.delete() | ||||
|         self.assertFalse( | ||||
|             os.path.isfile(path), | ||||
|             msg='Expecting the file of an place_image to be deleteed when an place_image is deleted' | ||||
|         ) | ||||
| @@ -3,43 +3,36 @@ import datetime | ||||
| from django.test import TestCase | ||||
| from django.db import models | ||||
|  | ||||
| from django.contrib.auth.models import User | ||||
|  | ||||
| from lostplaces_app.models import Place | ||||
| from lostplaces_app.tests.models import TestSubmittable | ||||
| from lostplaces_app.tests import mock_user | ||||
| from lostplaces_app.tests.models import TestModel | ||||
| from lostplaces_app.tests.models import SubmittableTestCase | ||||
|  | ||||
| from taggit.managers import TaggableManager | ||||
|  | ||||
| def mock_place(): | ||||
|     place = Place.objects.create( | ||||
|         name='Im a place', | ||||
|         submitted_when=datetime.datetime.now(), | ||||
|         submitted_by=mock_user().explorer, | ||||
|         location='Testtown', | ||||
|         latitude=50.5, | ||||
|         longitude=7.0, | ||||
|         description='This is just a test, do not worry' | ||||
|     ) | ||||
|     place.tags.add('I a tag', 'testlocation') | ||||
|  | ||||
|     return place | ||||
|  | ||||
| class PlaceTestCase(TestSubmittable, TestCase): | ||||
|     model_name = 'Place' | ||||
| class PlaceTestCase(SubmittableTestCase, TestCase): | ||||
|     model = Place | ||||
|     related_name = 'places' | ||||
|     nullable = True | ||||
|  | ||||
|     def setUp(self): | ||||
|         self.place = mock_place() | ||||
|         self.object = self.place | ||||
|  | ||||
|     def test_name_field(self): | ||||
|         self._test_char_field( | ||||
|             field_name='name',  | ||||
|             min_length=10, | ||||
|             max_length=100 | ||||
|     @classmethod | ||||
|     def setUpTestData(cls): | ||||
|         user = User.objects.create_user( | ||||
|             username='testpeter', | ||||
|             password='Develop123' | ||||
|         ) | ||||
|          | ||||
|         place = Place.objects.create( | ||||
|             name='Im a place', | ||||
|             submitted_when=datetime.datetime.now(), | ||||
|             submitted_by=user.explorer, | ||||
|             location='Testtown', | ||||
|             latitude=50.5, | ||||
|             longitude=7.0, | ||||
|             description='This is just a test, do not worry' | ||||
|         ) | ||||
|         place.tags.add('I a tag', 'testlocation') | ||||
|         place.save() | ||||
|  | ||||
|  | ||||
|     def test_location(self): | ||||
|         self._test_char_field( | ||||
|             field_name='location', | ||||
| @@ -47,26 +40,9 @@ class PlaceTestCase(TestSubmittable, TestCase): | ||||
|             max_length=100 | ||||
|         ) | ||||
|  | ||||
|     def test_latitude(self): | ||||
|         self._test_float_field( | ||||
|             field_name='latitude',  | ||||
|             min_value=-90,  | ||||
|             max_value=90 | ||||
|         ) | ||||
|  | ||||
|     def test_longitude(self): | ||||
|         self._test_float_field( | ||||
|             field_name='longitude', | ||||
|             min_value=-180,  | ||||
|             max_value=180 | ||||
|         ) | ||||
|  | ||||
|     def test_decsription(self): | ||||
|         self._test_field('description', models.TextField) | ||||
|  | ||||
|     def test_tags(self): | ||||
|         self._test_field('tags', TaggableManager) | ||||
|  | ||||
|     def test_average_latlon(self): | ||||
|         ''' | ||||
|         Tests the average latitude/longitude calculation of a list | ||||
| @@ -74,18 +50,28 @@ class PlaceTestCase(TestSubmittable, TestCase): | ||||
|         ''' | ||||
|         place_list = [] | ||||
|         for i in range(10): | ||||
|             place = mock_place() | ||||
|             place = Place.objects.get(id=1) | ||||
|             place.id = None | ||||
|             place.latitude = i+1 | ||||
|             place.longitude = i+10 | ||||
|             place.save() | ||||
|             place_list.append(place) | ||||
|  | ||||
|         avg_latlon = Place.average_latlon(place_list) | ||||
|         self.assertEqual(avg_latlon[0], 5.5, | ||||
|          | ||||
|         self.assertTrue('latitude' in avg_latlon, | ||||
|             msg='Expecting avg_latlon dict to have an \'latitude\' key' | ||||
|         ) | ||||
|         self.assertTrue('longitude' in avg_latlon, | ||||
|             msg='Expecting avg_latlon dict to have an \'longitude\' key' | ||||
|         ) | ||||
|          | ||||
|         self.assertEqual(avg_latlon['latitude'], 5.5, | ||||
|             msg='%s: average latitude missmatch' % ( | ||||
|                 self.model_name | ||||
|             ) | ||||
|         ) | ||||
|         self.assertEqual(avg_latlon[1], 14.5, | ||||
|         self.assertEqual(avg_latlon['longitude'], 14.5, | ||||
|             msg='%s: average longitude missmatch' % ( | ||||
|                 self.model_name | ||||
|             ) | ||||
| @@ -96,14 +82,14 @@ class PlaceTestCase(TestSubmittable, TestCase): | ||||
|         Tests the average latitude/longitude calculation of a list | ||||
|         of one place | ||||
|         ''' | ||||
|         place = mock_place() | ||||
|         place = Place.objects.get(id=1) | ||||
|         avg_latlon = Place.average_latlon([place]) | ||||
|         self.assertEqual(avg_latlon[0], place.latitude, | ||||
|         self.assertEqual(avg_latlon['latitude'], place.latitude, | ||||
|             msg='%s:(one place) average latitude missmatch' % ( | ||||
|                 self.model_name | ||||
|             ) | ||||
|         ) | ||||
|         self.assertEqual(avg_latlon[1], place.longitude, | ||||
|         self.assertEqual(avg_latlon['longitude'], place.longitude, | ||||
|             msg='%s: (one place) average longitude missmatch' % ( | ||||
|                 self.model_name | ||||
|             ) | ||||
| @@ -115,22 +101,21 @@ class PlaceTestCase(TestSubmittable, TestCase): | ||||
|         an empty list | ||||
|         ''' | ||||
|         avg_latlon = Place.average_latlon([]) | ||||
|         self.assertEqual(avg_latlon[0], 0, | ||||
|         self.assertEqual(avg_latlon['latitude'], 0, | ||||
|             msg='%s: (no places) average latitude missmatch' % ( | ||||
|                 self.model_name | ||||
|             ) | ||||
|         ) | ||||
|         self.assertEqual(avg_latlon[1], 0, | ||||
|         self.assertEqual(avg_latlon['longitude'], 0, | ||||
|             msg='%s: a(no places) verage longitude missmatch' % ( | ||||
|                 self.model_name | ||||
|             ) | ||||
|         ) | ||||
|  | ||||
|     def test_str(self): | ||||
|         place = mock_place() | ||||
|         self.assertEqual(str(place), place.name, | ||||
|             msg='%s __str__ should return the name' % ( | ||||
|         place = self.object | ||||
|         self.assertTrue(place.name.lower() in str(place).lower(), | ||||
|             msg='Expecting %s.__str__ to contain the name' % ( | ||||
|                 self.model_name | ||||
|             ) | ||||
|  | ||||
|         ) | ||||
|   | ||||
							
								
								
									
										49
									
								
								lostplaces/lostplaces_app/tests/models/test_voucher_model.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								lostplaces/lostplaces_app/tests/models/test_voucher_model.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| import datetime | ||||
|  | ||||
| from django.test import TestCase | ||||
| from django.db import models | ||||
| from django.utils import timezone | ||||
|  | ||||
| from lostplaces_app.models import Voucher | ||||
| from lostplaces_app.tests.models import ModelTestCase | ||||
|  | ||||
|  | ||||
| class VoucheTestCase(ModelTestCase, TestCase): | ||||
|     model = Voucher | ||||
|  | ||||
|     @classmethod | ||||
|     def setUpTestData(cls): | ||||
|         Voucher.objects.create( | ||||
|         code='ayDraJCCwfhcFiYmSR5GrcjcchDfcahv', | ||||
|         expires_when=timezone.now() + datetime.timedelta(days=1) | ||||
|     ) | ||||
|      | ||||
|     def test_voucher_code(self): | ||||
|         self._test_char_field( | ||||
|             'code', | ||||
|             10, | ||||
|             100, | ||||
|             must_have={'unique': True} | ||||
|         ) | ||||
|          | ||||
|     def test_voucher_created(self): | ||||
|         self._test_field( | ||||
|             'created_when', | ||||
|             models.DateTimeField, | ||||
|             must_have={'auto_now_add': True} | ||||
|         ) | ||||
|          | ||||
|     def test_voucher_expires(self): | ||||
|         self._test_field( | ||||
|             'expires_when', | ||||
|             models.DateTimeField, | ||||
|             must_not_have={'auto_now_add': True} | ||||
|         ) | ||||
|  | ||||
|     def test_str(self): | ||||
|         voucher = self.object | ||||
|         self.assertTrue(voucher.code.lower() in str(voucher).lower(), | ||||
|             msg='Expecting %s.__str__ to contain the voucher code' % ( | ||||
|                 self.model_name | ||||
|             ) | ||||
|         ) | ||||
| @@ -0,0 +1,28 @@ | ||||
| from django.test import Client | ||||
|  | ||||
| class ViewTestCase: | ||||
|     view = None | ||||
|      | ||||
|     def setUp(self): | ||||
|         self.view_name = self.view.__name__ | ||||
|         self. client = Client() | ||||
|      | ||||
|     def _test_has_context_key(self, response, context_key): | ||||
|         self.assertTrue( context_key in response.context, | ||||
|             msg='Expecting the context of %s to have an attribute \'%s\'' % ( | ||||
|                 self.view_name, | ||||
|                 context_key | ||||
|             ) | ||||
|         ) | ||||
|          | ||||
|     def _test_form(self, response, context_key, form_class): | ||||
|         self._test_has_context_key(response, context_key) | ||||
|         self.assertEqual( | ||||
|             type(response.context[context_key]), | ||||
|             form_class, | ||||
|             msg='Expecting %s\'s context.%s to be of the type %s' % ( | ||||
|                 self.view_name, | ||||
|                 context_key, | ||||
|                 form_class.__name__ | ||||
|             )  | ||||
|         ) | ||||
| @@ -1,17 +1,36 @@ | ||||
| import datetime | ||||
|  | ||||
| from django.test import TestCase, Client | ||||
| from django.urls import reverse_lazy | ||||
| from django.contrib.auth.models import User | ||||
|  | ||||
| from lostplaces_app.models import Place | ||||
|  | ||||
| from django.contrib.auth.models import User | ||||
| from lostplaces_app.tests.models.test_place_model import mock_place | ||||
| from lostplaces_app.tests import mock_user | ||||
|  | ||||
| class TestIsAuthenticated(TestCase): | ||||
|  | ||||
|     @classmethod | ||||
|     def setUpTestData(cls): | ||||
|         user = User.objects.create_user( | ||||
|             username='testpeter', | ||||
|             password='Develop123' | ||||
|         ) | ||||
|          | ||||
|         place = Place.objects.create( | ||||
|             name='Im a place', | ||||
|             submitted_when=datetime.datetime.now(), | ||||
|             submitted_by=User.objects.get(username='testpeter').explorer, | ||||
|             location='Testtown', | ||||
|             latitude=50.5, | ||||
|             longitude=7.0, | ||||
|             description='This is just a test, do not worry' | ||||
|         ) | ||||
|         place.tags.add('I a tag', 'testlocation') | ||||
|         place.save() | ||||
|          | ||||
|     def setUp(self): | ||||
|         self. client = Client() | ||||
|         mock_place() | ||||
|         mock_user() | ||||
|  | ||||
|     def test_logged_in(self): | ||||
|         self.client.login(username='testpeter', password='Develop123') | ||||
| @@ -36,10 +55,27 @@ class TestIsAuthenticated(TestCase): | ||||
|  | ||||
| class TestIsPlaceSubmitter(TestCase): | ||||
|  | ||||
|     @classmethod | ||||
|     def setUpTestData(cls): | ||||
|         user = User.objects.create_user( | ||||
|             username='testpeter', | ||||
|             password='Develop123' | ||||
|         ) | ||||
|          | ||||
|         place = Place.objects.create( | ||||
|             name='Im a place', | ||||
|             submitted_when=datetime.datetime.now(), | ||||
|             submitted_by=user.explorer, | ||||
|             location='Testtown', | ||||
|             latitude=50.5, | ||||
|             longitude=7.0, | ||||
|             description='This is just a test, do not worry' | ||||
|         ) | ||||
|         place.tags.add('I a tag', 'testlocation') | ||||
|         place.save() | ||||
|  | ||||
|     def setUp(self): | ||||
|         self. client = Client() | ||||
|         mock_place() | ||||
|         mock_user() | ||||
|  | ||||
|     def test_is_submitter(self): | ||||
|         self.client.login(username='testpeter', password='Develop123') | ||||
|   | ||||
| @@ -1,35 +1,73 @@ | ||||
| from django.test import TestCase, Client | ||||
| import datetime | ||||
|  | ||||
| from django.test import TestCase | ||||
| from django.urls import reverse_lazy | ||||
| from django.contrib.auth.models import User | ||||
|  | ||||
| from lostplaces_app.models import Place | ||||
| from lostplaces_app.views import ( | ||||
|     PlaceCreateView, | ||||
|     PlaceListView | ||||
| ) | ||||
| from lostplaces_app.forms import PlaceImageCreateForm, PlaceForm | ||||
| from lostplaces_app.tests.views import ViewTestCase | ||||
|  | ||||
| from lostplaces_app.tests.models.test_place_model import mock_place | ||||
| from lostplaces_app.tests import mock_user | ||||
| class TestPlaceCreateView(ViewTestCase, TestCase): | ||||
|      | ||||
| class TestPlaceCreateView(TestCase): | ||||
|     view = PlaceCreateView | ||||
|      | ||||
|     def setUp(self): | ||||
|         self. client = Client() | ||||
|         mock_place() | ||||
|         mock_user() | ||||
|  | ||||
|     def test_url_logged_in(self): | ||||
|         self.client.login(username='testpeter', password='Develop123') | ||||
|         response = self.client.get(reverse_lazy('place_detail', kwargs={'pk': 1})) | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|  | ||||
|     def test_url_not_logged_in(self): | ||||
|         url = reverse_lazy('place_detail', kwargs={'pk': 1}) | ||||
|         response = self.client.get(url) | ||||
|         self.assertRedirects( | ||||
|             response=response, | ||||
|             expected_url='?'.join([str(reverse_lazy('login')), 'next=/place/1/']), | ||||
|             status_code=302,  | ||||
|             target_status_code=200,  | ||||
|             msg_prefix='''Accesing PlaceDetailView while not logged should | ||||
|             redirect to login page with redirect params | ||||
|             ''',  | ||||
|             fetch_redirect_response=True | ||||
|     @classmethod | ||||
|     def setUpTestData(cls): | ||||
|         user = User.objects.create_user( | ||||
|             username='testpeter', | ||||
|             password='Develop123' | ||||
|         ) | ||||
|          | ||||
|         place = Place.objects.create( | ||||
|             name='Im a place', | ||||
|             submitted_when=datetime.datetime.now(), | ||||
|             submitted_by=user.explorer, | ||||
|             location='Testtown', | ||||
|             latitude=50.5, | ||||
|             longitude=7.0, | ||||
|             description='This is just a test, do not worry' | ||||
|         ) | ||||
|         place.tags.add('I a tag', 'testlocation') | ||||
|         place.save() | ||||
|          | ||||
|     def test_has_forms(self): | ||||
|         self.client.login(username='testpeter', password='Develop123') | ||||
|         response = self.client.get(reverse_lazy('place_create')) | ||||
|          | ||||
|         self._test_form(response, 'place_image_form', PlaceImageCreateForm) | ||||
|         self._test_form(response, 'place_form', PlaceForm) | ||||
|          | ||||
| class TestPlaceListView(ViewTestCase, TestCase): | ||||
|     view = PlaceListView | ||||
|      | ||||
|     @classmethod | ||||
|     def setUpTestData(cls): | ||||
|         user = User.objects.create_user( | ||||
|             username='testpeter', | ||||
|             password='Develop123' | ||||
|         ) | ||||
|          | ||||
|         place = Place.objects.create( | ||||
|             name='Im a place', | ||||
|             submitted_when=datetime.datetime.now(), | ||||
|             submitted_by=user.explorer, | ||||
|             location='Testtown', | ||||
|             latitude=50.5, | ||||
|             longitude=7.0, | ||||
|             description='This is just a test, do not worry' | ||||
|         ) | ||||
|         place.tags.add('I a tag', 'testlocation') | ||||
|         place.save() | ||||
|          | ||||
|     def test_list_view(self): | ||||
|         self.client.login(username='testpeter', password='Develop123') | ||||
|         response = self.client.get(reverse_lazy('place_list')) | ||||
|          | ||||
|         self._test_has_context_key(response, 'map_config') | ||||
|      | ||||
|      | ||||
| @@ -1,5 +1,5 @@ | ||||
| from django.urls import path | ||||
| from .views import ( | ||||
| from lostplaces_app.views import ( | ||||
|     HomeView,  | ||||
|     PlaceDetailView,  | ||||
|     PlaceListView,  | ||||
| @@ -25,6 +25,6 @@ urlpatterns = [ | ||||
|     path('flat/<slug:slug>/', FlatView, name='flatpage'), | ||||
|  | ||||
|     # POST-only URLs for tag submission | ||||
| 	path('place/tag/<int:place_id>', PlaceTagSubmitView.as_view(), name='place_tag_submit'), | ||||
| 	path('place/tag/<int:tagged_id>', PlaceTagSubmitView.as_view(), name='place_tag_submit'), | ||||
|     path('place/tag/delete/<int:tagged_id>/<int:tag_id>', PlaceTagDeleteView.as_view(), name='place_tag_delete') | ||||
| ] | ||||
|   | ||||
| @@ -23,7 +23,10 @@ class PlaceListView(IsAuthenticated, ListView): | ||||
|  | ||||
|     def get_context_data(self, **kwargs): | ||||
|         context = super().get_context_data(**kwargs) | ||||
|         context['place_map_center'] = Place.average_latlon(context['place_list']) | ||||
|         context['map_config'] = { | ||||
|             'point_list': context['place_list'], | ||||
|             'map_center': Place.average_latlon(context['place_list']) | ||||
|         } | ||||
|         return context | ||||
|  | ||||
| class PlaceDetailView(IsAuthenticated, View): | ||||
| @@ -31,13 +34,15 @@ class PlaceDetailView(IsAuthenticated, View): | ||||
|         place = Place.objects.get(pk=pk) | ||||
|         context = { | ||||
|             'place': place, | ||||
|             'place_list': [ place ], | ||||
|             'place_map_center': [ place.latitude, place.longitude ], | ||||
|             'all_tags': Tag.objects.all(), | ||||
|             'map_config': { | ||||
|                 'point_list': [ place ], | ||||
|                 'map_center': {'latitude': place.latitude, 'longitude': place.longitude},                                 | ||||
|             }, | ||||
|             'tagging_config': { | ||||
|                 'submit_url': reverse_lazy('place_tag_submit', kwargs={'place_id': place.id}), | ||||
|                 'all_tags': Tag.objects.all(), | ||||
|                 'submit_form': TagSubmitForm(), | ||||
|                 'tagged_item': place, | ||||
|                 'submit_url_name': 'place_tag_submit', | ||||
|                 'delete_url_name': 'place_tag_delete' | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -27,10 +27,12 @@ class SignUpView(SuccessMessageMixin, CreateView): | ||||
| class HomeView(IsAuthenticated, View): | ||||
|     def get(self, request, *args, **kwargs): | ||||
|         place_list = Place.objects.all().order_by('-submitted_when')[:10] | ||||
|         place_map_center = Place.average_latlon(place_list) | ||||
|         context = { | ||||
|             'place_list': place_list, | ||||
|             'place_map_center': place_map_center | ||||
|             'map_config': { | ||||
|                 'point_list': place_list, | ||||
|                 'map_center': Place.average_latlon(place_list) | ||||
|             } | ||||
|         } | ||||
|         return render(request, 'home.html', context) | ||||
|  | ||||
| @@ -54,8 +56,8 @@ class PhotoAlbumDeleteView(PlaceAssetDeleteView): | ||||
|     permission_denied_messsage = 'You do not have permissions to alter this photo album' | ||||
|  | ||||
| class PlaceTagSubmitView(IsAuthenticated, View): | ||||
| 	def post(self, request, place_id, *args, **kwargs): | ||||
| 		place = Place.objects.get(pk=place_id) | ||||
| 	def post(self, request, tagged_id, *args, **kwargs): | ||||
| 		place = Place.objects.get(pk=tagged_id) | ||||
| 		form = TagSubmitForm(request.POST) | ||||
| 		if form.is_valid(): | ||||
| 			tag_list_raw = form.cleaned_data['tag_list'] | ||||
|   | ||||
		Reference in New Issue
	
	Block a user