# -*- coding: utf-8 -*- from odoo.tests.common import TransactionCase from odoo.exceptions import ValidationError from hypothesis import given, strategies as st, settings class TestRatingModel(TransactionCase): """Test cases for the extended rating model""" def setUp(self): super(TestRatingModel, self).setUp() self.Rating = self.env['rating.rating'] self.Partner = self.env['res.partner'] self.User = self.env['res.users'] # Create test partner and user for rating context self.test_partner = self.Partner.create({ 'name': 'Test Customer', 'email': 'test@example.com', }) self.test_user = self.User.create({ 'name': 'Test User', 'login': 'testuser', 'email': 'testuser@example.com', }) def _create_rating(self, rating_value): """Helper method to create a rating with given value""" return self.Rating.create({ 'rating': rating_value, 'partner_id': self.test_partner.id, 'rated_partner_id': self.test_user.partner_id.id, 'res_model': 'res.partner', 'res_id': self.test_partner.id, }) # Feature: helpdesk-rating-five-stars, Property 4: Rating persistence within valid range @given(rating_value=st.floats(min_value=1.0, max_value=5.0, allow_nan=False, allow_infinity=False)) @settings(max_examples=100, deadline=None) def test_property_valid_rating_persistence(self, rating_value): """ Property 4: Rating persistence within valid range For any submitted rating between 1-5, the stored Rating_Value in the database should be between 1 and 5. Validates: Requirements 1.5 """ # Create rating with valid value rating = self._create_rating(rating_value) # Verify the rating was stored self.assertTrue(rating.id, "Rating should be created") # Verify the stored value is within valid range self.assertGreaterEqual(rating.rating, 1.0, f"Rating value {rating.rating} should be >= 1.0") self.assertLessEqual(rating.rating, 5.0, f"Rating value {rating.rating} should be <= 5.0") # Verify the value matches what we set self.assertAlmostEqual(rating.rating, rating_value, places=2, msg=f"Stored rating {rating.rating} should match input {rating_value}") def test_property_zero_rating_allowed(self): """ Property 4 (edge case): Zero rating is allowed A rating value of 0 (no rating) should be allowed and stored correctly. Validates: Requirements 1.5 """ rating = self._create_rating(0.0) self.assertTrue(rating.id, "Rating with value 0 should be created") self.assertEqual(rating.rating, 0.0, "Rating value should be exactly 0") # Feature: helpdesk-rating-five-stars, Property 16: Invalid rating values rejected @given(rating_value=st.one_of( st.floats(min_value=-1000.0, max_value=-0.01, allow_nan=False, allow_infinity=False), # Negative values st.floats(min_value=0.01, max_value=0.99, allow_nan=False, allow_infinity=False), # Between 0 and 1 st.floats(min_value=5.01, max_value=1000.0, allow_nan=False, allow_infinity=False) # Above 5 )) @settings(max_examples=100, deadline=None) def test_property_invalid_rating_rejection(self, rating_value): """ Property 16: Invalid rating values rejected For any rating value outside the 1-5 range (or 0), the system should reject the submission and raise a ValidationError or database error. Validates: Requirements 7.1 """ # Attempt to create rating with invalid value should raise an exception # This can be either ValidationError (from Python) or database constraint error with self.assertRaises(Exception, msg=f"Rating value {rating_value} should be rejected"): self._create_rating(rating_value) def test_rating_stars_computation(self): """Test that star computation works correctly for various ratings""" test_cases = [ (0, 0, 5), (1, 1, 4), (2, 2, 3), (3, 3, 2), (4, 4, 1), (5, 5, 0), (1.4, 1, 4), # rounds down (1.5, 2, 3), # rounds up (2.6, 3, 2), # rounds up ] for rating_value, expected_filled, expected_empty in test_cases: rating = self._create_rating(rating_value) self.assertEqual(rating.rating_stars_filled, expected_filled, f"Rating {rating_value} should have {expected_filled} filled stars") self.assertEqual(rating.rating_stars_empty, expected_empty, f"Rating {rating_value} should have {expected_empty} empty stars") def test_rating_stars_html_generation(self): """Test that HTML generation works correctly""" rating = self._create_rating(3.0) html = rating._get_rating_stars_html() # Check that HTML contains the expected structure self.assertIn('o_rating_stars', html, "HTML should contain rating stars class") self.assertIn('★', html, "HTML should contain filled star character") self.assertIn('☆', html, "HTML should contain empty star character") # Check that we have 3 filled and 2 empty stars filled_count = html.count('★') empty_count = html.count('☆') self.assertEqual(filled_count, 3, "Should have 3 filled stars") self.assertEqual(empty_count, 2, "Should have 2 empty stars")