17
17
WaitTimedOut , window_condition , window_disposed_condition ,
18
18
)
19
19
import crystal .tests .util .xtempfile as xtempfile
20
+ from crystal .util .wx_dialog import mocked_show_modal
20
21
from crystal .util .xos import is_mac_os
21
22
import os .path
22
23
import re
23
24
import sys
24
25
import tempfile
25
26
import traceback
26
27
from typing import TYPE_CHECKING
28
+ from unittest .mock import patch
27
29
import wx
28
30
29
31
if TYPE_CHECKING :
@@ -43,13 +45,55 @@ class OpenOrCreateDialog:
43
45
create_button : wx .Button
44
46
45
47
@staticmethod
46
- async def wait_for (timeout : float | None = None ) -> OpenOrCreateDialog :
48
+ async def wait_for (timeout : float | None = None , * , _attempt_recovery : bool = True ) -> OpenOrCreateDialog :
47
49
self = OpenOrCreateDialog (ready = True )
48
- open_or_create_project_dialog = await wait_for (
49
- window_condition ('cr-open-or-create-project' ),
50
- timeout = timeout ,
51
- stacklevel_extra = 1 ,
52
- ) # type: wx.Window
50
+ try :
51
+ open_or_create_project_dialog = await wait_for (
52
+ window_condition ('cr-open-or-create-project' ),
53
+ timeout = timeout ,
54
+ stacklevel_extra = 1 ,
55
+ ) # type: wx.Window
56
+ except WaitTimedOut as e :
57
+ if _attempt_recovery :
58
+ # Check if a MainWindow is open from a previous failed test
59
+ try :
60
+ main_window : wx .Window = await wait_for (
61
+ window_condition ('cr-main-window' ),
62
+ # Short timeout. Check whether a MainWindow is open.
63
+ timeout = 0.1 ,
64
+ # Attribute failure to this recovery logic
65
+ stacklevel_extra = 0 ,
66
+ )
67
+ assert isinstance (main_window , wx .Frame )
68
+
69
+ print (
70
+ 'WARNING: OpenOrCreateDialog.wait_for() noticed that '
71
+ 'a MainWindow was left open. '
72
+ 'Did a previous test fail to close it?' ,
73
+ file = sys .stderr
74
+ )
75
+
76
+ # 1. Try to close MainWindow that is open
77
+ # 2. If prompted whether to save the project, answer no
78
+ with patch ('crystal.browser.ShowModal' ,
79
+ mocked_show_modal ('cr-save-changes-dialog' , wx .ID_NO )):
80
+ main_window .Close ()
81
+
82
+ await wait_for (
83
+ window_disposed_condition ('cr-main-window' ),
84
+ timeout = 4.0 , # 2.0s isn't long enough for macOS test runners on GitHub Actions
85
+ # Attribute failure to this recovery logic
86
+ stacklevel_extra = 0 ,
87
+ )
88
+
89
+ # Try again to wait for the OpenOrCreateDialog
90
+ return await OpenOrCreateDialog .wait_for (timeout = timeout , _attempt_recovery = False )
91
+ except WaitTimedOut :
92
+ # Recovery failed
93
+ pass
94
+ # Raise original timeout
95
+ raise e from None
96
+
53
97
assert isinstance (open_or_create_project_dialog , wx .Dialog )
54
98
self .open_or_create_project_dialog = open_or_create_project_dialog
55
99
self .open_as_readonly = self .open_or_create_project_dialog .FindWindow (name =
0 commit comments