You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
544 lines
22 KiB
544 lines
22 KiB
|
6 months ago
|
import pytest
|
||
|
|
import datetime
|
||
|
|
from unittest.mock import Mock, patch
|
||
|
|
|
||
|
|
from TermTk.TTkCore.constant import TTkK
|
||
|
|
from TermTk.TTkCore.TTkTerm.inputkey import TTkKeyEvent
|
||
|
|
from TermTk.TTkWidgets.datetime_time import TTkTime, _FieldSelected
|
||
|
|
|
||
|
|
|
||
|
|
class TestTTkTimeKeyEvent:
|
||
|
|
|
||
|
|
def setup_method(self):
|
||
|
|
"""Set up test fixtures before each test method."""
|
||
|
|
self.time_widget = TTkTime(time=datetime.time(12, 30, 45))
|
||
|
|
|
||
|
|
def test_tab_navigation_forward(self):
|
||
|
|
"""Test forward Tab navigation through fields."""
|
||
|
|
# Start with NONE, tab to HOURS
|
||
|
|
self.time_widget._state.selected = _FieldSelected.NONE
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Tab, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget._state.selected == _FieldSelected.HOURS
|
||
|
|
|
||
|
|
# From HOURS to MINUTES
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Tab, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget._state.selected == _FieldSelected.MINUTES
|
||
|
|
|
||
|
|
# From MINUTES to SECONDS
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Tab, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget._state.selected == _FieldSelected.SECONDS
|
||
|
|
|
||
|
|
# From SECONDS should return False (end of navigation)
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Tab, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
assert result is False
|
||
|
|
|
||
|
|
def test_tab_navigation_backward(self):
|
||
|
|
"""Test backward Tab navigation (Shift+Tab) through fields."""
|
||
|
|
# Start with NONE, shift+tab to SECONDS
|
||
|
|
self.time_widget._state.selected = _FieldSelected.NONE
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Tab, "", TTkK.ShiftModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget._state.selected == _FieldSelected.SECONDS
|
||
|
|
|
||
|
|
# From SECONDS to MINUTES
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Tab, "", TTkK.ShiftModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget._state.selected == _FieldSelected.MINUTES
|
||
|
|
|
||
|
|
# From MINUTES to HOURS
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Tab, "", TTkK.ShiftModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget._state.selected == _FieldSelected.HOURS
|
||
|
|
|
||
|
|
# From HOURS should return False
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Tab, "", TTkK.ShiftModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
assert result is False
|
||
|
|
|
||
|
|
def test_arrow_key_navigation_right(self):
|
||
|
|
"""Test right arrow navigation through fields."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.HOURS
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Right, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget._state.selected == _FieldSelected.MINUTES
|
||
|
|
|
||
|
|
def test_arrow_key_navigation_left(self):
|
||
|
|
"""Test left arrow navigation through fields."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.MINUTES
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Left, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget._state.selected == _FieldSelected.HOURS
|
||
|
|
|
||
|
|
def test_up_arrow_increment_hours(self):
|
||
|
|
"""Test up arrow increments hours field."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.HOURS
|
||
|
|
initial_time = self.time_widget.time()
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Up, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
new_time = self.time_widget.time()
|
||
|
|
expected_hour = (initial_time.hour + 1) % 24
|
||
|
|
assert new_time.hour == expected_hour
|
||
|
|
|
||
|
|
def test_up_arrow_increment_minutes(self):
|
||
|
|
"""Test up arrow increments minutes field."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.MINUTES
|
||
|
|
initial_time = self.time_widget.time()
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Up, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
new_time = self.time_widget.time()
|
||
|
|
# Minutes increment by 1, wrapping at 60
|
||
|
|
expected_minutes = (initial_time.minute + 1) % 60
|
||
|
|
assert new_time.minute == expected_minutes
|
||
|
|
|
||
|
|
def test_up_arrow_increment_seconds(self):
|
||
|
|
"""Test up arrow increments seconds field."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.SECONDS
|
||
|
|
initial_time = self.time_widget.time()
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Up, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
new_time = self.time_widget.time()
|
||
|
|
expected_seconds = (initial_time.second + 1) % 60
|
||
|
|
assert new_time.second == expected_seconds
|
||
|
|
|
||
|
|
def test_down_arrow_decrement_hours(self):
|
||
|
|
"""Test down arrow decrements hours field."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.HOURS
|
||
|
|
initial_time = self.time_widget.time()
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Down, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
new_time = self.time_widget.time()
|
||
|
|
expected_hour = (initial_time.hour - 1) % 24
|
||
|
|
assert new_time.hour == expected_hour
|
||
|
|
|
||
|
|
def test_down_arrow_decrement_minutes(self):
|
||
|
|
"""Test down arrow decrements minutes field."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.MINUTES
|
||
|
|
initial_time = self.time_widget.time()
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Down, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
new_time = self.time_widget.time()
|
||
|
|
expected_minutes = (initial_time.minute - 1) % 60
|
||
|
|
assert new_time.minute == expected_minutes
|
||
|
|
|
||
|
|
def test_down_arrow_decrement_seconds(self):
|
||
|
|
"""Test down arrow decrements seconds field."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.SECONDS
|
||
|
|
initial_time = self.time_widget.time()
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Down, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
new_time = self.time_widget.time()
|
||
|
|
expected_seconds = (initial_time.second - 1) % 60
|
||
|
|
assert new_time.second == expected_seconds
|
||
|
|
|
||
|
|
def test_digit_input_hours_first_digit(self):
|
||
|
|
"""Test entering first digit in hours field."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.HOURS
|
||
|
|
self.time_widget._state.secondDigit = False
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.Character, "2", "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget.time().hour == 2
|
||
|
|
assert self.time_widget._state.secondDigit is True
|
||
|
|
|
||
|
|
def test_digit_input_hours_second_digit(self):
|
||
|
|
"""Test entering second digit in hours field."""
|
||
|
|
self.time_widget.setTime(datetime.time(2, 30, 45))
|
||
|
|
self.time_widget._state.selected = _FieldSelected.HOURS
|
||
|
|
self.time_widget._state.secondDigit = True
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.Character, "3", "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget.time().hour == 23
|
||
|
|
assert self.time_widget._state.secondDigit is False
|
||
|
|
|
||
|
|
def test_digit_input_hours_max_validation(self):
|
||
|
|
"""Test hours field validates maximum value (23)."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.HOURS
|
||
|
|
self.time_widget._state.secondDigit = True
|
||
|
|
self.time_widget.setTime(datetime.time(2, 30, 45))
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.Character, "9", "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
# Should be clamped to 23
|
||
|
|
assert self.time_widget.time().hour == 23
|
||
|
|
|
||
|
|
def test_digit_input_minutes_first_digit(self):
|
||
|
|
"""Test entering first digit in minutes field."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.MINUTES
|
||
|
|
self.time_widget._state.secondDigit = False
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.Character, "5", "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget.time().minute == 5
|
||
|
|
assert self.time_widget._state.secondDigit is True
|
||
|
|
|
||
|
|
def test_digit_input_minutes_second_digit(self):
|
||
|
|
"""Test entering second digit in minutes field."""
|
||
|
|
self.time_widget.setTime(datetime.time(12, 5, 45))
|
||
|
|
self.time_widget._state.selected = _FieldSelected.MINUTES
|
||
|
|
self.time_widget._state.secondDigit = True
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.Character, "7", "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget.time().minute == 57
|
||
|
|
assert self.time_widget._state.secondDigit is False
|
||
|
|
|
||
|
|
def test_digit_input_minutes_validation(self):
|
||
|
|
"""Test minutes field validates maximum value (59)."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.MINUTES
|
||
|
|
self.time_widget._state.secondDigit = True
|
||
|
|
self.time_widget.setTime(datetime.time(12, 6, 45))
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.Character, "9", "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
# Should be clamped to 59
|
||
|
|
assert self.time_widget.time().minute == 59
|
||
|
|
|
||
|
|
def test_digit_input_seconds_first_digit(self):
|
||
|
|
"""Test entering first digit in seconds field."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.SECONDS
|
||
|
|
self.time_widget._state.secondDigit = False
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.Character, "3", "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget.time().second == 3
|
||
|
|
assert self.time_widget._state.secondDigit is True
|
||
|
|
|
||
|
|
def test_digit_input_seconds_second_digit(self):
|
||
|
|
"""Test entering second digit in seconds field."""
|
||
|
|
self.time_widget.setTime(datetime.time(12, 30, 4))
|
||
|
|
self.time_widget._state.selected = _FieldSelected.SECONDS
|
||
|
|
self.time_widget._state.secondDigit = True
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.Character, "2", "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget.time().second == 42
|
||
|
|
assert self.time_widget._state.secondDigit is False
|
||
|
|
|
||
|
|
def test_digit_input_seconds_validation(self):
|
||
|
|
"""Test seconds field validates maximum value (59)."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.SECONDS
|
||
|
|
self.time_widget._state.secondDigit = True
|
||
|
|
self.time_widget.setTime(datetime.time(12, 30, 6))
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.Character, "9", "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
# Should be clamped to 59
|
||
|
|
assert self.time_widget.time().second == 59
|
||
|
|
|
||
|
|
def test_delete_key_clears_hours(self):
|
||
|
|
"""Test Delete key clears hours field."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.HOURS
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Delete, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget.time().hour == 0
|
||
|
|
|
||
|
|
def test_delete_key_clears_minutes(self):
|
||
|
|
"""Test Delete key clears minutes field."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.MINUTES
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Delete, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget.time().minute == 0
|
||
|
|
|
||
|
|
def test_delete_key_clears_seconds(self):
|
||
|
|
"""Test Delete key clears seconds field."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.SECONDS
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Delete, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget.time().second == 0
|
||
|
|
|
||
|
|
def test_backspace_key_clears_hours(self):
|
||
|
|
"""Test Backspace key clears hours field."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.HOURS
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Backspace, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget.time().hour == 0
|
||
|
|
|
||
|
|
def test_backspace_key_clears_minutes(self):
|
||
|
|
"""Test Backspace key clears minutes field."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.MINUTES
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Backspace, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget.time().minute == 0
|
||
|
|
|
||
|
|
def test_backspace_key_clears_seconds(self):
|
||
|
|
"""Test Backspace key clears seconds field."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.SECONDS
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Backspace, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget.time().second == 0
|
||
|
|
|
||
|
|
def test_enter_key_deselects_field(self):
|
||
|
|
"""Test Enter key deselects current field."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.HOURS
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Enter, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget._state.selected == _FieldSelected.NONE
|
||
|
|
|
||
|
|
def test_time_overflow_hours_23_to_0(self):
|
||
|
|
"""Test hour overflow (23:59:59 + 1 hour -> 0:59:59)."""
|
||
|
|
self.time_widget.setTime(datetime.time(23, 59, 59))
|
||
|
|
self.time_widget._state.selected = _FieldSelected.HOURS
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Up, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
# Should wrap to 0:59:59 (next day boundary)
|
||
|
|
assert self.time_widget.time().hour == 23
|
||
|
|
assert self.time_widget.time().minute == 59
|
||
|
|
assert self.time_widget.time().second == 59
|
||
|
|
|
||
|
|
def test_time_underflow_hours_0_to_23(self):
|
||
|
|
"""Test hour underflow (0:0:0 - 1 hour -> 23:0:0)."""
|
||
|
|
self.time_widget.setTime(datetime.time(0, 0, 0))
|
||
|
|
self.time_widget._state.selected = _FieldSelected.HOURS
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Down, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
# Should wrap to 23:0:0 (previous day boundary)
|
||
|
|
assert self.time_widget.time().hour == 0
|
||
|
|
assert self.time_widget.time().minute == 0
|
||
|
|
assert self.time_widget.time().second == 0
|
||
|
|
|
||
|
|
def test_time_overflow_minutes_59_to_0(self):
|
||
|
|
"""Test minute overflow (12:59:30 + 1 minute -> 13:0:30)."""
|
||
|
|
self.time_widget.setTime(datetime.time(12, 59, 30))
|
||
|
|
self.time_widget._state.selected = _FieldSelected.MINUTES
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Up, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
# Should increment hour and reset minutes
|
||
|
|
assert self.time_widget.time().hour == 13
|
||
|
|
assert self.time_widget.time().minute == 0
|
||
|
|
assert self.time_widget.time().second == 30
|
||
|
|
|
||
|
|
def test_time_overflow_seconds_59_to_0(self):
|
||
|
|
"""Test second overflow (12:30:59 + 1 second -> 12:31:0)."""
|
||
|
|
self.time_widget.setTime(datetime.time(12, 30, 59))
|
||
|
|
self.time_widget._state.selected = _FieldSelected.SECONDS
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Up, "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
# Should increment minute and reset seconds
|
||
|
|
assert self.time_widget.time().hour == 12
|
||
|
|
assert self.time_widget.time().minute == 31
|
||
|
|
assert self.time_widget.time().second == 0
|
||
|
|
|
||
|
|
# def test_no_field_selected_up_down_returns_false(self):
|
||
|
|
# """Test up/down keys return False when no field is selected."""
|
||
|
|
# self.time_widget._state.selected = _FieldSelected.NONE
|
||
|
|
|
||
|
|
# evt_up = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Up, "", TTkK.NoModifier)
|
||
|
|
# result_up = self.time_widget.keyEvent(evt_up)
|
||
|
|
# assert result_up is False
|
||
|
|
|
||
|
|
# evt_down = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Down, "", TTkK.NoModifier)
|
||
|
|
# result_down = self.time_widget.keyEvent(evt_down)
|
||
|
|
# assert result_down is False
|
||
|
|
|
||
|
|
def test_non_digit_character_returns_true(self):
|
||
|
|
"""Test non-digit character input returns True but doesn't change time."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.HOURS
|
||
|
|
initial_time = self.time_widget.time()
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.Character, "a", "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget.time() == initial_time
|
||
|
|
|
||
|
|
def test_digit_input_no_field_selected(self):
|
||
|
|
"""Test digit input when no field is selected returns True but no change."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.NONE
|
||
|
|
initial_time = self.time_widget.time()
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.Character, "5", "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget.time() == initial_time
|
||
|
|
|
||
|
|
@patch.object(TTkTime, 'update')
|
||
|
|
def test_update_called_on_navigation(self, mock_update):
|
||
|
|
"""Test that update is called during navigation."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.NONE
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Tab, "", TTkK.NoModifier)
|
||
|
|
self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
mock_update.assert_called()
|
||
|
|
|
||
|
|
@patch.object(TTkTime, 'update')
|
||
|
|
def test_update_called_on_time_change(self, mock_update):
|
||
|
|
"""Test that update is called when time changes."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.HOURS
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Up, "", TTkK.NoModifier)
|
||
|
|
self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
mock_update.assert_called()
|
||
|
|
|
||
|
|
def test_second_digit_reset_on_special_keys(self):
|
||
|
|
"""Test that secondDigit is reset when special keys are pressed."""
|
||
|
|
self.time_widget._state.secondDigit = True
|
||
|
|
self.time_widget._state.selected = _FieldSelected.HOURS
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Up, "", TTkK.NoModifier)
|
||
|
|
self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert self.time_widget._state.secondDigit is False
|
||
|
|
|
||
|
|
def test_second_digit_toggle_on_digit_input(self):
|
||
|
|
"""Test that secondDigit toggles correctly on digit input."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.HOURS
|
||
|
|
self.time_widget._state.secondDigit = False
|
||
|
|
|
||
|
|
# First digit input
|
||
|
|
evt = TTkKeyEvent(TTkK.Character, "1", "", TTkK.NoModifier)
|
||
|
|
self.time_widget.keyEvent(evt)
|
||
|
|
assert self.time_widget._state.secondDigit is True
|
||
|
|
|
||
|
|
# Second digit input
|
||
|
|
evt = TTkKeyEvent(TTkK.Character, "5", "", TTkK.NoModifier)
|
||
|
|
self.time_widget.keyEvent(evt)
|
||
|
|
assert self.time_widget._state.secondDigit is False
|
||
|
|
|
||
|
|
def test_unknown_special_key_returns_false(self):
|
||
|
|
"""Test unknown special keys return False."""
|
||
|
|
self.time_widget._state.selected = _FieldSelected.HOURS
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, 9999, "", TTkK.NoModifier) # Unknown key
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is False
|
||
|
|
|
||
|
|
def test_time_changed_signal_emission(self):
|
||
|
|
"""Test that timeChanged signal is emitted when time changes."""
|
||
|
|
signal_received = []
|
||
|
|
|
||
|
|
def slot(time_value):
|
||
|
|
signal_received.append(time_value)
|
||
|
|
|
||
|
|
self.time_widget.timeChanged.connect(slot)
|
||
|
|
self.time_widget._state.selected = _FieldSelected.HOURS
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.SpecialKey, TTkK.Key_Up, "", TTkK.NoModifier)
|
||
|
|
self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert len(signal_received) == 1
|
||
|
|
assert isinstance(signal_received[0], datetime.time)
|
||
|
|
|
||
|
|
def test_boundary_digit_input_hours(self):
|
||
|
|
"""Test digit input at hours boundaries."""
|
||
|
|
# Test hour 24 gets clamped to 23
|
||
|
|
self.time_widget._state.selected = _FieldSelected.HOURS
|
||
|
|
self.time_widget._state.secondDigit = True
|
||
|
|
self.time_widget.setTime(datetime.time(2, 30, 45))
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.Character, "4", "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget.time().hour == 23 # Should be clamped
|
||
|
|
|
||
|
|
def test_boundary_digit_input_minutes(self):
|
||
|
|
"""Test digit input at minutes boundaries."""
|
||
|
|
# Test minute 60 gets clamped to 59
|
||
|
|
self.time_widget._state.selected = _FieldSelected.MINUTES
|
||
|
|
self.time_widget._state.secondDigit = True
|
||
|
|
self.time_widget.setTime(datetime.time(12, 6, 45))
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.Character, "0", "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget.time().minute == 59 # Should be clamped
|
||
|
|
|
||
|
|
def test_boundary_digit_input_seconds(self):
|
||
|
|
"""Test digit input at seconds boundaries."""
|
||
|
|
# Test second 60 gets clamped to 59
|
||
|
|
self.time_widget._state.selected = _FieldSelected.SECONDS
|
||
|
|
self.time_widget._state.secondDigit = True
|
||
|
|
self.time_widget.setTime(datetime.time(12, 30, 6))
|
||
|
|
|
||
|
|
evt = TTkKeyEvent(TTkK.Character, "0", "", TTkK.NoModifier)
|
||
|
|
result = self.time_widget.keyEvent(evt)
|
||
|
|
|
||
|
|
assert result is True
|
||
|
|
assert self.time_widget.time().second == 59 # Should be clamped
|