def construct_test_chart_builder_page(
    driver, live_server, page, stub_subtopic_page, stub_topic_page, test_app_editor, stub_published_measure_page
):
    login(driver, live_server, test_app_editor)
    """
    BROWSE TO POINT WHERE WE CAN ADD A MEASURE
    """
    home_page = HomePage(driver, live_server)
    home_page.click_topic_link(stub_topic_page)
    topic_page = TopicPage(driver, live_server, stub_topic_page)
    topic_page.expand_accordion_for_subtopic(stub_subtopic_page)
    """
    SET UP A SIMPLE DIMENSION WE CAN BUILD TEST CHARTS ON
    """
    topic_page.click_add_measure(stub_subtopic_page)
    topic_page.wait_until_url_contains("/measure/new")
    create_measure(driver, live_server, page, stub_topic_page, stub_subtopic_page)
    topic_page.wait_until_url_contains("/edit")
    edit_measure_page = MeasureEditPage(driver)
    edit_measure_page.get()
    dimension = MinimalRandomDimension()
    edit_measure_page.click_add_dimension()
    edit_measure_page.wait_until_url_contains("/dimension/new")
    create_dimension_page = DimensionAddPage(driver)
    create_dimension_page.set_title(dimension.title)
    create_dimension_page.set_time_period(dimension.time_period)
    create_dimension_page.set_summary(dimension.summary)
    create_dimension_page.click_save()
    edit_dimension_page = DimensionEditPage(driver)
    edit_dimension_page.get()
    edit_dimension_page.wait_for_seconds(1)
    edit_dimension_page.click_create_chart()
    edit_dimension_page.wait_until_url_contains("create-chart")
    chart_builder_page = ChartBuilderPage(driver, edit_dimension_page)
    return chart_builder_page
def construct_test_table_builder_page(driver, live_server, measure_version, rdu_user):
    driver_login(driver, live_server, rdu_user)
    """
    BROWSE TO POINT WHERE WE CAN ADD A MEASURE
    """
    home_page = HomePage(driver, live_server)
    home_page.click_topic_link(measure_version.measure.subtopic.topic)
    topic_page = TopicPage(driver, live_server, measure_version.measure.subtopic.topic)
    topic_page.expand_accordion_for_subtopic(measure_version.measure.subtopic)
    """
    SET UP A SIMPLE DIMENSION WE CAN BUILD TEST TABLES ON
    """
    topic_page.click_add_measure(measure_version.measure.subtopic)
    topic_page.wait_until_url_contains("/measure/new")
    create_measure(
        driver, live_server, measure_version, measure_version.measure.subtopic.topic, measure_version.measure.subtopic
    )
    topic_page.wait_until_url_contains("/edit")
    edit_measure_page = MeasureEditPage(driver)
    edit_measure_page.get()
    dimension = MinimalRandomDimension()
    edit_measure_page.click_add_dimension()
    edit_measure_page.wait_until_url_contains("/dimension/new")
    create_dimension_page = DimensionAddPage(driver)
    create_dimension_page.set_title(dimension.title)
    create_dimension_page.set_time_period(dimension.time_period)
    create_dimension_page.set_summary(dimension.summary)
    create_dimension_page.click_save()
    edit_dimension_page = DimensionEditPage(driver)
    edit_dimension_page.get()
    edit_dimension_page.wait_for_seconds(1)
    edit_dimension_page.click_create_table()
    edit_dimension_page.wait_until_url_contains("create-table")
    table_builder_page = TableBuilderPage(driver)
    return table_builder_page
예제 #3
0
def test_site_search_form_action_updated_by_javascript(driver, live_server):
    home_page = HomePage(driver, live_server)
    home_page.get()
    assert home_page.is_current()

    expected_url = f"http://localhost:{live_server.port}/search"
    assert driver.find_element_by_id("search-form").get_attribute(
        "action") == expected_url
예제 #4
0
    def setUp(self):
        super(ActivitiesTest, self).setUp()
        self.browser = webdriver.Chrome()
        self.browser.implicitly_wait(2)

        # Initialize page-specific helpers
        self.home_page = HomePage(self)
        self.registration_page = RegistrationPage(self)
        self.details_page = ActivityDetailsPage(self)
        self.activity_page = ActivityPage(self)
        self.track_page = ActivityTrackPage(self)
        self.login_page = LoginPage(self)
        self.settings_page = SettingsPage(self)
예제 #5
0
def test_post(browser):

    link = "http://example.com"

    page = HomePage(browser, url)

    validate_title(page)
    validate_structure(page)
    validate_content(page, "URL Shortener")

    enter_link(page, link)
    submit(page)
    validate_redirect(page)
    validate_content(page, "URL Shortener")
    validate_structure(page)
    validate_result(page)

    submit(page)
    validate_redirect(page)
    validate_content(page, "Enter a valid URL")

    enter_link(page, "")
    submit(page)
    validate_redirect(page)
    validate_content(page, "Enter a valid URL")

    enter_link(page, "abc123")
    submit(page)
    validate_redirect(page)
    validate_content(page, "Enter a valid URL")
