From cfbe54a4e52112886c69dc0c3905a6dfe31c96e9 Mon Sep 17 00:00:00 2001 From: reverend Date: Sun, 4 Oct 2020 22:11:37 +0200 Subject: [PATCH 1/4] Making expireable a abstract model --- .../migrations/0002_reomve_vouchers.py | 22 ++++++++++++++++ .../lostplaces/migrations/0003_voucher.py | 25 +++++++++++++++++++ .../lostplaces/models/abstract_models.py | 12 +++++++-- 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 django_lostplaces/lostplaces/migrations/0002_reomve_vouchers.py create mode 100644 django_lostplaces/lostplaces/migrations/0003_voucher.py diff --git a/django_lostplaces/lostplaces/migrations/0002_reomve_vouchers.py b/django_lostplaces/lostplaces/migrations/0002_reomve_vouchers.py new file mode 100644 index 0000000..76a1aaf --- /dev/null +++ b/django_lostplaces/lostplaces/migrations/0002_reomve_vouchers.py @@ -0,0 +1,22 @@ +# Generated by Django 3.1.1 on 2020-10-04 19:37 +# Edited by reverend + +import datetime +from django.db import migrations, models +import django.utils.timezone +from django.utils.timezone import utc + +class Migration(migrations.Migration): + + dependencies = [ + ('lostplaces', '0001_initial'), + ] + + operations = [ + migrations.DeleteModel( + name='Voucher' + ), + migrations.DeleteModel( + name='Expireable' + ) + ] diff --git a/django_lostplaces/lostplaces/migrations/0003_voucher.py b/django_lostplaces/lostplaces/migrations/0003_voucher.py new file mode 100644 index 0000000..0fb7125 --- /dev/null +++ b/django_lostplaces/lostplaces/migrations/0003_voucher.py @@ -0,0 +1,25 @@ +# Generated by Django 3.1.1 on 2020-10-04 19:52 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('lostplaces', '0002_reomve_vouchers'), + ] + + operations = [ + migrations.CreateModel( + name='Voucher', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_when', models.DateTimeField(auto_now_add=True)), + ('expires_when', models.DateTimeField()), + ('code', models.CharField(max_length=30, unique=True)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/django_lostplaces/lostplaces/models/abstract_models.py b/django_lostplaces/lostplaces/models/abstract_models.py index c95ce61..ba4be73 100644 --- a/django_lostplaces/lostplaces/models/abstract_models.py +++ b/django_lostplaces/lostplaces/models/abstract_models.py @@ -1,4 +1,5 @@ +from django.utils import timezone from django.db import models from django.core.validators import MaxValueValidator, MinValueValidator @@ -55,7 +56,14 @@ class Submittable(models.Model): class Expireable(models.Model): """ - Base class for things that can expire, i.e. VouchersAv + Base class for things that can expire, i.e. Vouchers """ + class Meta: + abstract = True + created_when = models.DateTimeField(auto_now_add=True) - expires_when = models.DateTimeField() \ No newline at end of file + expires_when = models.DateTimeField() + + @property + def is_expired(self): + return timezone.now() > self.expires_when \ No newline at end of file From ae915681ac53bbfa7f3476dea087086b426609be Mon Sep 17 00:00:00 2001 From: reverend Date: Sun, 4 Oct 2020 22:12:24 +0200 Subject: [PATCH 2/4] Testing is_expired --- .../lostplaces/tests/models/__init__.py | 2 - .../tests/models/test_abstract_models.py | 38 ++++++++++++++++++- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/django_lostplaces/lostplaces/tests/models/__init__.py b/django_lostplaces/lostplaces/tests/models/__init__.py index 1e5f7f6..70b5253 100644 --- a/django_lostplaces/lostplaces/tests/models/__init__.py +++ b/django_lostplaces/lostplaces/tests/models/__init__.py @@ -2,11 +2,9 @@ # -*- coding: utf-8 -*- from django.db import models -from django.contrib.auth.models import User from django.core.exceptions import FieldDoesNotExist from django.test import TestCase -# Creating a test user class ModelTestCase(TestCase): ''' diff --git a/django_lostplaces/lostplaces/tests/models/test_abstract_models.py b/django_lostplaces/lostplaces/tests/models/test_abstract_models.py index 30415de..3d32b25 100644 --- a/django_lostplaces/lostplaces/tests/models/test_abstract_models.py +++ b/django_lostplaces/lostplaces/tests/models/test_abstract_models.py @@ -1,6 +1,9 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +import datetime + +from django.utils import timezone from django.test import TestCase from django.db import models from django.contrib.auth.models import User @@ -10,7 +13,8 @@ from lostplaces.models import ( Mapable, Submittable, PlaceAsset, - Expireable + Expireable, + Voucher ) from lostplaces.tests.models import ModelTestCase @@ -112,4 +116,34 @@ class PlaceAssetTestCase(ModelTestCase): ) class ExpireableTestCase(ModelTestCase): - model = Expireable \ No newline at end of file + model = Expireable + + def test_fields(self): + self.assertField( + field_name='created_when', + field_class=models.DateTimeField, + must_have={'auto_now_add': True} + ) + self.assertField( + field_name='expires_when', + field_class=models.DateTimeField + ) + + def test_is_expired(self): + valid_voucher = Voucher.objects.create( + code='Test123', + expires_when=timezone.now() + datetime.timedelta(minutes=2) + ) + self.assertFalse( + valid_voucher.is_expired, + msg='Expecing the expirable object to not be expired' + ) + + invalid_voucher = Voucher.objects.create( + code='Test1234', + expires_when=timezone.now() - datetime.timedelta(minutes=2) + ) + self.assertTrue( + invalid_voucher.is_expired, + msg='Expecing the expirable object to be expired' + ) \ No newline at end of file From ab3ecae54b9f8a5156c637604d96fb9f74dcb466 Mon Sep 17 00:00:00 2001 From: reverend Date: Sun, 4 Oct 2020 22:12:44 +0200 Subject: [PATCH 3/4] Voucher is_valid property --- django_lostplaces/lostplaces/models/models.py | 4 + .../lostplaces/tests/forms/__init__.py | 76 +++++++++++++++++++ .../tests/forms/test_explorer_forms.py | 59 ++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 django_lostplaces/lostplaces/tests/forms/__init__.py create mode 100644 django_lostplaces/lostplaces/tests/forms/test_explorer_forms.py diff --git a/django_lostplaces/lostplaces/models/models.py b/django_lostplaces/lostplaces/models/models.py index a545fe0..16b53da 100644 --- a/django_lostplaces/lostplaces/models/models.py +++ b/django_lostplaces/lostplaces/models/models.py @@ -49,6 +49,10 @@ class Voucher(Expireable): """ code = models.CharField(unique=True, max_length=30) + + @property + def valid(self): + return not self.is_expired def __str__(self): return "Voucher " + str(self.code) diff --git a/django_lostplaces/lostplaces/tests/forms/__init__.py b/django_lostplaces/lostplaces/tests/forms/__init__.py new file mode 100644 index 0000000..0cf6568 --- /dev/null +++ b/django_lostplaces/lostplaces/tests/forms/__init__.py @@ -0,0 +1,76 @@ +from django.test import TestCase +from django.core.exceptions import FieldDoesNotExist + +class FormTestCase(TestCase): + ''' + Base class for FormTests. + Parameters: + - form : Form to test + ''' + form = None + + def assertField(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. + 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) + ''' + try: + field = self.form.base_fields[field_name] + except FieldDoesNotExist: + self.fail( + 'Expecting %s to have a field named \'%s\'' % ( + self.form.__name__, + field_name + ) + ) + self.assertEqual( + type(field), field_class, + msg='Expecting type of %s to be %s' % ( + str(field), + field_class.__name__ + ) + ) + + for key, value in must_have.items(): + if value: + self.assertEqual( + getattr(field, key), value, + msg='Expeting the value of %s %s to be \'%s\'' % ( + str(field), + key, + value + ) + ) + else: + self.assertTrue( + hasattr(field, key), + msg='Expeting %s to have \'%s\'' % ( + str(field), + key + ) + ) + + for key, value in must_not_have.items(): + if value: + self.assertTrue( + getattr(field, key) != value, + msg='Expeting the value of %s %s to not be \'%s\'' % ( + str(field), + key, + value + ) + ) + else: + self.assertFalse( + hasattr(field, value), + msg='Expeting %s to not have \'%s\'' % ( + str(field), + key + ) + ) + + return field \ No newline at end of file diff --git a/django_lostplaces/lostplaces/tests/forms/test_explorer_forms.py b/django_lostplaces/lostplaces/tests/forms/test_explorer_forms.py new file mode 100644 index 0000000..89b6986 --- /dev/null +++ b/django_lostplaces/lostplaces/tests/forms/test_explorer_forms.py @@ -0,0 +1,59 @@ +import datetime + +from django import forms +from django.utils import timezone + +from lostplaces.tests.forms import FormTestCase +from lostplaces.forms import ExplorerCreationForm +from lostplaces.models.models import Voucher + +class ExplorerCreationFormTestCase(FormTestCase): + """ + This test case only tests for the voucher since all other aspects don't realy matter + to this project and are already tested by django + """ + form = ExplorerCreationForm + + @classmethod + def setUpTestData(cls): + Voucher.objects.create( + code='Imacode123', + expires_when=timezone.now() + datetime.timedelta(minutes=1) + ) + + def setUp(self): + self.post_data = { + 'voucher': 'Imacode123', + 'username': 'testpeter', + 'email': 'testpeter@example.org', + 'password1': 'Develop123', + 'password2': 'Develop123' + } + + def test_voucher_field(self): + self.assertField( + field_name='voucher', + field_class=forms.CharField + ) + + def test_validation_valid(self): + form = ExplorerCreationForm(self.post_data) + self.assertTrue( + form.is_valid(), + msg='Expecting the %s to validate' % ( + self.form.__name__ + ) + ) + + def test_validation_invalid(self): + self.post_data = { + 'voucher': 'Imanotacode123' + } + form = ExplorerCreationForm(self.post_data) + self.assertFalse( + form.is_valid(), + msg='Expecting the %s to not validate' % ( + self.form.__name__ + ) + ) + \ No newline at end of file From 86fbee4116e8fb5a4a72e606d4560a57bbf6f136 Mon Sep 17 00:00:00 2001 From: reverend Date: Sun, 4 Oct 2020 22:12:53 +0200 Subject: [PATCH 4/4] Merge from master --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index ede7639..c8e8ed8 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ with open('Readme.md') as f: setup( name='django-lostplaces', - version='0.1.a5', + version='0.1.2 HotFix', description='A django app to manage lost places', author='Reverend', author_email='reverend@reverend2048.de',