예제 #1
0
def administrator_edits_election_questions(browser, nh_question=False):
    """
    Initial browser (required) state: on the "Preparation of election" page, with questions not edited yet
    Final browser state: on the "Preparation of election" page (with questions edited)

    Alice, as an administrator who has recently started creating an election (election status is draft), configures its questions:
    - She clicks on the "Edit questions" link, to write her own questions
    - She arrives on the Questions page. She checks that the page title is correct
    - She removes answer 3
    - She clicks on the "Save changes" button (this redirects to the "Preparation of election" page)
    """

    # She clicks on the "Edit questions" link, to write her own questions
    edit_questions_link_css_selector = "#edit_questions"
    edit_questions_link_element = wait_for_element_exists(
        browser, edit_questions_link_css_selector,
        settings.EXPLICIT_WAIT_TIMEOUT)
    edit_questions_link_element.click()

    wait_a_bit()

    # She arrives on the Questions page. She checks that the page title is correct
    page_title_css_selector = "#header h1"
    page_title_expected_content = "Questions for"
    wait_for_element_exists_and_contains_expected_text(
        browser, page_title_css_selector, page_title_expected_content,
        settings.EXPLICIT_WAIT_TIMEOUT)

    if nh_question:
        # She ticks "Tick the box to activate this mode."
        browser.find_element_by_css_selector("#hybrid_mode").click()
        # She ticks "Alternative"
        nhtally_css_selector = ".nonhomomorphic_tally"
        nhtally_checkbox_element = browser.find_element_by_css_selector(
            nhtally_css_selector)
        nhtally_checkbox_element.click()

    # She removes answer 3
    question_to_remove = 3
    remove_button_css_selector = ".question_answer_item:nth-child(" + str(
        question_to_remove) + ") .btn_remove"
    remove_button_element = browser.find_element_by_css_selector(
        remove_button_css_selector)
    remove_button_element.click()

    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()

    wait_a_bit()
예제 #2
0
def administrator_edits_election_questions(browser):
    """
    Initial browser (required) state: on the "Preparation of election" page, with questions not edited yet
    Final browser state: on the "Preparation of election" page (with questions edited)

    Alice, as an administrator who has recently started creating an election (election status is draft), configures its questions:
    - She clicks on the "Edit questions" link, to write her own questions
    - She arrives on the Questions page. She checks that the page title is correct
    - She removes answer 3
    - She clicks on the "Save changes" button (this redirects to the "Preparation of election" page)
    """

    # She clicks on the "Edit questions" link, to write her own questions
    edit_questions_link_css_selector = "#edit_questions"
    edit_questions_link_element = wait_for_element_exists(browser, edit_questions_link_css_selector, settings.EXPLICIT_WAIT_TIMEOUT)
    edit_questions_link_element.click()

    wait_a_bit()

    # She arrives on the Questions page. She checks that the page title is correct
    page_title_css_selector = "#header h1"
    page_title_expected_content = "Questions for"
    wait_for_element_exists_and_contains_expected_text(browser, page_title_css_selector, page_title_expected_content, settings.EXPLICIT_WAIT_TIMEOUT)

    # She removes answer 3
    question_to_remove = 3
    remove_button_css_selector = ".question_answer_item:nth-child(" + str(question_to_remove) + ") .btn_remove"
    remove_button_element = browser.find_element_by_css_selector(remove_button_css_selector)
    remove_button_element.click()

    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()

    wait_a_bit()
