1# Copyright (c) 2019, Enthought, Inc. 2# All rights reserved. 3# 4# This software is provided without warranty under the terms of the BSD 5# license included in LICENSE.txt and may be redistributed only 6# under the conditions described in the aforementioned license. The license 7# is also available online at http://www.enthought.com/licenses/BSD.txt 8 9import unittest 10 11from pyface.timer.api import CallbackTimer 12from traits.api import HasTraits, Instance, Int 13from traitsui.api import Handler, Item, UIInfo, View, toolkit 14 15from ._tools import ( 16 BaseTestMixin, GuiTestAssistant, is_qt, no_gui_test_assistant 17) 18 19 20class SimpleModel(HasTraits): 21 cell = Int() 22 23 24class ClosableHandler(Handler): 25 26 info = Instance(UIInfo) 27 28 def init(self, info): 29 self.info = info 30 return True 31 32 def test_close(self): 33 self.info.ui.dispose() 34 35 36simple_view = View( 37 Item("cell"), title="Enter IDs and conditions", buttons=["OK", "Cancel"] 38) 39 40 41@unittest.skipIf(no_gui_test_assistant, "No GuiTestAssistant") 42class TestViewApplication(BaseTestMixin, GuiTestAssistant, unittest.TestCase): 43 def setUp(self): 44 BaseTestMixin.setUp(self) 45 GuiTestAssistant.setUp(self) 46 self.model = SimpleModel() 47 self.handler = ClosableHandler() 48 self.event_loop_timeout = False 49 self.closed = False 50 51 if is_qt(): 52 if len(self.qt_app.topLevelWidgets()) > 0: 53 with self.event_loop_with_timeout(repeat=5): 54 self.gui.invoke_later(self.qt_app.closeAllWindows) 55 56 def tearDown(self): 57 GuiTestAssistant.tearDown(self) 58 BaseTestMixin.tearDown(self) 59 60 def view_application(self, kind, button=None): 61 if button is None: 62 self.gui.invoke_later(self.close_dialog) 63 else: 64 self.gui.invoke_later(self.click_button, text=button) 65 66 timer = CallbackTimer.single_shot( 67 callback=self.stop_event_loop, interval=1.0 68 ) 69 try: 70 self.result = toolkit().view_application( 71 context=self.model, 72 view=simple_view, 73 kind=kind, 74 handler=self.handler, 75 ) 76 finally: 77 timer.stop() 78 79 def view_application_event_loop(self, kind): 80 with self.event_loop_until_condition(lambda: self.closed): 81 self.gui.invoke_later( 82 toolkit().view_application, 83 context=self.model, 84 view=simple_view, 85 kind=kind, 86 handler=self.handler, 87 ) 88 self.gui.invoke_after(100, self.close_dialog) 89 90 def close_dialog(self): 91 if is_qt(): 92 self.handler.info.ui.control.close() 93 self.closed = True 94 else: 95 raise NotImplementedError("Can't close current backend") 96 97 def click_button(self, text): 98 if is_qt(): 99 from pyface.qt.QtGui import QPushButton 100 from pyface.ui.qt4.util.testing import find_qt_widget 101 102 button = find_qt_widget( 103 self.handler.info.ui.control, 104 QPushButton, 105 lambda widget: widget.text() == text, 106 ) 107 if button is None: 108 raise RuntimeError("Can't find {} button".format(text)) 109 button.click() 110 self.closed = True 111 else: 112 raise NotImplementedError("Can't click current backend") 113 114 def stop_event_loop(self): 115 self.gui.stop_event_loop() 116 self.event_loop_timeout = True 117 118 def test_modal_view_application_close(self): 119 self.view_application("modal") 120 121 self.assertTrue(self.closed) 122 self.assertFalse(self.event_loop_timeout) 123 self.assertFalse(self.result) 124 125 def test_nonmodal_view_application_close(self): 126 self.view_application("nonmodal") 127 128 self.assertTrue(self.closed) 129 self.assertFalse(self.event_loop_timeout) 130 self.assertTrue(self.result) 131 132 def test_livemodal_view_application_close(self): 133 self.view_application("livemodal") 134 135 self.assertTrue(self.closed) 136 self.assertFalse(self.event_loop_timeout) 137 self.assertFalse(self.result) 138 139 def test_live_view_application_close(self): 140 self.view_application("live") 141 142 self.assertTrue(self.closed) 143 self.assertFalse(self.event_loop_timeout) 144 self.assertTrue(self.result) 145 146 def test_modal_view_application_ok(self): 147 self.view_application("modal", button="OK") 148 149 self.assertTrue(self.closed) 150 self.assertFalse(self.event_loop_timeout) 151 self.assertTrue(self.result) 152 153 def test_nonmodal_view_application_ok(self): 154 self.view_application("nonmodal", button="OK") 155 156 self.assertTrue(self.closed) 157 self.assertFalse(self.event_loop_timeout) 158 self.assertTrue(self.result) 159 160 def test_livemodal_view_application_ok(self): 161 self.view_application("livemodal", button="OK") 162 163 self.assertTrue(self.closed) 164 self.assertFalse(self.event_loop_timeout) 165 self.assertTrue(self.result) 166 167 def test_live_view_application_ok(self): 168 self.view_application("live", button="OK") 169 170 self.assertTrue(self.closed) 171 self.assertFalse(self.event_loop_timeout) 172 self.assertTrue(self.result) 173 174 def test_modal_view_application_cancel(self): 175 self.view_application("modal", button="Cancel") 176 177 self.assertTrue(self.closed) 178 self.assertFalse(self.event_loop_timeout) 179 self.assertFalse(self.result) 180 181 def test_nonmodal_view_application_cancel(self): 182 self.view_application("nonmodal", button="Cancel") 183 184 self.assertTrue(self.closed) 185 self.assertFalse(self.event_loop_timeout) 186 self.assertFalse(self.result) 187 188 def test_livemodal_view_application_cancel(self): 189 self.view_application("livemodal", button="Cancel") 190 191 self.assertTrue(self.closed) 192 self.assertFalse(self.event_loop_timeout) 193 self.assertFalse(self.result) 194 195 def test_live_view_application_cancel(self): 196 self.view_application("live", button="Cancel") 197 198 self.assertTrue(self.closed) 199 self.assertFalse(self.event_loop_timeout) 200 self.assertFalse(self.result) 201 202 def test_modal_view_application_eventloop_close(self): 203 self.view_application_event_loop("modal") 204 205 self.assertTrue(self.closed) 206 self.assertFalse(self.event_loop_timeout) 207 208 def test_nonmodal_view_application_eventloop_close(self): 209 self.view_application_event_loop("nonmodal") 210 211 self.assertTrue(self.closed) 212 self.assertFalse(self.event_loop_timeout) 213 214 def test_livemodal_view_application_eventloop_close(self): 215 self.view_application_event_loop("livemodal") 216 217 self.assertTrue(self.closed) 218 self.assertFalse(self.event_loop_timeout) 219 220 def test_live_view_application_eventloop_close(self): 221 self.view_application_event_loop("live") 222 223 self.assertTrue(self.closed) 224 self.assertFalse(self.event_loop_timeout) 225