def test_adding_an_existing_data_source(driver, app, live_server):
    rdu_user = UserFactory(user_type=TypeOfUser.RDU_USER, active=True)

    topic = TopicFactory.create(title="Police and crime")
    subtopic = SubtopicFactory.create(title="Policing", topic=topic)
    DataSourceFactory.create(title="Police statistics 2019")

    existing_measure = MeasureFactory.create(subtopics=[subtopic])
    MeasureVersionFactory.create(status="APPROVED", measure=existing_measure)

    driver_login(driver, live_server, rdu_user)
    home_page = HomePage(driver, live_server)

    home_page.click_topic_link(topic)

    topic_page = TopicPage(driver, live_server, topic)
    topic_page.expand_accordion_for_subtopic(subtopic)

    topic_page.click_add_measure(subtopic)

    create_measure_page = MeasureEditPage(driver)
    create_measure_page.set_title("Arrests")
    create_measure_page.click_save()

    create_measure_page.click_add_primary_data_source()

    fill_in(driver,
            label_text="Search for an existing data source",
            with_text="Police statistics")
    click_button_with_text(driver, "Search")

    label_for_existing_data_source = driver.find_element_by_xpath(
        "//label[text()='Police statistics 2019']")

    label_for_existing_data_source.click()

    click_button_with_text(driver, "Select")

    assert "Successfully added the data source ‘Police statistics 2019’" in driver.page_source

    click_link_with_text(driver, "Preview this version")

    assert "Police statistics 2019" in driver.page_source
def navigate_to_topic_page(driver, live_server, topic_page):
    """
    ENTRY 1: Home page
    """
    home_page = HomePage(driver, live_server)
    home_page.get()
    assert home_page.is_current()
    """
    ENTRY 1: Go to topic page
    """
    home_page.click_topic_link(topic_page)
예제 #8
0
def test_can_search_from_homepage_with_javascript(driver, live_server):
    home_page = HomePage(driver, live_server)
    home_page.get()
    assert home_page.is_current()

    home_page.search_site("health")
예제 #9
0
def test_get(browser):
    page = HomePage(browser, url)

    validate_title(page)
    validate_structure(page)
    validate_content(page, "URL Shortener")
def test_can_create_a_measure_page(driver, app, test_app_editor, live_server,
                                   stub_topic_page, stub_subtopic_page,
                                   stub_published_measure_page):
    page = RandomMeasure()

    login(driver, live_server, test_app_editor)
    """
    BROWSE TO POINT WHERE WE CAN ADD A MEASURE
    """
    home_page = HomePage(driver, live_server)
    home_page.click_topic_link(stub_topic_page)

    topic_page = TopicPage(driver, live_server, stub_topic_page)
    topic_page.expand_accordion_for_subtopic(stub_subtopic_page)
    """
    CREATE A NEW MEASURE
    """
    topic_page.click_add_measure(stub_subtopic_page)
    topic_page.wait_until_url_contains("/measure/new")
    create_measure(driver, live_server, page, stub_topic_page,
                   stub_subtopic_page)
    """
    EDIT THE MEASURE
    """
    topic_page.wait_until_url_contains("/edit")
    edit_measure_page = MeasureEditPage(driver)

    edit_measure_page.set_measure_summary(page.measure_summary)
    edit_measure_page.set_summary(page.summary)
    edit_measure_page.click_save()
    assert edit_measure_page.is_current()
    """
    PREVIEW CURRENT PROGRESS
    """
    edit_measure_page.click_preview()
    edit_measure_page.wait_until_url_does_not_contain("/cms/")

    preview_measure_page = MeasurePreviewPage(driver)
    assert preview_measure_page.is_current()

    assert_page_contains(preview_measure_page, page.title)
    assert_page_contains(preview_measure_page, page.measure_summary)
    assert_page_contains(preview_measure_page, page.summary)
    """
    ADD A DIMENSION
    Save some dimension data
    """
    edit_measure_page.get()
    assert edit_measure_page.is_current()

    dimension = RandomDimension()

    edit_measure_page.click_add_dimension()
    edit_measure_page.wait_until_url_contains("/dimension/new")

    create_dimension_page = DimensionAddPage(driver)

    create_dimension_page.set_title(dimension.title)
    create_dimension_page.set_time_period(dimension.time_period)
    create_dimension_page.set_summary(dimension.summary)
    create_dimension_page.click_save()

    create_dimension_page.wait_for_seconds(1)
    edit_dimension_page = DimensionEditPage(driver)
    assert edit_dimension_page.is_current()

    preview_measure_page.get()
    edit_dimension_page.wait_until_url_does_not_contain("/cms/")
    assert_page_contains(preview_measure_page, dimension.title)
    assert_page_contains(preview_measure_page, dimension.time_period)
    assert_page_contains(preview_measure_page, dimension.summary)
    """
    EDIT A DIMENSION
    """
    edit_dimension_page.get()
    edit_dimension_page.wait_for_seconds(1)
    assert edit_dimension_page.is_current()

    edit_dimension_page.set_summary("some updated text")
    edit_dimension_page.click_update()

    assert edit_dimension_page.is_current()

    preview_measure_page.get()
    edit_dimension_page.wait_until_url_does_not_contain("/cms/")
    assert_page_contains(preview_measure_page, "some updated text")
    """
    CHART BUILDER
    test content has been moved to a separate set of functional tests
    """
    """
    CREATE A SIMPLE TABLE
    """
    edit_dimension_page.get()
    edit_dimension_page.wait_for_seconds(1)
    assert edit_dimension_page.is_current()
    edit_dimension_page.click_create_table()
    edit_dimension_page.wait_until_url_contains("create-table")

    table_builder_page = TableBuilderPage(driver)
    assert table_builder_page.is_current()

    inject_data(driver, simple_data)
    table_builder_page.click_data_okay()
    table_builder_page.wait_for_seconds(1)
    table_builder_page.select_column(1, "Value")
    table_builder_page.wait_for_seconds(1)
    table_builder_page.click_save()
    table_builder_page.wait_for_seconds(1)
    """
    CREATE A TABLE WITH TWO COLUMNS
    """
    table_builder_page.get()
    table_builder_page.click_data_edit()
    table_builder_page.wait_for_seconds(1)
    inject_data(driver, ethnicity_by_gender_data)
    table_builder_page.click_data_okay()
    table_builder_page.wait_for_seconds(1)

    table_builder_page.select_data_style("Use ethnicity for rows")
    table_builder_page.wait_for_seconds(1)
    table_builder_page.select_columns_when_ethnicity_is_row("Gender")
    table_builder_page.select_column(1, "Value")
    table_builder_page.select_column(2, "Gender")
    table_builder_page.wait_for_seconds(1)

    table_builder_page.click_save()
    table_builder_page.wait_for_seconds(1)
