Skip to content

Commit

Permalink
Complete tick tests on Windows and Android
Browse files Browse the repository at this point in the history
  • Loading branch information
mhsmith committed Jan 7, 2023
1 parent ccf3ed9 commit 37b6e1f
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 19 deletions.
7 changes: 7 additions & 0 deletions android/tests_backend/widgets/slider.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ def position(self):
def change(self, position):
self.native.setProgress(self._min + round(position * (self._max - self._min)))

@property
def tick_count(self):
# The Android backend does not currently display tick marks, so assume that it's
# in continuous mode if the range is very large.
range = self._max - self._min + 1
return range if range < 10000 else None

@property
def _min(self):
return 0 if (Build.VERSION.SDK_INT < 26) else self.native.getMin()
Expand Down
2 changes: 2 additions & 0 deletions core/src/toga/widgets/slider.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ def tick_count(self):

@tick_count.setter
def tick_count(self, tick_count):
if (tick_count is not None) and (tick_count < 2):
raise ValueError("Tick count must be at least 2")
self._tick_count = tick_count
self._impl.set_tick_count(tick_count)

Expand Down
63 changes: 52 additions & 11 deletions core/tests/widgets/test_slider.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ def test_widget_created(self):
self.assertEqual(self.slider._impl.interface, self.slider)
self.assertActionPerformed(self.slider, "create Slider")

def test_get_value_invokes_impl_method(self):
self.slider.value
self.assertValueGet(self.slider, "value")

def test_set_value_between_min_and_max(self):
value = 30
tick_value = 4
Expand Down Expand Up @@ -64,16 +60,43 @@ def test_set_value_to_be_too_big(self):
self.slider.value = self.max_val + 1
self.assert_slider_value(tick_value=self.default_tick, value=self.value)

def test_set_tick_value_between_min_and_max(self):
value = 30
tick_value = 4
self.slider.tick_value = tick_value
self.assert_slider_value(
value=value, tick_value=tick_value, on_change_call_count=1
)

def test_set_tick_value_to_be_min(self):
self.slider.tick_value = 1
self.assert_slider_value(
value=self.min_val, tick_value=1, on_change_call_count=1
)

def test_set_tick_value_to_be_max(self):
self.slider.tick_value = self.tick_count
self.assert_slider_value(
value=self.max_val, tick_value=self.tick_count, on_change_call_count=1
)

def test_set_tick_value_to_be_too_small(self):
with self.assertRaises(ValueError):
self.slider.tick_value = 0
self.assert_slider_value(tick_value=self.default_tick, value=self.value)

def test_set_tick_value_to_be_too_big(self):
with self.assertRaises(ValueError):
self.slider.tick_value = self.max_val + 1
self.slider.tick_value = self.tick_count + 1
self.assert_slider_value(tick_value=self.default_tick, value=self.value)

def test_tick_value_without_tick_count(self):
self.slider.tick_count = None
with self.assertRaisesRegex(
ValueError, "Cannot set tick value when tick count is None"
):
self.slider.tick_value = 4

def test_new_value_is_None(self):
self.slider.value = None
self.assertEqual(self.slider.value, 50)
Expand Down Expand Up @@ -122,9 +145,12 @@ def test_working_range_values(self):
self.assert_set_range(0, 100)
self.assert_set_range(100, 1000)

def test_false_range(self):
with self.assertRaises(ValueError):
self.slider.range = (100, 0)
def test_invalid_range_values(self):
for range in [(0, 0), (100, 0)]:
with self.assertRaisesRegex(
ValueError, "Range min value has to be smaller than max value."
):
self.slider.range = range

def test_set_enabled_with_working_values(self):
self.assertEqual(self.slider.enabled, self.enabled)
Expand All @@ -136,9 +162,24 @@ def test_get_tick_count(self):
self.assertEqual(self.tick_count, tick_count)

def test_set_tick_count(self):
new_tick_count = 5
self.slider.tick_count = new_tick_count
self.assertValueSet(self.slider, "tick_count", new_tick_count)
self.slider.range = (10, 110)
for tick_count, tick_step, tick_value in [
(None, None, None),
(11, 10, 5), # Exactly 50
(5, 25, 3), # Round up to 60
(4, 100 / 3, 2), # Round down to 43.333
(2, 100, 1), # Round down to 10 (2 is the minimum possible tick_count)
]:
self.slider.tick_count = tick_count
self.assertEqual(self.slider.tick_count, tick_count)
self.assertValueSet(self.slider, "tick_count", tick_count)
self.assertEqual(self.slider.tick_step, tick_step)
self.assert_slider_value(tick_value=tick_value, value=self.value)

def test_set_tick_count_too_small(self):
for tick_count in [1, 0, -1]:
with self.assertRaisesRegex(ValueError, "Tick count must be at least 2"):
self.slider.tick_count = tick_count

def test_focus(self):
self.slider.focus()
Expand Down
18 changes: 12 additions & 6 deletions testbed/tests/widgets/test_slider.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ async def test_init(widget, probe, on_change):
on_change.assert_not_called()


# Bounds checks are covered by core tests.
async def test_value(widget, probe, on_change):
for scale in SCALES:
widget.range = (0, scale)
Expand All @@ -54,12 +55,11 @@ async def test_change(widget, probe, on_change):
on_change.assert_called_once_with(widget)


# Bounds checks and the `min` property are covered by the core tests.
async def test_min(widget, probe, on_change):
for min in POSITIONS[:-1]:
on_change.reset_mock()
range = (min, 1)
assert_set_get(widget, "range", range)
assert (widget.min, widget.max) == range
assert_set_get(widget, "range", (min, 1))

if min <= 0.5:
# The existing value is in the range, so it should not change.
Expand All @@ -73,13 +73,12 @@ async def test_min(widget, probe, on_change):
on_change.assert_called_once_with(widget)


# Bounds checks and the `max` property are covered by the core tests.
async def test_max(widget, probe, on_change):
# If the existing value is in the range, it should not change.
for max in POSITIONS[-1:0:-1]:
on_change.reset_mock()
range = (0, max)
assert_set_get(widget, "range", range)
assert (widget.min, widget.max) == range
assert_set_get(widget, "range", (0, max))

if max >= 0.5:
# The existing value is in the range, so it should not change.
Expand All @@ -91,3 +90,10 @@ async def test_max(widget, probe, on_change):
assert widget.value == max
assert probe.position == 1
on_change.assert_called_once_with(widget)


# All other tick functionality is covered by the core tests.
async def test_ticks(widget, probe):
for tick_count in [2, None, 10]:
widget.tick_count = tick_count
assert probe.tick_count == tick_count
14 changes: 12 additions & 2 deletions winforms/tests_backend/widgets/slider.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import System.Windows.Forms
from System.Windows.Forms import TickStyle, TrackBar

from .base import SimpleProbe


class SliderProbe(SimpleProbe):
native_class = System.Windows.Forms.TrackBar
native_class = TrackBar

@property
def position(self):
Expand All @@ -13,6 +13,16 @@ def position(self):
def change(self, position):
self.native.Value = self._min + round(position * (self._max - self._min))

@property
def tick_count(self):
tick_style = self.native.TickStyle
if tick_style == TickStyle.BottomRight:
return self._max - self._min + 1
elif tick_style == getattr(TickStyle, "None"):
return None
else:
raise ValueError(f"unknown TickStyle {tick_style}")

@property
def _min(self):
return self.native.Minimum
Expand Down

0 comments on commit 37b6e1f

Please sign in to comment.