예제 #3
0
    def administrator_verifies_vote_results(self):
        """
        Initial browser (required) state: on the vote results page
        Final browser state: on the accepted ballots page

        She checks consistency of the vote result:
        - 1) She checks that the number of accepted ballots is the same as the number of voters who voted
        - 2) For each available answer in the question, she checks that the total number of votes in favor of Answer X displayed in result page is the same as the sum of votes for Answer X in all votes of voters who voted that have been randomly generated in advance
        - 3) She checks that each ballot content corresponds to content that of this vote that has been randomly generated in advance


        This screen looks like this:

        This is the development version!
        By using this site, you accept our <personal data policy>. <Accept>
        <en> <fr> <de> <ro> <it>

        This election has been tallied.

            Question 1?
            Answer 1    6
            Answer 2    8

        Number of accepted ballots: 10
        You can also download the <result with cryptographic proofs>.

        <See accepted ballots>

        Where <...> is a link
        """

        browser = self.browser

        # - 1) She checks that the number of accepted ballots is the same as the number of voters who voted

        main_css_selector = "#main"
        main_expected_content = "Number of accepted ballots:"
        main_element = wait_for_element_exists_and_contains_expected_text(
            browser, main_css_selector, main_expected_content,
            settings.EXPLICIT_WAIT_TIMEOUT)
        main_text_content = main_element.get_attribute('innerText')

        number_of_accepted_ballots = None
        match = re.search(r'Number of accepted ballots:\s*(\d+)\s',
                          main_text_content, re.MULTILINE | re.DOTALL)
        if match:
            number_of_accepted_ballots = match.group(1)
            number_of_accepted_ballots = number_of_accepted_ballots.strip()
        else:
            raise Exception(
                "Number of accepted ballots not found in election tally page: "
                + main_text_content)
        assert str(number_of_accepted_ballots) == str(
            settings.NUMBER_OF_VOTING_VOTERS
        ), "Number of accepted ballots (" + str(
            number_of_accepted_ballots
        ) + ") is not the same as number of voters (" + str(
            settings.NUMBER_OF_VOTING_VOTERS) + ")" + printable_page_source(
                browser)

        # - 2) For each available answer in the question, she checks that the total number of votes in favor of Answer X displayed in result page is the same as the sum of votes for Answer X in all votes of voters who voted that have been randomly generated in advance

        number_of_votes_per_answer = self.compute_number_of_votes_per_answer()
        question_id = 1
        for answer_id in range(1, 3):
            base_selector = "#main li:nth-child(" + str(
                question_id) + ") tr:nth-child(" + str(answer_id) + ")"
            answer_label_css_selector = base_selector + " td:nth-child(1)"
            answer_total_css_selector = base_selector + " td:nth-child(2)"
            answer_expected_label = "Answer " + str(answer_id)
            answer_element = browser.find_element_by_css_selector(
                answer_label_css_selector)
            verify_element_label(answer_element, answer_expected_label)
            answer_total_real_value_element = browser.find_element_by_css_selector(
                answer_total_css_selector)
            answer_total_real_value = answer_total_real_value_element.get_attribute(
                'innerText').strip()
            answer_total_expected_value = str(
                number_of_votes_per_answer['answer' + str(answer_id)])
            assert answer_total_real_value == answer_total_expected_value, "Number of votes for Answer " + str(
                answer_id
            ) + " displayed on vote result page  (" + answer_total_real_value + ") does not match expected value (" + answer_total_expected_value + "). " + printable_page_source(
                browser)

        # - 3) She checks that each smart ballot tracker in the ballot box page corresponds to the smart ballot tracker of one of our voters, and that there is only one of these, and that the number of smart ballot trackers in this page is the same as the number of voters who voted

        all_ballots_link_label = "See accepted ballots"
        all_ballots_link_element = wait_for_an_element_with_partial_link_text_exists(
            browser, all_ballots_link_label, settings.EXPLICIT_WAIT_TIMEOUT)
        all_ballots_link_element.click()

        all_smart_ballot_trackers_css_selector = "#main ul li a"
        all_smart_ballot_trackers_elements = wait_for_elements_exist(
            browser, all_smart_ballot_trackers_css_selector,
            settings.EXPLICIT_WAIT_TIMEOUT)
        assert len(self.voters_email_addresses_who_have_voted
                   ) == settings.NUMBER_OF_VOTING_VOTERS
        assert len(all_smart_ballot_trackers_elements
                   ) == settings.NUMBER_OF_VOTING_VOTERS
        for voter_email_address in self.voters_email_addresses_who_have_voted:
            voter = self.voters_data[voter_email_address]
            matches = [
                element for element in all_smart_ballot_trackers_elements
                if element.get_attribute('innerText') ==
                voter["smart_ballot_tracker"]
            ]
            assert len(matches) is 1