예제 #11
0
class ActivitiesTest(FileDeleter, StaticLiveServerTestCase):
    fixtures = ['two-users-no-data.json']

    def setUp(self):
        super(ActivitiesTest, self).setUp()
        self.browser = webdriver.Chrome()
        self.browser.implicitly_wait(2)

        # Initialize page-specific helpers
        self.home_page = HomePage(self)
        self.registration_page = RegistrationPage(self)
        self.details_page = ActivityDetailsPage(self)
        self.activity_page = ActivityPage(self)
        self.track_page = ActivityTrackPage(self)
        self.login_page = LoginPage(self)
        self.settings_page = SettingsPage(self)

    def tearDown(self):
        super(ActivitiesTest, self).tearDown()
        self.browser.quit()

    def test_basic_look_and_feel(self):
        # Visitor comes to homepage and notices title is SailTrail
        self.home_page.go_to_homepage()
        self.assertIn('SailTrail', self.browser.title)

    def test_registration(self):
        # Visitor comes to homepage
        self.home_page.go_to_homepage()

        # The notice the register link and click it, then try to immediately
        # click register
        self.home_page.go_to_registration()
        self.registration_page.click_register()

        # They are warned that fields cannot be empty
        alerts = self.registration_page.get_all_alerts()
        self.assertEqual(4, len(alerts))
        self.assertIn('This field is required.', alerts[0].text)

        # They enter just a username, and are still warned
        self.registration_page.enter_username('testuser')
        self.registration_page.click_register()
        alerts = self.registration_page.get_all_alerts()
        self.assertEqual(3, len(alerts))
        self.assertIn('This field is required.', alerts[0].text)

        # They enter a username and valid email, and are still warned
        self.registration_page.enter_username('testuser')
        self.registration_page.enter_email('*****@*****.**')
        self.registration_page.click_register()
        alerts = self.registration_page.get_all_alerts()
        self.assertEqual(2, len(alerts))
        self.assertIn('This field is required.', alerts[0].text)

        # They enter a username, valid email, and first password, and
        # are still warned
        self.registration_page.enter_username('testuser')
        self.registration_page.enter_email('*****@*****.**')
        self.registration_page.enter_password1('password')
        self.registration_page.click_register()
        alerts = self.registration_page.get_all_alerts()
        self.assertEqual(1, len(alerts))
        self.assertIn('This field is required.', alerts[0].text)

        # They enter a username, valid email, and two passwords
        # that don't match, and are warned
        self.registration_page.enter_username('testuser')
        self.registration_page.enter_email('*****@*****.**')
        self.registration_page.enter_password1('password')
        self.registration_page.enter_password2('other')
        self.registration_page.click_register()
        alerts = self.registration_page.get_all_alerts()
        self.assertEqual(1, len(alerts))
        self.assertIn("You must type the same password each time.",
                      alerts[0].text)

        # They enter a username, invalid email, and matching passwords
        # and are warned about the email address
        self.registration_page.enter_username('testuser')
        self.registration_page.enter_email('testuser')
        self.registration_page.enter_password('password')
        self.registration_page.click_register()
        alerts = self.registration_page.get_all_alerts()
        self.assertEqual(1, len(alerts))
        self.assertIn("Enter a valid email address.", alerts[0].text)

        # They enter an existing username, valid email, and matching passwords
        # and are warned about the email address
        self.registration_page.enter_username('registered')
        self.registration_page.enter_email('*****@*****.**')
        self.registration_page.enter_password('password')
        self.registration_page.click_register()
        alerts = self.registration_page.get_all_alerts()
        self.assertEqual(1, len(alerts))
        self.assertIn("A user with that username already exists",
                      alerts[0].text)

        # Finally, the fill in good info, submit, and
        # are taken to a page telling them that they need to confirm their
        # email address.
        self.home_page.go_to_registration()
        self.registration_page.register('testuser')

        # They see a message about how they will be recieving an email
        self.assertIn('Verify Your E-mail Address',
                      self.home_page.get_page_content())

        # Internally, an email is sent, with registration confirmation details
        self.assertEqual(1, len(mail.outbox))
        message = mail.outbox[0]
        self.assertEqual('*****@*****.**', message.from_email)
        self.assertIn('Please Confirm Your E-mail Address', message.subject)

        for line in message.body.split('\n'):
            if 'localhost' in line:
                url = line.split(' ')[-1][8:]

        # The user follows the link in the email, and is asked
        # to confirm that they entered this info
        self.browser.get(url)
        self.assertIn('Confirm E-mail Address',
                      self.home_page.get_page_content())

        # They click confirm and are taken to the login page
        submit_btn = self.browser.find_element_by_id('submit-btn')
        self.home_page.click_through_to_new_page(submit_btn)

        # They login and are taken home
        self.login_page.login_as_user('testuser', 'password')
        self.assertTrue(self.home_page.is_current_url())

    def test_new_user_flow(self):
        # Visitor comes to homepage
        with self.settings(MEDIA_ROOT=self.temp_dir,
                           REMOTE_MAP_SOURCE='fake'):
            self.home_page.go_to_homepage()

            # The notice the register link and click it, fill in their info,
            # submit, and are taken back to the homepage
            self.home_page.go_to_registration()
            self.registration_page.register('testuser')

            message = mail.outbox[0]
            for line in message.body.split('\n'):
                if 'localhost' in line:
                    url = line.split(' ')[-1][8:]
            self.browser.get(url)
            submit_btn = self.browser.find_element_by_id('submit-btn')
            self.home_page.click_through_to_new_page(submit_btn)
            self.login_page.login_as_user('testuser', 'password')

            self.assertTrue(self.home_page.is_current_url())

            # They notice a file upload box and are prompted to upload a file
            self.home_page.upload_file('tiny.SBN')

            # They are taken to the new details page, where they notice
            # the date and time and duration of the session listed
            self.assertIn('July 15, 2014',
                          self.details_page.get_page_content())
            self.assertIn('10:37 p.m.', self.details_page.get_page_content())
            self.assertIn('0:00:03', self.details_page.get_page_content())

            # They are taken to the new activity page, where they are
            # prompted to enter details about the uploaded file
            name = 'First winter kite session!'
            desc = 'The very first session of the year'
            self.details_page.enter_details(name, desc)

            # They hit 'OK' and are redirected to the activity page,
            # where they notice that their name and description are shown
            self.details_page.click_ok()
            self.assertIn(name, self.activity_page.get_page_content())

            # They return to the homepage and see the activity listed
            self.home_page.go_to_homepage()
            self.assertIn(name, self.home_page.get_page_content())

            # The visitor decides to logout, and when the homepage refreshes
            # they notice that they are no longer logged in
            self.home_page.logout()
            self.assertTrue(self.home_page.is_current_url())
            self.assertFalse(
                self.home_page.is_user_dropdown_present('testuser'))

            # They decide to log back in, and can again see their name
            self.home_page.login()
            self.login_page.login_as_user('testuser', 'password')
            self.assertTrue(self.home_page.is_current_url())
            self.assertTrue(
                self.home_page.is_user_dropdown_present('testuser'))

    def test_login_logout(self):
        # Visit goes to homepage and clicks Login
        self.home_page.go_to_homepage()
        self.home_page.login()

        # They try to click the login button without entering, and see
        # errors
        self.login_page.click_login()
        self.assertIn('This field is required', self.login_page.get_alerts())

        # They enter a username, but forget a password, and are warned
        self.login_page.login_as_user('testuser', '')
        self.assertIn('This field is required', self.login_page.get_alerts())

        # They enter a password, but forget a username, and are warned
        self.login_page.login_as_user('', 'password')
        self.assertIn('This field is required', self.login_page.get_alerts())

        # They enter a bad username and password and are warned
        self.login_page.login_as_user('testuser', 'password')
        self.assertIn('The username and/or password you specified are ' +
                      'not correct', self.login_page.get_alerts())

        # They enter a good, existing username and are taken back to the
        # homepage where they can see they are logged in
        self.login_page.login_as_user('registered', 'password')
        self.assertTrue(self.home_page.is_current_url())
        self.assertTrue(self.home_page.is_user_dropdown_present('registered'))

        # They click logout and are logged out
        self.home_page.logout()
        self.assertTrue(self.home_page.is_current_url())
        self.assertFalse(self.home_page.is_user_dropdown_present('registered'))

    def test_uploading(self):
        with self.settings(MEDIA_ROOT=self.temp_dir,
                           REMOTE_MAP_SOURCE='fake'):
            # Known user comes to homepage and logs in
            self.home_page.go_to_homepage()
            self.home_page.login()
            self.login_page.login_as_user('registered', 'password')
            self.assertTrue(
                self.home_page.is_user_dropdown_present('registered'))

            # They upload an SBN file
            self.home_page.upload_file('tiny.SBN')

            # They are taken to the new details page, where they notice
            # the date and time and duration of the session listed
            self.assertIn('July 15, 2014',
                          self.details_page.get_page_content())
            self.assertIn('10:37 p.m.', self.details_page.get_page_content())
            self.assertIn('0:00:03', self.details_page.get_page_content())

            name = 'First winter kite session!'
            desc = 'The very first session of the year'
            self.details_page.enter_details(name, desc)

            # They hit 'OK' and are redirected to the activity page,
            # where they notice that their name and description are shown
            self.details_page.click_ok()
            self.assertIn(name, self.activity_page.get_page_content())
            self.assertIn(desc, self.activity_page.get_page_content())

            # They return to the homepage and click upload without
            # choosing a file!
            self.home_page.go_to_homepage()
            self.home_page.upload_without_file()

            # They get a helpful error message telling them this
            # is not okay! They decide to cancel
            self.assertIn(ERROR_NO_UPLOAD_FILE_SELECTED,
                          self.home_page.get_alerts())
            self.home_page.cancel_upload()

            # They upload another file (choosing a GPX file this time),
            # but this time on the details screen they click cancel
            self.home_page.upload_file('tiny-run.gpx')
            name = 'A short GPX-based activity'
            desc = 'Very short'
            self.details_page.enter_details(name, desc)
            self.details_page.select_activity_type("Windsurfing")

            # They hit 'OK' and are redirected to the activity page,
            # where they see the usual details, as well as a notice that
            # the activity is marked as private.
            self.details_page.click_ok()
            content = self.activity_page.get_page_content()
            self.assertIn(name, content)
            self.assertIn(desc, content)
            self.assertIn("Windsurfing", content)
            self.assertIn("March 16, 2011", content)
            self.assertIn("0:03:01", content)
            self.assertIn("0.27 nmi", content)
            self.assertIn("5.6 knots", content)

            # They try the upload again (with a non-supported text-file)
            # and see an error warning them not to do that, so they hit cancel
            self.home_page.go_to_homepage()
            self.home_page.upload_file('bad.txt')
            self.assertIn(ERROR_UNSUPPORTED_FILE_TYPE,
                          self.home_page.get_alerts())
            self.home_page.cancel_upload()

    def test_change_user_password(self):
        settings_page = SettingsPage(self)
        change_password_page = ChangePasswordPage(self)

        self.home_page.go_to_homepage()
        self.home_page.login()
        self.login_page.login_as_user('registered', 'password')
        self.assertTrue(self.home_page.is_user_dropdown_present('registered'))

        # User goes to their settings page
        self.home_page.goto_user_settings()
        content = settings_page.get_page_content()
        self.assertIn("Settings for registered", content)

        # Click link to change password and are taken to the password page
        settings_page.click_change_password()
        self.assertIn('Change Password', self.browser.title)

        # They try to click change password without entering anything and
        # are warned not to do that
        change_password_page.submit_password_change()
        alerts = change_password_page.get_all_alerts()
        self.assertEqual(3, len(alerts))
        self.assertIn("This field is required", alerts[0].text)
        self.assertIn("This field is required", alerts[1].text)
        self.assertIn("This field is required", alerts[2].text)

        # They then enter the wrong current password, but a matching new
        # password
        change_password_page.change_password('badpassword', 'newpassword',
                                             'newpassword')
        alerts = change_password_page.get_all_alerts()
        self.assertEqual(1, len(alerts))
        self.assertIn("Please type your current password", alerts[0].text)

        # They then enter the current password, but non-matching new passwords
        change_password_page.change_password('password', 'newpassword',
                                             'newpassword2')
        alerts = change_password_page.get_all_alerts()
        self.assertEqual(1, len(alerts))
        self.assertIn("You must type the same password each time",
                      alerts[0].text)

        # They then enter the current password and matching new passwords and
        # are redirected back to the homepage where an alert tells them they
        # have successfully updated their password
        change_password_page.change_password('password', 'newpassword',
                                             'newpassword')
        settings_page.assert_is_current_url_for_user('registered')
        self.assertIn("Password successfully updated",
                      settings_page.get_success_alert_text())

        # They refresh the page and notice that the alert is now gone
        self.browser.refresh()
        settings_page.assert_is_current_url_for_user('registered')
        with self.assertRaises(NoSuchElementException):
            settings_page.get_success_alert_text()

        # The logout and are able to log back in with the new password
        # They enter a good, existing username and are taken back to the
        # homepage where they can see they are logged in
        self.home_page.logout()
        self.assertFalse(self.home_page.is_user_dropdown_present('registered'))

        self.home_page.login()
        self.login_page.login_as_user('registered', 'newpassword')
        self.assertTrue(self.home_page.is_current_url())
        self.assertTrue(self.home_page.is_user_dropdown_present('registered'))

    def test_change_email(self):
        settings_page = SettingsPage(self)
        change_email_page = ChangeEmailPage(self)

        self.home_page.go_to_homepage()
        self.home_page.login()
        self.login_page.login_as_user('registered', 'password')
        self.assertTrue(self.home_page.is_user_dropdown_present('registered'))

        # User goes to their settings page
        self.home_page.goto_user_settings()

        # They click the change email link and are taken to the email page
        settings_page.click_change_email()
        self.assertIn('Your email addresses', self.browser.title)

        # They try to add a new email address without entering anything
        # and are warned about it
        change_email_page.click_add_email()
        self.assertIn("This field is required",
                      change_email_page.get_alerts())

        # They enter an invalid address and are warned about it
        change_email_page.enter_email_and_submit("test")
        self.assertIn("Enter a valid email address",
                      change_email_page.get_alerts())

        # They enter the address they are already registered with and are
        # warned
        change_email_page.enter_email_and_submit("*****@*****.**")
        self.assertIn("This e-mail address is already associated with " +
                      "this account", change_email_page.get_alerts())

        # They enter the address that another user has used and are warned
        change_email_page.enter_email_and_submit("*****@*****.**")
        self.assertIn("This e-mail address is already associated with " +
                      "another account", change_email_page.get_alerts())

        # They enter a new address and see it added to the list, unverified
        change_email_page.enter_email_and_submit("*****@*****.**")
        content = change_email_page.get_page_content()
        self.assertIn("*****@*****.**", content)
        self.assertIn("Unverified", content)

        # They check their inbox, where they have a confirmation link, which
        # they follow
        message = mail.outbox[0]
        for line in message.body.split('\n'):
            if 'localhost' in line:
                url = line.split(' ')[-1][8:]
        self.browser.get(url)
        submit_btn = self.browser.find_element_by_id('submit-btn')
        content = change_email_page.get_page_content()
        self.assertIn("Please confirm that [email protected]", content)
        self.home_page.click_through_to_new_page(submit_btn)

        # User goes to their settings page and go back to the email page, where
        # they see that their new address is verified
        self.home_page.goto_user_settings()
        settings_page.click_change_email()
        content = change_email_page.get_page_content()
        self.assertIn("*****@*****.**", content)
        self.assertNotIn("Unverified", content)

        # They select the new email from the list and click remove
        self.browser.find_element_by_id('email_radio_2').click()
        self.browser.find_element_by_name('action_remove').click()

        # The are warned, and click cancel
        alert = self.browser.switch_to.alert
        self.assertEqual(alert.text,
                         "Do you really want to remove " +
                         "the selected e-mail address?")
        alert.dismiss()

        # The address is still in the list
        content = change_email_page.get_page_content()
        self.assertIn("*****@*****.**", content)

        # They click cancel again
        self.browser.find_element_by_id('email_radio_2').click()
        self.browser.find_element_by_name('action_remove').click()
        alert = self.browser.switch_to.alert
        alert.accept()

        # The address is no longer in the list
        content = change_email_page.get_page_content()
        self.assertNotIn("*****@*****.**", content)

    def test_private_activity(self):
        # Registered user comes in and logs in
        with self.settings(MEDIA_ROOT=self.temp_dir,
                           REMOTE_MAP_SOURCE='fake'):
            self.home_page.go_to_homepage()
            self.home_page.login()
            self.login_page.login_as_user('registered', 'password')
            self.assertTrue(
                self.home_page.is_user_dropdown_present('registered'))

            # They successfully upload a GPX file and
            # fill in the revelant details, including the category. They notice
            # the Private checkbox and check it
            self.home_page.upload_file('tiny-run.gpx')
            name = 'A short GPX-based activity'
            desc = 'Very short'
            self.details_page.enter_details(name, desc)
            self.details_page.select_activity_type("Windsurfing")
            self.details_page.enable_private()

            # They hit 'OK' and are redirected to the activity page,
            # where they see the usual details, as well as a notice that
            # the activity is marked as private.
            self.details_page.click_ok()
            content = self.activity_page.get_page_content()
            self.assertIn(name, content)
            self.assertIn(desc, content)
            self.assertIn("Windsurfing", content)
            self.assertIn("March 16, 2011", content)
            self.assertIn("0:03:01", content)
            self.assertIn("0.27 nmi", content)
            self.assertIn("5.6 knots", content)
            self.assertIn("This activity is currently private", content)
            private_url = self.browser.current_url

            # The visitor returns to the home page and sees their new
            # activity (marked as private)
            self.home_page.go_to_homepage()
            content = self.home_page.get_page_content()
            self.assertIn(name, content)
            self.assertIn("Sailed by registered", content)
            self.assertIn("Private", content)

            # The visitor decides to logout, and when the homepage refreshes
            # they notice that their private activity is not longer visible
            self.home_page.logout()
            content = self.home_page.get_page_content()
            self.assertNotIn(name, content)
            self.assertNotIn("Private", content)

            # They decide to log back in, and can again see their activity
            self.home_page.login()
            self.login_page.login_as_user('registered', 'password')
            content = self.home_page.get_page_content()
            self.assertIn(name, content)
            self.assertIn("Sailed by registered", content)
            self.assertIn("Private", content)

            # The visitor logouts, and when the homepage refreshes
            # they notice that their private activity is not longer visible
            self.home_page.logout()
            content = self.home_page.get_page_content()
            self.assertNotIn(name, content)
            self.assertNotIn("Private", content)

            # Another user comes along and logs in, and they don't see
            # the other users private activity
            self.home_page.login()
            self.login_page.login_as_user('another', 'password')
            content = self.home_page.get_page_content()
            self.assertNotIn(name, content)
            self.assertNotIn("Private", content)

            # Somehow the second user guesses the url of the other
            # users private activity and tries to visit it.
            self.browser.get(private_url)
            content = self.home_page.get_page_content()
            self.assertIn("Access Denied", content)

    def test_edit_activity_details(self):
        with self.settings(MEDIA_ROOT=self.temp_dir,
                           REMOTE_MAP_SOURCE='fake'):
            self.home_page.go_to_homepage()
            self.home_page.login()
            self.login_page.login_as_user('registered', 'password')
            self.assertTrue(
                self.home_page.is_user_dropdown_present('registered'))

            # They upload a file with some details
            self.home_page.upload_file('tiny.SBN')
            name = 'First winter kite session!'
            desc = 'The very first session of the year'
            self.details_page.enter_details(name, desc)

            # They hit 'OK' and are redirected to the activity page,
            # where they notice that their name and description are shown
            self.details_page.click_ok()
            self.assertIn(name, self.activity_page.get_page_content())
            self.assertIn(desc, self.activity_page.get_page_content())

            # They notice an 'edit' link, and click it
            self.activity_page.click_edit()

            # They are taken to a page where they can edit their page.
            # They make a change to the description and hit ok
            new_desc = 'Updated description'
            self.details_page.enter_description(new_desc)
            self.details_page.click_ok()

            # They are redirected to the activity page,
            # where they can see that the description has been updated
            self.assertIn(name, self.activity_page.get_page_content())
            self.assertIn(new_desc, self.activity_page.get_page_content())
            self.assertNotIn(desc, self.activity_page.get_page_content())

            # They click the edit button again, update the name, then
            # change their mind and hit 'cancel'
            self.activity_page.click_edit()
            new_name = 'Updated activity name'
            self.details_page.enter_name(new_name)
            self.details_page.click_cancel()

            # They are taken back to the activity page and the details
            # are as they were before
            self.assertIn(name, self.activity_page.get_page_content())
            self.assertNotIn(new_name, self.activity_page.get_page_content())
            self.assertIn(new_desc, self.activity_page.get_page_content())
            self.assertNotIn(desc, self.activity_page.get_page_content())

            # They click the edit button again, blank out the name, try to
            # save, and are warned that that's not okay,
            self.activity_page.click_edit()
            new_name = ''
            self.details_page.enter_name(new_name)
            self.details_page.click_ok()
            self.assertIn(ERROR_ACTIVITY_NAME_MISSING,
                          self.details_page.get_alerts())

            # They then change their mind and hit 'cancel'
            self.details_page.click_cancel()

            # They are taken back to the activity page and the details
            # are as they were before
            self.assertIn(name, self.activity_page.get_page_content())
            self.assertIn(new_desc, self.activity_page.get_page_content())

            time.sleep(.5)  # Wait for javascript to finish

            # They notice the computed wind direction on the activity page
            self.assertEqual('3', self.activity_page.get_winddir())

            # They press the down button three times, noticing the wind
            # direction updates afterwards
            self.browser.find_element_by_tag_name('body').send_keys(
                Keys.ARROW_DOWN, Keys.ARROW_DOWN, Keys.ARROW_DOWN
            )
            self.assertEqual('0', self.activity_page.get_winddir())
            time.sleep(.5)  # Wait for AJAX POST to finish

            # They reload the browser and see that the value is still 0
            self.browser.refresh()
            self.assertEqual('0', self.activity_page.get_winddir())

    def test_deleting_activity(self):
        with self.settings(MEDIA_ROOT=self.temp_dir,
                           REMOTE_MAP_SOURCE='fake'):
            self.home_page.go_to_homepage()
            self.home_page.login()
            self.login_page.login_as_user('registered', 'password')
            self.assertTrue(
                self.home_page.is_user_dropdown_present('registered'))

            # They upload a file with some details
            self.home_page.upload_file('tiny.SBN')
            name = 'First winter kite session!'
            desc = 'The very first session of the year'
            self.details_page.enter_details(name, desc)
            self.details_page.click_ok()

            # They head over to the home page, where they see the activity
            self.home_page.go_to_homepage()
            self.assertIn(name, self.home_page.get_page_content())

            # They return to the activity page, and click delete.
            self.home_page.go_to_activity(name)
            self.activity_page.click_delete()
            self.assertTrue(self.activity_page.delete_modal_is_visible())
            self.activity_page.click_cancel_delete()
            self.assertFalse(self.activity_page.delete_modal_is_visible())

            # They head over to the home page, where they see the activity
            self.home_page.go_to_homepage()
            self.assertIn(name, self.home_page.get_page_content())

            # They return to the activity page, and click delete.
            # decide to confirm, and are returned to the homepage,
            self.home_page.go_to_activity(name)
            self.activity_page.click_delete()
            self.assertTrue(self.activity_page.delete_modal_is_visible())
            self.activity_page.click_confirm_delete()
            self.assertTrue(self.home_page.is_current_url())

            # They notice that their activity is no longer listed
            self.assertNotIn(name, self.home_page.get_page_content())

    def test_adding_and_deleting_tracks(self):
        with self.settings(MEDIA_ROOT=self.temp_dir,
                           REMOTE_MAP_SOURCE='fake'):
            self.home_page.go_to_homepage()
            self.home_page.login()
            self.login_page.login_as_user('registered', 'password')
            self.assertTrue(
                self.home_page.is_user_dropdown_present('registered'))

            # Third times the charm, they successful upload a GPX file and
            # fill in the revelant details, including the category. They notice
            # the Private checkbox and check it
            self.home_page.upload_file('tiny-run.gpx')
            name = 'A short GPX-based activity'
            self.details_page.enter_details(name, '')
            self.details_page.click_ok()

            # They return to their activity, and click "Add Track"
            self.activity_page.click_add_track()
            self.assertTrue(self.activity_page.add_track_modal_is_visible())

            # The visitor uploads a new track
            self.activity_page.upload_track('tiny-run-2.gpx')
            content = self.activity_page.get_page_content()
            self.assertIn("tiny-run.gpx", content)
            self.assertIn("tiny-run-2.gpx", content)
            self.assertIn("0:05:31", content)
            self.assertIn("0.54 nmi", content)
            self.assertIn("11.89 knots", content)

            # They click "Add Track" again and try to upload
            # without choosing a file, and are warned not to do that
            self.activity_page.click_add_track()
            self.activity_page.click_upload()
            self.assertIn(ERROR_NO_UPLOAD_FILE_SELECTED,
                          self.activity_page.get_alerts())
            self.activity_page.cancel_upload()

            # They next try to upload a non-supported text-file as a new track
            # and see an error warning them not to do that, so they hit cancel
            self.activity_page.upload_track('bad.txt')
            self.assertIn(ERROR_UNSUPPORTED_FILE_TYPE,
                          self.activity_page.get_alerts())
            self.activity_page.cancel_upload()

            # They click on the link to get to first track segment and
            # notice the trim activity section
            self.activity_page.go_to_track("tiny-run.gpx")
            content = self.track_page.get_page_content()
            self.assertIn("Trim Track", content)

            # They notice the delete button and click it,
            # and the model pops up
            self.track_page.click_delete()
            self.assertTrue(self.track_page.delete_modal_is_visible())

            # They click cancel and the modal disappears
            self.track_page.click_cancel()
            self.assertFalse(self.track_page.delete_modal_is_visible())

            # They change their mind, click delete again and confirm
            self.track_page.click_delete()
            self.track_page.click_delete_it()

            # The visitor is taken back to the activity page, where
            # the track is no longer listed
            content = self.activity_page.get_page_content()
            self.assertIn("tiny-run-2.gpx", content)
            self.assertNotIn("tiny-run.gpx", content)
            self.assertIn("0:02:00", content)
            self.assertIn("0.27 nmi", content)
            self.assertIn("11.89 knots", content)

    def test_track_trimming(self):

        trim_page = ActivityTrackTrimPage(self)

        with self.settings(MEDIA_ROOT=self.temp_dir,
                           REMOTE_MAP_SOURCE='fake'):
            self.home_page.go_to_homepage()
            self.home_page.login()
            self.login_page.login_as_user('registered', 'password')
            self.assertTrue(
                self.home_page.is_user_dropdown_present('registered'))

            # Third times the charm, they successful upload a GPX file and
            # fill in the relevant details, including the category. They notice
            # the Private checkbox and check it
            self.home_page.upload_file('tiny-run-2.gpx')
            name = 'A short GPX-based activity'
            self.details_page.enter_details(name, '')
            self.details_page.click_ok()

            # The activity page contains details about their activity
            content = self.activity_page.get_page_content()
            self.assertIn("0:02:00", content)
            self.assertIn("0.27 nmi", content)
            self.assertIn("11.89 knots", content)

            # They return to the individual track page, and decide to try
            # trimming it
            self.activity_page.go_to_track("tiny-run-2.gpx")
            self.track_page.go_to_trim()
            trim_page.press_right_arrow()
            trim_page.press_down_arrow()
            trim_page.click_trim_activity()

            # The visitor is taken back to the activity page, where
            # the track is now trimmed
            content = self.activity_page.get_page_content()
            self.assertIn("0:01:00", content)
            self.assertIn("0.19 nmi", content)
            self.assertIn("11.89 knots", content)
            self.assertIn("tiny-run-2.gpx (trimmed)", content)

            # They return to the track page, and click untrim
            self.activity_page.go_to_track("tiny-run-2.gpx (trimmed)")
            self.track_page.click_untrim()

            # The activity details are untrimmed
            content = self.activity_page.get_page_content()
            self.assertIn("0:02:00", content)
            self.assertIn("0.27 nmi", content)
            self.assertIn("11.89 knots", content)
            self.assertNotIn("(trimmed)", content)