Skip to content

feat: Add comprehensive unit tests for chat, pagos, and principal apps#1

Open
adrleogom wants to merge 1 commit intodespliegue-s3from
feat/add-unit-tests
Open

feat: Add comprehensive unit tests for chat, pagos, and principal apps#1
adrleogom wants to merge 1 commit intodespliegue-s3from
feat/add-unit-tests

Conversation

@adrleogom
Copy link
Owner

@adrleogom adrleogom commented Jun 18, 2025

User description

This commit introduces a significant number of new unit tests to improve code coverage and verify the functionality of various components across the chat, pagos, and principal applications.

Key additions include:

  • chat:

    • Model tests for ChatRoom (group logic, publicKey, last_message).
    • View tests for SMS validation, error handling, and varied context scenarios.
    • Form tests for CrearGrupo (validation and dynamic choices).
    • Detailed asynchronous tests for ChatConsumer (connection, messaging, encryption, error handling).
  • pagos:

    • View tests for SMS validation.
    • Tests for handling invalid subscription primary keys.
    • Improved assertions for payment completion logic.
    • Ensured usage of reverse() for URL resolution.
  • principal:

    • Model tests for Usuario (get_edad, es_premium).
    • Detailed tests for the dice_coefficient recommendation logic.
    • View tests for SMS validation, piso_encontrado logic, filtering users with unvalidated SMS, mate actions against users with unvalidated SMS, and some permission checks for profile details.
    • (Note: A second batch of planned tests for principal, including error handlers, Twilio mocking, and detailed form/statistics tests, could not be applied due to technical diffing issues.)

Unfortunately, running the full test suite was not possible in the current environment due to persistent issues with installing the psycopg2 dependency (a sub-dependency of django-heroku) which requires system-level libraries not available. The implemented tests are therefore submitted without a full successful test run in this specific environment.


PR Type

Tests


Description

Chat app: Complete test suite rewrite expanding from 153 to 538 lines with comprehensive coverage including:

  • Model tests for ChatRoom (group() method, public_key generation, last_message default)
  • Form validation tests for CrearGrupo with dynamic choices and validation rules
  • Detailed asynchronous tests for ChatConsumer covering WebSocket connections, message encryption/decryption, and error handling
  • Enhanced view tests with proper URL reversal and SMS validation checks
    Principal app: Added extensive unit tests for:
  • Usuario model methods (get_edad(), es_premium())
  • Recommendation system with detailed dice_coefficient function testing
  • Mate system with comprehensive edge case coverage and SMS validation
  • Permission and access control tests for profile detail views
    Pagos app: Enhanced payment system tests with:
  • SMS validation requirements across payment views
  • Improved payment completion assertions with timezone handling
  • Invalid subscription primary key handling tests
  • Proper URL resolution using reverse() instead of hardcoded URLs
    General improvements: Fixed user creation to use objects.create_user() for proper password hashing across all test suites

Changes walkthrough 📝

Relevant files
Tests
tests.py
Comprehensive unit tests for Usuario model and view functionality

MakeAMate/principal/tests.py

• Added comprehensive test class TestUsuarioModel for testing Usuario
model methods like get_edad() and es_premium()
• Enhanced
recommendation system tests with detailed dice_coefficient function
testing and improved test data setup
• Expanded mate system tests with
better error handling, SMS validation checks, and comprehensive edge
case coverage
• Added new test class
ViewTestsSMSValidationAndBasicAccess for testing SMS validation
requirements across views
• Improved existing test classes with proper
use of reverse() for URL resolution and objects.create_user() for user
creation
• Added extensive permission and access control tests for
profile detail views

+655/-550
tests.py
Enhanced payment system tests with SMS validation               

MakeAMate/pagos/tests.py

• Enhanced existing payment tests with proper use of reverse() for URL
resolution instead of hardcoded URLs
• Added SMS validation tests for
payment views to ensure users with unvalidated SMS are redirected
appropriately
• Improved payment completion tests with better
assertions and timezone handling using timezone.localtime()
• Added
test for handling invalid subscription primary keys in paypal view

Fixed user creation to use objects.create_user() for proper password
hashing

+108/-44
tests.py
Comprehensive test suite expansion for chat functionality

MakeAMate/chat/tests.py

• Completely rewrote and expanded test suite from 153 to 538 lines
with comprehensive coverage
• Added new test classes:
TestChatRoomModel, TestChatForms, and TestChatConsumer for better
organization
• Implemented extensive model tests for ChatRoom
including group() method, public_key generation, and last_message
default
• Added comprehensive form validation tests for CrearGrupo
form with dynamic choices, min/max selection validation, and name
length validation
• Created detailed asynchronous tests for
ChatConsumer covering WebSocket connections, message
encryption/decryption, error handling, and message history retrieval

Enhanced existing view tests with proper URL reversal using reverse()
and added SMS validation checks
• Improved test data setup using
objects.create() methods and added scenarios for users with
unvalidated SMS

+500/-115

