Skip to content

Commit

Permalink
Add test probe and tests for Cocoa Box.
Browse files Browse the repository at this point in the history
  • Loading branch information
freakboy3742 committed Apr 3, 2023
1 parent d79bf87 commit 511d602
Show file tree
Hide file tree
Showing 18 changed files with 159 additions and 11 deletions.
18 changes: 10 additions & 8 deletions cocoa/src/toga_cocoa/widgets/base.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from abc import abstractmethod

from toga.colors import TRANSPARENT
from toga_cocoa.colors import native_color
from toga_cocoa.constraints import Constraints
Expand Down Expand Up @@ -30,13 +32,12 @@ def container(self):
@container.setter
def container(self, container):
if self.container:
if container:
raise RuntimeError("Already have a container")
else:
# existing container should be removed
self.constraints.container = None
self._container = None
self.native.removeFromSuperview()
assert container is None, "Widget already has a container"

# Existing container should be removed
self.constraints.container = None
self._container = None
self.native.removeFromSuperview()
elif container:
# setting container
self._container = container
Expand Down Expand Up @@ -118,5 +119,6 @@ def add_constraints(self):
def refresh(self):
self.rehint()

@abstractmethod
def rehint(self):
pass
...
6 changes: 6 additions & 0 deletions cocoa/src/toga_cocoa/widgets/optioncontainer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from travertino.size import at_least

from toga_cocoa.libs import NSObject, NSTabView, NSTabViewItem, objc_method
from toga_cocoa.window import CocoaViewport

Expand Down Expand Up @@ -112,3 +114,7 @@ def get_current_tab_index(self):

def set_current_tab_index(self, current_tab_index):
self.native.selectTabViewItemAtIndex(current_tab_index)

def rehint(self):
self.interface.intrinsic.width = at_least(self.interface._MIN_WIDTH)
self.interface.intrinsic.height = at_least(self.interface._MIN_HEIGHT)
6 changes: 6 additions & 0 deletions cocoa/src/toga_cocoa/widgets/splitcontainer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from travertino.size import at_least

from toga_cocoa.libs import NSObject, NSSize, NSSplitView, objc_method
from toga_cocoa.window import CocoaViewport

Expand Down Expand Up @@ -79,3 +81,7 @@ def set_direction(self, value):

def on_resize(self):
pass

def rehint(self):
self.interface.intrinsic.width = at_least(self.interface._MIN_WIDTH)
self.interface.intrinsic.height = at_least(self.interface._MIN_HEIGHT)
18 changes: 18 additions & 0 deletions cocoa/tests_backend/widgets/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ def assert_container(self, container):
else:
raise ValueError(f"cannot find {self.native} in {container_native}")

def assert_not_contained(self):
assert self.widget._impl.container is None
assert self.native.superview is None
assert self.native.window is None

def assert_alignment(self, expected):
assert self.alignment == expected

Expand Down Expand Up @@ -58,6 +63,16 @@ def width(self):
def height(self):
return self.native.frame.size.height

def assert_layout(self, size, position):
# Widget is contained and in a window.
assert self.widget._impl.container is not None
assert self.native.superview is not None
assert self.native.window is not None

# size and position is as expected.
assert (self.native.frame.size.width, self.native.frame.size.height) == size
assert (self.native.frame.origin.x, self.native.frame.origin.y) == position

