This commit is contained in:
283
backlogger/tests.py
Normal file
283
backlogger/tests.py
Normal file
@@ -0,0 +1,283 @@
|
||||
from django.contrib.auth.models import User
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from .forms import ItemForm, SignupForm
|
||||
from .models import Item
|
||||
|
||||
|
||||
def make_user(username='alice', active=True):
|
||||
user = User.objects.create_user(username=username, password='testpass123', email=f'{username}@example.com')
|
||||
user.is_active = active
|
||||
user.save()
|
||||
return user
|
||||
|
||||
|
||||
def make_item(user, name='Test Game', category=Item.GAMES, **kwargs):
|
||||
return Item.objects.create(user=user, name=name, category=category, **kwargs)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Auth
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class AuthRequiredTests(TestCase):
|
||||
def test_list_redirects_anonymous(self):
|
||||
response = self.client.get(reverse('backlogger:list'))
|
||||
self.assertRedirects(response, '/accounts/login/?next=/backlogger/')
|
||||
|
||||
def test_add_redirects_anonymous(self):
|
||||
response = self.client.get(reverse('backlogger:add'))
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
def test_inactive_user_cannot_login(self):
|
||||
make_user('bob', active=False)
|
||||
response = self.client.post(reverse('login'), {'username': 'bob', 'password': 'testpass123'})
|
||||
# Should stay on login page, not redirect to backlogger
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertFalse(response.wsgi_request.user.is_authenticated)
|
||||
|
||||
def test_active_user_can_login(self):
|
||||
make_user('alice')
|
||||
response = self.client.post(reverse('login'), {'username': 'alice', 'password': 'testpass123'}, follow=True)
|
||||
self.assertTrue(response.wsgi_request.user.is_authenticated)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Signup
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class SignupTests(TestCase):
|
||||
def test_get_signup_page(self):
|
||||
response = self.client.get(reverse('signup'))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, 'Request account')
|
||||
|
||||
def test_signup_creates_inactive_user(self):
|
||||
response = self.client.post(reverse('signup'), {
|
||||
'username': 'newuser',
|
||||
'email': 'new@example.com',
|
||||
'password1': 'StrongPass99!',
|
||||
'password2': 'StrongPass99!',
|
||||
})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, 'pending')
|
||||
user = User.objects.get(username='newuser')
|
||||
self.assertFalse(user.is_active)
|
||||
|
||||
def test_signup_invalid_mismatched_passwords(self):
|
||||
self.client.post(reverse('signup'), {
|
||||
'username': 'newuser',
|
||||
'email': 'new@example.com',
|
||||
'password1': 'StrongPass99!',
|
||||
'password2': 'WrongPass99!',
|
||||
})
|
||||
self.assertFalse(User.objects.filter(username='newuser').exists())
|
||||
|
||||
def test_signup_duplicate_username(self):
|
||||
make_user('taken')
|
||||
response = self.client.post(reverse('signup'), {
|
||||
'username': 'taken',
|
||||
'email': 'other@example.com',
|
||||
'password1': 'StrongPass99!',
|
||||
'password2': 'StrongPass99!',
|
||||
})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(User.objects.filter(username='taken').count(), 1)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Item list
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class ItemListTests(TestCase):
|
||||
def setUp(self):
|
||||
self.alice = make_user('alice')
|
||||
self.bob = make_user('bob')
|
||||
self.client.force_login(self.alice)
|
||||
|
||||
def test_list_shows_own_items(self):
|
||||
make_item(self.alice, name='Alice Game')
|
||||
make_item(self.bob, name='Bob Game')
|
||||
response = self.client.get(reverse('backlogger:list'))
|
||||
self.assertContains(response, 'Alice Game')
|
||||
self.assertNotContains(response, 'Bob Game')
|
||||
|
||||
def test_list_category_filter(self):
|
||||
make_item(self.alice, name='My Game', category=Item.GAMES)
|
||||
make_item(self.alice, name='My Book', category=Item.BOOKS)
|
||||
response = self.client.get(reverse('backlogger:list') + '?category=games')
|
||||
self.assertContains(response, 'My Game')
|
||||
self.assertNotContains(response, 'My Book')
|
||||
|
||||
def test_list_empty_state(self):
|
||||
response = self.client.get(reverse('backlogger:list'))
|
||||
self.assertContains(response, 'Add your first one')
|
||||
|
||||
def test_list_sort_az(self):
|
||||
make_item(self.alice, name='Zelda')
|
||||
make_item(self.alice, name='Ape')
|
||||
response = self.client.get(reverse('backlogger:list') + '?sort=az')
|
||||
names = [item.name for item in response.context['items']]
|
||||
self.assertEqual(names, sorted(names))
|
||||
|
||||
def test_list_sort_favorites_first(self):
|
||||
make_item(self.alice, name='Normal')
|
||||
make_item(self.alice, name='Fav', favorite=True)
|
||||
response = self.client.get(reverse('backlogger:list') + '?sort=fav')
|
||||
names = [item.name for item in response.context['items']]
|
||||
self.assertEqual(names[0], 'Fav')
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Item add
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class ItemAddTests(TestCase):
|
||||
def setUp(self):
|
||||
self.user = make_user('alice')
|
||||
self.client.force_login(self.user)
|
||||
|
||||
def test_add_game(self):
|
||||
self.client.post(reverse('backlogger:add'), {
|
||||
'category': 'games',
|
||||
'name': 'Elden Ring',
|
||||
'progress_percent': 50,
|
||||
'favorite': False,
|
||||
'hours_played': 20,
|
||||
'total_hours': 80,
|
||||
})
|
||||
item = Item.objects.get(name='Elden Ring')
|
||||
self.assertEqual(item.user, self.user)
|
||||
self.assertEqual(item.category, Item.GAMES)
|
||||
self.assertEqual(item.hours_played, 20)
|
||||
|
||||
def test_add_assigns_current_user(self):
|
||||
self.client.post(reverse('backlogger:add'), {
|
||||
'category': 'books',
|
||||
'name': 'Dune',
|
||||
'progress_percent': 0,
|
||||
'favorite': False,
|
||||
})
|
||||
item = Item.objects.get(name='Dune')
|
||||
self.assertEqual(item.user, self.user)
|
||||
|
||||
def test_add_invalid_shows_form(self):
|
||||
response = self.client.post(reverse('backlogger:add'), {'name': ''})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertFalse(Item.objects.exists())
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Item edit
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class ItemEditTests(TestCase):
|
||||
def setUp(self):
|
||||
self.alice = make_user('alice')
|
||||
self.bob = make_user('bob')
|
||||
self.client.force_login(self.alice)
|
||||
|
||||
def test_edit_own_item(self):
|
||||
item = make_item(self.alice, name='Original')
|
||||
self.client.post(reverse('backlogger:edit', args=[item.pk]), {
|
||||
'category': 'games',
|
||||
'name': 'Updated',
|
||||
'progress_percent': 75,
|
||||
'favorite': False,
|
||||
})
|
||||
item.refresh_from_db()
|
||||
self.assertEqual(item.name, 'Updated')
|
||||
|
||||
def test_edit_other_user_item_returns_404(self):
|
||||
item = make_item(self.bob, name='Bobs Item')
|
||||
response = self.client.get(reverse('backlogger:edit', args=[item.pk]))
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Item delete
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class ItemDeleteTests(TestCase):
|
||||
def setUp(self):
|
||||
self.alice = make_user('alice')
|
||||
self.bob = make_user('bob')
|
||||
self.client.force_login(self.alice)
|
||||
|
||||
def test_delete_own_item(self):
|
||||
item = make_item(self.alice, name='To Delete')
|
||||
self.client.post(reverse('backlogger:delete', args=[item.pk]))
|
||||
self.assertFalse(Item.objects.filter(pk=item.pk).exists())
|
||||
|
||||
def test_delete_other_user_item_returns_404(self):
|
||||
item = make_item(self.bob, name='Bobs Item')
|
||||
response = self.client.post(reverse('backlogger:delete', args=[item.pk]))
|
||||
self.assertEqual(response.status_code, 404)
|
||||
self.assertTrue(Item.objects.filter(pk=item.pk).exists())
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Forms
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class ItemFormTests(TestCase):
|
||||
def _post(self, **kwargs):
|
||||
data = {'category': 'games', 'name': 'Test', 'progress_percent': 0, 'favorite': False}
|
||||
data.update(kwargs)
|
||||
form = ItemForm(data)
|
||||
form.is_valid()
|
||||
return form
|
||||
|
||||
def test_game_fields_kept_for_games(self):
|
||||
form = self._post(category='games', hours_played=10, total_hours=40)
|
||||
self.assertEqual(form.cleaned_data['hours_played'], 10)
|
||||
|
||||
def test_game_fields_nulled_for_books(self):
|
||||
form = self._post(category='books', hours_played=10)
|
||||
self.assertIsNone(form.cleaned_data['hours_played'])
|
||||
|
||||
def test_book_fields_kept_for_books(self):
|
||||
form = self._post(category='books', pages_read=100, total_pages=300)
|
||||
self.assertEqual(form.cleaned_data['pages_read'], 100)
|
||||
|
||||
def test_book_fields_nulled_for_games(self):
|
||||
form = self._post(category='games', pages_read=100)
|
||||
self.assertIsNone(form.cleaned_data['pages_read'])
|
||||
|
||||
def test_film_fields_nulled_for_games(self):
|
||||
form = self._post(category='games', duration_minutes=120)
|
||||
self.assertIsNone(form.cleaned_data['duration_minutes'])
|
||||
|
||||
def test_progress_over_100_invalid(self):
|
||||
form = self._post(progress_percent=150)
|
||||
self.assertIn('progress_percent', form.errors)
|
||||
|
||||
def test_progress_negative_invalid(self):
|
||||
form = self._post(progress_percent=-1)
|
||||
self.assertIn('progress_percent', form.errors)
|
||||
|
||||
|
||||
class SignupFormTests(TestCase):
|
||||
def _data(self, **overrides):
|
||||
data = {
|
||||
'username': 'newuser',
|
||||
'email': 'new@example.com',
|
||||
'password1': 'StrongPass99!',
|
||||
'password2': 'StrongPass99!',
|
||||
}
|
||||
data.update(overrides)
|
||||
return data
|
||||
|
||||
def test_valid_form(self):
|
||||
form = SignupForm(self._data())
|
||||
self.assertTrue(form.is_valid())
|
||||
|
||||
def test_email_required(self):
|
||||
form = SignupForm(self._data(email=''))
|
||||
self.assertFalse(form.is_valid())
|
||||
self.assertIn('email', form.errors)
|
||||
|
||||
def test_password_mismatch(self):
|
||||
form = SignupForm(self._data(password2='different'))
|
||||
self.assertFalse(form.is_valid())
|
||||
Reference in New Issue
Block a user