Commit 68cd6f41 authored by Swergas's avatar Swergas

refactoring: split code relative to fake sent emails management and selenium...

refactoring: split code relative to fake sent emails management and selenium tooling to their own file
parent b69badfb
This diff is collapsed.
#!/usr/bin/python
# -*- coding: utf-8 -*
import re
import subprocess
class FakeSentEmailsManager:
def __init__(self, log_file_path):
self.log_file_path = log_file_path
# self.install_fake_sendmail_log_file()
def find_in_sent_emails(self, text):
with open(self.log_file_path) as fl:
return text in fl.read()
def count_occurences_in_sent_emails(self, text):
with open(self.log_file_path) as file:
count = file.read().count(text)
return count
def separate_sent_emails(self):
"""
Converts the file that gathers all sent emails to an array with one element per sent email. Each element is a dictionary with fields "to", "subject", and "full_content".
:return: array
"""
# Email content is encoded using "quoted-printable" encoding. Please refer to https://en.wikipedia.org/wiki/Quoted-printable for more information. For example, this enconding transforms "@" into "=40". TODO: We could improve this function by having it directly decode the part of the email that is encoded, using `quopri` library for example.
marker_for_end_of_email = "--=20"
result = []
with open(self.log_file_path) as file:
contents = file.read()
separated_emails = contents.split(marker_for_end_of_email)
if len(separated_emails[-1]) < 5: # The last sent email ends with marker_for_end_of_email, so we can ignore what comes after
separated_emails.pop()
for email_full_content in separated_emails:
email_to = ""
match = re.search(r'^To: "(.*)"', email_full_content, re.MULTILINE)
if match:
email_to = match.group(1)
email_subject = ""
match = re.search(r'^Subject: (.*)$', email_full_content, re.MULTILINE)
if match:
email_subject = match.group(1)
element = {
"to": email_to,
"subject": email_subject,
"full_content": email_full_content
}
result.append(element)
return result
def install_fake_sendmail_log_file(self):
subprocess.run(["rm", "-f", self.log_file_path]) # TODO: Execute a command that works on other OS, like `os.remove()`
subprocess.run(["touch", self.log_file_path]) # TODO: Execute a command that works on other OS, like `pathlib.Path.touch()`
def uninstall_fake_sendmail_log_file(self):
subprocess.run(["rm", "-f", self.log_file_path]) # TODO: Execute a command that works on other OS, like `os.remove()`
#!/usr/bin/python
# -*- coding: utf-8 -*
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import StaleElementReferenceException
class element_has_non_empty_content(object):
"""
An expectation for checking that an element has a non-empty innerText attribute.
This class is meant to be used in combination with Selenium's `WebDriverWait::until()`. For example:
```
custom_wait = WebDriverWait(browser, 10)
smart_ballot_tracker_element = custom_wait.until(element_has_non_empty_content((By.ID, "my_id")))
```
:param locator: Selenium locator used to find the element. For example: `(By.ID, "my_id")`
:return: The WebElement once it has a non-empty innerText attribute
"""
def __init__(self, locator):
self.locator = locator
def __call__(self, driver):
element = driver.find_element(*self.locator) # Finding the referenced element
if not element:
return False
element_content = element.get_attribute('innerText').strip()
if len(element_content) > 0:
return element
else:
return False
class element_exists_and_contains_expected_text(object):
"""
An expectation for checking that an element exists and its innerText attribute contains expected text.
This class is meant to be used in combination with Selenium's `WebDriverWait::until()`. For example:
```
custom_wait = WebDriverWait(browser, 10)
smart_ballot_tracker_element = custom_wait.until(element_exists_and_contains_expected_text((By.ID, "my_id"), "my expected text"))
```
:param locator: Selenium locator used to find the element. For example: `(By.ID, "my_id")`
:param expected_text: Text expected in element's innerText attribute (parameter type: string)
:return: The WebElement once its innerText attribute contains expected_text
"""
def __init__(self, locator, expected_text):
self.locator = locator
self.expected_text = expected_text
def __call__(self, driver):
element = driver.find_element(*self.locator) # Finding the referenced element
if not element:
return False
element_content = element.get_attribute('innerText').strip()
if self.expected_text in element_content:
return element
else:
return False
def wait_for_element_exists_and_contains_expected_text(browser, css_selector, expected_text, wait_duration=10):
"""
Waits for the presence of an element that matches CSS selector `css_selector` and that has an innerText attribute that contains string `expected_text`.
:param browser: Selenium browser
:param css_selector: CSS selector of the expected element
:param expected_text: String of the expected text that element must contain
:param wait_duration: Maximum duration in seconds that we wait for the presence of this element before raising an exception
:return: The WebElement once it matches expected conditions
"""
try:
ignored_exceptions = (NoSuchElementException, StaleElementReferenceException,)
custom_wait = WebDriverWait(browser, wait_duration, ignored_exceptions=ignored_exceptions)
page_title_element = custom_wait.until(element_exists_and_contains_expected_text((By.CSS_SELECTOR, css_selector), expected_text))
return page_title_element
except Exception:
raise Exception("Could not find expected DOM element '" + css_selector + "' with text content '" + expected_text + "' until timeout of " + str(wait_duration) + " seconds")
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment