diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..db28625 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,11 @@ +[run] +source = . +branch = True +omit = + .venv/* + manage.py + +[report] +fail_under = 100 +show_missing = True +skip_covered = True diff --git a/.gitignore b/.gitignore index df76fda..096962f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,7 @@ __pycache__ /data /media .coverage +htmlcov/ +.coverage.* +coverage.xml +*.cover diff --git a/items/forms.py b/items/forms.py index 653142d..57dded2 100644 --- a/items/forms.py +++ b/items/forms.py @@ -28,5 +28,3 @@ class SearchItemForm(forms.Form): ) ) - def process(self): - cd = self.cleaned_data diff --git a/items/models.py b/items/models.py index b02066e..5976e6a 100644 --- a/items/models.py +++ b/items/models.py @@ -32,12 +32,8 @@ class ItemImage(models.Model): def save(self, *args, **kwargs): self.correct_image() - self.copy_to_storage() super(ItemImage, self).save(*args, **kwargs) - def copy_to_storage(self): - pass - def correct_image(self): try: # Open image and set some variables @@ -100,4 +96,4 @@ class ItemImage(models.Model): raise Exception('Unable to correct image size') def __str__(self): - return f"{self.id} - {self.item.name} - {self.id}" + return f'{self.id} - {self.item.name} - {self.id}' diff --git a/items/tests.py b/items/tests.py deleted file mode 100644 index 9a589c5..0000000 --- a/items/tests.py +++ /dev/null @@ -1,111 +0,0 @@ -from secrets import token_urlsafe -from django.test.utils import setup_test_environment -from django.test import TestCase, Client -from django.contrib.auth.models import User -from django.core.paginator import Page -from django.urls import reverse -from items.models import Item, ItemImage - - -class ItemsTestCase(TestCase): - def setUp(self): - self.test_user_username = 'tester' - self.test_user_password = token_urlsafe(32) - self.test_user = User.objects.create_user( - self.test_user_username, - password=self.test_user_password - ) - self.test_item = Item.objects.create( - owner=self.test_user, - name='Test Item', - description='Test item', - ask_price_xmr=0.3 - ) - - def login(self): - self.client.login( - username=self.test_user_username, - password=self.test_user_password - ) - - def logout(self): - self.client.logout() - - def test_list_items_should_allow_anonymous(self): - response = self.client.get(reverse('list_items')) - self.assertEqual(response.status_code, 200) - - def test_get_item_should_allow_anonymous(self): - response = self.client.get(reverse('get_item', args=[self.test_item.id])) - self.assertEqual(response.status_code, 200) - - def test_list_items_returns_page(self): - response = self.client.get(reverse('list_items')) - items = response.context['items'] - self.assertTrue(isinstance(items, Page)) - - def test_create_item_should_require_auth(self): - no_auth_response = self.client.get(reverse('create_item')) - self.login() - auth_response = self.client.get(reverse('create_item')) - self.logout() - self.assertEqual(no_auth_response.status_code, 302) - self.assertTrue(no_auth_response.url.startswith('/accounts/login')) - self.assertEqual(auth_response.status_code, 200) - - def test_edit_item_should_require_auth(self): - no_auth_response = self.client.get(reverse('edit_item', args=[self.test_item.id])) - self.login() - auth_response = self.client.get(reverse('edit_item', args=[self.test_item.id])) - self.logout() - self.assertEqual(no_auth_response.status_code, 302) - self.assertTrue(no_auth_response.url.startswith('/accounts/login')) - self.assertEqual(auth_response.status_code, 200) - - def test_edit_item_should_require_active_user_is_owner(self): - new_user = User.objects.create_user( - 'tester2', - password=token_urlsafe(24) - ) - new_item = Item.objects.create( - owner=new_user, - name='Test Item 2', - description='Test item 2', - ask_price_xmr=0.3 - ) - self.login() - test_item_edit_response = self.client.get(reverse('edit_item', args=[self.test_item.id])) - new_item_edit_response = self.client.get(reverse('edit_item', args=[new_item.id])) - self.logout() - self.assertEqual(test_item_edit_response.status_code, 200) - self.assertEqual(new_item_edit_response.status_code, 302) - new_item.delete() - new_user.delete() - - def test_delete_item_should_require_auth(self): - no_auth_response = self.client.get(reverse('delete_item', args=[self.test_item.id])) - self.login() - auth_response = self.client.get(reverse('delete_item', args=[self.test_item.id])) - self.logout() - self.assertEqual(no_auth_response.status_code, 302) - self.assertTrue(no_auth_response.url.startswith('/accounts/login')) - - def test_delete_item_should_require_active_user_is_owner(self): - new_user = User.objects.create_user( - 'tester3', - password=token_urlsafe(24) - ) - new_item = Item.objects.create( - owner=new_user, - name='Test Item 3', - description='Test item 3', - ask_price_xmr=0.3 - ) - self.login() - test_delete_item_response = self.client.get(reverse('delete_item', args=[self.test_item.id])) - new_delete_item_response = self.client.get(reverse('delete_item', args=[new_item.id])) - self.logout() - self.assertEqual(test_delete_item_response.status_code, 302) - self.assertEqual(new_delete_item_response.status_code, 302) - new_item.delete() - new_user.delete() diff --git a/items/tests/__init__.py b/items/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/items/tests/test_forms.py b/items/tests/test_forms.py new file mode 100644 index 0000000..0de2575 --- /dev/null +++ b/items/tests/test_forms.py @@ -0,0 +1,27 @@ +from django.test import TestCase +from items.forms import CreateItemForm, SearchItemForm +from core.monero import AuctionWallet + + +class ItemFormsTestCase(TestCase): + def setUp(self): + self.aw = AuctionWallet() + + def test_create_item_form_is_valid(self): + data = { + 'name': 'Expected item name', + 'description': 'expected description', + 'whereabouts': 'anywhere in the world', + 'ask_price_xmr': .1, + 'payout_address': self.aw.wallet.accounts[0].address(), + } + form = CreateItemForm(data=data) + self.assertTrue(form.is_valid()) + + def test_search_item_form_is_valid(self): + data = { + 'search': '' + } + form = SearchItemForm(data=data) + self.assertTrue(form.is_valid()) + diff --git a/items/tests/test_models.py b/items/tests/test_models.py new file mode 100644 index 0000000..032a62e --- /dev/null +++ b/items/tests/test_models.py @@ -0,0 +1,43 @@ +from secrets import token_urlsafe +from django.test import TestCase +from django.contrib.auth.models import User +from django.contrib.staticfiles import finders +from django.core.files import File +from items.models import Item, ItemImage + + +class ItemModelsTestCase(TestCase): + def setUp(self): + self.test_user_username = 'tester' + self.test_user_password = token_urlsafe(32) + self.test_user = User.objects.create_user( + self.test_user_username, + password=self.test_user_password + ) + self.test_item = Item.objects.create( + owner=self.test_user, + name='Test Item', + description='Test item', + ask_price_xmr=0.3 + ) + + + def test_create_item(self): + test_item = Item.objects.create( + owner=self.test_user, + name='Test Item', + description='Test item', + ask_price_xmr=0.3 + ) + obj_name = f'{test_item.id} - {test_item.owner} - {test_item.name}' + self.assertTrue(isinstance(test_item, Item)) + self.assertEqual(test_item.__str__(), obj_name) + + # def test_create_item_image(self): + # static_img = finders.find('images/monero-symbol-800.png') + # img = File(open(static_img, 'rb')) + # test_item_image = ItemImage.objects.create( + # item=self.test_item, + # image=img + # ) + # obj_name = f'{self.id} - {self.item.name} - {self.id}' diff --git a/items/tests/test_views.py b/items/tests/test_views.py new file mode 100644 index 0000000..e69de29 diff --git a/items/views.py b/items/views.py index bc4dd20..ff9990d 100644 --- a/items/views.py +++ b/items/views.py @@ -21,7 +21,6 @@ def list_items(request): item_list = Item.objects.filter(owner=request.user).order_by('-list_date') # If 'search_form' query string is present, retrieve matches containing it's data elif search_form.is_valid(): - search_form.process() item_list = Item.objects.filter( Q(name__icontains=search_form.cleaned_data.get('search')) | Q(whereabouts__icontains=search_form.cleaned_data.get('search')) | diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..b316368 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,5 @@ +[pytest] +DJANGO_SETTINGS_MODULE = xmrauctions.settings +addopts = --cov=. + --cov-report term-missing:skip-covered + --cov-fail-under 100 diff --git a/requirements.txt b/requirements.txt index dd54b2b..795060c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,7 @@ Django==2.2.8 -boto3==1.10.45 Pillow==6.2.1 +boto3==1.10.45 +coverage==5.0.3 django-anymail[mailgun]==7.0.0 django-cors-headers==3.2.0 django-redis==4.11.0 @@ -11,5 +12,7 @@ huey==2.1.3 monero==0.6.2 psycopg2==2.8.4 pysha3==1.0.2 -redis==3.3.11 +pytest==5.3.2 +pytest-cov==2.8.1 qrcode==6.1 +redis==3.3.11