CI Python Linter

""" Comprehensive test suite for dating app views. Tests all views in dating/views.py. """ from django.test import TestCase, Client from django.contrib.auth.models import User from django.urls import reverse from .models import Profile class BaseViewTestCase(TestCase): """Base test case with common setUp data""" def setUp(self): """Create test users and client""" self.client = Client() self.user = User.objects.create_user( username='testuser', email='test@example.com', password='testpass123' ) self.user2 = User.objects.create_user( username='testuser2', email='test2@example.com', password='testpass123' ) class HomeViewTests(TestCase): """Tests for Home template view""" def test_home_view_accessible(self): """Home page should be accessible to everyone""" url = reverse('home') response = self.client.get(url) self.assertEqual(response.status_code, 200) def test_home_view_anonymous_user(self): """Home page should work for anonymous users""" url = reverse('home') response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'dating/index.html') class ProfileGetStartedTests(TestCase): """Tests for ProfileGetStarted view redirects""" def setUp(self): self.client = Client() self.user = User.objects.create_user( username='testuser', password='testpass123' ) def test_redirect_anonymous_to_signup(self): """Unauthenticated users should redirect to signup""" url = reverse('profile_getstarted') response = self.client.get(url) # Assumes allauth signup URL name self.assertRedirects( response, '/account/signup/', fetch_redirect_response=False ) def test_redirect_no_profile_to_create(self): """Users without profile should redirect to profile creation""" self.client.login(username='testuser', password='testpass123') url = reverse('profile_getstarted') response = self.client.get(url) self.assertRedirects(response, reverse('profile_create')) def test_redirect_with_profile_to_about(self): """Users with profile should redirect to profile about""" Profile.objects.create( user=self.user, age=25, gender='M', location='Test City', bio='This is a test bio that is long enough', interests='Reading' ) self.client.login(username='testuser', password='testpass123') url = reverse('profile_getstarted') response = self.client.get(url) self.assertRedirects(response, reverse('profile_about')) class ProfileCreateTests(BaseViewTestCase): """Tests for ProfileCreate view""" def test_get_create_requires_login(self): """Profile creation page requires authentication""" url = reverse('profile_create') response = self.client.get(url) self.assertRedirects(response, '/account/login/?next=' + url) def test_get_create_authenticated(self): """Authenticated users can access profile creation form""" self.client.login(username='testuser', password='testpass123') url = reverse('profile_create') response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'dating/profile_form.html') def test_post_create_profile_success(self): """POST with valid data should create profile and redirect""" self.client.login(username='testuser', password='testpass123') url = reverse('profile_create') data = { 'age': 25, 'gender': 'M', 'location': 'Test City', 'bio': 'This is a test bio that is long enough for validation', 'interests': 'Reading, Coding' } response = self.client.post(url, data) # Should redirect to profile detail self.assertEqual(response.status_code, 302) # Profile should be created profile = Profile.objects.get(user=self.user) self.assertIsNotNone(profile) # Verify redirect URL contains the profile pk self.assertIn(str(profile.pk), response.url) def test_post_create_profile_validation_error_age_too_young(self): """Age below 18 should fail validation""" self.client.login(username='testuser', password='testpass123') url = reverse('profile_create') data = { 'age': 17, 'gender': 'M', 'location': 'Test City', 'bio': 'This is a test bio that is long enough', 'interests': 'Reading' } response = self.client.post(url, data) # Form re-rendered with errors self.assertEqual(response.status_code, 200) self.assertFalse(Profile.objects.filter(user=self.user).exists()) def test_post_create_profile_validation_error_age_too_old(self): """Age above 99 should fail validation""" self.client.login(username='testuser', password='testpass123') url = reverse('profile_create') data = { 'age': 100, 'gender': 'M', 'location': 'Test City', 'bio': 'This is a test bio that is long enough', 'interests': 'Reading' } response = self.client.post(url, data) self.assertEqual(response.status_code, 200) self.assertFalse(Profile.objects.filter(user=self.user).exists()) def test_post_create_profile_validation_error_bio_too_short(self): """Bio shorter than 10 characters should fail validation""" self.client.login(username='testuser', password='testpass123') url = reverse('profile_create') data = { 'age': 25, 'gender': 'M', 'location': 'Test City', 'bio': 'Short', # Too short 'interests': 'Reading' } response = self.client.post(url, data) self.assertEqual(response.status_code, 200) self.assertFalse(Profile.objects.filter(user=self.user).exists()) def test_post_create_profile_already_exists(self): """Creating a second profile should show error message""" # Create first profile Profile.objects.create( user=self.user, age=25, gender='M', location='Test City', bio='This is a test bio that is long enough', interests='Reading' ) self.client.login(username='testuser', password='testpass123') url = reverse('profile_create') data = { 'age': 30, 'gender': 'F', 'location': 'Another City', 'bio': 'This is another test bio that is long enough', 'interests': 'Dancing' } response = self.client.post(url, data) self.assertEqual(response.status_code, 200) # Form re-rendered # Should still have only one profile self.assertEqual(Profile.objects.filter(user=self.user).count(), 1) def test_form_class_validation(self): """Test form validation directly""" from .views import ProfileCreate view = ProfileCreate() form_class = view.get_form_class() # Valid form valid_data = { 'age': 25, 'gender': 'M', 'location': 'Test City', 'bio': 'This is a test bio that is long enough', 'interests': 'Reading, Coding', } form = form_class(data=valid_data) self.assertTrue(form.is_valid()) class ProfileUpdateTests(BaseViewTestCase): """Tests for ProfileUpdate view""" def setUp(self): super().setUp() self.profile = Profile.objects.create( user=self.user, age=25, gender='M', location='Test City', bio='This is a test bio that is long enough', interests='Reading' ) def test_get_update_requires_login(self): """Profile update page requires authentication""" url = reverse('profile_update') response = self.client.get(url) self.assertRedirects(response, '/account/login/?next=' + url) def test_get_update_authenticated(self): """Authenticated users can access profile update form""" self.client.login(username='testuser', password='testpass123') url = reverse('profile_update') response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'dating/profile_form.html') def test_post_update_profile_success(self): """POST with valid data should update profile""" self.client.login(username='testuser', password='testpass123') url = reverse('profile_update') data = { 'age': 30, 'gender': 'M', 'location': 'Updated City', 'bio': 'This is an updated test bio that is long enough', 'interests': 'Updated Interests' } response = self.client.post(url, data) self.assertRedirects(response, reverse('profile_about')) # Profile should be updated self.profile.refresh_from_db() self.assertEqual(self.profile.age, 30) self.assertEqual(self.profile.location, 'Updated City') # Check success message messages = list(response.wsgi_request._messages) msg_text = any('successfully updated' in str(m) for m in messages) self.assertTrue(msg_text) class ProfileDeleteTests(BaseViewTestCase): """Tests for ProfileDelete view""" def setUp(self): super().setUp() self.profile = Profile.objects.create( user=self.user, age=25, gender='M', location='Test City', bio='This is a test bio that is long enough', interests='Reading' ) def test_get_delete_requires_login(self): """Profile delete page requires authentication""" url = reverse('profile_delete') response = self.client.get(url) self.assertRedirects(response, '/account/login/?next=' + url) def test_get_delete_requires_profile(self): """Users without profile should redirect to create""" User.objects.create_user( username='noprofile', password='testpass123' ) self.client.login(username='noprofile', password='testpass123') url = reverse('profile_delete') response = self.client.get(url) self.assertRedirects(response, reverse('profile_create')) def test_get_delete_authenticated_with_profile(self): """Authenticated users with profile can access delete page""" self.client.login(username='testuser', password='testpass123') url = reverse('profile_delete') response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'dating/profile_delete.html') def test_post_delete_profile_success(self): """POST should delete profile and redirect to home""" self.client.login(username='testuser', password='testpass123') url = reverse('profile_delete') response = self.client.post(url) self.assertRedirects(response, reverse('home')) # Profile should be deleted self.assertFalse(Profile.objects.filter(user=self.user).exists()) # Check success message messages = list(response.wsgi_request._messages) msg_text = any('successfully deleted' in str(m) for m in messages) self.assertTrue(msg_text) class ProfileDetailTests(BaseViewTestCase): """Tests for ProfileDetail view""" def setUp(self): super().setUp() self.profile = Profile.objects.create( user=self.user, age=25, gender='M', location='Test City', bio='This is a test bio that is long enough', interests='Reading' ) def test_get_detail_requires_login(self): """Profile detail page requires authentication""" url = reverse('profile_detail', args=[self.profile.pk]) response = self.client.get(url) self.assertRedirects(response, '/account/login/?next=' + url) def test_get_detail_authenticated(self): """Authenticated users can view profile detail""" self.client.login(username='testuser', password='testpass123') url = reverse('profile_detail', args=[self.profile.pk]) response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'dating/profile_detail.html') self.assertEqual(response.context['profile'], self.profile) def test_get_detail_with_origin_parameter(self): """Profile detail should handle origin query parameter""" self.client.login(username='testuser', password='testpass123') url = reverse('profile_detail', args=[self.profile.pk]) url += '?origin=/connections/discover/' response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertIn('next_url', response.context) expected_url = '/connections/discover/' self.assertEqual(response.context['next_url'], expected_url) def test_get_detail_with_invalid_origin_parameter(self): """Profile detail should default to discover if origin is invalid""" self.client.login(username='testuser', password='testpass123') url = reverse('profile_detail', args=[self.profile.pk]) url += '?origin=http://evil.com/' response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertIn('next_url', response.context) # Should default to discover, not the evil URL expected_url = '/connections/discover/' self.assertEqual(response.context['next_url'], expected_url) def test_get_detail_nonexistent_profile(self): """Accessing non-existent profile should return 404""" self.client.login(username='testuser', password='testpass123') url = reverse('profile_detail', args=[99999]) response = self.client.get(url) self.assertEqual(response.status_code, 404) class ProfileAboutTests(BaseViewTestCase): """Tests for ProfileAbout view""" def setUp(self): super().setUp() self.profile = Profile.objects.create( user=self.user, age=25, gender='M', location='Test City', bio='This is a test bio that is long enough', interests='Reading' ) def test_get_about_requires_login(self): """Profile about page requires authentication""" url = reverse('profile_about') response = self.client.get(url) self.assertRedirects(response, '/account/login/?next=' + url) def test_get_about_requires_profile(self): """Users without profile should redirect to create""" User.objects.create_user( username='noprofile', password='testpass123' ) self.client.login(username='noprofile', password='testpass123') url = reverse('profile_about') response = self.client.get(url) self.assertRedirects(response, reverse('profile_create')) def test_get_about_authenticated_with_profile(self): """Authenticated users with profile can view their profile""" self.client.login(username='testuser', password='testpass123') url = reverse('profile_about') response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'dating/profile_detail.html') self.assertEqual(response.context['profile'], self.profile) class AboutViewTests(TestCase): """Tests for AboutView template""" def test_about_view_accessible(self): """About page should be accessible to everyone""" url = reverse('about') response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'dating/about.html') class ContactViewTests(TestCase): """Tests for ContactView template""" def test_contact_view_accessible(self): """Contact page should be accessible to everyone""" url = reverse('contact') response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'dating/contact.html')

Settings:


Results:

All clear, no errors found