mirror of https://github.com/chriskiehl/Gooey.git
Browse Source
closes #517 - radio group not enabling widget when initial_selection is set
1.0.4-release--issue-470
closes #517 - radio group not enabling widget when initial_selection is set
1.0.4-release--issue-470
Chris
4 years ago
5 changed files with 258 additions and 10 deletions
Unified View
Diff Options
-
7gooey/gui/application.py
-
18gooey/gui/components/widgets/radio_group.py
-
32gooey/python_bindings/gooey_decorator.py
-
22gooey/tests/harness.py
-
189gooey/tests/test_radiogroup.py
@ -0,0 +1,22 @@ |
|||||
|
from contextlib import contextmanager |
||||
|
|
||||
|
import wx |
||||
|
|
||||
|
from gui import application |
||||
|
from python_bindings.config_generator import create_from_parser |
||||
|
from python_bindings.gooey_decorator import defaults |
||||
|
|
||||
|
|
||||
|
@contextmanager |
||||
|
def instrumentGooey(parser, **kwargs): |
||||
|
""" |
||||
|
Context manager used during testing for setup/tear down of the |
||||
|
WX infrastructure during subTests. |
||||
|
""" |
||||
|
buildspec = create_from_parser(parser, "", **defaults) |
||||
|
app, gooey = application.build_app(buildspec) |
||||
|
try: |
||||
|
yield (app, gooey) |
||||
|
finally: |
||||
|
wx.CallAfter(app.ExitMainLoop) |
||||
|
app.Destroy() |
@ -0,0 +1,189 @@ |
|||||
|
import unittest |
||||
|
|
||||
|
import wx |
||||
|
|
||||
|
from gooey import GooeyParser |
||||
|
from tests.harness import instrumentGooey |
||||
|
|
||||
|
|
||||
|
class TestRadioGroupBehavior(unittest.TestCase): |
||||
|
|
||||
|
def mutext_group(self, options): |
||||
|
""" |
||||
|
Basic radio group consisting of two options. |
||||
|
""" |
||||
|
parser = GooeyParser() |
||||
|
group = parser.add_mutually_exclusive_group(**options) |
||||
|
group.add_argument("-b", type=str) |
||||
|
group.add_argument("-d", type=str, widget="DateChooser") |
||||
|
return parser |
||||
|
|
||||
|
|
||||
|
def test_initial_selection_options(self): |
||||
|
""" |
||||
|
Ensure that the initial_selection GooeyOption behaves as expected. |
||||
|
""" |
||||
|
# each pair in the below datastructure represents input/output |
||||
|
# First position: kwargs which will be supplied to the parser |
||||
|
# Second position: expected indices which buttons/widgets should be enabled/disabled |
||||
|
testCases = [ |
||||
|
[{'required': True, 'gooey_options': {}}, |
||||
|
{'selected': None, 'enabled': [], 'disabled': [0, 1]}], |
||||
|
|
||||
|
# Issue #517 - initial section with required=True was not enabling |
||||
|
# the inner widget |
||||
|
[{'required': True, 'gooey_options': {"initial_selection": 0}}, |
||||
|
{'selected': 0, 'enabled': [0], 'disabled': [1]}], |
||||
|
|
||||
|
[{'required': True, 'gooey_options': {"initial_selection": 1}}, |
||||
|
{'selected': 1, 'enabled': [1], 'disabled': [0]}], |
||||
|
|
||||
|
[{'required': False, 'gooey_options': {}}, |
||||
|
{'selected': None, 'enabled': [], 'disabled': [0, 1]}], |
||||
|
|
||||
|
[{'required': False, 'gooey_options': {"initial_selection": 0}}, |
||||
|
{'selected': 0, 'enabled': [0], 'disabled': [1]}], |
||||
|
|
||||
|
[{'required': False, 'gooey_options': {"initial_selection": 1}}, |
||||
|
{'selected': 1, 'enabled': [1], 'disabled': [0]}], |
||||
|
] |
||||
|
for options, expected in testCases: |
||||
|
parser = self.mutext_group(options) |
||||
|
with self.subTest(options): |
||||
|
with instrumentGooey(parser) as (app, gooeyApp): |
||||
|
radioGroup = gooeyApp.configs[0].reifiedWidgets[0] |
||||
|
|
||||
|
# verify that the checkboxes themselves are correct |
||||
|
if expected['selected'] is not None: |
||||
|
self.assertEqual( |
||||
|
radioGroup.selected, |
||||
|
radioGroup.radioButtons[expected['selected']]) |
||||
|
else: |
||||
|
self.assertEqual(radioGroup.selected, None) |
||||
|
|
||||
|
# verify the widgets contained in the radio group |
||||
|
# are in the correct state |
||||
|
for enabled in expected['enabled']: |
||||
|
# The widget contained within the group should be enabled |
||||
|
self.assertTrue(radioGroup.widgets[enabled].IsEnabled()) |
||||
|
|
||||
|
# make sure all widgets other than the selected |
||||
|
# are disabled |
||||
|
for enabled in expected['disabled']: |
||||
|
self.assertFalse(radioGroup.widgets[enabled].IsEnabled()) |
||||
|
|
||||
|
|
||||
|
def test_optional_radiogroup_click_behavior(self): |
||||
|
""" |
||||
|
Testing that select/deselect behaves as expected |
||||
|
""" |
||||
|
testcases = [ |
||||
|
self.click_scenarios_optional_widget(), |
||||
|
self.click_scenarios_required_widget(), |
||||
|
self.click_scenarios_initial_selection() |
||||
|
] |
||||
|
|
||||
|
for testcase in testcases: |
||||
|
with self.subTest(testcase['name']): |
||||
|
# wire up the parse with our test case options |
||||
|
parser = self.mutext_group(testcase['input']) |
||||
|
|
||||
|
with instrumentGooey(parser) as (app, gooeyApp): |
||||
|
radioGroup = gooeyApp.configs[0].reifiedWidgets[0] |
||||
|
|
||||
|
for scenario in testcase['scenario']: |
||||
|
targetButton = scenario['clickButton'] |
||||
|
|
||||
|
event = wx.CommandEvent(wx.wxEVT_LEFT_DOWN, wx.NewId()) |
||||
|
event.SetEventObject(radioGroup.radioButtons[targetButton]) |
||||
|
|
||||
|
radioGroup.radioButtons[targetButton].ProcessEvent(event) |
||||
|
|
||||
|
expectedEnabled, expectedDisabled = scenario['postState'] |
||||
|
|
||||
|
for index in expectedEnabled: |
||||
|
self.assertEqual(radioGroup.selected, radioGroup.radioButtons[index]) |
||||
|
self.assertTrue(radioGroup.widgets[index].IsEnabled()) |
||||
|
|
||||
|
for index in expectedDisabled: |
||||
|
self.assertNotEqual(radioGroup.selected, radioGroup.radioButtons[index]) |
||||
|
self.assertFalse(radioGroup.widgets[index].IsEnabled()) |
||||
|
|
||||
|
|
||||
|
def click_scenarios_optional_widget(self): |
||||
|
return { |
||||
|
'name': 'click_scenarios_optional_widget', |
||||
|
'input': {'required': False}, |
||||
|
'scenario': [ |
||||
|
# clicking enabled the button |
||||
|
{'clickButton': 0, |
||||
|
'postState': [[0], [1]]}, |
||||
|
|
||||
|
# clicking again disables the button (*when not required*) |
||||
|
{'clickButton': 0, |
||||
|
'postState': [[], [0, 1]]}, |
||||
|
|
||||
|
# clicking group 2 enabled it |
||||
|
{'clickButton': 1, |
||||
|
'postState': [[1], [0]]}, |
||||
|
|
||||
|
# and similarly clicking group 2 again disables it |
||||
|
{'clickButton': 1, |
||||
|
'postState': [[], [0, 1]]}, |
||||
|
|
||||
|
# enable second group |
||||
|
{'clickButton': 1, |
||||
|
'postState': [[1], [0]]}, |
||||
|
|
||||
|
# can switch to group one |
||||
|
{'clickButton': 0, |
||||
|
'postState': [[0], [1]]}, |
||||
|
] |
||||
|
} |
||||
|
|
||||
|
def click_scenarios_required_widget(self): |
||||
|
return { |
||||
|
'name': 'click_scenarios_required_widget', |
||||
|
'input': {'required': True}, |
||||
|
'scenario': [ |
||||
|
# clicking enables the button |
||||
|
{'clickButton': 0, |
||||
|
'postState': [[0], [1]]}, |
||||
|
|
||||
|
# unlike the the optional case, this |
||||
|
# has no effect. You cannot _not_ select something |
||||
|
# when it is required. |
||||
|
{'clickButton': 0, |
||||
|
'postState': [[0], [1]]}, |
||||
|
|
||||
|
# we can select a different button |
||||
|
{'clickButton': 1, |
||||
|
'postState': [[1], [0]]}, |
||||
|
|
||||
|
# again, if we click it again, we cannot deselect it |
||||
|
{'clickButton': 1, |
||||
|
'postState': [[1], [0]]}, |
||||
|
|
||||
|
# we can click back to the other group |
||||
|
{'clickButton': 0, |
||||
|
'postState': [[0], [1]]}, |
||||
|
]} |
||||
|
|
||||
|
def click_scenarios_initial_selection(self): |
||||
|
return { |
||||
|
'name': 'click_scenarios_initial_selection', |
||||
|
'input': {'required': False, 'gooey_options': {'initial_selection': 0}}, |
||||
|
'scenario': [ |
||||
|
# we start already selected via GooeyOptions. As such, |
||||
|
# clicking on the radiobutton should deselect it |
||||
|
{'clickButton': 0, |
||||
|
'postState': [[], [0, 1]]}, |
||||
|
# clicking again reselected it |
||||
|
{'clickButton': 0, |
||||
|
'postState': [[0], [1]]}, |
||||
|
]} |
||||
|
|
||||
|
|
||||
|
|
||||
|
if __name__ == '__main__': |
||||
|
unittest.main() |
Write
Preview
Loading…
Cancel
Save