예제 #4
0
    def administrator_verifies_vote_results(self):
        """
        Initial browser (required) state: on the vote results page
        Final browser state: on the accepted ballots page

        She checks consistency of the vote result:
        - 1) She checks that the number of accepted ballots is the same as the number of voters who voted
        - 2) For each available answer in the question, she checks that the total number of votes in favor of Answer X displayed in result page is the same as the sum of votes for Answer X in all votes of voters who voted that have been randomly generated in advance
        - 3) She checks that each ballot content corresponds to content that of this vote that has been randomly generated in advance


        This screen looks like this:

        This is the development version!
        By using this site, you accept our <personal data policy>. <Accept>
        <en> <fr> <de> <ro> <it>

        This election has been tallied.

            Question 1?
            Answer 1    6
            Answer 2    8

        Number of accepted ballots: 10
        You can also download the <result with cryptographic proofs>.

        <See accepted ballots>

        Where <...> is a link
        """

        browser = self.browser

        # - 1) She checks that the number of accepted ballots is the same as the number of voters who voted

        main_css_selector = "#main"
        main_expected_content = "Number of accepted ballots:"
        main_element = wait_for_element_exists_and_contains_expected_text(browser, main_css_selector, main_expected_content, settings.EXPLICIT_WAIT_TIMEOUT)
        main_text_content = main_element.get_attribute('innerText')

        number_of_accepted_ballots = None
        match = re.search(r'Number of accepted ballots:\s*(\d+)\s', main_text_content, re.MULTILINE | re.DOTALL)
        if match:
            number_of_accepted_ballots = match.group(1)
            number_of_accepted_ballots = number_of_accepted_ballots.strip()
        else:
            raise Exception("Number of accepted ballots not found in election tally page: " + main_text_content)
        assert str(number_of_accepted_ballots) == str(settings.NUMBER_OF_VOTING_VOTERS), "Number of accepted ballots (" + str(number_of_accepted_ballots) + ") is not the same as number of voters (" + str(settings.NUMBER_OF_VOTING_VOTERS) + ")"


        # - 2) For each available answer in the question, she checks that the total number of votes in favor of Answer X displayed in result page is the same as the sum of votes for Answer X in all votes of voters who voted that have been randomly generated in advance

        number_of_votes_per_answer = self.compute_number_of_votes_per_answer()
        question_id = 1
        for answer_id in range(1, 3):
            base_selector = "#main li:nth-child(" + str(question_id) + ") tr:nth-child(" + str(answer_id) + ")"
            answer_label_css_selector = base_selector + " td:nth-child(1)"
            answer_total_css_selector = base_selector + " td:nth-child(2)"
            answer_expected_label = "Answer " + str(answer_id)
            answer_element = browser.find_element_by_css_selector(answer_label_css_selector)
            verify_element_label(answer_element, answer_expected_label)
            answer_total_real_value_element = browser.find_element_by_css_selector(answer_total_css_selector)
            answer_total_real_value = answer_total_real_value_element.get_attribute('innerText').strip()
            answer_total_expected_value = str(number_of_votes_per_answer['answer' + str(answer_id)])
            assert answer_total_real_value == answer_total_expected_value, "Number of votes for Answer " + str(answer_id) + " displayed on vote result page  (" + answer_total_real_value + ") does not match expected value (" + answer_total_expected_value


        # - 3) She checks that each smart ballot tracker in the ballot box page corresponds to the smart ballot tracker of one of our voters, and that there is only one of these, and that the number of smart ballot trackers in this page is the same as the number of voters who voted

        all_ballots_link_label = "See accepted ballots"
        all_ballots_link_element = wait_for_an_element_with_partial_link_text_exists(browser, all_ballots_link_label, settings.EXPLICIT_WAIT_TIMEOUT)
        all_ballots_link_element.click()

        all_smart_ballot_trackers_css_selector = "#main ul li a"
        all_smart_ballot_trackers_elements = wait_for_elements_exist(browser, all_smart_ballot_trackers_css_selector, settings.EXPLICIT_WAIT_TIMEOUT)
        assert len(self.voters_email_addresses_who_have_voted) == settings.NUMBER_OF_VOTING_VOTERS
        assert len(all_smart_ballot_trackers_elements) == settings.NUMBER_OF_VOTING_VOTERS
        for voter_email_address in self.voters_email_addresses_who_have_voted:
            voter = self.voters_data[voter_email_address]
            matches = [element for element in all_smart_ballot_trackers_elements if element.get_attribute('innerText') == voter["smart_ballot_tracker"]]
            assert len(matches) is 1