mirror of
https://github.com/konpa/devicon.git
synced 2025-08-11 17:14:27 +02:00
New Feature: Upgrade Peekbot (#966)
* Moved stroke detection down * Add code to retry no connection in peekbot * Change upload artifact to earlier version * Clean up logging msg * Add ability to customize port number * Update Selenium and geckodriver * Move upload-artifact version to 2.2.4 * Add logging for webdriver retry * Add color checking to peek-bot
This commit is contained in:
@@ -5,17 +5,18 @@ from build_assets.selenium_runner.SeleniumRunner import SeleniumRunner
|
||||
from build_assets.selenium_runner.enums import IcomoonPage, IcomoonAlerts
|
||||
|
||||
class PeekSeleniumRunner(SeleniumRunner):
|
||||
def peek(self, svgs: List[str], screenshot_folder: str):
|
||||
def peek(self, svgs: List[str], screenshot_folder: str, icon_info: dict):
|
||||
"""
|
||||
Upload the SVGs and peek at how Icomoon interpret its SVGs and
|
||||
font versions.
|
||||
:param svgs: a list of svg Paths that we'll upload to icomoon.
|
||||
:param screenshot_folder: the name of the screenshot_folder.
|
||||
:param icon_info: a dictionary containing info on an icon. Taken from the devicon.json.
|
||||
:return an array of svgs with strokes as strings. These show which icon
|
||||
contains stroke.
|
||||
"""
|
||||
messages = self.peek_svgs(svgs, screenshot_folder)
|
||||
self.peek_icons(svgs, screenshot_folder)
|
||||
self.peek_icons(screenshot_folder, icon_info)
|
||||
return messages
|
||||
|
||||
def peek_svgs(self, svgs: List[str], screenshot_folder: str):
|
||||
@@ -61,10 +62,11 @@ class PeekSeleniumRunner(SeleniumRunner):
|
||||
print("Finished peeking the svgs...")
|
||||
return svgs_with_strokes
|
||||
|
||||
def peek_icons(self, svgs: List[str], screenshot_folder: str):
|
||||
def peek_icons(self, screenshot_folder: str, icon_info: dict):
|
||||
"""
|
||||
Peek at the icon versions of the SVGs that were uploaded.
|
||||
:param screenshot_folder: the name of the screenshot_folder.
|
||||
:param icon_info: a dictionary containing info on an icon. Taken from the devicon.json.
|
||||
"""
|
||||
print("Begin peeking at the icons...")
|
||||
# ensure all icons in the set is selected.
|
||||
@@ -85,7 +87,7 @@ class PeekSeleniumRunner(SeleniumRunner):
|
||||
main_content = self.driver.find_element_by_xpath(main_content_xpath)
|
||||
main_content.screenshot(new_icons_path);
|
||||
|
||||
# go downward so we get the oldest icon first
|
||||
# go in reverse order so we get the oldest icon first
|
||||
icon_divs_xpath = f'//div[@id="glyphSet0"]/div'
|
||||
icon_divs = self.driver.find_elements_by_xpath(icon_divs_xpath)
|
||||
icon_divs.reverse()
|
||||
@@ -98,6 +100,23 @@ class PeekSeleniumRunner(SeleniumRunner):
|
||||
Path(screenshot_folder, f"new_icon_{i}.png").resolve()
|
||||
)
|
||||
icon_div.screenshot(icon_screenshot)
|
||||
|
||||
i += 1
|
||||
|
||||
# test the colors
|
||||
style = "#glyphSet0 span:first-of-type {color: " + icon_info["color"] + "}"
|
||||
script = f"document.styleSheets[0].insertRule('{style}', 0)"
|
||||
self.driver.execute_script(script)
|
||||
i = 0
|
||||
for icon_div in icon_divs:
|
||||
if not icon_div.is_displayed():
|
||||
continue
|
||||
|
||||
icon_screenshot = str(
|
||||
Path(screenshot_folder, f"new_colored_icon_{i}.png").resolve()
|
||||
)
|
||||
icon_div.screenshot(icon_screenshot)
|
||||
|
||||
i += 1
|
||||
|
||||
print("Finished peeking the icons...")
|
||||
|
@@ -1,6 +1,8 @@
|
||||
from pathlib import Path
|
||||
from selenium.webdriver.common import service
|
||||
|
||||
from selenium.webdriver.firefox.webdriver import WebDriver
|
||||
from selenium.webdriver.firefox.service import Service
|
||||
from selenium.webdriver.firefox.options import Options
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
@@ -69,6 +71,11 @@ class SeleniumRunner:
|
||||
IcomoonPage.GENERATE_FONT: ICOMOON_URL + "/font"
|
||||
}
|
||||
|
||||
"""
|
||||
Number of retries for creating a web driver instance.
|
||||
"""
|
||||
MAX_RETRY = 5
|
||||
|
||||
"""
|
||||
The different types of alerts that this workflow will encounter.
|
||||
It contains part of the text in the actual alert and buttons
|
||||
@@ -126,6 +133,7 @@ class SeleniumRunner:
|
||||
:raises AssertionError: if the page title does not contain
|
||||
"IcoMoon App".
|
||||
"""
|
||||
# customize the download options
|
||||
options = Options()
|
||||
allowed_mime_types = "application/zip, application/gzip, application/octet-stream"
|
||||
# disable prompt to download from Firefox
|
||||
@@ -138,15 +146,62 @@ class SeleniumRunner:
|
||||
options.headless = headless
|
||||
|
||||
print("Activating browser client...")
|
||||
self.driver = WebDriver(options=options, executable_path=geckodriver_path)
|
||||
self.driver = self.create_driver_instance(options, geckodriver_path)
|
||||
|
||||
self.driver.get(self.ICOMOON_URL)
|
||||
assert "IcoMoon App" in self.driver.title
|
||||
# wait until the whole web page is loaded by testing the hamburger input
|
||||
WebDriverWait(self.driver, self.LONG_WAIT_IN_SEC).until(
|
||||
ec.element_to_be_clickable((By.XPATH, "(//i[@class='icon-menu'])[2]"))
|
||||
)
|
||||
print("Accessed icomoon.io")
|
||||
|
||||
def create_driver_instance(self, options: Options, geckodriver_path: str):
|
||||
"""
|
||||
Create a WebDriver instance. Isolate retrying code here to address
|
||||
"no connection can be made" error.
|
||||
:param options: the FirefoxOptions for the browser.
|
||||
:param geckodriver_path: the path to the firefox executable.
|
||||
the icomoon.zip to.
|
||||
"""
|
||||
retries = SeleniumRunner.MAX_RETRY
|
||||
finished = False
|
||||
driver = None
|
||||
err_msgs = [] # keep for logging purposes
|
||||
while not finished and retries > 0:
|
||||
try:
|
||||
# order matters, don't change the lines below
|
||||
finished = True # signal we are done in case we are actually done
|
||||
|
||||
# customize the local server
|
||||
service = None
|
||||
# first retry: use 8080
|
||||
# else: random
|
||||
if retries == SeleniumRunner.MAX_RETRY:
|
||||
service = Service(executable_path=geckodriver_path, port=8080)
|
||||
else:
|
||||
service = Service(executable_path=geckodriver_path)
|
||||
driver = WebDriver(options=options, service=service)
|
||||
except SeleniumTimeoutException as e:
|
||||
# retry. This is intended to catch "no connection could be made" error
|
||||
retries -= 1
|
||||
finished = False # flip the var so we can retry
|
||||
msg = f"Retry {retries}/{SeleniumRunner.MAX_RETRY} SeleniumTimeoutException: {e.msg}"
|
||||
print(msg)
|
||||
err_msgs.append(msg)
|
||||
except Exception as e:
|
||||
# anything else: unsure if retry works. Just end the retry
|
||||
msg = f"Retry {retries}/{SeleniumRunner.MAX_RETRY} Exception: {e}"
|
||||
err_msgs.append(msg)
|
||||
print(msg)
|
||||
break
|
||||
|
||||
if driver is not None:
|
||||
return driver
|
||||
|
||||
err_msg_formatted = '\n'.join(reversed(err_msgs))
|
||||
msg = f"Unable to create WebDriver Instance:\n{err_msg_formatted}"
|
||||
raise Exception(msg)
|
||||
|
||||
def switch_toolbar_option(self, option: IcomoonOptionState):
|
||||
"""
|
||||
Switch the toolbar option to the option argument.
|
||||
@@ -248,7 +303,7 @@ class SeleniumRunner:
|
||||
except SeleniumTimeoutException:
|
||||
pass # do nothing cause sometimes, the color tab doesn't appear in the site
|
||||
|
||||
if screenshot_folder != None and index != None:
|
||||
if screenshot_folder is not None and index is not None:
|
||||
edit_screen_selector = "div.overlay div.overlayWindow"
|
||||
screenshot_path = str(
|
||||
Path(screenshot_folder, f"new_svg_{index}.png").resolve()
|
||||
|
Reference in New Issue
Block a user