1
1
from pathlib import Path
2
+ from selenium .webdriver .common import service
2
3
3
4
from selenium .webdriver .firefox .webdriver import WebDriver
5
+ from selenium .webdriver .firefox .service import Service
4
6
from selenium .webdriver .firefox .options import Options
5
7
from selenium .webdriver .common .by import By
6
8
from selenium .webdriver .support .ui import WebDriverWait
@@ -69,6 +71,11 @@ class SeleniumRunner:
69
71
IcomoonPage .GENERATE_FONT : ICOMOON_URL + "/font"
70
72
}
71
73
74
+ """
75
+ Number of retries for creating a web driver instance.
76
+ """
77
+ MAX_RETRY = 5
78
+
72
79
"""
73
80
The different types of alerts that this workflow will encounter.
74
81
It contains part of the text in the actual alert and buttons
@@ -126,6 +133,7 @@ def set_browser_options(self, download_path: str, geckodriver_path: str,
126
133
:raises AssertionError: if the page title does not contain
127
134
"IcoMoon App".
128
135
"""
136
+ # customize the download options
129
137
options = Options ()
130
138
allowed_mime_types = "application/zip, application/gzip, application/octet-stream"
131
139
# disable prompt to download from Firefox
@@ -138,15 +146,62 @@ def set_browser_options(self, download_path: str, geckodriver_path: str,
138
146
options .headless = headless
139
147
140
148
print ("Activating browser client..." )
141
- self .driver = WebDriver (options = options , executable_path = geckodriver_path )
149
+ self .driver = self .create_driver_instance (options , geckodriver_path )
150
+
142
151
self .driver .get (self .ICOMOON_URL )
143
- assert "IcoMoon App" in self .driver .title
144
152
# wait until the whole web page is loaded by testing the hamburger input
145
153
WebDriverWait (self .driver , self .LONG_WAIT_IN_SEC ).until (
146
154
ec .element_to_be_clickable ((By .XPATH , "(//i[@class='icon-menu'])[2]" ))
147
155
)
148
156
print ("Accessed icomoon.io" )
149
157
158
+ def create_driver_instance (self , options : Options , geckodriver_path : str ):
159
+ """
160
+ Create a WebDriver instance. Isolate retrying code here to address
161
+ "no connection can be made" error.
162
+ :param options: the FirefoxOptions for the browser.
163
+ :param geckodriver_path: the path to the firefox executable.
164
+ the icomoon.zip to.
165
+ """
166
+ retries = SeleniumRunner .MAX_RETRY
167
+ finished = False
168
+ driver = None
169
+ err_msgs = [] # keep for logging purposes
170
+ while not finished and retries > 0 :
171
+ try :
172
+ # order matters, don't change the lines below
173
+ finished = True # signal we are done in case we are actually done
174
+
175
+ # customize the local server
176
+ service = None
177
+ # first retry: use 8080
178
+ # else: random
179
+ if retries == SeleniumRunner .MAX_RETRY :
180
+ service = Service (executable_path = geckodriver_path , port = 8080 )
181
+ else :
182
+ service = Service (executable_path = geckodriver_path )
183
+ driver = WebDriver (options = options , service = service )
184
+ except SeleniumTimeoutException as e :
185
+ # retry. This is intended to catch "no connection could be made" error
186
+ retries -= 1
187
+ finished = False # flip the var so we can retry
188
+ msg = f"Retry { retries } /{ SeleniumRunner .MAX_RETRY } SeleniumTimeoutException: { e .msg } "
189
+ print (msg )
190
+ err_msgs .append (msg )
191
+ except Exception as e :
192
+ # anything else: unsure if retry works. Just end the retry
193
+ msg = f"Retry { retries } /{ SeleniumRunner .MAX_RETRY } Exception: { e } "
194
+ err_msgs .append (msg )
195
+ print (msg )
196
+ break
197
+
198
+ if driver is not None :
199
+ return driver
200
+
201
+ err_msg_formatted = '\n ' .join (reversed (err_msgs ))
202
+ msg = f"Unable to create WebDriver Instance:\n { err_msg_formatted } "
203
+ raise Exception (msg )
204
+
150
205
def switch_toolbar_option (self , option : IcomoonOptionState ):
151
206
"""
152
207
Switch the toolbar option to the option argument.
@@ -248,7 +303,7 @@ def edit_svg(self, screenshot_folder: str=None, index: int=None):
248
303
except SeleniumTimeoutException :
249
304
pass # do nothing cause sometimes, the color tab doesn't appear in the site
250
305
251
- if screenshot_folder != None and index != None :
306
+ if screenshot_folder is not None and index is not None :
252
307
edit_screen_selector = "div.overlay div.overlayWindow"
253
308
screenshot_path = str (
254
309
Path (screenshot_folder , f"new_svg_{ index } .png" ).resolve ()
0 commit comments