1# (C) Copyright 2005-2020 Enthought, Inc., Austin, TX
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 under
6# the conditions described in the aforementioned license. The license
7# is also available online at http://www.enthought.com/licenses/BSD.txt
8#
9# Thanks for using Enthought open source!
10
11
12import platform
13import unittest
14
15from ..confirmation_dialog import ConfirmationDialog, confirm
16from ..constant import YES, NO, OK, CANCEL
17from ..image_resource import ImageResource
18from ..toolkit import toolkit_object
19from ..window import Window
20
21is_qt = toolkit_object.toolkit == "qt4"
22if is_qt:
23    from pyface.qt import qt_api
24
25GuiTestAssistant = toolkit_object("util.gui_test_assistant:GuiTestAssistant")
26no_gui_test_assistant = GuiTestAssistant.__name__ == "Unimplemented"
27
28ModalDialogTester = toolkit_object(
29    "util.modal_dialog_tester:ModalDialogTester"
30)
31no_modal_dialog_tester = ModalDialogTester.__name__ == "Unimplemented"
32
33is_pyqt5 = is_qt and qt_api == "pyqt5"
34is_pyqt4_linux = is_qt and qt_api == "pyqt" and platform.system() == "Linux"
35
36
37@unittest.skipIf(no_gui_test_assistant, "No GuiTestAssistant")
38class TestConfirmationDialog(unittest.TestCase, GuiTestAssistant):
39    def setUp(self):
40        GuiTestAssistant.setUp(self)
41        self.dialog = ConfirmationDialog()
42
43    def tearDown(self):
44        if self.dialog.control is not None:
45            with self.delete_widget(self.dialog.control):
46                self.dialog.destroy()
47        self.dialog = None
48        GuiTestAssistant.tearDown(self)
49
50    def test_create(self):
51        # test that creation and destruction works as expected
52        with self.event_loop():
53            self.dialog._create()
54        with self.event_loop():
55            self.dialog.destroy()
56
57    def test_destroy(self):
58        # test that destroy works even when no control
59        with self.event_loop():
60            self.dialog.destroy()
61
62    def test_size(self):
63        # test that size works as expected
64        self.dialog.size = (100, 100)
65        with self.event_loop():
66            self.dialog._create()
67        with self.event_loop():
68            self.dialog.destroy()
69
70    def test_position(self):
71        # test that position works as expected
72        self.dialog.position = (100, 100)
73        with self.event_loop():
74            self.dialog._create()
75        with self.event_loop():
76            self.dialog.destroy()
77
78    def test_create_parent(self):
79        # test that creation and destruction works as expected with a parent
80        with self.event_loop():
81            parent = Window()
82            self.dialog.parent = parent.control
83            parent._create()
84        with self.event_loop():
85            self.dialog._create()
86        with self.event_loop():
87            self.dialog.destroy()
88        with self.event_loop():
89            parent.destroy()
90
91    def test_create_yes_renamed(self):
92        # test that creation and destruction works as expected with ok_label
93        self.dialog.yes_label = "Sure"
94        with self.event_loop():
95            self.dialog._create()
96        with self.event_loop():
97            self.dialog.destroy()
98
99    def test_create_no_renamed(self):
100        # test that creation and destruction works as expected with ok_label
101        self.dialog.no_label = "No Way"
102        with self.event_loop():
103            self.dialog._create()
104        with self.event_loop():
105            self.dialog.destroy()
106
107    def test_create_yes_default(self):
108        # test that creation and destruction works as expected with ok_label
109        self.dialog.default = YES
110        with self.event_loop():
111            self.dialog._create()
112        with self.event_loop():
113            self.dialog.destroy()
114
115    def test_create_cancel(self):
116        # test that creation and destruction works with cancel button
117        self.dialog.cancel = True
118        with self.event_loop():
119            self.dialog._create()
120        with self.event_loop():
121            self.dialog.destroy()
122
123    def test_create_cancel_renamed(self):
124        # test that creation and destruction works with cancel button
125        self.dialog.cancel = True
126        self.dialog.cancel_label = "Back"
127        with self.event_loop():
128            self.dialog._create()
129        with self.event_loop():
130            self.dialog.destroy()
131
132    def test_create_cancel_default(self):
133        # test that creation and destruction works as expected with ok_label
134        self.dialog.cancel = True
135        self.dialog.default = CANCEL
136        with self.event_loop():
137            self.dialog._create()
138        with self.event_loop():
139            self.dialog.destroy()
140
141    def test_create_image(self):
142        # test that creation and destruction works with a non-standard image
143        self.dialog.image = ImageResource("core")
144        with self.event_loop():
145            self.dialog._create()
146        with self.event_loop():
147            self.dialog.destroy()
148
149    @unittest.skipIf(no_modal_dialog_tester, "ModalDialogTester unavailable")
150    def test_close(self):
151        # test that closing works as expected
152        # XXX duplicate of Dialog test, not needed?
153        tester = ModalDialogTester(self.dialog.open)
154        tester.open_and_run(when_opened=lambda x: self.dialog.close())
155
156        self.assertEqual(tester.result, NO)
157        self.assertEqual(self.dialog.return_code, NO)
158
159    @unittest.skipIf(no_modal_dialog_tester, "ModalDialogTester unavailable")
160    def test_close_with_cancel(self):
161        # test that closing works as expected
162        self.dialog.cancel = True
163        tester = ModalDialogTester(self.dialog.open)
164        tester.open_and_run(when_opened=lambda x: self.dialog.close())
165
166        self.assertEqual(tester.result, CANCEL)
167        self.assertEqual(self.dialog.return_code, CANCEL)
168
169    @unittest.skipIf(
170        is_pyqt5, "Confirmation dialog click tests don't work on pyqt5."
171    )  # noqa
172    @unittest.skipIf(
173        is_pyqt4_linux,
174        "Confirmation dialog click tests don't work reliably on linux.  Issue #282.",
175    )  # noqa
176    @unittest.skipIf(no_modal_dialog_tester, "ModalDialogTester unavailable")
177    def test_yes(self):
178        # test that Yes works as expected
179        tester = ModalDialogTester(self.dialog.open)
180        tester.open_and_wait(when_opened=lambda x: x.click_button(YES))
181
182        self.assertEqual(tester.result, YES)
183        self.assertEqual(self.dialog.return_code, YES)
184
185    @unittest.skipIf(
186        is_pyqt5, "Confirmation dialog click tests don't work on pyqt5."
187    )  # noqa
188    @unittest.skipIf(
189        is_pyqt4_linux,
190        "Confirmation dialog click tests don't work reliably on linux.  Issue #282.",
191    )  # noqa
192    @unittest.skipIf(no_modal_dialog_tester, "ModalDialogTester unavailable")
193    def test_renamed_yes(self):
194        self.dialog.yes_label = "Sure"
195        # test that Yes works as expected if renamed
196        tester = ModalDialogTester(self.dialog.open)
197        tester.open_and_wait(when_opened=lambda x: x.click_widget("Sure"))
198
199        self.assertEqual(tester.result, YES)
200        self.assertEqual(self.dialog.return_code, YES)
201
202    @unittest.skipIf(
203        is_pyqt5, "Confirmation dialog click tests don't work on pyqt5."
204    )  # noqa
205    @unittest.skipIf(
206        is_pyqt4_linux,
207        "Confirmation dialog click tests don't work reliably on linux.  Issue #282.",
208    )  # noqa
209    @unittest.skipIf(no_modal_dialog_tester, "ModalDialogTester unavailable")
210    def test_no(self):
211        # test that No works as expected
212        tester = ModalDialogTester(self.dialog.open)
213        tester.open_and_wait(when_opened=lambda x: x.click_button(NO))
214
215        self.assertEqual(tester.result, NO)
216        self.assertEqual(self.dialog.return_code, NO)
217
218    @unittest.skipIf(
219        is_pyqt5, "Confirmation dialog click tests don't work on pyqt5."
220    )  # noqa
221    @unittest.skipIf(
222        is_pyqt4_linux,
223        "Confirmation dialog click tests don't work reliably on linux.  Issue #282.",
224    )  # noqa
225    @unittest.skipIf(no_modal_dialog_tester, "ModalDialogTester unavailable")
226    def test_renamed_no(self):
227        self.dialog.no_label = "No way"
228        # test that No works as expected if renamed
229        tester = ModalDialogTester(self.dialog.open)
230        tester.open_and_wait(when_opened=lambda x: x.click_widget("No way"))
231
232        self.assertEqual(tester.result, NO)
233        self.assertEqual(self.dialog.return_code, NO)
234
235    @unittest.skipIf(
236        is_pyqt5, "Confirmation dialog click tests don't work on pyqt5."
237    )  # noqa
238    @unittest.skipIf(
239        is_pyqt4_linux,
240        "Confirmation dialog click tests don't work reliably on linux.  Issue #282.",
241    )  # noqa
242    @unittest.skipIf(no_modal_dialog_tester, "ModalDialogTester unavailable")
243    def test_cancel(self):
244        self.dialog.cancel = True
245        # test that Cancel works as expected
246        tester = ModalDialogTester(self.dialog.open)
247        tester.open_and_wait(when_opened=lambda x: x.click_button(CANCEL))
248
249        self.assertEqual(tester.result, CANCEL)
250        self.assertEqual(self.dialog.return_code, CANCEL)
251
252    @unittest.skipIf(
253        is_pyqt5, "Confirmation dialog click tests don't work on pyqt5."
254    )  # noqa
255    @unittest.skipIf(
256        is_pyqt4_linux,
257        "Confirmation dialog click tests don't work reliably on linux.  Issue #282.",
258    )  # noqa
259    @unittest.skipIf(no_modal_dialog_tester, "ModalDialogTester unavailable")
260    def test_cancel_renamed(self):
261        self.dialog.cancel = True
262        self.dialog.cancel_label = "Back"
263        # test that Cancel works as expected
264        tester = ModalDialogTester(self.dialog.open)
265        tester.open_and_wait(when_opened=lambda x: x.click_widget("Back"))
266
267        self.assertEqual(tester.result, CANCEL)
268        self.assertEqual(self.dialog.return_code, CANCEL)
269
270    @unittest.skipIf(no_modal_dialog_tester, "ModalDialogTester unavailable")
271    def test_parent(self):
272        # test that lifecycle works with a parent
273        parent = Window()
274        self.dialog.parent = parent.control
275        with self.event_loop():
276            parent.open()
277        tester = ModalDialogTester(self.dialog.open)
278        tester.open_and_run(when_opened=lambda x: x.close(accept=True))
279        with self.event_loop():
280            parent.close()
281
282        self.assertEqual(tester.result, OK)
283        self.assertEqual(self.dialog.return_code, OK)
284
285
286@unittest.skipIf(no_gui_test_assistant, "No GuiTestAssistant")
287class TestConfirm(unittest.TestCase, GuiTestAssistant):
288    def setUp(self):
289        GuiTestAssistant.setUp(self)
290
291    def tearDown(self):
292        GuiTestAssistant.tearDown(self)
293
294    @unittest.skipIf(no_modal_dialog_tester, "ModalDialogTester unavailable")
295    def test_reject(self):
296        # test that cancel works as expected
297        tester = ModalDialogTester(
298            lambda: confirm(None, "message", cancel=True)
299        )
300        tester.open_and_run(when_opened=lambda x: x.close(accept=False))
301
302        self.assertEqual(tester.result, CANCEL)
303
304    @unittest.skipIf(
305        is_pyqt5, "Confirmation dialog click tests don't work on pyqt5."
306    )  # noqa
307    @unittest.skipIf(
308        is_pyqt4_linux,
309        "Confirmation dialog click tests don't work reliably on linux.  Issue #282.",
310    )  # noqa
311    @unittest.skipIf(no_modal_dialog_tester, "ModalDialogTester unavailable")
312    def test_yes(self):
313        # test that yes works as expected
314        tester = ModalDialogTester(lambda: confirm(None, "message"))
315        tester.open_and_wait(when_opened=lambda x: x.click_button(YES))
316
317        self.assertEqual(tester.result, YES)
318
319    @unittest.skipIf(
320        is_pyqt5, "Confirmation dialog click tests don't work on pyqt5."
321    )  # noqa
322    @unittest.skipIf(
323        is_pyqt4_linux,
324        "Confirmation dialog click tests don't work reliably on linux.  Issue #282.",
325    )  # noqa
326    @unittest.skipIf(no_modal_dialog_tester, "ModalDialogTester unavailable")
327    def test_no(self):
328        # test that yes works as expected
329        tester = ModalDialogTester(lambda: confirm(None, "message"))
330        tester.open_and_wait(when_opened=lambda x: x.click_button(NO))
331
332        self.assertEqual(tester.result, NO)
333
334    @unittest.skipIf(
335        is_pyqt5, "Confirmation dialog click tests don't work on pyqt5."
336    )  # noqa
337    @unittest.skipIf(
338        is_pyqt4_linux,
339        "Confirmation dialog click tests don't work reliably on linux.  Issue #282.",
340    )  # noqa
341    @unittest.skipIf(no_modal_dialog_tester, "ModalDialogTester unavailable")
342    def test_cancel(self):
343        # test that cancel works as expected
344        tester = ModalDialogTester(
345            lambda: confirm(None, "message", cancel=True)
346        )
347        tester.open_and_wait(when_opened=lambda x: x.click_button(CANCEL))
348
349        self.assertEqual(tester.result, CANCEL)
350
351    @unittest.skipIf(
352        is_pyqt5, "Confirmation dialog click tests don't work on pyqt5."
353    )  # noqa
354    @unittest.skipIf(
355        is_pyqt4_linux,
356        "Confirmation dialog click tests don't work reliably on linux.  Issue #282.",
357    )  # noqa
358    @unittest.skipIf(no_modal_dialog_tester, "ModalDialogTester unavailable")
359    def test_title(self):
360        # test that title works as expected
361        tester = ModalDialogTester(
362            lambda: confirm(None, "message", title="Title")
363        )
364        tester.open_and_run(when_opened=lambda x: x.click_button(NO))
365
366        self.assertEqual(tester.result, NO)
367
368    @unittest.skipIf(
369        is_pyqt5, "Confirmation dialog click tests don't work on pyqt5."
370    )  # noqa
371    @unittest.skipIf(
372        is_pyqt4_linux,
373        "Confirmation dialog click tests don't work reliably on linux.  Issue #282.",
374    )  # noqa
375    @unittest.skipIf(no_modal_dialog_tester, "ModalDialogTester unavailable")
376    def test_default_yes(self):
377        # test that default works as expected
378        tester = ModalDialogTester(
379            lambda: confirm(None, "message", default=YES)
380        )
381        tester.open_and_run(when_opened=lambda x: x.click_button(YES))
382
383        self.assertEqual(tester.result, YES)
384
385    @unittest.skipIf(
386        is_pyqt5, "Confirmation dialog click tests don't work on pyqt5."
387    )  # noqa
388    @unittest.skipIf(
389        is_pyqt4_linux,
390        "Confirmation dialog click tests don't work reliably on linux.  Issue #282.",
391    )  # noqa
392    @unittest.skipIf(no_modal_dialog_tester, "ModalDialogTester unavailable")
393    def test_default_cancel(self):
394        # test that default works as expected
395        tester = ModalDialogTester(
396            lambda: confirm(None, "message", cancel=True, default=YES)
397        )
398        tester.open_and_run(when_opened=lambda x: x.click_button(CANCEL))
399
400        self.assertEqual(tester.result, CANCEL)
401