1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
|
#------------------------------------------------------------------------------
# Copyright (c) 2019-2024, Nucleic Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file LICENSE, distributed with this software.
#------------------------------------------------------------------------------
import pytest
from textwrap import dedent
from utils import compile_source, wait_for_window_displayed
from enaml.core.api import Looper
from enaml.widgets.api import Label
def test_looper_refresh(enaml_qtbot, enaml_sleep):
""" Test that the loop index is valid when items are reordered.
"""
source = dedent("""\
from enaml.core.api import Looper
from enaml.widgets.api import Window, Container, Label, PushButton
enamldef Main(Window): window:
attr data: list = []
alias container
Container: container:
Looper:
iterable << window.data
Label:
text << '{} {}'.format(loop.index, loop.item)
""")
tester = compile_source(source, 'Main')()
tester.show()
wait_for_window_displayed(enaml_qtbot, tester)
for data in (
# Set initial
['a', 'b', 'c'],
# Resort order data and ensure it matches
['b', 'c', 'a'],
# Remove and resort ensure it still matches
['a', 'b']
):
enaml_qtbot.wait(enaml_sleep)
tester.data = data
expected = ['{} {}'.format(*it) for it in enumerate(data)]
assert [c.text for c in tester.container.children
if isinstance(c, Label)] == expected
def test_looper_refresh_iterator(enaml_qtbot, enaml_sleep):
""" Test that a looper properly refreshes when given an iterator.
"""
source = dedent("""\
from enaml.core.api import Looper, Conditional
from enaml.widgets.api import Window, Container, Label, ObjectCombo
enamldef Main(Window): window:
attr data: list = []
attr flag: str = 'a'
attr show_more: bool << flag == 'b' or flag == 'c'
alias container
Container: container:
ObjectCombo: combo:
items = ['a', 'b', 'c']
selected := window.flag
Conditional:
condition << show_more
# Nested loop forces re-eval twice
Conditional:
condition << flag == 'c'
Looper:
iterable << reversed(data)
Label:
text << '{} {}'.format(loop.index, loop.item)
""")
tester = compile_source(source, 'Main')()
tester.show()
wait_for_window_displayed(enaml_qtbot, tester)
enaml_qtbot.wait(enaml_sleep)
data = [1, 2, 3]
tester.data = data
# Conditional is still hiding it
assert not any(
c for c in tester.container.children if isinstance(c, Label))
# Now they should all be shown
tester.flag = 'c'
enaml_qtbot.wait(enaml_sleep)
expected = ['{} {}'.format(*it) for it in enumerate(reversed(data))]
assert [c.text for c in tester.container.children
if isinstance(c, Label)] == expected
def test_looper_iterable():
""" Test that a looper validates the iterator properly.
"""
looper = Looper()
looper.iterable = {1, 2, 3}
looper.iterable = {'a': 1, 'b': 2}
looper.iterable = 'abc'
with pytest.raises(TypeError):
looper.iterable = 1
with pytest.raises(TypeError):
looper.iterable = None
|