364 lines
14 KiB
Python
364 lines
14 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
from odoo.tests.common import TransactionCase
|
|
from hypothesis import given, strategies as st, settings
|
|
|
|
|
|
class TestHoverFeedback(TransactionCase):
|
|
"""
|
|
Test cases for hover feedback behavior
|
|
|
|
Property 3: Hover provides visual feedback
|
|
For any star hovered, the system should display visual feedback
|
|
indicating the potential rating.
|
|
|
|
Validates: Requirements 1.4
|
|
"""
|
|
|
|
def setUp(self):
|
|
super(TestHoverFeedback, self).setUp()
|
|
# We'll test the hover feedback logic that would be used in the frontend
|
|
# The logic is: when hovering, hoverValue is set, and displayValue uses hoverValue
|
|
self.max_stars = 5
|
|
|
|
def _simulate_hover(self, hover_star, selected_star=0):
|
|
"""
|
|
Simulate the hover logic from the JavaScript component.
|
|
|
|
This mirrors the logic in rating_stars.js:
|
|
- onStarHover sets state.hoverValue = starNumber
|
|
- displayValue returns hoverValue || selectedValue
|
|
- isStarFilled checks if starNumber <= displayValue
|
|
|
|
Args:
|
|
hover_star: The star number being hovered (1-5)
|
|
selected_star: The currently selected star (0-5)
|
|
|
|
Returns:
|
|
dict with:
|
|
- hover_value: The hover value set
|
|
- display_value: The value used for display
|
|
- filled_stars: List of star numbers that should be filled
|
|
"""
|
|
hover_value = hover_star
|
|
display_value = hover_value if hover_value > 0 else selected_star
|
|
|
|
# Stars that should be filled during hover
|
|
filled_stars = list(range(1, int(display_value) + 1)) if display_value > 0 else []
|
|
|
|
return {
|
|
'hover_value': hover_value,
|
|
'display_value': display_value,
|
|
'filled_stars': filled_stars,
|
|
}
|
|
|
|
def _simulate_no_hover(self, selected_star=0):
|
|
"""
|
|
Simulate when not hovering (mouse leave).
|
|
|
|
This mirrors the logic in rating_stars.js:
|
|
- onStarLeave sets state.hoverValue = 0
|
|
- displayValue returns hoverValue || selectedValue (so just selectedValue)
|
|
|
|
Args:
|
|
selected_star: The currently selected star (0-5)
|
|
|
|
Returns:
|
|
dict with:
|
|
- hover_value: The hover value (0)
|
|
- display_value: The value used for display
|
|
- filled_stars: List of star numbers that should be filled
|
|
"""
|
|
hover_value = 0
|
|
display_value = selected_star
|
|
|
|
# Stars that should be filled when not hovering
|
|
filled_stars = list(range(1, int(display_value) + 1)) if display_value > 0 else []
|
|
|
|
return {
|
|
'hover_value': hover_value,
|
|
'display_value': display_value,
|
|
'filled_stars': filled_stars,
|
|
}
|
|
|
|
def _verify_hover_feedback_property(self, hover_star, selected_star=0):
|
|
"""
|
|
Verify that hovering over a star provides visual feedback.
|
|
|
|
The property states: For any star hovered, the system should display
|
|
visual feedback indicating the potential rating.
|
|
|
|
Visual feedback means:
|
|
1. The hovered star and all stars before it should be filled
|
|
2. The display should show the hover value, not the selected value
|
|
3. Stars after the hovered star should not be filled
|
|
|
|
Args:
|
|
hover_star: The star number being hovered (1-5)
|
|
selected_star: The currently selected star (0-5)
|
|
"""
|
|
result = self._simulate_hover(hover_star, selected_star)
|
|
|
|
# Property 1: Hover value should be set to the hovered star
|
|
self.assertEqual(
|
|
result['hover_value'],
|
|
hover_star,
|
|
f"Hovering star {hover_star} should set hover_value to {hover_star}"
|
|
)
|
|
|
|
# Property 2: Display value should use hover value (visual feedback)
|
|
self.assertEqual(
|
|
result['display_value'],
|
|
hover_star,
|
|
f"When hovering star {hover_star}, display should show {hover_star}, "
|
|
f"not selected value {selected_star}"
|
|
)
|
|
|
|
# Property 3: All stars from 1 to hover_star should be filled (visual feedback)
|
|
expected_filled = list(range(1, hover_star + 1))
|
|
self.assertEqual(
|
|
result['filled_stars'],
|
|
expected_filled,
|
|
f"Hovering star {hover_star} should fill stars {expected_filled}, "
|
|
f"but got {result['filled_stars']}"
|
|
)
|
|
|
|
# Property 4: The number of filled stars should equal the hovered star
|
|
self.assertEqual(
|
|
len(result['filled_stars']),
|
|
hover_star,
|
|
f"Hovering star {hover_star} should fill exactly {hover_star} stars, "
|
|
f"but {len(result['filled_stars'])} were filled"
|
|
)
|
|
|
|
# Property 5: All filled stars should be <= hovered star
|
|
for star in result['filled_stars']:
|
|
self.assertLessEqual(
|
|
star,
|
|
hover_star,
|
|
f"Filled star {star} should be <= hovered star {hover_star}"
|
|
)
|
|
|
|
# Property 6: All stars > hovered star should NOT be filled
|
|
for star in range(hover_star + 1, self.max_stars + 1):
|
|
self.assertNotIn(
|
|
star,
|
|
result['filled_stars'],
|
|
f"Star {star} should NOT be filled when hovering star {hover_star}"
|
|
)
|
|
|
|
# Feature: helpdesk-rating-five-stars, Property 3: Hover provides visual feedback
|
|
@given(
|
|
hover_star=st.integers(min_value=1, max_value=5),
|
|
selected_star=st.integers(min_value=0, max_value=5)
|
|
)
|
|
@settings(max_examples=100, deadline=None)
|
|
def test_property_hover_provides_visual_feedback(self, hover_star, selected_star):
|
|
"""
|
|
Property 3: Hover provides visual feedback
|
|
|
|
For any star hovered (1-5) and any selected star (0-5), the system
|
|
should display visual feedback indicating the potential rating.
|
|
|
|
This tests that:
|
|
1. Hovering sets the hover value
|
|
2. The display uses the hover value (not selected value)
|
|
3. The correct stars are filled to show the potential rating
|
|
4. Visual feedback is independent of current selection
|
|
|
|
Validates: Requirements 1.4
|
|
"""
|
|
self._verify_hover_feedback_property(hover_star, selected_star)
|
|
|
|
def test_hover_feedback_overrides_selection(self):
|
|
"""
|
|
Test that hover feedback overrides the current selection
|
|
"""
|
|
# Test case 1: Selected 2 stars, hover over 4 stars
|
|
result = self._simulate_hover(hover_star=4, selected_star=2)
|
|
self.assertEqual(result['display_value'], 4,
|
|
"Hover should override selection")
|
|
self.assertEqual(len(result['filled_stars']), 4,
|
|
"Should show 4 filled stars when hovering, not 2")
|
|
|
|
# Test case 2: Selected 5 stars, hover over 1 star
|
|
result = self._simulate_hover(hover_star=1, selected_star=5)
|
|
self.assertEqual(result['display_value'], 1,
|
|
"Hover should override selection")
|
|
self.assertEqual(len(result['filled_stars']), 1,
|
|
"Should show 1 filled star when hovering, not 5")
|
|
|
|
# Test case 3: Selected 3 stars, hover over 3 stars (same)
|
|
result = self._simulate_hover(hover_star=3, selected_star=3)
|
|
self.assertEqual(result['display_value'], 3,
|
|
"Hover should show same value")
|
|
self.assertEqual(len(result['filled_stars']), 3,
|
|
"Should show 3 filled stars")
|
|
|
|
def test_hover_feedback_no_selection(self):
|
|
"""
|
|
Test hover feedback when no star is selected
|
|
"""
|
|
for hover_star in range(1, self.max_stars + 1):
|
|
result = self._simulate_hover(hover_star=hover_star, selected_star=0)
|
|
|
|
self.assertEqual(
|
|
result['display_value'],
|
|
hover_star,
|
|
f"Hovering star {hover_star} with no selection should show {hover_star}"
|
|
)
|
|
|
|
self.assertEqual(
|
|
len(result['filled_stars']),
|
|
hover_star,
|
|
f"Should show {hover_star} filled stars"
|
|
)
|
|
|
|
def test_hover_feedback_removal(self):
|
|
"""
|
|
Test that visual feedback is removed when hover ends
|
|
"""
|
|
# Test with various selected values
|
|
for selected_star in range(0, self.max_stars + 1):
|
|
result = self._simulate_no_hover(selected_star=selected_star)
|
|
|
|
# When not hovering, display should show selected value
|
|
self.assertEqual(
|
|
result['display_value'],
|
|
selected_star,
|
|
f"When not hovering, should display selected value {selected_star}"
|
|
)
|
|
|
|
# Hover value should be 0
|
|
self.assertEqual(
|
|
result['hover_value'],
|
|
0,
|
|
"Hover value should be 0 when not hovering"
|
|
)
|
|
|
|
# Filled stars should match selected value
|
|
expected_filled = list(range(1, selected_star + 1)) if selected_star > 0 else []
|
|
self.assertEqual(
|
|
result['filled_stars'],
|
|
expected_filled,
|
|
f"When not hovering with selection {selected_star}, "
|
|
f"should show {expected_filled} filled stars"
|
|
)
|
|
|
|
def test_hover_feedback_all_stars(self):
|
|
"""
|
|
Test hover feedback for each individual star
|
|
"""
|
|
for hover_star in range(1, self.max_stars + 1):
|
|
result = self._simulate_hover(hover_star=hover_star, selected_star=0)
|
|
|
|
# Verify correct number of stars filled
|
|
self.assertEqual(
|
|
len(result['filled_stars']),
|
|
hover_star,
|
|
f"Hovering star {hover_star} should fill {hover_star} stars"
|
|
)
|
|
|
|
# Verify the filled stars are exactly [1, 2, ..., hover_star]
|
|
expected = list(range(1, hover_star + 1))
|
|
self.assertEqual(
|
|
result['filled_stars'],
|
|
expected,
|
|
f"Hovering star {hover_star} should fill stars {expected}"
|
|
)
|
|
|
|
def test_hover_feedback_boundary_cases(self):
|
|
"""
|
|
Test boundary cases for hover feedback
|
|
"""
|
|
# Minimum hover (star 1)
|
|
result = self._simulate_hover(hover_star=1, selected_star=0)
|
|
self.assertEqual(len(result['filled_stars']), 1,
|
|
"Hovering star 1 should fill 1 star")
|
|
self.assertEqual(result['filled_stars'], [1],
|
|
"Only star 1 should be filled")
|
|
|
|
# Maximum hover (star 5)
|
|
result = self._simulate_hover(hover_star=5, selected_star=0)
|
|
self.assertEqual(len(result['filled_stars']), 5,
|
|
"Hovering star 5 should fill 5 stars")
|
|
self.assertEqual(result['filled_stars'], [1, 2, 3, 4, 5],
|
|
"All stars should be filled")
|
|
|
|
# Hover with maximum selection
|
|
result = self._simulate_hover(hover_star=1, selected_star=5)
|
|
self.assertEqual(result['display_value'], 1,
|
|
"Hover should override even maximum selection")
|
|
self.assertEqual(len(result['filled_stars']), 1,
|
|
"Should show hover feedback, not selection")
|
|
|
|
def test_hover_feedback_consistency(self):
|
|
"""
|
|
Test that hover feedback is consistent across multiple calls
|
|
"""
|
|
for hover_star in range(1, self.max_stars + 1):
|
|
for selected_star in range(0, self.max_stars + 1):
|
|
# Call multiple times with same values
|
|
result1 = self._simulate_hover(hover_star, selected_star)
|
|
result2 = self._simulate_hover(hover_star, selected_star)
|
|
result3 = self._simulate_hover(hover_star, selected_star)
|
|
|
|
# All results should be identical
|
|
self.assertEqual(result1, result2,
|
|
"Hover feedback should be consistent")
|
|
self.assertEqual(result2, result3,
|
|
"Hover feedback should be consistent")
|
|
self.assertEqual(result1, result3,
|
|
"Hover feedback should be consistent")
|
|
|
|
def test_hover_feedback_sequential(self):
|
|
"""
|
|
Test hover feedback when hovering over stars sequentially
|
|
"""
|
|
selected_star = 2
|
|
|
|
# Simulate hovering over each star in sequence
|
|
for hover_star in range(1, self.max_stars + 1):
|
|
result = self._simulate_hover(hover_star, selected_star)
|
|
|
|
# Each hover should show the correct feedback
|
|
self.assertEqual(
|
|
result['display_value'],
|
|
hover_star,
|
|
f"Hovering star {hover_star} should display {hover_star}"
|
|
)
|
|
|
|
# Verify filled stars match hover position
|
|
expected_filled = list(range(1, hover_star + 1))
|
|
self.assertEqual(
|
|
result['filled_stars'],
|
|
expected_filled,
|
|
f"Hovering star {hover_star} should fill {expected_filled}"
|
|
)
|
|
|
|
def test_hover_feedback_independence(self):
|
|
"""
|
|
Test that hover feedback is independent of selection
|
|
"""
|
|
# For each possible selection
|
|
for selected_star in range(0, self.max_stars + 1):
|
|
# For each possible hover
|
|
for hover_star in range(1, self.max_stars + 1):
|
|
result = self._simulate_hover(hover_star, selected_star)
|
|
|
|
# Hover feedback should always show hover_star, regardless of selection
|
|
self.assertEqual(
|
|
result['display_value'],
|
|
hover_star,
|
|
f"Hover feedback should show {hover_star}, "
|
|
f"not selection {selected_star}"
|
|
)
|
|
|
|
# Number of filled stars should match hover, not selection
|
|
self.assertEqual(
|
|
len(result['filled_stars']),
|
|
hover_star,
|
|
f"Should fill {hover_star} stars when hovering, "
|
|
f"regardless of selection {selected_star}"
|
|
)
|