def assert_width(self, min_width, max_width):
assert (
min_width <= self.width <= max_width
Expand All @@ -80,3 +95,6 @@ def background_color(self):

def press(self):
self.native.performClick(None)

def has_focus(self):
return self.native.window.firstResponder == self.native
4 changes: 4 additions & 0 deletions core/src/toga/widgets/activityindicator.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ def enabled(self, value):
# ActivityIndicator doesn't have a "disabled" state
pass

def focus(self):
"No-op; ActivityIndicator cannot accept input focus"
pass

@property
def is_running(self):
"""Determine if the activity indicator is currently running.
Expand Down
2 changes: 1 addition & 1 deletion core/src/toga/widgets/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,5 +247,5 @@ def refresh_sublayouts(self):
child.refresh_sublayouts()

def focus(self):
"""Give this widget to have the input focus."""
"""Give this widget the input focus."""
self._impl.focus()
4 changes: 4 additions & 0 deletions core/src/toga/widgets/box.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@ def __init__(
def enabled(self, value):
# Box doesn't have a "disabled" state
pass

def focus(self):
"No-op; ActivityIndicator cannot accept input focus"
pass
4 changes: 4 additions & 0 deletions core/src/toga/widgets/divider.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ def enabled(self, value):
# Divider doesn't have a "disabled" state
pass

def focus(self):
"No-op; Divider cannot accept input focus"
pass

@property
def direction(self):
"""The direction in which the visual separator will be drawn.
Expand Down
4 changes: 4 additions & 0 deletions core/src/toga/widgets/label.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ def __init__(

self.text = text

def focus(self):
"No-op; Label cannot accept input focus"
pass

@property
def text(self):
"""The text displayed by the label.
Expand Down
3 changes: 3 additions & 0 deletions core/src/toga/widgets/optioncontainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,9 @@ def _insert(self, index, text, widget, enabled=True):


class OptionContainer(Widget):
_MIN_WIDTH = 100
_MIN_HEIGHT = 100

"""The option container widget.
Args:
Expand Down
3 changes: 3 additions & 0 deletions core/src/toga/widgets/splitcontainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ class SplitContainer(Widget):
flex (boolean): Should the content expand when the widget is resized. (optional)
"""

_MIN_HEIGHT = 100
_MIN_WIDTH = 100

HORIZONTAL = False
VERTICAL = True

Expand Down
40 changes: 39 additions & 1 deletion testbed/tests/widgets/properties.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from pytest import approx

import toga
from toga.colors import RED, TRANSPARENT, color as named_color
from toga.fonts import BOLD, FANTASY, ITALIC, NORMAL, SERIF, SYSTEM
from toga.style.pack import COLUMN

from ..assertions import assert_color
from ..data import COLORS, TEXTS
from .probe import get_probe

# An upper bound for widths
MAX_WIDTH = 2000
Expand Down Expand Up @@ -47,6 +49,42 @@ async def test_enable_noop(widget, probe):
assert probe.enabled


# async def test_hidden(widget, probe):


async def test_focus(widget, probe):
"The widget can be given focus"
# Add a separate widget that can take take focus
other = toga.Button("Other")
widget.parent.add(other)
other_probe = get_probe(other)

other.focus()
assert not probe.has_focus()
assert other_probe.has_focus()

widget.focus()
assert probe.has_focus()
assert not other_probe.has_focus()


async def test_focus_noop(widget, probe):
"The widget cannot be given focus"
# Add a separate widget that can take take focus
other = toga.Button("Other")
widget.parent.add(other)
other_probe = get_probe(other)

other.focus()
assert not probe.has_focus()
assert other_probe.has_focus()

# Widget has *not* taken focus
widget.focus()
assert not probe.has_focus()
assert other_probe.has_focus()


async def test_text(widget, probe):
"The text displayed on a widget can be changed"
for text in TEXTS:
Expand Down Expand Up @@ -197,7 +235,7 @@ async def test_flex_widget_size(widget, probe):
# Check the initial widget size
# Match isn't exact because of pixel scaling on some platforms
assert probe.width == approx(100, rel=0.01)
assert probe.height == approx(100, rel=0.01)
assert probe.height == approx(200, rel=0.01)

# Drop the fixed height, and make the widget flexible
widget.style.flex = 1
Expand Down
1 change: 1 addition & 0 deletions testbed/tests/widgets/test_activityindicator.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from ..conftest import skip_on_platforms
from .properties import ( # noqa: F401
test_enable_noop,
test_focus_noop,
)


Expand Down
53 changes: 52 additions & 1 deletion testbed/tests/widgets/test_box.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,67 @@
import pytest

import toga
from toga.colors import BLACK, BLUE, GREEN, RED
from toga.style import Pack

from .probe import get_probe
from .properties import ( # noqa: F401
test_background_color,
test_background_color_reset,
test_enable_noop,
test_flex_widget_size,
test_focus_noop,
)


@pytest.fixture
async def widget():
return toga.Box(style=Pack(width=100, height=100))
return toga.Box(style=Pack(width=100, height=200))


async def test_parenting(widget, probe):
widget.style.background_color = RED
box = widget.parent

child = toga.Box(style=Pack(width=50, height=75, background_color=GREEN))
child_probe = get_probe(child)
other = toga.Box(style=Pack(width=100, height=200, background_color=BLUE))
other_probe = get_probe(other)
other_child = toga.Box(style=Pack(width=25, height=50, background_color=BLACK))
other.add(other_child)

# Layout has the test widget, plus other, horizontally laid out.
# Child isn't in the layout yet.
box.add(other)
await probe.redraw()
probe.assert_layout(position=(0, 0), size=(100, 200))
other_probe.assert_layout(position=(100, 0), size=(100, 200))
child_probe.assert_not_contained()

# Add child to widget.
widget.add(child)
await probe.redraw()
probe.assert_layout(position=(0, 0), size=(100, 200))
other_probe.assert_layout(position=(100, 0), size=(100, 200))
child_probe.assert_layout(position=(0, 0), size=(50, 75))

# Reparent child to other without removing first
other.add(child)
await probe.redraw()
probe.assert_layout(position=(0, 0), size=(100, 200))
other_probe.assert_layout(position=(100, 0), size=(100, 200))
child_probe.assert_layout(position=(125, 0), size=(50, 75))

# Remove child from the layout entirely
other.remove(child)
await probe.redraw()
probe.assert_layout(position=(0, 0), size=(100, 200))
other_probe.assert_layout(position=(100, 0), size=(100, 200))
child_probe.assert_not_contained()

# Insert the child into the root layout
box.insert(1, child)
await probe.redraw()
probe.assert_layout(position=(0, 0), size=(100, 200))
other_probe.assert_layout(position=(150, 0), size=(100, 200))
child_probe.assert_layout(position=(100, 0), size=(50, 75))
1 change: 1 addition & 0 deletions testbed/tests/widgets/test_button.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
test_color_reset,
test_enabled,
test_flex_horizontal_widget_size,
test_focus,
test_font,
test_font_attrs,
test_text_width_change,
Expand Down
1 change: 1 addition & 0 deletions testbed/tests/widgets/test_divider.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from ..conftest import skip_on_platforms
from .properties import ( # noqa: F401
test_enable_noop,
test_focus_noop,
)


Expand Down
1 change: 1 addition & 0 deletions testbed/tests/widgets/test_label.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
test_color_reset,
test_enabled,
test_flex_horizontal_widget_size,
test_focus_noop,
test_font,
test_font_attrs,
test_text,
Expand Down
1 change: 1 addition & 0 deletions testbed/tests/widgets/test_switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
test_color_reset,
test_enabled,
test_flex_horizontal_widget_size,
test_focus,
test_font,
test_font_attrs,
test_text_width_change,
Expand Down

0 comments on commit 511d602

Please sign in to comment.