Commit b69badfb authored by Swergas's avatar Swergas

code style: respect PEP8 except line length and E501,E261,E303

parent 9fbdfc0e
......@@ -62,11 +62,12 @@ def count_occurences_in_sent_emails(text):
return count
"""
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
"""
def separate_sent_emails():
"""
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 = []
......@@ -97,11 +98,12 @@ def separate_sent_emails():
return result
"""
Reads the file that gathers all sent emails to find, for each voter provided in array voters_email_addresses, their credential and their latest sent password. Returns an array, where each element is a dictionary with fields "email_address", "credential", "election_page_url", "username", and "password".
:return: array
"""
def populate_credential_and_password_for_voters_from_sent_emails(voters_email_addresses, election_title):
"""
Reads the file that gathers all sent emails to find, for each voter provided in array voters_email_addresses, their credential and their latest sent password. Returns an array, where each element is a dictionary with fields "email_address", "credential", "election_page_url", "username", and "password".
:return: array
"""
result = []
sent_emails = separate_sent_emails()
for voter_email_address in voters_email_addresses:
......@@ -151,7 +153,7 @@ def populate_credential_and_password_for_voters_from_sent_emails(voters_email_ad
voter_username = match.group(1)
else:
raise Exception("Username not found in password email for voter " + voter_email_address)
# Step 4: Insert all extracted information into returned array
element = {}
element["email_address"] = voter_email_address
......@@ -246,6 +248,7 @@ def repopulate_vote_confirmations_for_voters_from_sent_emails(voters_with_creden
voter["smart_ballot_tracker_in_vote_confirmation_email"] = voter_smart_ballot_confirmation
return voters_with_credentials
def remove_database_folder():
shutil.rmtree(os.path.join(GIT_REPOSITORY_ABSOLUTE_PATH, DATABASE_FOLDER_PATH_RELATIVE_TO_GIT_REPOSITORY), ignore_errors=True)
......@@ -344,11 +347,11 @@ def verify_election_consistency(election_id, snapshot_folder=None):
print("Verification of election consistency has been correctly processed")
assert match
else:
raise Exception ("Error: Verification of election consistency is wrong. STDOUT was: " + outs + " STDERR was:" + errs)
raise Exception("Error: Verification of election consistency is wrong. STDOUT was: " + outs + " STDERR was:" + errs)
except subprocess.TimeoutExpired:
running_process.kill()
outs, errs = proc.communicate()
raise Exception ("Error: Verification took longer than " + process_timeout + " seconds. STDOUT was: " + outs + " STDERR was:" + errs)
outs, errs = running_process.communicate()
raise Exception("Error: Verification took longer than " + process_timeout + " seconds. STDOUT was: " + outs + " STDERR was:" + errs)
def create_election_data_snapshot(election_id):
......@@ -363,7 +366,7 @@ def create_election_data_snapshot(election_id):
else:
raise Exception("Could not extract absolute path from output of mktemp:", out)
# Remark: If this command is run before any vote is cast, files `public_creds.txt` and `ballots.jsons` do not exist yet
# Remark: If this command is run before any vote is cast, files `public_creds.txt` and `ballots.jsons` do not exist yet
subprocess.run(["cp", "election.json", "public_creds.txt", "public_keys.jsons", "ballots.jsons", temporary_folder_absolute_path], cwd=election_folder)
return temporary_folder_absolute_path
......@@ -374,57 +377,57 @@ def delete_election_data_snapshot(snapshot_folder):
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
"""
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_has_non_empty_content((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
"""
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_has_non_empty_content((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):
......@@ -437,261 +440,261 @@ def wait_for_element_exists_and_contains_expected_text(browser, css_selector, ex
:return: The WebElement once it matches expected conditions
"""
try:
ignored_exceptions=(NoSuchElementException,StaleElementReferenceException,)
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:
except Exception:
raise Exception("Could not find expected DOM element '" + css_selector + "' with text content '" + expected_text + "' until timeout of " + str(wait_duration) + " seconds")
class BeleniosTestElectionScenario1(unittest.TestCase):
"""
Properties:
- server
- browser
- voters_email_addresses
- voters_email_addresses_who_have_lost_their_password
- voters_data
- election_page_url
- election_id
"""
def setUp(self):
install_fake_sendmail_log_file()
"""
Properties:
- server
- browser
- voters_email_addresses
- voters_email_addresses_who_have_lost_their_password
- voters_data
- election_page_url
- election_id
"""
remove_database_folder()
def setUp(self):
install_fake_sendmail_log_file()
self.server = initialize_server()
remove_database_folder()
self.browser = initialize_browser()
self.server = initialize_server()
self.voters_email_addresses = []
self.voters_email_addresses_who_have_lost_their_password = []
self.voters_data = dict()
self.election_page_url = None
self.election_id = None
self.browser = initialize_browser()
self.voters_email_addresses = []
self.voters_email_addresses_who_have_lost_their_password = []
self.voters_data = dict()
self.election_page_url = None
self.election_id = None
def tearDown(self):
self.browser.quit()
self.server.kill()
def tearDown(self):
self.browser.quit()
remove_database_folder()
self.server.kill()
uninstall_fake_sendmail_log_file()
remove_database_folder()
uninstall_fake_sendmail_log_file()
def update_voters_data(self, some_voters_data):
"""
:param some_voters: a list of voter data
"""
for voter in some_voters_data:
self.voters_data[voter["email_address"]] = voter
def update_voters_data(self, some_voters_data):
"""
:param some_voters: a list of voter data
"""
for voter in some_voters_data:
self.voters_data[voter["email_address"]] = voter
def log_in_as_administrator(self, from_a_login_page=False):
browser = self.browser
if from_a_login_page:
local_login_link_label = "local"
browser.find_element_by_partial_link_text(local_login_link_label).click()
else:
# Edith has been given administrator rights on an online voting app called Belenios. She goes
# to check out its homepage
browser.get(SERVER_URL)
def log_in_as_administrator(self, from_a_login_page=False):
browser = self.browser
# She notices the page title mentions an election
assert 'Election Server' in browser.title, "Browser title was: " + browser.title
if from_a_login_page:
local_login_link_label = "local"
browser.find_element_by_partial_link_text(local_login_link_label).click()
else:
# Edith has been given administrator rights on an online voting app called Belenios. She goes
# to check out its homepage
# If a personal data policy modal appears (it does not appear after it has been accepted), she clicks on the "Accept" button
accept_button_label = "Accept"
button_elements = find_buttons_in_page_content_by_value(browser, accept_button_label)
if len(button_elements) > 0:
assert len(button_elements) is 1
button_elements[0].click()
browser.get(SERVER_URL)
wait_a_bit()
# She notices the page title mentions an election
assert 'Election Server' in browser.title, "Browser title was: " + browser.title
# She clicks on "local" to go to the login page
login_link_id = "login_local"
login_element = browser.find_element_by_id(login_link_id)
login_element.click()
# If a personal data policy modal appears (it does not appear after it has been accepted), she clicks on the "Accept" button
accept_button_label = "Accept"
button_elements = find_buttons_in_page_content_by_value(browser, accept_button_label)
if len(button_elements) > 0:
assert len(button_elements) is 1
button_elements[0].click()
wait_a_bit()
# She enters her identifier and password and submits the form to log in
login_form_username_value = "user1"
login_form_password_value = "phiexoey" # This is the 4th column of file demo/password_db.csv
# She clicks on "local" to go to the login page
login_link_id = "login_local"
login_element = browser.find_element_by_id(login_link_id)
login_element.click()
login_form_username_css_selector = '#main form input[name=username]'
login_form_password_css_selector = '#main form input[name=password]'
# She enters her identifier and password and submits the form to log in
login_form_username_value = "user1"
login_form_password_value = "phiexoey" # This is the 4th column of file demo/password_db.csv
login_form_username_element = browser.find_element_by_css_selector(login_form_username_css_selector)
login_form_password_element = browser.find_element_by_css_selector(login_form_password_css_selector)
login_form_username_css_selector = '#main form input[name=username]'
login_form_password_css_selector = '#main form input[name=password]'
login_form_username_element.send_keys(login_form_username_value)
login_form_password_element.send_keys(login_form_password_value)
login_form_password_element.submit()
login_form_username_element = browser.find_element_by_css_selector(login_form_username_css_selector)
login_form_password_element = browser.find_element_by_css_selector(login_form_password_css_selector)
# She verifies that she arrived on the administration page (instead of any login error page)
login_form_username_element.send_keys(login_form_username_value)
login_form_password_element.send_keys(login_form_password_value)
login_form_password_element.submit()
# Here we use Selenium's Explicit Wait to wait for the h1 element of the page to contain expected text, meaning browser will have changed from login page to administration page. If we had used an Implicit Wait (with a defined duration) instead of an Explicit one, we risk to have some errors sometimes (we experienced them before doing this refactoring):
# - Sometimes we get an error like `selenium.common.exceptions.StaleElementReferenceException: Message: The element reference of <h1> is stale; either the element is no longer attached to the DOM, it is not in the current frame context, or the document has been refreshed` or `selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: #header h1`. This is because page content changed in between two of our instructions.
# - Value read from the page is still the value contained in previous page, because page content has not changed yet.
# She verifies that she arrived on the administration page (instead of any login error page)
page_title_css_selector = "#header h1"
page_title_expected_content = "Administration"
page_title_element = wait_for_element_exists_and_contains_expected_text(browser, page_title_css_selector, page_title_expected_content)
assert page_title_element
# Here we use Selenium's Explicit Wait to wait for the h1 element of the page to contain expected text, meaning browser will have changed from login page to administration page. If we had used an Implicit Wait (with a defined duration) instead of an Explicit one, we risk to have some errors sometimes (we experienced them before doing this refactoring):
# - Sometimes we get an error like `selenium.common.exceptions.StaleElementReferenceException: Message: The element reference of <h1> is stale; either the element is no longer attached to the DOM, it is not in the current frame context, or the document has been refreshed` or `selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: #header h1`. This is because page content changed in between two of our instructions.
# - Value read from the page is still the value contained in previous page, because page content has not changed yet.
page_title_css_selector = "#header h1"
page_title_expected_content = "Administration"
page_title_element = wait_for_element_exists_and_contains_expected_text(browser, page_title_css_selector, page_title_expected_content)
assert page_title_element
def log_out(self):
browser = self.browser
# In the header of the page, she clicks on the "Log out" link
logout_link_css_id = "logout"
logout_element = browser.find_element_by_id(logout_link_css_id)
logout_element.click()
wait_a_bit()
def log_out(self):
browser = self.browser
# In the header of the page, she clicks on the "Log out" link
logout_link_css_id = "logout"
logout_element = browser.find_element_by_id(logout_link_css_id)
logout_element.click()
# She arrives back on the logged out home page. She checks that a login link is present
login_link_id = "login_local"
browser.find_element_by_id(login_link_id)
wait_a_bit()
# She arrives back on the logged out home page. She checks that a login link is present
login_link_id = "login_local"
login_element = browser.find_element_by_id(login_link_id)
def administrator_creates_election(self):
# # Setting up a new election (action of the administrator)
# Edith has been given administrator rights on an online voting app called Belenios. She goes
# to check out its homepage and logs in
self.log_in_as_administrator()
def administrator_creates_election(self):
# # Setting up a new election (action of the administrator)
# She clicks on the "Prepare a new election" link
browser = self.browser
create_election_link_text = "Prepare a new election"
links_css_selector = "#main a"
links_elements = browser.find_elements_by_css_selector(links_css_selector)
assert len(links_elements)
create_election_link_element = links_elements[0]
verify_element_label(create_election_link_element, create_election_link_text)
create_election_link_element.click()
# Edith has been given administrator rights on an online voting app called Belenios. She goes
# to check out its homepage and logs in
self.log_in_as_administrator()
wait_a_bit()
# She clicks on the "Prepare a new election" link
browser = self.browser
create_election_link_text = "Prepare a new election"
links_css_selector = "#main a"
links_elements = browser.find_elements_by_css_selector(links_css_selector)
assert len(links_elements)
create_election_link_element = links_elements[0]
verify_element_label(create_election_link_element, create_election_link_text)
create_election_link_element.click()
# She clicks on the "Proceed" button (this redirects to the "Preparation of election" page)
proceed_button_css_selector = "#main form input[type=submit]"
proceed_button_element = browser.find_element_by_css_selector(proceed_button_css_selector)
proceed_button_element.click()
wait_a_bit()
wait_a_bit()
# She clicks on the "Proceed" button (this redirects to the "Preparation of election" page)
proceed_button_css_selector = "#main form input[type=submit]"
proceed_button_element = browser.find_element_by_css_selector(proceed_button_css_selector)
proceed_button_element.click()
# She changes values of fields name and description of the election
election_name_field_css_selector = "#main form input[name=__co_eliom_name]"
election_name_field_element = browser.find_element_by_css_selector(election_name_field_css_selector)
election_name_field_value = ELECTION_TITLE
election_name_field_element.clear()
election_name_field_element.send_keys(election_name_field_value)
wait_a_bit()
wait_a_bit()
# She changes values of fields name and description of the election
election_name_field_css_selector = "#main form input[name=__co_eliom_name]"
election_name_field_element = browser.find_element_by_css_selector(election_name_field_css_selector)
election_name_field_value = ELECTION_TITLE
election_name_field_element.clear()
election_name_field_element.send_keys(election_name_field_value)
election_description_field_css_selector = "#main form textarea[name=__co_eliom_description]"
election_description_field_element = browser.find_element_by_css_selector(election_description_field_css_selector)
election_description_field_value = "This is the description of my test election for Scenario 1"
election_description_field_element.clear()
election_description_field_element.send_keys(election_description_field_value)
wait_a_bit()
wait_a_bit()
election_description_field_css_selector = "#main form textarea[name=__co_eliom_description]"
election_description_field_element = browser.find_element_by_css_selector(election_description_field_css_selector)
election_description_field_value = "This is the description of my test election for Scenario 1"
election_description_field_element.clear()
election_description_field_element.send_keys(election_description_field_value)
# She clicks on the "Save changes button" (the one that is next to the election description field)
save_changes_button_css_selector = "#main > div:nth-child(1) form input[type=submit]" # Warning: form:nth-child(1) selects another form
save_changes_button_element = browser.find_element_by_css_selector(save_changes_button_css_selector)
save_changes_button_element.click()
wait_a_bit()
wait_a_bit()
# She clicks on the "Save changes button" (the one that is next to the election description field)
save_changes_button_css_selector = "#main > div:nth-child(1) form input[type=submit]" # Warning: form:nth-child(1) selects another form
save_changes_button_element = browser.find_element_by_css_selector(save_changes_button_css_selector)
save_changes_button_element.click()
# She clicks on the "Edit questions" link, to write her own questions
edit_questions_link_css_selector = "#edit_questions"
edit_questions_link_element = browser.find_element_by_css_selector(edit_questions_link_css_selector)
edit_questions_link_element.click()
wait_a_bit()
wait_a_bit()
# She clicks on the "Edit questions" link, to write her own questions
edit_questions_link_css_selector = "#edit_questions"
edit_questions_link_element = browser.find_element_by_css_selector(edit_questions_link_css_selector)
edit_questions_link_element.click()
# She arrives on the Questions page. She checks that the page title is correct
find_element_by_css_selector_and_label(browser, "#header h1", "Questions for")
wait_a_bit()
# She removes answer 3
question_to_remove = 3
remove_button_css_selector = ".question_answers > div:nth-child(" + str(question_to_remove) + ") button:nth-child(2)"
remove_button_element = browser.find_element_by_css_selector(remove_button_css_selector)
remove_button_element.click()
# She arrives on the Questions page. She checks that the page title is correct
find_element_by_css_selector_and_label(browser, "#header h1", "Questions for")
wait_a_bit()
# She removes answer 3
question_to_remove = 3
remove_button_css_selector = ".question_answers > div:nth-child("+str(question_to_remove)+") button:nth-child(2)"
remove_button_element = browser.find_element_by_css_selector(remove_button_css_selector)
remove_button_element.click()
# She clicks on the "Save changes" button (this redirects to the "Preparation of election" page)
save_changes_button_expected_label = "Save changes"
button_elements = browser.find_elements_by_css_selector("button")
assert len(button_elements)
save_changes_button_element = button_elements[-1]
verify_element_label(save_changes_button_element, save_changes_button_expected_label)
save_changes_button_element.click()
wait_a_bit()
wait_a_bit()
# She clicks on the "Save changes" button (this redirects to the "Preparation of election" page)
save_changes_button_expected_label = "Save changes"
button_elements = browser.find_elements_by_css_selector("button")
assert len(button_elements)
save_changes_button_element = button_elements[-1]
verify_element_label(save_changes_button_element, save_changes_button_expected_label)
save_changes_button_element.click()
# She clicks on the "Edit voters" link, to then type the list of voters
edit_voters_link_css_selector = "#edit_voters"
edit_voters_link_element = browser.find_element_by_css_selector(edit_voters_link_css_selector)
edit_voters_link_element.click()
wait_a_bit()
# She clicks on the "Edit voters" link, to then type the list of voters
edit_voters_link_css_selector = "#edit_voters"
edit_voters_link_element = browser.find_element_by_css_selector(edit_voters_link_css_selector)
edit_voters_link_element.click()
wait_a_bit()
wait_a_bit()
# She types N e-mail addresses (the list of invited voters)
self.voters_email_addresses = random_email_addresses_generator(NUMBER_OF_INVITED_VOTERS)
voters_list_field_css_selector = "#main form textarea"
voters_list_field_element = browser.find_element_by_css_selector(voters_list_field_css_selector)
voters_list_field_element.clear()
is_first = True
for email_address in self.voters_email_addresses:
if is_first:
is_first = False
else:
voters_list_field_element.send_keys(Keys.ENTER)
voters_list_field_element.send_keys(email_address)
# She types N e-mail addresses (the list of invited voters)
self.voters_email_addresses = random_email_addresses_generator(NUMBER_OF_INVITED_VOTERS)
voters_list_field_css_selector = "#main form textarea"
voters_list_field_element = browser.find_element_by_css_selector(voters_list_field_css_selector)
voters_list_field_element.clear()
is_first = True
for email_address in self.voters_email_addresses:
if is_first:
is_first = False
else:
voters_list_field_element.send_keys(Keys.ENTER)
voters_list_field_element.send_keys(email_address)
wait_a_bit()
wait_a_bit()
# She clicks on the "Add" button to submit changes
add_button_css_selector = "#main form input[type=submit]"
add_button_element = browser.find_element_by_css_selector(add_button_css_selector)
add_button_element.click()
# She clicks on the "Add" button to submit changes
add_button_css_selector = "#main form input[type=submit]"
add_button_element = browser.find_element_by_css_selector(add_button_css_selector)
add_button_element.click()
wait_a_bit()
wait_a_bit()
# She clicks on "Return to draft page" link
return_link_label = "Return to draft page"
browser.find_element_by_partial_link_text(return_link_label).click()
# She clicks on "Return to draft page" link
return_link_label = "Return to draft page"
browser.find_element_by_partial_link_text(return_link_label).click()
wait_a_bit()
wait_a_bit()
# She clicks on button "Generate on server"
generate_on_server_button_label = "Generate on server"
generate_on_server_button_element = find_button_in_page_content_by_value(browser, generate_on_server_button_label)
generate_on_server_button_element.click()
# She clicks on button "Generate on server"
generate_on_server_button_label = "Generate on server"
generate_on_server_button_element = find_button_in_page_content_by_value(browser, generate_on_server_button_label)
generate_on_server_button_element.click()
wait_a_bit()
wait_a_bit()
# (Server sends emails to voters.) She checks that server does not show any error that would happen when trying to send these emails (this can happen if sendmail is not configured)
confirmation_sentence_expected_text = "Credentials have been generated and mailed!"
confirmation_sentence_css_selector = "#main p"
confirmation_sentence_element = browser.find_element_by_css_selector(confirmation_sentence_css_selector)
verify_element_label(confirmation_sentence_element, confirmation_sentence_expected_text)
# (Server sends emails to voters.) She checks that server does not show any error that would happen when trying to send these emails (this can happen if sendmail is not configured)
confirmation_sentence_expected_text = "Credentials have been generated and mailed!"
confirmation_sentence_css_selector = "#main p"
confirmation_sentence_element = browser.find_element_by_css_selector(confirmation_sentence_css_selector)
verify_element_label(confirmation_sentence_element, confirmation_sentence_expected_text)
# Now we do a sanity check that server has really tried to send emails. For this, we look for email addresses in the temporary file where our fake sendmail executable redirects its inputs to.
# Now we do a sanity check that server has really tried to send emails. For this, we look for email addresses in the temporary file where our fake sendmail executable redirects its inputs to.
"""
An email sent by Belenios (using sendmail or using the fake sendmail) to a voter looks like this:
"""
An email sent by Belenios (using sendmail or using the fake sendmail) to a voter looks like this:
Content-type: text/plain; charset="UTF-8"
Content-type: text/plain; charset="UTF-8"
Content-transfer-encoding: quoted-printable
From: Belenios public server <noreply@example.org>
To: "820E7G83JBY0F4Z3DY2Y@mailinator.com"
......@@ -745,117 +748,32 @@ Notez que vous pouvez voter plusieurs fois. Seul le dernier vote est
pris en compte.
--=20
"""
email_address_to_look_for = self.voters_email_addresses[0]
text_to_look_for = 'To: "' + email_address_to_look_for + '"'
email_address_found = find_in_sent_emails(text_to_look_for)
assert email_address_found, "Text '" + email_address_to_look_for + "'' not found in fake sendmail log file"
# She clicks on the "Proceed" link
proceed_link_expected_label = "Proceed"
proceed_link_css_selector = "#main a"
proceed_link_element = browser.find_element_by_css_selector(proceed_link_css_selector)
verify_element_label(proceed_link_element, proceed_link_expected_label)
proceed_link_element.click()
wait_a_bit()
# In "Authentication" section, she clicks on the "Generate and mail missing passwords" button
generate_and_mail_missing_passwords_button_label = "Generate and mail missing passwords"
generate_and_mail_missing_passwords_button_element = find_button_in_page_content_by_value(browser, generate_and_mail_missing_passwords_button_label)
generate_and_mail_missing_passwords_button_element.click()
wait_a_bit()
# She checks that the page contains expected confirmation text, instead of an error (TODO: explain in which case an error can happen, and check that it does not show)
confirmation_sentence_expected_text = "Passwords have been generated and mailed!"
confirmation_sentence_css_selector = "#main p"
confirmation_sentence_element = browser.find_element_by_css_selector(confirmation_sentence_css_selector)
verify_element_label(confirmation_sentence_element, confirmation_sentence_expected_text)
# She clicks on the "Proceed" link
proceed_link_expected_label = "Proceed"
proceed_link_css_selector = "#main a"
proceed_link_element = browser.find_element_by_css_selector(proceed_link_css_selector)
verify_element_label(proceed_link_element, proceed_link_expected_label)
proceed_link_element.click()
wait_a_bit()
# In "Validate creation" section, she clicks on the "Create election" link
create_election_link_label = "Create election"
browser.find_element_by_partial_link_text(create_election_link_label).click()
wait_a_bit()
# She arrives on the "Checklist" page, that lists all main parameters of the election for review, and that flags incoherent or misconfigured parameters. For example, in this test scenario, it displays 2 warnings: "Warning: No trustees were set. This means that the server will manage the election key by itself.", and "Warning: No contact was set!"
# In the "Validate creation" section, she clicks on the "Create election" button
create_election_button_label = "Create election"
create_election_button_element = find_button_in_page_content_by_value(browser, create_election_button_label)
create_election_button_element.click()
wait_a_bit()
# She arrives back on the "My test election for Scenario 1 — Administration" page. Its contents have changed. There is now a text saying "The election is open. Voters can vote.", and there are now buttons "Close election", "Archive election", "Delete election"
# She remembers the URL of the voting page, that is where the "Election home" link points to
election_page_link_label = "Election home"
election_page_link_element = browser.find_element_by_partial_link_text(election_page_link_label)
self.election_page_url = election_page_link_element.get_attribute('href')
print("election_page_url:", self.election_page_url)
self.election_id = election_page_url_to_election_id(self.election_page_url)
print("election_id:", self.election_id)
# She checks that a "Close election" button is present (but she does not click on it)
close_election_button_label = "Close election"
close_election_button_element = find_button_in_page_content_by_value(browser, close_election_button_label)
self.log_out()
def administrator_regenerates_passwords_for_some_voters(self):
# Edith has been contacted by some voters who say they lost their password. She wants to re-generate their passwords and have the platform send them by email. For this, she logs in as administrator.
self.log_in_as_administrator()
# She remembers the list of voters who contacted her and said they lost their password. For this, we pick NUMBER_OF_REGENERATED_PASSWORD_VOTERS voters from all the voters. TODO: We could pick them randomly or force an overlap with voters that are in NUMBER_OF_REVOTING_VOTERS
browser = self.browser
self.voters_email_addresses_who_have_lost_their_password = self.voters_email_addresses[0:NUMBER_OF_REGENERATED_PASSWORD_VOTERS]
"""
# She selects the election that she wants to edit (li a[href^="election/admin?uuid="][0])
election_to_edit_css_selector = "#main li a[href^='election/admin?uuid=']"
election_to_edit_elements = browser.find_elements_by_css_selector(election_to_edit_css_selector)
assert len(election_to_edit_elements) > 0
election_to_edit_elements[0].click()
email_address_to_look_for = self.voters_email_addresses[0]
text_to_look_for = 'To: "' + email_address_to_look_for + '"'
email_address_found = find_in_sent_emails(text_to_look_for)
assert email_address_found, "Text '" + email_address_to_look_for + "'' not found in fake sendmail log file"
wait_a_bit()
# She arrives to the election administration page. For each voter of the NUMBER_OF_REGENERATED_PASSWORD_VOTERS selected voters:
for email_address in self.voters_email_addresses_who_have_lost_their_password:
# She clicks on the "Regenerate and mail a password" link (a[href^="regenpwd?uuid="][0])
regenerate_and_mail_a_password_link_css_selector = "#main a[href^='regenpwd?uuid=']"
regenerate_and_mail_a_password_link_element = browser.find_element_by_css_selector(regenerate_and_mail_a_password_link_css_selector)
regenerate_and_mail_a_password_link_element.click()