Need help?
  • Type /help how to ... in the comments thread for any questions about Qodo Merge usage.
  • Check out the documentation for more information.
  • This commit introduces a significant number of new unit tests to improve
    code coverage and verify the functionality of various components across
    the chat, pagos, and principal applications.
    
    Key additions include:
    
    - chat:
      - Model tests for ChatRoom (group logic, publicKey, last_message).
      - View tests for SMS validation, error handling, and varied context scenarios.
      - Form tests for CrearGrupo (validation and dynamic choices).
      - Detailed asynchronous tests for ChatConsumer (connection, messaging, encryption, error handling).
    
    - pagos:
      - View tests for SMS validation.
      - Tests for handling invalid subscription primary keys.
      - Improved assertions for payment completion logic.
      - Ensured usage of reverse() for URL resolution.
    
    - principal:
      - Model tests for Usuario (get_edad, es_premium).
      - Detailed tests for the dice_coefficient recommendation logic.
      - View tests for SMS validation, piso_encontrado logic, filtering users
        with unvalidated SMS, mate actions against users with unvalidated SMS,
        and some permission checks for profile details.
      - (Note: A second batch of planned tests for principal, including error
        handlers, Twilio mocking, and detailed form/statistics tests, could
        not be applied due to technical diffing issues.)
    
    Unfortunately, running the full test suite was not possible in the
    current environment due to persistent issues with installing the psycopg2
    dependency (a sub-dependency of django-heroku) which requires system-level
    libraries not available. The implemented tests are therefore submitted
    without a full successful test run in this specific environment.
    @qodo-code-review
    Copy link

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
    🧪 PR contains tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Test Data Isolation

    Multiple test classes create users and objects with potentially conflicting data (phone numbers, usernames, zones). Some tests use hardcoded IDs which could cause conflicts. The tearDown method in RegistroTest only deletes users with '_reg' suffix, but other test classes don't have similar cleanup.

    class TestUsuarioModel(TestCase):
        def setUp(self):
            self.test_user = User.objects.create_user(username='testuser_model', password='password')
            self.usuario_profile = Usuario.objects.create(
                usuario=self.test_user,
                fecha_nacimiento=date(2000, 1, 15), # Default birthday for tests
                lugar="Testville",
                telefono="+34999888777", # Unique phone
                genero='O',
                estudios="Testing",
                sms_validado=True
            )
    
        def test_get_edad_various_scenarios(self):
            # Scenario 1: Birthday passed this year
            self.usuario_profile.fecha_nacimiento = date(timezone.now().year - 25, 1, 1)
            self.usuario_profile.save()
            self.assertEqual(self.usuario_profile.get_edad(), 25)
    
            # Scenario 2: Birthday not yet passed this year
            self.usuario_profile.fecha_nacimiento = date(timezone.now().year - 25, 12, 31)
            self.usuario_profile.save()
            self.assertEqual(self.usuario_profile.get_edad(), 24)
    
            # Scenario 3: Birthday is today
            today = timezone.now().date()
            self.usuario_profile.fecha_nacimiento = date(today.year - 20, today.month, today.day)
            self.usuario_profile.save()
            self.assertEqual(self.usuario_profile.get_edad(), 20)
    
        def test_es_premium_exact_time(self):
            self.usuario_profile.fecha_premium = timezone.now() 
            self.usuario_profile.save()
            self.assertFalse(self.usuario_profile.es_premium())
    
            self.usuario_profile.fecha_premium = timezone.now() + timedelta(seconds=1)
            self.usuario_profile.save()
            self.assertTrue(self.usuario_profile.es_premium())
    
            self.usuario_profile.fecha_premium = timezone.now() - timedelta(seconds=1)
            self.usuario_profile.save()
            self.assertFalse(self.usuario_profile.es_premium())
    
    
    # Tests Sistema de Recomendación
    class RecommendationTestCase(TestCase):
        def setUp(self):
            self.user1 = User.objects.create_user(id=0,username="us1", password='123') # Ensure password hashing
            self.user2 = User.objects.create_user(id=1,username="us2", password='123')
            self.user3 = User.objects.create_user(id=2,username="us3", password='123')
    
            premium_fin = timezone.now()+ relativedelta(months=1)
            self.perfil1 = Usuario.objects.create(usuario=self.user1,fecha_nacimiento=datetime.now(),lugar="Sevilla",telefono="+34655444333",
                                genero='F',estudios="Informática",fecha_premium=premium_fin,sms_validado=True)
            self.perfil2 = Usuario.objects.create(usuario=self.user2,fecha_nacimiento=datetime.now(),lugar="Sevilla",telefono="+34655444334",
                                genero='F',estudios="Informática",sms_validado=True)
            self.perfil3 = Usuario.objects.create(usuario=self.user3,fecha_nacimiento=datetime.now(),lugar="Sevilla",telefono="+34655444335",
                                genero='F',estudios="Informática",sms_validado=True)
    
            tag1, _ = Tag.objects.get_or_create(etiqueta="No fumador") # Use get_or_create to avoid issues on re-runs
            tag2, _ = Tag.objects.get_or_create(etiqueta="Mascotas")
    
            af1, _ = Aficiones.objects.get_or_create(opcionAficiones="Futbol")
            af2, _ = Aficiones.objects.get_or_create(opcionAficiones="Lolango")
    
            self.perfil1.tags.add(tag1)
            self.perfil1.aficiones.add(af1)  
            self.perfil2.tags.add(tag1)
            self.perfil2.aficiones.add(af1)
            self.perfil3.tags.add(tag2)
            self.perfil3.aficiones.add(af2)
            # Save after adding M2M fields
            self.perfil1.save()
            self.perfil2.save()
            self.perfil3.save()
    
    
        def test_perfect_score(self):
            score = rs_score(self.perfil1,self.perfil2)
    
            self.assertEqual(score,1.0)
    
        def test_perfect_score_premium(self):
            score = rs_score(self.perfil2,self.perfil1)
    
            self.assertEqual(score,1.0*BONUS_PREMIUM)
    
        def test_no_score(self):
            score = rs_score(self.perfil3,self.perfil1)
    
            self.assertEqual(score,0.0)
    
        def test_recommendation(self):
            self.client.login(username='us1', password='123')
    
            response=self.client.get(reverse('homepage')) # Use reverse
    
            self.assertEqual(list(response.context['usuarios'])[0], self.perfil2)
            self.assertEqual(response.status_code, 200)
    
        def test_dice_coefficient_no_common_interests(self):
            score = dice_coefficient(
                set(self.perfil1.tags.all()), set(self.perfil3.tags.all()),
                set(self.perfil1.aficiones.all()), set(self.perfil3.aficiones.all())
            )
            self.assertEqual(score, 0.0)
    
        def test_dice_coefficient_only_tags_common(self):
            user4 = User.objects.create_user(username='rec_user4_tags', password='123') 
            perfil4 = Usuario.objects.create(usuario=user4, fecha_nacimiento=datetime.now(), lugar="Sevilla", telefono="+34655444100", genero='F', estudios="Informática", sms_validado=True)
            perfil4.tags.add(Tag.objects.get(etiqueta="No fumador")) 
            perfil4.aficiones.add(Aficiones.objects.get(opcionAficiones="Lolango")) 
            perfil4.save()
            score = dice_coefficient(
                set(self.perfil1.tags.all()), set(perfil4.tags.all()),
                set(self.perfil1.aficiones.all()), set(perfil4.aficiones.all())
            )
            self.assertAlmostEqual(score, 2.0/3.0)
    
        def test_dice_coefficient_only_aficiones_common(self):
            user5 = User.objects.create_user(username='rec_user5_afic', password='123') 
            perfil5 = Usuario.objects.create(usuario=user5, fecha_nacimiento=datetime.now(), lugar="Sevilla", telefono="+34655444101", genero='F', estudios="Informática", sms_validado=True)
            perfil5.tags.add(Tag.objects.get(etiqueta="Mascotas")) 
            perfil5.aficiones.add(Aficiones.objects.get(opcionAficiones="Futbol")) 
            perfil5.save()
            score = dice_coefficient(
                set(self.perfil1.tags.all()), set(perfil5.tags.all()),
                set(self.perfil1.aficiones.all()), set(perfil5.aficiones.all())
            )
            self.assertAlmostEqual(score, 1.0/3.0) # Corrected expected score: 1 common aficion, 1 in p1, 2 in p5. (2*1)/(1+2) = 2/3. Tags: 0 common. (0+2/3)/2 = 1/3
    
        def test_dice_coefficient_one_user_no_interests(self):
            user_no_interest = User.objects.create_user(username='rec_no_interest_dice', password='123') 
            perfil_no_interest = Usuario.objects.create(usuario=user_no_interest, fecha_nacimiento=datetime.now(), lugar="Sevilla", telefono="+34655444102", genero='M', estudios="Bioquímica", sms_validado=True)
            perfil_no_interest.save()
            score = dice_coefficient(
                set(self.perfil1.tags.all()), set(perfil_no_interest.tags.all()),
                set(self.perfil1.aficiones.all()), set(perfil_no_interest.aficiones.all())
            )
            self.assertEqual(score, 0.0)
    
        def test_dice_coefficient_both_users_no_interests(self):
            user_no_interest1 = User.objects.create_user(username='rec_no_interest1_dice', password='123') 
            perfil_no_interest1 = Usuario.objects.create(usuario=user_no_interest1, fecha_nacimiento=datetime.now(), lugar="Sevilla", telefono="+34655444103", genero='M', estudios="Bioquímica", sms_validado=True)
            perfil_no_interest1.save()
            user_no_interest2 = User.objects.create_user(username='rec_no_interest2_dice', password='123') 
            perfil_no_interest2 = Usuario.objects.create(usuario=user_no_interest2, fecha_nacimiento=datetime.now(), lugar="Sevilla", telefono="+34655444104", genero='F', estudios="Medicina", sms_validado=True)
            perfil_no_interest2.save()
            score = dice_coefficient(
                set(perfil_no_interest1.tags.all()), set(perfil_no_interest2.tags.all()),
                set(perfil_no_interest1.aficiones.all()), set(perfil_no_interest2.aficiones.all())
            )
            self.assertEqual(score, 0.0)
    
    
    # Tests mates
    class MateTestCase(TestCase):
        def setUp(self):
    
            self.user1 = User.objects.create_user(id=0,username="us1", password='123')
            self.user2 = User.objects.create_user(id=1,username="us2", password='123')
            self.user3 = User.objects.create_user(id=2,username="us3", password='123')
            self.user4 = User.objects.create_user(id=3,username="us4", password='123')
            self.user5 = User.objects.create_user(id=4,username="us5", password='123')
            self.user6 = User.objects.create_user(id=5,username="us6", password='123')
    
            piso1 = Piso.objects.create(zona="Calle Marqués Luca de Tena 3", descripcion="Descripción de prueba 2")
            piso2 = Piso.objects.create(zona="Calle Marqués Luca de Tena 4", descripcion="Descripción de prueba 2") # Unique zona
    
            self.perfil1 = Usuario.objects.create(usuario=self.user1,fecha_nacimiento=date(2000,12,31),lugar="Sevilla",
                                genero='F',estudios="Informática",telefono="+34655444333",sms_validado=True)
            self.perfil2 = Usuario.objects.create(usuario=self.user2,fecha_nacimiento=date(2000,12,31),lugar="sevilla",
                                genero='F',estudios="Informática",telefono="+34655444334",sms_validado=True)
            self.perfil3 = Usuario.objects.create(usuario=self.user3,fecha_nacimiento=date(2000,12,31),lugar="Sevilla",
                                genero='F',estudios="Informática",piso=piso1,telefono="+34655444335",sms_validado=True)
            self.perfil4 = Usuario.objects.create(usuario=self.user4,fecha_nacimiento=date(2000,12,31),lugar="Sevilla",
                                genero='M',estudios="Informática",piso=piso2,telefono="+34655444336",sms_validado=True)
            self.perfil5 = Usuario.objects.create(usuario=self.user5,fecha_nacimiento=date(2000,12,31),lugar="Murcia",
                                genero='M',estudios="Informática",telefono="+34655444337",sms_validado=True)
            self.perfil6 = Usuario.objects.create(usuario=self.user6,fecha_nacimiento=date(2000,12,31),lugar="Sevilla",
                                genero='M',estudios="Informática",telefono="+34655444369",sms_validado=False)
    
            Mate.objects.create(userEntrada=self.user3, userSalida=self.user1, mate=True)
            Mate.objects.create(userEntrada=self.user4, userSalida=self.user1, mate=False)
    
    
        def test_accept_no_sms(self):
            self.client.login(username='us1', password='123')
    
            data = {'id_us': self.perfil6.usuario.id} # Use ID of user6 who has sms_validado=False
            response = self.client.post(reverse('accept_mate'), data, format='json')
            json_resp = response.json() # Use response.json() for Django 3.1+
    
            self.assertFalse(json_resp['success'])
    
        def test_reject_no_sms(self):
            self.client.login(username='us1', password='123')
    
            data = {'id_us': self.perfil6.usuario.id} # Use ID of user6 who has sms_validado=False
            response = self.client.post(reverse('reject_mate'), data, format='json')
            json_resp = response.json()
    
            self.assertFalse(json_resp['success'])
    
        def test_accept_mate(self):
            self.client.login(username='us1', password='123')
    
            data = {'id_us': self.user2.id} # user2 is a valid target
            response = self.client.post(reverse('accept_mate'), data, format='json')
            json_resp = response.json()
            mate_exists = Mate.objects.filter(userEntrada=self.user1, userSalida=self.user2, mate=True).exists()
    
    
            self.assertTrue(mate_exists)
            self.assertTrue(json_resp['success'])
            self.assertFalse(json_resp['mate_achieved']) # Assuming no pre-existing mate from user2 to user1
    
    
        def test_reject_mate(self):
            self.client.login(username='us1', password='123')
    
            data = {'id_us': self.user2.id}
            response = self.client.post(reverse('reject_mate'), data, format='json')
            json_resp = response.json()
            mate_exists = Mate.objects.filter(userEntrada=self.user1, userSalida=self.user2, mate=False).exists()
    
            self.assertTrue(mate_exists) # Check if a mate object with mate=False was created
            self.assertTrue(json_resp['success'])
    
        def test_mate_achieved(self):
            # Ensure user3 has already sent a mate request to user1 for this test
            Mate.objects.update_or_create(userEntrada=self.user3, userSalida=self.user1, defaults={'mate': True})
    
            self.client.login(username='us1', password='123')
    
            data = {'id_us': self.user3.id}
            response = self.client.post(reverse('accept_mate'), data, format='json')
            json_resp = response.json()
            mate = Mate.objects.get(userEntrada=self.user1, userSalida=self.user3)
    
            self.assertTrue(mate.mate)
            self.assertTrue(json_resp['success'])
            self.assertTrue(json_resp['mate_achieved'])
    
        def test_accept_mate_self(self):
            self.client.login(username='us1', password='123')
    
            data = {'id_us': self.user1.id} # Targeting self
            response = self.client.post(reverse('accept_mate'), data, format='json')
            json_resp = response.json()
    
            self.assertFalse(json_resp['success'])
    
        def test_reject_mate_self(self):
            self.client.login(username='us1', password='123')
    
            data = {'id_us': self.user1.id} # Targeting self
            response = self.client.post(reverse('reject_mate'), data, format='json')
            json_resp = response.json()
    
            self.assertFalse(json_resp['success'])
    
        def test_accept_not_same_city(self):
            self.client.login(username='us1', password='123') # us1 is in Sevilla
    
            data = {'id_us': self.user5.id} # user5 is in Murcia
            response = self.client.post(reverse('accept_mate'), data, format='json')
            json_resp = response.json()
    
            self.assertFalse(json_resp['success'])
    
        def test_reject_not_same_city(self):
            self.client.login(username='us1', password='123')
    
            data = {'id_us': self.user5.id}
            response = self.client.post(reverse('reject_mate'), data, format='json')
            json_resp = response.json()
    
            self.assertFalse(json_resp['success'])
    
        def test_accept_rejected_mate(self):
            # user4 has already rejected user1 (mate=False in setUp)
            self.client.login(username='us1', password='123')
            data = {'id_us': self.user4.id}
            response = self.client.post(reverse('accept_mate'), data, format='json')
            json_resp = response.json()
    
            self.assertFalse(json_resp['success'])
    
    
        def test_reject_rejected_mate(self):
            # user4 has already rejected user1 (mate=False in setUp)
            self.client.login(username='us1', password='123')
            data = {'id_us': self.user4.id}
            response = self.client.post(reverse('reject_mate'), data, format='json')
            json_resp = response.json()
    
            self.assertFalse(json_resp['success'])
    
        def test_accept_already_mated(self):
            # user3 has already mated with user1 (mate=True in setUp for user3 -> user1)
            self.client.login(username='us1', password='123') # user1 trying to accept user3
            data = {'id_us': self.user3.id}
            response = self.client.post(reverse('accept_mate'), data, format='json')
            json_resp = response.json()
            # This behavior depends on the view logic: can you re-accept an existing mate?
            # Assuming the current logic might prevent re-mating or creating duplicates.
            # If it's allowed and 'mate_achieved' becomes true, this test needs adjustment.
            # For now, let's assume it might be false if the mate already exists from user1's side.
            # The original test had user4 (who had a false mate with user1) trying to accept user1 (id=0)
            # Let's stick to user1 accepting user3, where user3 already liked user1.
            self.assertTrue(json_resp['success']) # It should be a successful operation to form the mutual mate
            self.assertTrue(json_resp['mate_achieved'])
    
    
        def test_reject_already_mated(self):
            # user3 has already mated with user1
            self.client.login(username='us1', password='123') # user1 trying to reject user3
            data = {'id_us': self.user3.id}
            response = self.client.post(reverse('reject_mate'), data, format='json')
            json_resp = response.json()
            # Rejecting an existing mate should probably be successful in terms of API call,
            # but the mate status would become False.
            self.assertTrue(json_resp['success'])
            mate_after_reject = Mate.objects.get(userEntrada=self.user1, userSalida=self.user3)
            self.assertFalse(mate_after_reject.mate)
    
    
        def test_accept_both_pisos(self):
            # user4 has piso, user3 has piso.
            self.client.login(username=self.user4.username, password='123')
            data = {'id_us': self.user3.id}
            response = self.client.post(reverse('accept_mate'), data, format='json')
            json_resp = response.json()
            self.assertFalse(json_resp['success'])
    
        def test_reject_both_pisos(self):
            self.client.login(username=self.user3.username, password='123')
            data = {'id_us': self.user4.id}
            response = self.client.post(reverse('reject_mate'), data, format='json')
            json_resp = response.json()
            self.assertFalse(json_resp['success'])
    
        def test_accept_mate_inexistent_user(self):
            self.client.login(username='us1', password='123')
            data = {'id_us': 100}
            response = self.client.post(reverse('accept_mate'), data, format='json')
            self.assertEqual(response.status_code,404) # Corrected: assertEquals to assertEqual
    
        def test_reject_mate_inexistent_user(self):
            self.client.login(username='us1', password='123')
            data = {'id_us': 100}
            response = self.client.post(reverse('reject_mate'), data, format='json')
            self.assertEqual(response.status_code,404) # Corrected: assertEquals to assertEqual
    
        def test_accept_mate_not_logged(self):
            data = {'id_us': self.user1.id} # Use a valid user ID
            response = self.client.post(reverse('accept_mate'), data, format='json')
            self.assertEqual(response.status_code,302) # Corrected: assertEquals to assertEqual
            self.assertRedirects(response, reverse("login") + "?next=" + reverse("accept_mate"), target_status_code=200)
    
    
        def test_reject_mate_not_logged(self):
            data = {'id_us': self.user1.id} # Use a valid user ID
            response = self.client.post(reverse('reject_mate'), data, format='json')
            self.assertEqual(response.status_code,302) # Corrected: assertEquals to assertEqual
            self.assertRedirects(response, reverse("login") + "?next=" + reverse("reject_mate"), target_status_code=200)
    
        def test_accept_mate_target_sms_not_validated(self):
            target_sms_false_user = User.objects.create_user(username='target_sms_false_accept', password='password')
            profile_target_sms_false = Usuario.objects.create(usuario=target_sms_false_user, fecha_nacimiento=date(2000,1,1), estudios="Arte", telefono="+34655444106", 
                                                            lugar="Sevilla", genero='M', sms_validado=False)
            self.client.login(username='us1', password='123') 
            data = {'id_us': profile_target_sms_false.usuario.id}
            response = self.client.post(reverse('accept_mate'), data, format='json')
            json_resp = response.json()
            self.assertFalse(json_resp['success'])
    
        def test_reject_mate_target_sms_not_validated(self):
            target_sms_false_user = User.objects.create_user(username='target_sms_false_reject', password='password')
            profile_target_sms_false = Usuario.objects.create(usuario=target_sms_false_user, fecha_nacimiento=date(2000,1,1), estudios="Arte", telefono="+34655444107", 
                                                            lugar="Sevilla", genero='M', sms_validado=False)
            self.client.login(username='us1', password='123')
            data = {'id_us': profile_target_sms_false.usuario.id}
            response = self.client.post(reverse('reject_mate'), data, format='json')
            json_resp = response.json()
            self.assertFalse(json_resp['success'])
    
    
    #Test filtros automáticos
    class FiltesTests(TestCase): # Renamed from FiltesTests for consistency
    
        def setUp(self):
            self.userPepe_auth = User.objects.create_user(username="Pepe", password="asdfg")
            self.userMaria_auth = User.objects.create_user(username="Maria", password="asdfg")
            self.userSara_auth = User.objects.create_user(username="Sara", password="asdfg")
            self.userPepa_auth = User.objects.create_user(username="Pepa", password="asdfg")
            self.userJuan_auth = User.objects.create_user(username="Juan", password="asdfg")
    
            tfn1 = "+34666777111"
            tfn2 = "+34666777222"
            tfn3 = "+34666777333"
            tfn4 = "+34666777444"
            tfn5 = "+34666777555"
    
            piso_maria = Piso.objects.create(zona="Calle Marqués Luca de Tena 3 Filter", descripcion="Descripción de prueba 2")
            piso_sara = Piso.objects.create(zona="Calle Marqués Luca de Tena 5 Filter", descripcion="Descripción de prueba 3")
    
            self.Pepe = Usuario.objects.create(usuario=self.userPepe_auth, fecha_nacimiento=date(2000,12,31),lugar="Sevilla", telefono=tfn1, sms_validado=True)
            self.Maria = Usuario.objects.create(usuario=self.userMaria_auth, fecha_nacimiento=date(2000,12,30),lugar="Sevilla", piso=piso_maria, telefono=tfn2, sms_validado=True)
            self.Sara = Usuario.objects.create(usuario=self.userSara_auth,fecha_nacimiento=date(2000,12,29),lugar="Cádiz", piso=piso_sara, telefono=tfn3, sms_validado=True)
            self.Pepa = Usuario.objects.create(usuario=self.userPepa_auth, fecha_nacimiento=date(2000,12,28), lugar="Sevilla",telefono=tfn5, sms_validado=True)
            self.Juan = Usuario.objects.create(usuario=self.userJuan_auth, fecha_nacimiento=date(2000,12,27), lugar ="Sevilla", telefono=tfn4, sms_validado=True)
    
    
       #Nos logeamos como Pepe usuario sin Piso en Sevilla y 
       # comprobamos que solo nos sale 3 usuarios, que son los que están en la misma ciudad
        def test_filter_piso_y_ciudad(self):
            c = Client() # Use self.client if preferred
            login= c.login(username='Pepe', password= 'asdfg')
            response=c.get(reverse('homepage')) # Use reverse
    
            self.assertTrue( len(response.context['usuarios']) == 3) # Maria, Pepa, Juan (all in Sevilla, Sara is Cadiz)
            self.assertEqual(response.status_code, 200)
    
    
        #Nos logeamos como Pepe usuario sin Piso en Sevilla y 
        #comprobamos que efectivamente no salen 4 usuarios ya que uno de ellos no vive en la misma ciudad
        def test_filter_error(self):
            c= Client()
            c.login(username='Pepe', password= 'asdfg')
            response=c.get(reverse('homepage'))
            self.assertFalse( len(response.context['usuarios']) == 4) # Sara should be filtered out
            self.assertEqual(response.status_code, 200)
    
        def test_filter_rejected_mate(self):
            c= Client()
            c.login(username='Pepe', password= 'asdfg')
            response=c.get(reverse('homepage'))
            #Comprombamos que antes de rechazar a un usuario nos salen 3 en total
            self.assertTrue( len(response.context['usuarios']) == 3)
            Mate.objects.create(userEntrada=self.userPepe_auth, userSalida=self.userPepa_auth, mate=False)
            response=c.get(reverse('homepage'))
            #Comprobamos que tras rechazar a un usuario ese ya no nos aparece como usuario recomendado
            self.assertTrue( len(response.context['usuarios']) == 2) # Pepa should be filtered out
    
        def test_filter_accepted_mate(self):
            c= Client()
            c.login(username='Pepe', password= 'asdfg')
            response=c.get(reverse('homepage'))
            #Comprombamos que antes de hacer mate con un usuario nos salen 3 en total
            self.assertTrue( len(response.context['usuarios']) == 3)
            Mate.objects.create(userEntrada=self.userPepe_auth, userSalida=self.userJuan_auth, mate=True)
            response=c.get(reverse('homepage'))
            #Comprobamos que tras hacer mate con un usuario ese ya no nos aparece como usuario recomendado
            self.assertTrue( len(response.context['usuarios']) == 2) # Juan should be filtered out
    
        def test_homepage_filter_user_sms_not_validated(self):
            sms_false_user = User.objects.create_user(username='sms_false_candidate_filter', password='password')
            Usuario.objects.create(usuario=sms_false_user, fecha_nacimiento=date(2001, 1, 1), estudios="Derecho", telefono="+34666777890", 
                                    lugar="Sevilla", genero='O', sms_validado=False)
    
            self.client.login(username='Pepe', password='asdfg') 
            response = self.client.get(reverse('homepage'))
            self.assertEqual(response.status_code, 200)
            if 'usuarios' in response.context and response.context['usuarios']:
                for recommended_user_profile_dict_key in response.context['usuarios']: # Key is actually the Usuario object
                    self.assertTrue(recommended_user_profile_dict_key.sms_validado)
    
    
    #Test de login
    class LoginTest(TestCase):
        def setUp(self):
            self.user_auth = User.objects.create_user(username='usuario_login_test', password='qwery') # Unique username
            tfn = "+34666777444"
            piso = Piso.objects.create(zona="Calle Marqués Luca de Tena 3 LoginTest", descripcion="Descripción de prueba 2") # Unique zona
            self.perfil = Usuario.objects.create(usuario=self.user_auth,piso=piso,fecha_nacimiento="2000-1-1",lugar="Sevilla",
                    genero='F',estudios="Informática", telefono=tfn, sms_validado=True)
            super().setUp()
    
    
        #Test de inicio de sesión con un usuario existente
        def test_login_positive(self):
            c = Client()
            response = c.post(reverse('login'), {'username': 'usuario_login_test', 'pass': 'qwery'}) # Use reverse, updated username
            user = auth.get_user(c)
            self.assertTrue(user.is_authenticated)
            self.assertRedirects(response, reverse('homepage'), status_code=302, # Use reverse for homepage
            target_status_code=200, fetch_redirect_response=True)
    
        def test_logout_positive(self):
            c = Client()
            c.post(reverse('login'), {'username': 'usuario_login_test', 'pass': 'qwery'}) # Use reverse
            response = c.get(reverse('logout')) # Use reverse
            user = auth.get_user(c)
            self.assertTrue(response.status_code == 302)
            self.assertFalse(user.is_authenticated)
    
    
    class ViewTestsSMSValidationAndBasicAccess(TestCase): # New Test Class for some view tests
        def setUp(self):
            self.user_sms_not_validated_auth = User.objects.create_user(username='sms_false_view_user', password='password')
            self.profile_sms_not_validated = Usuario.objects.create(
                usuario=self.user_sms_not_validated_auth,
                fecha_nacimiento="2000-03-01",
                lugar="SMSFalseCity",
                telefono="+34111222555", # Unique phone
                genero='F',
                sms_validado=False
            )
    
            self.regular_user_for_views_auth = User.objects.create_user(username='regular_view_user', password='password')
            self.regular_profile_for_views = Usuario.objects.create(
                usuario=self.regular_user_for_views_auth,
                fecha_nacimiento="1999-03-01",
                lugar="RegularCity",
                telefono="+34111222666", # Unique phone
                genero='M',
                sms_validado=True
            )
            # Ensure a Suscripcion object exists for payments view tests, if not created by other setups
            if not Suscripcion.objects.exists():
                Suscripcion.objects.create(id=10, name="Test Plan Basic", price=1.99, description="Basic plan for testing")
    
    
        def test_homepage_sms_not_validated(self):
            self.client.login(username=self.profile_sms_not_validated.usuario.username, password='password')
            response = self.client.get(reverse('homepage'))
            self.assertRedirects(response, reverse('registerSMS'))
    
        def test_homepage_user_piso_encontrado(self):
            self.regular_profile_for_views.piso_encontrado = True
            self.regular_profile_for_views.save()
            self.client.login(username=self.regular_profile_for_views.usuario.username, password='password')
            response = self.client.get(reverse('homepage'))
            self.assertEqual(response.status_code, 200)
            self.assertTemplateUsed(response, 'perfildesactivado.html')
    
        def test_payments_view_sms_not_validated(self):
            self.client.login(username=self.profile_sms_not_validated.usuario.username, password='password')
            response = self.client.get(reverse('payments')) # Assuming 'payments' is the URL name for pagos:pagos
            self.assertRedirects(response, reverse('registerSMS'))
    
        def test_payments_view_no_suscripcion_object(self):
            self.client.login(username=self.regular_profile_for_views.usuario.username, password='password')
            Suscripcion.objects.all().delete()
            response = self.client.get(reverse('payments'))
            self.assertEqual(response.status_code, 200)
            self.assertFalse(response.context.get('hay_suscripciones')) # Assuming context variable is 'hay_suscripciones'
    
        def test_profile_view_sms_not_validated(self):
            self.client.login(username=self.profile_sms_not_validated.usuario.username, password='password')
            response = self.client.get(reverse('profile')) 
            self.assertRedirects(response, reverse('registerSMS'))
    
        def test_detalles_perfil_logged_in_user_sms_not_validated(self):
            self.client.login(username=self.profile_sms_not_validated.usuario.username, password='password')
            response = self.client.get(reverse('detalles_perfil', args=[self.regular_profile_for_views.usuario.id]))
            self.assertRedirects(response, reverse('registerSMS'))
    
        def test_detalles_perfil_target_non_existent(self):
            self.client.login(username=self.regular_profile_for_views.usuario.username, password='password')
            non_existent_id = 999999
            response = self.client.get(reverse('detalles_perfil', args=[non_existent_id]))
            self.assertEqual(response.status_code, 404)
    
    
    class NotificacionesTest(TestCase):
    
        def setUp(self):
            self.user_notif1 = User.objects.create_user(username='usuario_notif1', password='qwery') # Unique
            self.user_notif2 = User.objects.create_user(username='usuario_notif2', password='qwery') # Unique
            self.user_notif3 = User.objects.create_user(username='usuario_notif3', password='qwery') # Unique
    
            tfn1 = "+34654234573"
            tfn2 = "+34666777211"
            tfn3 = "+34666777000"
            # Removed tfn4, tfn5 as they were not used for created users
    
            piso_pepe = Piso.objects.create(zona="Calle Marqués Luca de Tena 1 Notif", descripcion="Descripción de prueba 1")   # Unique
            piso_maria = Piso.objects.create(zona="Calle Marqués Luca de Tena 3 Notif", descripcion="Descripción de prueba 2")  # Unique
            piso_sara = Piso.objects.create(zona="Calle Marqués Luca de Tena 5 Notif", descripcion="Descripción de prueba 3")   # Unique
    
            fecha_premium=timezone.now() + timedelta(days=120)
            self.pepe = Usuario.objects.create(usuario=self.user_notif1, piso=piso_pepe, fecha_nacimiento=date(2000,12,31),lugar="Sevilla", fecha_premium=fecha_premium, telefono = tfn1, sms_validado = True)
            self.maria = Usuario.objects.create(usuario=self.user_notif2, piso=piso_maria, fecha_nacimiento=date(2000,12,30),lugar="Sevilla", telefono = tfn2, sms_validado = True)
            self.sara = Usuario.objects.create(usuario=self.user_notif3, piso=piso_sara,fecha_nacimiento=date(2000,12,29),lugar="Cádiz", telefono = tfn3, sms_validado = True)
    
            Mate.objects.create(mate=True,userEntrada=self.user_notif1, userSalida=self.user_notif2)
            Mate.objects.create(mate=True,userEntrada=self.user_notif2, userSalida=self.user_notif1)
    
            Mate.objects.create(mate=True,userEntrada=self.user_notif3, userSalida=self.user_notif1)
            Mate.objects.create(mate=True,userEntrada=self.user_notif3, userSalida=self.user_notif2)
            super().setUp()
    
    
        #El usuario "user" tiene un mate y como es premium tb tiene un like, la lista será de tamaño 2
        def test_notificaciones_premium(self):
            c = Client()
            response_user = c.post(reverse('login'), {'username': 'usuario_notif1', 'pass': 'qwery'}) # Use reverse
            response2 = c.get(reverse('homepage')) # Use reverse
            lista_mates = response2.context['notificaciones']
    
            self.assertTrue(len(lista_mates) == 2)
    
        #El usuario "user2" tiene un mate y un like, la lista será de tamaño 1 porque al no ser premium el like
        #no se le notifica
        def test_notificaciones_no_premium(self):
            c = Client()
            response = c.post(reverse('login'), {'username': 'usuario_notif2', 'pass': 'qwery'}) # Use reverse
            response2 = c.get(reverse('homepage')) # Use reverse
            lista_mates = response2.context['notificaciones']
            self.assertTrue(len(lista_mates) == 1)
    
        #El usuario "user3" no tiene ningún mate ni like, por lo que su lista de mates será de tamaño 0
        def test_notificaciones_false(self):
            c = Client()
            response = c.post(reverse('login'), {'username': 'usuario_notif3', 'pass': 'qwery'}) # Use reverse
            response2 = c.get(reverse('homepage')) # Use reverse
            lista_mates = response2.context['notificaciones']
            self.assertTrue(len(lista_mates) == 0)
    
        def test_notificaciones_list(self):
            c = Client()
            response = c.post(reverse('login'), {'username': 'usuario_notif3', 'pass': 'qwery'}) # Use reverse
            response2 = c.get(reverse('notifications_list')) # Assuming 'notifications_list' is the name for /notifications/
            self.assertTrue(response2.status_code == 200)
    
    def create_image(storage, filename, size=(100, 100), image_mode='RGB', image_format='PNG'):
    
        data = BytesIO()
        Image.new(image_mode, size).save(data, image_format)
        data.seek(0)
        if not storage:
            return data
        image_file = ContentFile(data.read())
        return storage.save(filename, image_file)
    
    
    class RegistroTest(TestCase):
    
        def setUp(self):
            # Use get_or_create for tags and aficiones to prevent errors on re-running tests
            Tag.objects.get_or_create(etiqueta='etiqueta1_reg') # Unique names
            Tag.objects.get_or_create(etiqueta='etiqueta2_reg')
            Tag.objects.get_or_create(etiqueta='etiqueta3_reg')
    
            Aficiones.objects.get_or_create(opcionAficiones='Aficion1_reg') # Unique names
            Aficiones.objects.get_or_create(opcionAficiones='Aficion2_reg')
            Aficiones.objects.get_or_create(opcionAficiones='Aficion3_reg')
    
            avatar = create_image(None, 'avatar_reg.png')
            avatar_file = SimpleUploadedFile('front_reg.png', avatar.getvalue())
    
            self.data = {
                'username':'usuariotest_reg', # Unique username
                'password':'passwordtest1',
                'password2': 'passwordtest1',
                'nombre': 'nombreprueba',
                'apellidos':'apellidosprueba',
                'correo':'prueba_reg@gmail.com', # Unique email
                'piso_encontrado': True,
                'zona_piso':'Ejemplo de zona Reg', # Slightly different data
                'telefono_usuario':'+34666777888', # Assume this is unique for the test run
                'foto_usuario': avatar_file,
                'fecha_nacimiento':'01-01-2000',
                'lugar':'Ejemplo de lugar Reg',
                'genero':'M',
                'tags': [t.id for t in Tag.objects.filter(etiqueta__contains='_reg')], # Ensure we get the correct tags
                'aficiones': [a.id for a in Aficiones.objects.filter(opcionAficiones__contains='_reg')], # Correct aficiones
                'terminos': True
            }
            super().setUp()
    
    
        def tearDown(self): # Clean up created users and profiles to avoid conflicts in other tests
            User.objects.filter(username__contains='_reg').delete()
            # Usuario objects should cascade delete or be handled if necessary
            super().tearDown()
    
    
        def test_register_positive(self):
            c = Client()
            response = c.post(reverse('register'), self.data) # Use reverse
            existe_usuario = Usuario.objects.filter(telefono=self.data['telefono_usuario']).exists()
            self.assertTrue(response.status_code == 302) # Should redirect to registerSMS
            self.assertRedirects(response, reverse('registerSMS'))
            self.assertTrue(existe_usuario)
            # No need to delete here if tearDown is implemented
    
        def test_username_already_exists(self):
            c = Client()
            # First registration
            User.objects.create_user(username='usuariotest_reg', password='passwordtest1') # Create the user that will cause conflict
    
            # Attempt to register with the same username
            self.data['correo'] = "correonuevo_reg@gmail.com"
            self.data['telefono_usuario'] = "+34666777333" # New phone
            response2 = c.post(reverse('register'), self.data)
    
            self.assertEqual(response2.status_code, 200) # Should re-render form with error
            self.assertIn('username', response2.context['form'].errors)
    
    
        def test_different_passwords(self):
            c = Client()
            self.data['password'] = "password01"
            self.data['password2'] = "password02"
            response = c.post(reverse('register'), self.data)
            num_usuarios = Usuario.objects.count() # Count existing Usuario objects
            self.assertTrue(num_usuarios == 0) # No new user should be created
            error = response.context['form'].errors['password2'][0]
            self.assertTrue(error == "Las contraseñas no coinciden")
    
    
        def test_email_already_exists(self):
            c = Client()
            # Create a user with the email that will cause a conflict
            User.objects.create_user(username='anotheruser_reg', password='somepassword', email='prueba_reg@gmail.com')
    
            self.data['username'] = "NewUsername_reg" # New username
            self.data['telefono_usuario'] = "+34666111222" # New phone
            avatar = create_image(None, 'avatar2_reg.png')
            avatar_file = SimpleUploadedFile('front2_reg.png', avatar.getvalue())
            self.data['foto_usuario'] = avatar_file
    
            response2 = c.post(reverse('register'), self.data)
            self.assertEqual(response2.status_code, 200) # Should re-render form
            self.assertIn('correo', response2.context['form'].errors)
            self.assertTrue("La dirección de correo electrónico ya está en uso" in response2.context['form'].errors['correo'])
    
    
        def test_phone_number_already_exists(self):
            c = Client()
            # Create a user with the phone number that will cause a conflict
            conflicting_user = User.objects.create_user(username='phoneconflictuser_reg', password='password')
            Usuario.objects.create(usuario=conflicting_user, telefono='+34666777888', fecha_nacimiento='2000-01-01', lugar='TestPlace', sms_validado=True)
    
            self.data['username'] = "NewUsernamePhone_reg" # New username
            self.data['correo'] = "newEmail_reg@gmail.com" # New email
            avatar = create_image(None, 'avatar3_reg.png')
            avatar_file = SimpleUploadedFile('front3_reg.png', avatar.getvalue())
            self.data['foto_usuario'] = avatar_file
    
            response2 = c.post(reverse('register'), self.data)
            self.assertEqual(response2.status_code, 200) # Re-render form
            self.assertIn('telefono_usuario', response2.context['form'].errors)
            self.assertTrue("El teléfono ya está en uso" in response2.context['form'].errors['telefono_usuario'])
    
    
        def test_select_at_least_three_tags(self):
            c = Client()
            tags_qs = Tag.objects.filter(etiqueta__contains='_reg')
            self.data['tags'] = [tags_qs[0].id, tags_qs[1].id] if tags_qs.count() >=2 else [] # Select only 2 or fewer
            response = c.post(reverse('register'), self.data)
            num_usuarios = Usuario.objects.count()
            self.assertTrue(num_usuarios == 0)
            error = response.context['form'].errors['tags'][0]
            self.assertTrue(error == "Por favor, elige al menos tres etiquetas que te definan")
    
        def test_select_at_least_three_aficiones(self):
            c = Client()
            aficiones_qs = Aficiones.objects.filter(opcionAficiones__contains='_reg')
            self.data['aficiones'] = [aficiones_qs[0].id, aficiones_qs[1].id] if aficiones_qs.count() >=2 else []
            response = c.post(reverse('register'), self.data)
            num_usuarios = Usuario.objects.count()
            error = response.context['form'].errors['aficiones'][0]
            self.assertTrue(num_usuarios == 0)
            self.assertTrue(error == "Por favor, elige al menos tres aficiones que te gusten")
    
        def test_see_terminos(self):
            c = Client()
            response = c.get(reverse('terminos')) # Assuming 'terminos' is the name for /register/terminos/
            self.assertTrue(response.status_code == 200)
    
    
    class EdicionTest(TestCase):
        def setUp(self):
            self.user_pepe_auth = User.objects.create_user(username="pepe_edit", password="asdfg") # Unique username
    
            tfn1 = "+34666777111" # This phone should be unique for this test user
    
            # Use get_or_create for tags and aficiones
            Tag.objects.get_or_create(etiqueta='etiqueta1_edit')
            Tag.objects.get_or_create(etiqueta='etiqueta2_edit')
            Tag.objects.get_or_create(etiqueta='etiqueta3_edit')
    
            Aficiones.objects.get_or_create(opcionAficiones='Aficion1_edit')
            Aficiones.objects.get_or_create(opcionAficiones='Aficion2_edit')
            Aficiones.objects.get_or_create(opcionAficiones='Aficion3_edit')
    
            piso_pepe = Piso.objects.create(zona="Calle Marqués Luca de Tena 3 Edit", descripcion="Descripción de prueba 2") # Unique
            self.pepe_profile = Usuario.objects.create(usuario=self.user_pepe_auth, fecha_nacimiento=date(2000,12,31),lugar="Sevilla", telefono=tfn1, piso=piso_pepe, sms_validado=True)
            self.pepe_profile.tags.set(Tag.objects.filter(etiqueta__contains='_edit'))
            self.pepe_profile.aficiones.set(Aficiones.objects.filter(opcionAficiones__contains='_edit'))
    
            avatar = create_image(None, 'insta_edit.png')
            SimpleUploadedFile('insta_edit.png', avatar.getvalue())
    
            self.data = {
                'actualizarPerfil': 'actualizarPerfil',
                'piso_encontrado': True,
                'zona_piso':'Ejemplo de zona Edit',
                'lugar':'Ejemplo de lugar Edit',
                'genero':'M',
                'descripcion': 'Ejemplo de descripción Edit',
                'desactivar_perfil': False,
                'tags': [t.id for t in Tag.objects.filter(etiqueta__contains='_edit')],
                'aficiones': [a.id for a in Aficiones.objects.filter(opcionAficiones__contains='_edit')],
            }
    
            tags_qs_edit = Tag.objects.filter(etiqueta__contains='_edit')
            lista_tags_wrong = [tags_qs_edit[0].id] if tags_qs_edit.exists() else []
    
    
            self.data_wrong = {
                'actualizarPerfil': 'actualizarPerfil',
                'zona_piso':'Ejemplo de zona Edit Wrong',
                'lugar':'', # Invalid
                'genero':'W', # Invalid
                'piso_encontrado': True,
                'descripcion': 'Ejemplo de descripción Edit Wrong',
                'tags': lista_tags_wrong, # Less than 3 tags
                'aficiones': [a.id for a in Aficiones.objects.filter(opcionAficiones__contains='_edit')],
            }
    
            self.data_password = {
                'actualizarContraseña': 'actualizarContraseña',
                'password':'ContraseñaDeEjemplo1',
                'password2':'ContraseñaDeEjemplo1',
            }
    
            self.data_password_wrong = {
                'actualizarContraseña': 'actualizarContraseña',
                'password':'ContraseñaEscritaMal12',
                'password2':'ContraseñaDeEjemplo12', # Mismatch
            }
    
            self.data_password_wrong_2 = {
                'actualizarContraseña': 'actualizarContraseña',
                'password':'corto', # Too short
                'password2':'corto',
            }
    
            avatar_photo = create_image(None, 'avatar_edit.png')
            avatar_file_photo = SimpleUploadedFile('front_edit.png', avatar_photo.getvalue())
    
            self.data_photo = {
                'actualizarFoto': 'actualizarFoto',
                'foto_usuario': avatar_file_photo,
            }
    
            self.data_photo_wrong = {
                'actualizarFoto': 'actualizarFoto',
                'foto_usuario': "EstoEsTextoYNoUnaFoto", # Invalid photo
            }
    
    
        def test_positive_edition_profile(self):
            c = Client()
            c.login(username='pepe_edit', pass='asdfg')
            response = c.post(reverse('profile'), self.data) # Use reverse
            usuario_update = Usuario.objects.get(telefono="+34666777111")
            self.assertTrue(usuario_update.piso.zona == self.data['zona_piso'])
            self.assertEqual(response.status_code, 302) # Successful profile update redirects
            self.assertRedirects(response, reverse('profile'))
    
    
        def test_negative_edition_profile(self):
            c = Client()
            c.login(username='pepe_edit', pass='asdfg')
            response = c.post(reverse('profile'), self.data_wrong)
            self.assertEqual(response.status_code, 200) # Form re-rendered with errors
            self.assertTrue(len(response.context['form_perfil'].errors) > 0)
    
    
        def test_positive_edition_password(self):
            c = Client()
            c.login(username='pepe_edit', pass='asdfg')
            response = c.post(reverse('profile'), self.data_password)
            self.assertEqual(response.status_code, 200) # Password change form is on the same page
            self.assertTrue('messageContraseña' in response.context) # Check for success message
            # Verify login with new password
            c.logout()
            response2 = c.post(reverse('login'), {'username':'pepe_edit', 'pass':'ContraseñaDeEjemplo1'})
            self.assertEqual(response2.status_code, 302) # Successful login redirects
            self.assertRedirects(response2, reverse('homepage'))
    
    
        def test_negative_edition_password(self): # Mismatched passwords
            c = Client()
            c.login(username='pepe_edit', pass='asdfg')
            response = c.post(reverse('profile'), self.data_password_wrong)
            self.assertEqual(response.status_code, 200)
            self.assertIn('password2', response.context['form_contraseña'].errors)
    
    
        def test_negative_edition_password_2(self): # Password too short
            c = Client()
            c.login(username='pepe_edit', pass='asdfg')
            response = c.post(reverse('profile'), self.data_password_wrong_2)
            self.assertEqual(response.status_code, 200)
            self.assertIn('password', response.context['form_contraseña'].errors)
    
        def test_positive_edition_photo(self):
            c = Client()
            c.login(username='pepe_edit', pass='asdfg')
            response = c.post(reverse('profile'), self.data_photo, format='multipart') # Ensure format for file uploads
            self.assertEqual(response.status_code, 302) # Successful photo update redirects
            self.assertRedirects(response, reverse('profile'))
            usuario_update = Usuario.objects.get(telefono="+34666777111")
            self.assertTrue(usuario_update.foto_usuario.name.startswith('fotosPerfil/')) # Check if photo path is updated
    
    
        def test_negative_edition_photo(self):
            c = Client()
            c.login(username='pepe_edit', pass='asdfg')
            response = c.post(reverse('profile'), self.data_photo_wrong, format='multipart')
            self.assertEqual(response.status_code, 200) # Form re-rendered
            self.assertIn('foto_usuario', response.context['form_foto'].errors)
    
    
    class EstadisticasTest(TestCase):
    
        def setUp(self):
            self.user_stats1 = User.objects.create_user(username='usuario_stats1', password='qwery') # Unique
            self.user_stats2 = User.objects.create_user(username='usuario_stats2', password='qwery') # Unique
            self.user_stats3 = User.objects.create_user(username='usuario_stats3', password='qwery') # Unique
            self.user_stats4 = User.objects.create_user(username='usuario_stats4', password='qwery') # Unique
    
            # Use get_or_create for Tags and Aficiones
            self.et1, _ = Tag.objects.get_or_create(etiqueta="Netflix_stats")
            self.et2, _ = Tag.objects.get_or_create(etiqueta="Chill_stats")
            self.et3, _ = Tag.objects.get_or_create(etiqueta="Fiesta_stats")
            self.af1, _ = Aficiones.objects.get_or_create(opcionAficiones="Moda_stats")
            self.af2, _ = Aficiones.objects.get_or_create(opcionAficiones="Cine_stats")
            self.af3, _ = Aficiones.objects.get_or_create(opcionAficiones="Leer_stats")
    
            piso_pepe = Piso.objects.create(zona="Calle Marqués Luca de Tena 1 Stats", descripcion="Descripción de prueba 1") # Unique
            piso_maria = Piso.objects.create(zona="Calle Marqués Luca de Tena 3 Stats", descripcion="Descripción de prueba 2") # Unique
            piso_sara = Piso.objects.create(zona="Calle Marqués Luca de Tena 5 Stats", descripcion="Descripción de prueba 3") # Unique
            piso_juan = Piso.objects.create(zona="Calle Marqués Luca de Tena 4 Stats", descripcion="Descripción de prueba ") # Unique
    
            fecha_premium=timezone.now() + timedelta(days=120)
            self.pepe_stats = Usuario.objects.create(usuario=self.user_stats1, piso=piso_pepe, fecha_nacimiento=date(2000,12,31),lugar="Sevilla", fecha_premium=fecha_premium, telefono='+34111222333', sms_validado=True)
            self.pepe_stats.tags.add(self.et1, self.et2, self.et3)
            self.pepe_stats.aficiones.add(self.af1)
    
            self.maria_stats = Usuario.objects.create(usuario=self.user_stats2, piso=piso_maria, fecha_nacimiento=date(2000,12,30),lugar="Sevilla",telefono='+34111222334', sms_validado=True)
            self.maria_stats.tags.add(self.et2)
            self.maria_stats.aficiones.add(self.af2)
    
            self.sara_stats = Usuario.objects.create(usuario=self.user_stats3, piso=piso_sara,fecha_nacimiento=date(2000,12,29),lugar="Cádiz",telefono='+34111222335', sms_validado=True)
            self.sara_stats.tags.add(self.et1, self.et3)
            self.sara_stats.aficiones.add(self.af2, self.af3)
    
            self.juan_stats = Usuario.objects.create(usuario=self.user_stats4, piso=piso_juan,fecha_nacimiento=date(2000,1,2),lugar="Granada",telefono='+34111222336', sms_validado=True)
            self.juan_stats.tags.add(self.et1, self.et2)
            self.juan_stats.aficiones.add(self.af1, self.af2, self.af3)
    
            Mate.objects.create(mate=True,userEntrada=self.user_stats1, userSalida=self.user_stats2, fecha_mate=timezone.now())
            Mate.objects.create(mate=True,userEntrada=self.user_stats2, userSalida=self.user_stats1, fecha_mate=timezone.now())
            Mate.objects.create(mate=True,userEntrada=self.user_stats3, userSalida=self.user_stats1, fecha_mate=timezone.now())
            Mate.objects.create(mate=True,userEntrada=self.user_stats4, userSalida=self.user_stats1, fecha_mate=timezone.now())
            super().setUp()
    
    
        def test_interacciones(self):
            c = Client()
            c.login(username='usuario_stats1', pass='qwery')
            response = c.get(reverse('stats')) # Use reverse
            interacciones = response.context['interacciones']
            self.assertEqual(interacciones, 3) # Pepe received likes from user2 (mutual), user3, user4
    
        def test_likes_mes(self):
            c = Client()
            c.login(username='usuario_stats1', pass='qwery')
            response = c.get(reverse('stats'))
            likeMes = response.context['lista'] # 'lista' seems to hold users who liked Pepe this month
            self.assertEqual(len(likeMes), 3) # user2, user3, user4
    
        def test_likes_hoy(self):
            c = Client()
            c.login(username='usuario_stats1', pass='qwery')
            response = c.get(reverse('stats'))
            dictLikeFecha = response.context['matesGrafica']
            today_str = datetime.today().strftime('%d/%m/%Y')
            self.assertEqual(dictLikeFecha.get(today_str, 0), 3) # All 3 likes were today
    
        def test_top_tags(self):
            c = Client()
            c.login(username='usuario_stats1', pass='qwery')
            response = c.get(reverse('stats'))
            dictTags = response.context['topTags']
            # User2: Chill_stats
            # User3: Netflix_stats, Fiesta_stats
            # User4: Netflix_stats, Chill_stats
            # Expected: Netflix_stats:2, Chill_stats:2, Fiesta_stats:1
            self.assertEqual(dictTags.get(self.et1.etiqueta, 0), 2)  # Netflix_stats
            self.assertEqual(dictTags.get(self.et2.etiqueta, 0), 2)  # Chill_stats
            self.assertEqual(dictTags.get(self.et3.etiqueta, 0), 1)  # Fiesta_stats
    
        def test_score_likes(self):
            c = Client()
            c.login(username='usuario_stats1', pass='qwery')
            response = c.get(reverse('stats'))
            scoreLikes = response.context['scoreLikes']
            # This depends heavily on the rs_score logic and the specific setup of user_stats3 and user_stats4
            # For now, just check if the keys exist
            self.assertIn(self.user_stats3, scoreLikes)
            self.assertIn(self.user_stats4, scoreLikes)
    
    class InfoTest(TestCase):
        def setUp(self):
            self.userMaria_auth = User.objects.create_user(username="Maria_info", password="asdfg") # Unique
            tfn2 = "+34666777222" # Should be unique for this user
            piso_maria = Piso.objects.create(zona="Calle Marqués Luca de Tena 3 Info", descripcion="Descripción de prueba 2") # Unique
            self.Maria_info = Usuario.objects.create(usuario=self.userMaria_auth, fecha_nacimiento=date(2000,12,30),lugar="Sevilla", piso=piso_maria, telefono=tfn2, sms_validado=True)
    
        def test_info(self):
            c = Client()
            c.login(username='Maria_info', pass='asdfg')
            response = c.get(reverse('info')) # Use reverse
            self.assertEqual(response.status_code, 200) # Use assertEqual
    
    class DetallesPerfil(TestCase):
        def setUp(self):
            self.userMaria_auth = User.objects.create_user(id=100,username="Maria_details", password="asdfg") # Unique
            self.maria_profile = Usuario.objects.create(id=100, usuario=self.userMaria_auth, fecha_nacimiento="2000-1-1",lugar="Sevilla", telefono="+34666777222",genero='F',estudios="Informática", sms_validado=True, fecha_premium=timezone.now() + relativedelta(months=1))
    
            self.userPepe_auth = User.objects.create_user(id=101,username='usuario2_details', password='qwery') # Unique
            self.pepe_profile = Usuario.objects.create(id=101, usuario=self.userPepe_auth, fecha_nacimiento="2000-1-1",lugar="Sevilla", telefono='+34111222333',genero='F',estudios="Informática", sms_validado=True)
    
            self.user_no_sms_auth = User.objects.create_user(id=102,username='noSMS_details', password='qwery') # Unique
            self.noSMS_profile = Usuario.objects.create(id=102, usuario=self.user_no_sms_auth, fecha_nacimiento="2000-1-1", lugar="Sevilla", telefono="+34666555444",genero='F',estudios="Informática", sms_validado=False)
    
            Mate.objects.create(mate=True,userEntrada=self.userPepe_auth, userSalida=self.userMaria_auth)
    
    
        #María entra en Make A Mate y ve el perfil de Pepe
        def test_positive_detalles(self):
            c = Client()
            c.login(username='Maria_details', pass='asdfg')
            pepe_id = self.pepe_profile.usuario.id
            response = c.get(reverse('detalles_perfil', args=[pepe_id])) # Use reverse
            self.assertEqual(response.status_code, 200)
    
        #Pepe entra en Make A Mate y no puede ver el perfil de María
        def test_negative_detalles_no_mate(self):
            c = Client()
            c.login(username='usuario2_details', pass='qwery')
            maria_id = self.maria_profile.usuario.id
            response = c.get(reverse('detalles_perfil', args=[maria_id]))
            self.assertEqual(response.status_code, 302) # Assert redirect
            self.assertRedirects(response, reverse('homepage')) # Check redirect target
    
    
        def test_negative_detalles_no_login(self):
            c = Client()
            maria_id = self.maria_profile.usuario.id
            response = c.get(reverse('detalles_perfil', args=[maria_id]))
            self.assertEqual(response.status_code, 302)
            self.assertRedirects(response, reverse('login') + "?next=" + reverse('detalles_perfil', args=[maria_id]))
    
    
        def test_negative_detalles_sms_no_validado(self): # Viewing user is SMS not validated
            c = Client()
            c.login(username='noSMS_details', password='qwery') # Log in as user with SMS not validated
            # Attempt to view Pepe's profile (who is SMS validated)
            response = c.get(reverse('detalles_perfil', args=[self.pepe_profile.usuario.id]))
            # This test should check if the *viewing* user (noSMS_details) gets redirected.
            self.assertRedirects(response, reverse('registerSMS'))
    
    
        def test_detalles_perfil_permission_no_mate_viewer_not_premium(self):
            userC_auth = User.objects.create_user(username='UserC_details_no_mate', password='password') 
            Usuario.objects.create(usuario=userC_auth, fecha_nacimiento="2000-1-1", lugar="Sevilla", telefono="+34666777230", genero='M', estudios="Historia", sms_validado=True) 
    
            self.client.login(username=userC_auth.username, password='password')
            pepe_user_id = self.pepe_profile.usuario.id
            response = self.client.get(reverse('detalles_perfil', args=[pepe_user_id]))
            self.assertRedirects(response, reverse('homepage'))
    
        def test_detalles_perfil_permission_received_like_viewer_is_premium(self):
            self.client.login(username='Maria_details', password='asdfg') # Maria is premium
            pepe_user_id = self.pepe_profile.usuario.id # Pepe liked Maria in setUp
            response = self.client.get(reverse('detalles_perfil', args=[pepe_user_id]))
            self.assertEqual(response.status_code, 200)
    
        def test_detalles_perfil_permission_mutual_mate_viewer_not_premium(self):
            userC_auth = User.objects.create_user(username='UserC_details_mutual', password='password') 
            Usuario.objects.create(usuario=userC_auth, fecha_nacimiento="2000-1-1", lugar="Sevilla", telefono="+34666777231", genero='M', estudios="Historia", sms_validado=True)
    
            Mate.objects.get_or_create(userEntrada=userC_auth, userSalida=self.pepe_profile.usuario, defaults={'mate':True})
            Mate.objects.get_or_create(userEntrada=self.pepe_profile.usuario, userSalida=userC_auth, defaults={'mate':True})
    
            self.client.login(username=userC_auth.username, password='password') # UserC is not premium by default
            response = self.client.get(reverse('detalles_perfil', args=[self.pepe_profile.usuario.id]))
            self.assertEqual(response.status_code, 200)
    
    
    Hardcoded Values

    Tests contain hardcoded user IDs, phone numbers, and other values that may not be reliable across different test environments or when tests run in different orders. This could lead to test failures due to database state dependencies.

            self.user1 = User.objects.create_user(id=0,username="us1", password='123') # Ensure password hashing
            self.user2 = User.objects.create_user(id=1,username="us2", password='123')
            self.user3 = User.objects.create_user(id=2,username="us3", password='123')
    
            premium_fin = timezone.now()+ relativedelta(months=1)
            self.perfil1 = Usuario.objects.create(usuario=self.user1,fecha_nacimiento=datetime.now(),lugar="Sevilla",telefono="+34655444333",
                                genero='F',estudios="Informática",fecha_premium=premium_fin,sms_validado=True)
            self.perfil2 = Usuario.objects.create(usuario=self.user2,fecha_nacimiento=datetime.now(),lugar="Sevilla",telefono="+34655444334",
                                genero='F',estudios="Informática",sms_validado=True)
            self.perfil3 = Usuario.objects.create(usuario=self.user3,fecha_nacimiento=datetime.now(),lugar="Sevilla",telefono="+34655444335",
                                genero='F',estudios="Informática",sms_validado=True)
    
            tag1, _ = Tag.objects.get_or_create(etiqueta="No fumador") # Use get_or_create to avoid issues on re-runs
            tag2, _ = Tag.objects.get_or_create(etiqueta="Mascotas")
    
            af1, _ = Aficiones.objects.get_or_create(opcionAficiones="Futbol")
            af2, _ = Aficiones.objects.get_or_create(opcionAficiones="Lolango")
    
            self.perfil1.tags.add(tag1)
            self.perfil1.aficiones.add(af1)  
            self.perfil2.tags.add(tag1)
            self.perfil2.aficiones.add(af1)
            self.perfil3.tags.add(tag2)
            self.perfil3.aficiones.add(af2)
            # Save after adding M2M fields
            self.perfil1.save()
            self.perfil2.save()
            self.perfil3.save()
    
    
        def test_perfect_score(self):
            score = rs_score(self.perfil1,self.perfil2)
    
            self.assertEqual(score,1.0)
    
        def test_perfect_score_premium(self):
            score = rs_score(self.perfil2,self.perfil1)
    
            self.assertEqual(score,1.0*BONUS_PREMIUM)
    
        def test_no_score(self):
            score = rs_score(self.perfil3,self.perfil1)
    
            self.assertEqual(score,0.0)
    
        def test_recommendation(self):
            self.client.login(username='us1', password='123')
    
            response=self.client.get(reverse('homepage')) # Use reverse
    
            self.assertEqual(list(response.context['usuarios'])[0], self.perfil2)
            self.assertEqual(response.status_code, 200)
    
        def test_dice_coefficient_no_common_interests(self):
            score = dice_coefficient(
                set(self.perfil1.tags.all()), set(self.perfil3.tags.all()),
                set(self.perfil1.aficiones.all()), set(self.perfil3.aficiones.all())
            )
            self.assertEqual(score, 0.0)
    
        def test_dice_coefficient_only_tags_common(self):
            user4 = User.objects.create_user(username='rec_user4_tags', password='123') 
            perfil4 = Usuario.objects.create(usuario=user4, fecha_nacimiento=datetime.now(), lugar="Sevilla", telefono="+34655444100", genero='F', estudios="Informática", sms_validado=True)
            perfil4.tags.add(Tag.objects.get(etiqueta="No fumador")) 
            perfil4.aficiones.add(Aficiones.objects.get(opcionAficiones="Lolango")) 
            perfil4.save()
            score = dice_coefficient(
                set(self.perfil1.tags.all()), set(perfil4.tags.all()),
                set(self.perfil1.aficiones.all()), set(perfil4.aficiones.all())
            )
            self.assertAlmostEqual(score, 2.0/3.0)
    
        def test_dice_coefficient_only_aficiones_common(self):
            user5 = User.objects.create_user(username='rec_user5_afic', password='123') 
            perfil5 = Usuario.objects.create(usuario=user5, fecha_nacimiento=datetime.now(), lugar="Sevilla", telefono="+34655444101", genero='F', estudios="Informática", sms_validado=True)
            perfil5.tags.add(Tag.objects.get(etiqueta="Mascotas")) 
            perfil5.aficiones.add(Aficiones.objects.get(opcionAficiones="Futbol")) 
            perfil5.save()
            score = dice_coefficient(
                set(self.perfil1.tags.all()), set(perfil5.tags.all()),
                set(self.perfil1.aficiones.all()), set(perfil5.aficiones.all())
            )
            self.assertAlmostEqual(score, 1.0/3.0) # Corrected expected score: 1 common aficion, 1 in p1, 2 in p5. (2*1)/(1+2) = 2/3. Tags: 0 common. (0+2/3)/2 = 1/3
    
        def test_dice_coefficient_one_user_no_interests(self):
            user_no_interest = User.objects.create_user(username='rec_no_interest_dice', password='123') 
            perfil_no_interest = Usuario.objects.create(usuario=user_no_interest, fecha_nacimiento=datetime.now(), lugar="Sevilla", telefono="+34655444102", genero='M', estudios="Bioquímica", sms_validado=True)
            perfil_no_interest.save()
            score = dice_coefficient(
                set(self.perfil1.tags.all()), set(perfil_no_interest.tags.all()),
                set(self.perfil1.aficiones.all()), set(perfil_no_interest.aficiones.all())
            )
            self.assertEqual(score, 0.0)
    
        def test_dice_coefficient_both_users_no_interests(self):
            user_no_interest1 = User.objects.create_user(username='rec_no_interest1_dice', password='123') 
            perfil_no_interest1 = Usuario.objects.create(usuario=user_no_interest1, fecha_nacimiento=datetime.now(), lugar="Sevilla", telefono="+34655444103", genero='M', estudios="Bioquímica", sms_validado=True)
            perfil_no_interest1.save()
            user_no_interest2 = U...

    @qodo-code-review
    Copy link

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Impact
    Possible issue
    Fix incorrect dice coefficient calculation

    The expected score calculation in the comment is incorrect. With 1 common
    aficion between perfil1 and perfil5, the dice coefficient for aficiones is
    (2*1)/(1+1) = 1.0, not 2/3. The final average should be (0+1.0)/2 = 0.5.

    MakeAMate/principal/tests.py [145-155]

     def test_dice_coefficient_only_aficiones_common(self):
         user5 = User.objects.create_user(username='rec_user5_afic', password='123') 
         perfil5 = Usuario.objects.create(usuario=user5, fecha_nacimiento=datetime.now(), lugar="Sevilla", telefono="+34655444101", genero='F', estudios="Informática", sms_validado=True)
         perfil5.tags.add(Tag.objects.get(etiqueta="Mascotas")) 
         perfil5.aficiones.add(Aficiones.objects.get(opcionAficiones="Futbol")) 
         perfil5.save()
         score = dice_coefficient(
             set(self.perfil1.tags.all()), set(perfil5.tags.all()),
             set(self.perfil1.aficiones.all()), set(perfil5.aficiones.all())
         )
    -    self.assertAlmostEqual(score, 1.0/3.0) # Corrected expected score: 1 common aficion, 1 in p1, 2 in p5. (2*1)/(1+2) = 2/3. Tags: 0 common. (0+2/3)/2 = 1/3
    +    self.assertAlmostEqual(score, 0.5) # Corrected: 1 common aficion, dice = (2*1)/(1+1) = 1.0. Tags: 0 common, dice = 0. Average: (0+1.0)/2 = 0.5
    • Apply / Chat
    Suggestion importance[1-10]: 7

    __

    Why: The suggestion correctly identifies a logical error in the test case's expected value. The existing code asserts an incorrect score based on a flawed calculation in the comment. The improved code provides the correct assertion, making the test valid and reliable.

    Medium
    Handle potential DoesNotExist exception safely

    The test assumes a Mate object will exist after rejection, but this may cause a
    DoesNotExist exception if the view deletes the mate record instead of updating
    it. Use filter().first() or handle the potential exception.

    MakeAMate/principal/tests.py [341-351]

     def test_reject_already_mated(self):
         # user3 has already mated with user1
    -    self.client.login(username='us1', password='123') # user1 trying to reject user3
    +    self.client.login(username='us1', password='123')
         data = {'id_us': self.user3.id}
         response = self.client.post(reverse('reject_mate'), data, format='json')
         json_resp = response.json()
    -    # Rejecting an existing mate should probably be successful in terms of API call,
    -    # but the mate status would become False.
         self.assertTrue(json_resp['success'])
    -    mate_after_reject = Mate.objects.get(userEntrada=self.user1, userSalida=self.user3)
    -    self.assertFalse(mate_after_reject.mate)
    +    mate_after_reject = Mate.objects.filter(userEntrada=self.user1, userSalida=self.user3).first()
    +    if mate_after_reject:
    +        self.assertFalse(mate_after_reject.mate)
    • Apply / Chat
    Suggestion importance[1-10]: 7

    __

    Why: The suggestion correctly points out that Mate.objects.get() could raise a DoesNotExist exception if the view logic deletes the object upon rejection. Using filter().first() is a more robust way to handle this, preventing the test from failing unexpectedly and making it more resilient to implementation changes.

    Medium
    General
    Remove commented alternatives in test

    The test has inconsistent logic with commented alternatives that make it unclear
    what behavior is expected. Remove the commented code and implement a single,
    clear test assertion based on the actual consumer behavior.

    MakeAMate/chat/tests.py [285-296]

     async def test_consumer_connect_non_existent_room(self):
         communicator = WebsocketCommunicator(ChatConsumer.as_asgi(), "/ws/chat/nonexistentroomconsumer/")
         communicator.scope['user'] = self.user_consumer1
    -    # This test assumes that URL routing or middleware handles non-existent rooms before the consumer's connect() is called,
    -    # or that the consumer's connect() method correctly raises an error like ChatRoom.DoesNotExist if it tries to fetch the room.
    -    # If using Django Channels routing, the connection might simply be rejected if no route matches.
    -    # If the consumer's connect method is reached and tries to fetch a non-existent room:
    -    with self.assertRaises(ChatRoom.DoesNotExist): # Or a more specific error if the consumer handles it differently
    +    with self.assertRaises(ChatRoom.DoesNotExist):
              await communicator.connect()
    -    # If the connection is just closed without an exception bubbling up to here:
    -    # connected, _ = await communicator.connect()
    -    # self.assertFalse(connected)
    • Apply / Chat
    Suggestion importance[1-10]: 3

    __

    Why: The suggestion correctly identifies that the test test_consumer_connect_non_existent_room contains confusing comments and a commented-out alternative implementation. Removing them improves code clarity and maintainability. The impact is minor, focusing on readability.

    Low
    Remove verbose explanatory comments

    The test contains extensive commented explanations that create confusion about
    expected behavior. Remove the verbose comments and keep only the essential
    assertion to improve code clarity.

    MakeAMate/pagos/tests.py [91-100]

     def test_payment_complete_user_not_login(self):
    -    # c= Client()
    -    response=self.client.get(reverse("pagos:complete")) # Use reverse
    -    # For unauthenticated users, views often redirect to login or raise 403 if @login_required is used.
    -    # If it's a 404, it implies the URL might not be found or is protected in a way that leads to 404 for anon.
    -    # Let's assume it redirects to login if @login_required is used.
    -    # If the view truly returns 404 for not logged in, then self.assertEqual(response.status_code, 404) is correct.
    -    # Given other tests redirect to login, that's more standard for unauthorized access.
    -    # However, the original test expects 404. I will keep it, but it's unusual.
    +    response=self.client.get(reverse("pagos:complete"))
         self.assertEqual(response.status_code, 404)
    • Apply / Chat
    Suggestion importance[1-10]: 3

    __

    Why: The suggestion correctly points out verbose comments in test_payment_complete_user_not_login that discuss alternative behaviors, making the test's purpose unclear. Removing these comments improves readability, which is a minor but positive change.

    Low
    Remove confusing test logic comments

    The test logic is inconsistent and contains confusing comments about uncertain
    behavior. The test should have clear expectations based on the actual business
    logic rather than assumptions.

    MakeAMate/principal/tests.py [325-338]

     def test_accept_already_mated(self):
         # user3 has already mated with user1 (mate=True in setUp for user3 -> user1)
    -    self.client.login(username='us1', password='123') # user1 trying to accept user3
    +    self.client.login(username='us1', password='123')
         data = {'id_us': self.user3.id}
         response = self.client.post(reverse('accept_mate'), data, format='json')
         json_resp = response.json()
    -    # This behavior depends on the view logic: can you re-accept an existing mate?
    -    # Assuming the current logic might prevent re-mating or creating duplicates.
    -    # If it's allowed and 'mate_achieved' becomes true, this test needs adjustment.
    -    # For now, let's assume it might be false if the mate already exists from user1's side.
    -    # The original test had user4 (who had a false mate with user1) trying to accept user1 (id=0)
    -    # Let's stick to user1 accepting user3, where user3 already liked user1.
    -    self.assertTrue(json_resp['success']) # It should be a successful operation to form the mutual mate
    +    # When user1 accepts user3 who already liked user1, it should create a mutual mate
    +    self.assertTrue(json_resp['success'])
         self.assertTrue(json_resp['mate_achieved'])
    • Apply / Chat
    Suggestion importance[1-10]: 2

    __

    Why: The suggestion proposes removing comments that express uncertainty about the test's behavior. While this improves clarity, it's a minor code style improvement with low impact on functionality. The test's assertions are already correct according to the PR's logic.

    Low
    • More

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Projects

    None yet

    Development

    Successfully merging this pull request may close these issues.

    1 participant