From 022ee6cf2d553b81f1e079d13714611e0b600a03 Mon Sep 17 00:00:00 2001 From: Dave Hunt Date: Thu, 16 Nov 2017 00:49:52 +0100 Subject: [PATCH] Migrate to PyPOM and remove implicit waits (#387) --- pages/about.py | 3 - pages/auth0.py | 14 +-- pages/base.py | 71 +++++++------- pages/confirm_profile_delete.py | 5 +- pages/create_group_page.py | 15 ++- pages/edit_group.py | 100 ++++++++++---------- pages/edit_profile.py | 51 +++++------ pages/group_info_page.py | 18 ++-- pages/groups_page.py | 13 ++- pages/home_page.py | 19 +--- pages/invite.py | 13 +-- pages/invite_success.py | 5 +- pages/link_crawler.py | 2 - pages/location_search_results.py | 17 ++-- pages/page.py | 102 --------------------- pages/profile.py | 54 +++++------ pages/register.py | 60 ++++++------ pages/search.py | 47 +++++----- pages/settings.py | 153 +++++++++++++++---------------- requirements/tests.txt | 1 + tests/conftest.py | 7 -- tests/test_about_page.py | 4 +- tests/test_account.py | 8 +- tests/test_group.py | 8 +- tests/test_invite.py | 6 +- tests/test_profile.py | 49 +++++----- tests/test_redirects.py | 2 - tests/test_register.py | 6 +- tests/test_search.py | 14 ++- 29 files changed, 344 insertions(+), 523 deletions(-) delete mode 100644 pages/page.py diff --git a/pages/about.py b/pages/about.py index b0d31a4..642fbba 100644 --- a/pages/about.py +++ b/pages/about.py @@ -1,10 +1,7 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. - from selenium.webdriver.common.by import By from pages.base import Base diff --git a/pages/auth0.py b/pages/auth0.py index c98d8b4..cc46511 100644 --- a/pages/auth0.py +++ b/pages/auth0.py @@ -2,9 +2,9 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +from pypom import Page from selenium.webdriver.common.by import By - -from pages.page import Page +from selenium.webdriver.support import expected_conditions as expected class Auth0(Page): @@ -14,8 +14,8 @@ class Auth0(Page): _send_email_button_locator = (By.CSS_SELECTOR, '.auth0-lock-passwordless-submit') def request_login_link(self, username): - self.wait_for_element_visible(*self._login_with_email_button_locator) - self.selenium.find_element(*self._login_with_email_button_locator).click() - self.wait_for_element_visible(*self._email_input_locator) - self.selenium.find_element(*self._email_input_locator).send_keys(username) - self.selenium.find_element(*self._send_email_button_locator).click() + self.wait.until(expected.visibility_of_element_located( + self._login_with_email_button_locator)).click() + self.wait.until(expected.visibility_of_element_located( + self._email_input_locator)).send_keys(username) + self.find_element(*self._send_email_button_locator).click() diff --git a/pages/base.py b/pages/base.py index be53f9b..db82899 100644 --- a/pages/base.py +++ b/pages/base.py @@ -1,20 +1,19 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +from pypom import Page from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys +from selenium.webdriver.support import expected_conditions as expected from selenium.webdriver.support.select import Select -from selenium.webdriver.support.ui import WebDriverWait from pages.auth0 import Auth0 -from pages.page import Page from tests import conftest class Base(Page): + URL_TEMPLATE = '/{locale}' _logout_locator = (By.ID, 'nav-logout') @@ -24,18 +23,21 @@ class Base(Page): # Not logged in _sign_in_button_locator = (By.ID, 'nav-login') + def __init__(self, selenium, base_url, locale='en-US', **url_kwargs): + super(Base, self).__init__(selenium, base_url, locale=locale, **url_kwargs) + @property def page_title(self): - WebDriverWait(self.selenium, self.timeout).until(lambda s: self.selenium.title) + self.wait.until(lambda s: self.selenium.title) return self.selenium.title @property def is_pending_approval_visible(self): - return self.is_element_visible(*self._pending_approval_locator) + return self.is_element_displayed(*self._pending_approval_locator) @property def was_account_created_successfully(self): - return self.is_element_visible(*self._account_created_successfully_locator) + return self.is_element_displayed(*self._account_created_successfully_locator) # Not logged in @@ -48,36 +50,28 @@ class Base(Page): return self.is_element_present(*self._logout_locator) def click_sign_in_button(self): - self.selenium.find_element(*self._sign_in_button_locator).click() + self.find_element(*self._sign_in_button_locator).click() def login(self, email): self.click_sign_in_button() - auth0 = Auth0(self.base_url, self.selenium) + auth0 = Auth0(self.selenium, self.base_url) auth0.request_login_link(email) login_link = conftest.login_link(email) self.selenium.get(login_link) - WebDriverWait(self.selenium, self.timeout).until(lambda s: self.is_user_loggedin) + self.wait.until(lambda s: self.is_user_loggedin) def create_new_user(self, email): self.login(email) from pages.register import Register - return Register(self.base_url, self.selenium) + return Register(self.selenium, self.base_url).wait_for_page_to_load() @property def header(self): - return self.Header(self.base_url, self.selenium) + return self.Header(self.selenium, self.base_url) @property def footer(self): - return self.Footer(self.base_url, self.selenium) - - def open_user_profile(self, username): - self.get_relative_path(u'/u/%s' % username) - from pages.profile import Profile - return Profile(self.base_url, self.selenium) - - def logout_using_url(self): - self.get_relative_path(u'/logout') + return self.Footer(self.selenium, self.base_url) class Header(Page): @@ -99,18 +93,19 @@ class Base(Page): def search_for(self, search_term, loggedin=False): if loggedin: - search_field = self.selenium.find_element(*self._search_box_loggedin_locator) + search_field = self.find_element(*self._search_box_loggedin_locator) else: - search_field = self.selenium.find_element(*self._search_box_locator) + search_field = self.find_element(*self._search_box_locator) search_field.send_keys(search_term) search_field.send_keys(Keys.RETURN) from pages.search import Search - return Search(self.base_url, self.selenium) + return Search(self.selenium, self.base_url).wait_for_page_to_load() def click_options(self): - self.wait_for_element_present(*self._profile_menu_locator) - self.selenium.find_element(*self._profile_menu_locator).click() - WebDriverWait(self.selenium, self.timeout).until(lambda s: self.selenium.find_element(*self._dropdown_menu_locator)) + self.wait.until(expected.visibility_of_element_located( + self._profile_menu_locator)).click() + self.wait.until(expected.visibility_of_element_located( + self._dropdown_menu_locator)) @property def is_logout_menu_item_present(self): @@ -123,26 +118,26 @@ class Base(Page): # menu items def click_view_profile_menu_item(self): self.click_options() - self.selenium.find_element(*self._view_profile_menu_item_locator).click() + self.find_element(*self._view_profile_menu_item_locator).click() from pages.profile import Profile - return Profile(self.base_url, self.selenium) + return Profile(self.selenium, self.base_url).wait_for_page_to_load() def click_invite_menu_item(self): self.click_options() - self.selenium.find_element(*self._invite_menu_item_locator).click() + self.find_element(*self._invite_menu_item_locator).click() from pages.invite import Invite - return Invite(self.base_url, self.selenium) + return Invite(self.selenium, self.base_url) def click_settings_menu_item(self): self.click_options() - self.selenium.find_element(*self._settings_menu_item_locator).click() + self.find_element(*self._settings_menu_item_locator).click() from pages.settings import Settings - return Settings(self.base_url, self.selenium) + return Settings(self.selenium, self.base_url) def click_logout_menu_item(self): self.click_options() - self.selenium.find_element(*self._logout_menu_item_locator).click() - WebDriverWait(self.selenium, self.timeout).until(lambda s: not self.is_logout_menu_item_present) + self.find_element(*self._logout_menu_item_locator).click() + self.wait.until(lambda s: not self.is_logout_menu_item_present) class Footer(Page): @@ -151,11 +146,11 @@ class Base(Page): _language_selection_ok_button = (By.CSS_SELECTOR, '#language-switcher button') def click_about_link(self): - self.selenium.find_element(*self._about_mozillians_link_locator).click() + self.find_element(*self._about_mozillians_link_locator).click() from pages.about import About - return About(self.base_url, self.selenium) + return About(self.selenium, self.base_url) def select_language(self, lang_code): - element = self.selenium.find_element(*self._language_selector_locator) + element = self.find_element(*self._language_selector_locator) select = Select(element) select.select_by_value(lang_code) diff --git a/pages/confirm_profile_delete.py b/pages/confirm_profile_delete.py index dd8db45..31c500d 100644 --- a/pages/confirm_profile_delete.py +++ b/pages/confirm_profile_delete.py @@ -1,10 +1,7 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. - from selenium.webdriver.common.by import By from pages.base import Base @@ -18,7 +15,7 @@ class ConfirmProfileDelete(Base): @property def is_confirm_text_present(self): - return self.is_element_visible(*self._confirm_profile_delete_text_locator) + return self.is_element_displayed(*self._confirm_profile_delete_text_locator) @property def is_delete_button_present(self): diff --git a/pages/create_group_page.py b/pages/create_group_page.py index e40d379..7b86d6d 100644 --- a/pages/create_group_page.py +++ b/pages/create_group_page.py @@ -1,11 +1,9 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. - from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as expected from pages.base import Base @@ -17,12 +15,11 @@ class CreateGroupPage(Base): _create_group_submit_button = (By.CSS_SELECTOR, 'form.add-group .btn-primary') def create_group_name(self, group_name): - self.wait_for_element_visible(*self._create_group_name) - element = self.selenium.find_element(*self._create_group_name) - element.send_keys(group_name) + self.wait.until(expected.visibility_of_element_located( + self._create_group_name)).send_keys(group_name) def click_create_group_submit(self): - self.wait_for_element_visible(*self._create_group_form) - self.selenium.find_element(*self._create_group_submit_button).click() + self.wait.until(expected.visibility_of_element_located(self._create_group_form)) + self.find_element(*self._create_group_submit_button).click() from pages.edit_group import EditGroupPage - return EditGroupPage(self.base_url, self.selenium) + return EditGroupPage(self.selenium, self.base_url) diff --git a/pages/edit_group.py b/pages/edit_group.py index d8fb572..ed9372e 100644 --- a/pages/edit_group.py +++ b/pages/edit_group.py @@ -2,11 +2,11 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +from pypom import Region from selenium.webdriver.common.by import By -from selenium.webdriver.support.wait import WebDriverWait +from selenium.webdriver.support import expected_conditions as expected from pages.base import Base -from pages.page import PageRegion class EditGroupPage(Base): @@ -17,138 +17,130 @@ class EditGroupPage(Base): _invitations_button_locator = (By.ID, 'invitations-tab') _invitations_tab_locator = (By.ID, 'invitations') - def __init__(self, base_url, selenium): - super(EditGroupPage, self).__init__(base_url, selenium) - WebDriverWait(self.selenium, self.timeout).until( - lambda s: self.is_element_visible(*self._description_button_locator)) + def wait_for_page_to_load(self): + self.wait.until(lambda s: self.is_element_displayed(*self._description_button_locator)) + return self @property def description(self): - self.selenium.find_element(*self._description_button_locator).click() - return self.DescriptionTab(self.base_url, self.selenium, - self.selenium.find_element(*self._description_tab_locator)) + self.find_element(*self._description_button_locator).click() + return self.DescriptionTab(self, self.find_element(*self._description_tab_locator)) @property def access(self): - self.selenium.find_element(*self._access_button_locator).click() - return self.AccessTab(self.base_url, self.selenium, - self.selenium.find_element(*self._access_tab_locator)) + self.find_element(*self._access_button_locator).click() + return self.AccessTab(self, self.find_element(*self._access_tab_locator)) @property def invitations(self): - self.wait_for_element_visible(*self._invitations_button_locator) - self.selenium.find_element(*self._invitations_button_locator).click() - return self.InvitationsTab(self.base_url, self.selenium, - self.selenium.find_element(*self._invitations_tab_locator)) + self.wait.until(expected.visibility_of_element_located( + self._invitations_button_locator)).click() + return self.InvitationsTab(self, self.find_element(*self._invitations_tab_locator)) - class DescriptionTab(PageRegion): + class DescriptionTab(Region): _description_form_locator = (By.ID, 'description-form') _delete_panel_locator = (By.CSS_SELECTOR, '.panel-danger') @property def description_info(self): - return self.DescriptionForm(self.base_url, self.selenium, - self._root_element.find_element(*self._description_form_locator)) + return self.DescriptionForm(self.page, self.find_element(*self._description_form_locator)) @property def delete_group(self): - return self.DeletePanel(self.base_url, self.selenium, - self._root_element.find_element(*self._delete_panel_locator)) + return self.DeletePanel(self.page, self.find_element(*self._delete_panel_locator)) - class DescriptionForm(PageRegion): + class DescriptionForm(Region): _description_locator = (By.ID, 'id_description') _irc_channel_locator = (By.ID, 'id_irc_channel') _update_locator = (By.ID, 'form-submit-description') def set_description(self, description_text): - element = self._root_element.find_element(*self._description_locator) + element = self.find_element(*self._description_locator) element.clear() element.send_keys(description_text) def set_irc_channel(self, irc_channel): - element = self._root_element.find_element(*self._irc_channel_locator) + element = self.find_element(*self._irc_channel_locator) element.clear() element.send_keys(irc_channel) def click_update(self): - self._root_element.find_element(*self._update_locator).click() - self.wait_for_element_not_present(*self._update_locator) - self.wait_for_element_present(*self._update_locator) + el = self.find_element(*self._update_locator) + el.click() + self.wait.until(expected.staleness_of(el)) + self.wait.until(expected.presence_of_element_located( + self._update_locator)) - class DeletePanel(PageRegion): + class DeletePanel(Region): _delete_acknowledgement_locator = (By.ID, 'delete-checkbox') _delete_group_button_locator = (By.ID, 'delete-group') def check_acknowledgement(self): - self._root_element.find_element(*self._delete_acknowledgement_locator).click() + self.find_element(*self._delete_acknowledgement_locator).click() @property def is_delete_button_enabled(self): - return 'disabled' not in self._root_element.find_element(*self._delete_group_button_locator).get_attribute('class') + return 'disabled' not in self.find_element(*self._delete_group_button_locator).get_attribute('class') def click_delete_group(self): - self._root_element.find_element(*self._delete_group_button_locator).click() + self.find_element(*self._delete_group_button_locator).click() from pages.groups_page import GroupsPage - return GroupsPage(self.base_url, self.selenium) + return GroupsPage(self.page.selenium, self.page.base_url) - class AccessTab(PageRegion): + class AccessTab(Region): _group_type_form_locator = (By.ID, 'grouptype-form') @property def group_type(self): - return self.GroupTypeForm(self.base_url, self.selenium, - self._root_element.find_element(*self._group_type_form_locator)) + return self.GroupTypeForm(self.page, self.find_element(*self._group_type_form_locator)) - class GroupTypeForm(PageRegion): + class GroupTypeForm(Region): _reviewed_type_locator = (By.ID, 'id_accepting_new_members_1') _new_member_criteria_locator = (By.ID, 'id_new_member_criteria_fieldset') def set_reviewed_group_type(self): - self._root_element.find_element(*self._reviewed_type_locator).click() + self.find_element(*self._reviewed_type_locator).click() @property def is_member_criteria_visible(self): - return self._root_element.find_element(*self._new_member_criteria_locator).is_displayed() + return self.find_element(*self._new_member_criteria_locator).is_displayed() - class InvitationsTab(PageRegion): + class InvitationsTab(Region): _invite_form_locator = (By.ID, 'invite-form') _invitations_list_form_locator = (By.ID, 'invitations-form') @property def invitations_list(self): - return self.InvitationsForm(self.base_url, self.selenium, - self._root_element.find_element(*self._invitations_list_form_locator)) + return self.InvitationsForm(self.page, self.find_element(*self._invitations_list_form_locator)) @property def invite(self): - return self.InviteForm(self.base_url, self.selenium, - self._root_element.find_element(*self._invite_form_locator)) + return self.InviteForm(self.page, self.find_element(*self._invite_form_locator)) - class InvitationsForm(PageRegion): + class InvitationsForm(Region): _invitatation_list_locator = (By.CSS_SELECTOR, '.invitee') @property def search_invitation_list(self): - return [self.SearchResult(self.base_url, self.selenium, el) for el in - self.selenium.find_elements(*self._invitatation_list_locator)] + return [self.SearchResult(self.page, el) for el in + self.find_elements(*self._invitatation_list_locator)] - class SearchResult(PageRegion): + class SearchResult(Region): _name_locator = (By.CSS_SELECTOR, '.invitee a:nth-child(2)') @property def name(self): - return self._root_element.find_element(*self._name_locator).text + return self.find_element(*self._name_locator).text - class InviteForm(PageRegion): + class InviteForm(Region): _invite_search_locator = (By.CSS_SELECTOR, '.select2-search__field') _invite_locator = (By.ID, 'form-submit-invite') def invite_new_member(self, mozillian): - search = self._root_element.find_element(*self._invite_search_locator) + search = self.find_element(*self._invite_search_locator) search.send_keys(mozillian) - self.wait_for_element_visible(By.XPATH, '//li[contains(text(), "{0}")]'.format(mozillian)) - result = self._root_element.find_element(By.XPATH, '//li[contains(text(), "{0}")]'.format(mozillian)) - result.click() + self.wait.until(expected.visibility_of_element_located(( + By.XPATH, '//li[contains(text(), "{0}")]'.format(mozillian)))).click() def click_invite(self): - self._root_element.find_element(*self._invite_locator).click() + self.find_element(*self._invite_locator).click() diff --git a/pages/edit_profile.py b/pages/edit_profile.py index 5c8e684..a4f8ae3 100644 --- a/pages/edit_profile.py +++ b/pages/edit_profile.py @@ -1,10 +1,7 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. - import random from selenium.webdriver.common.by import By @@ -42,92 +39,92 @@ class EditProfile(Base): _services_mozilla_reps_locator = (By.ID, 'services-mozilla-reps') def click_update_button(self): - self.selenium.find_element(*self._update_button_locator).click() - return Profile(self.base_url, self.selenium) + self.find_element(*self._update_button_locator).click() + return Profile(self.selenium, self.base_url) def click_cancel_button(self): - self.selenium.find_element(*self._cancel_button_locator).click() + self.find_element(*self._cancel_button_locator).click() def click_find_group_link(self): - self.selenium.find_element(*self._find_group_page).click() - return GroupsPage(self.base_url, self.selenium) + self.find_element(*self._find_group_page).click() + return GroupsPage(self.selenium, self.base_url) def set_full_name(self, full_name): - element = self.selenium.find_element(*self._full_name_field_locator) + element = self.find_element(*self._full_name_field_locator) element.clear() element.send_keys(full_name) def set_website(self, website): - element = self.selenium.find_element(*self._website_field_locator) + element = self.find_element(*self._website_field_locator) element.clear() element.send_keys(website) def set_bio(self, biography): - element = self.selenium.find_element(*self._bio_field_locator) + element = self.find_element(*self._bio_field_locator) element.clear() element.send_keys(biography) def add_skill(self, skill_name): - element = self.selenium.find_element(*self._skills_field_locator) + element = self.find_element(*self._skills_field_locator) element.send_keys(skill_name) element.send_keys(Keys.RETURN) @property def vouched_by(self): - return self.selenium.find_element(*self._voucher_name_locator).text + return self.find_element(*self._voucher_name_locator).text @property def username(self): - return self.selenium.find_element(*self._username_field_locator).text + return self.find_element(*self._username_field_locator).text def click_delete_profile_button(self): - self.selenium.find_element(*self._acknowledge_deletion_checkbox_locator).click() - self.selenium.find_element(*self._delete_profile_button_locator).click() + self.find_element(*self._acknowledge_deletion_checkbox_locator).click() + self.find_element(*self._delete_profile_button_locator).click() from pages.confirm_profile_delete import ConfirmProfileDelete - return ConfirmProfileDelete(self.base_url, self.selenium) + return ConfirmProfileDelete(self.selenium, self.base_url) def select_month(self, option_month): - element = self.selenium.find_element(*self._select_month_locator) + element = self.find_element(*self._select_month_locator) select = Select(element) select.select_by_value(option_month) def select_year(self, option_year): - element = self.selenium.find_element(*self._select_year_locator) + element = self.find_element(*self._select_year_locator) select = Select(element) select.select_by_value(option_year) @property def month(self): - return self.selenium.find_element(*self._selected_month_locator).text + return self.find_element(*self._selected_month_locator).text @property def year(self): - return self.selenium.find_element(*self._selected_year_locator).text + return self.find_element(*self._selected_year_locator).text @property def months_values(self): - return [month.get_attribute('value') for month in self.selenium.find_elements(*self._month_locator)] + return [month.get_attribute('value') for month in self.find_elements(*self._month_locator)] def select_random_month(self): return self.select_month(random.choice(self.months_values[1:])) @property def years_values(self): - return [year.get_attribute('value') for year in self.selenium.find_elements(*self._year_locator)] + return [year.get_attribute('value') for year in self.find_elements(*self._year_locator)] @property def groups(self): - groups = self.selenium.find_elements(*self._groups_locator) + groups = self.find_elements(*self._groups_locator) return [groups[i].text for i in range(0, len(groups))] @property def skills(self): - skills = self.selenium.find_elements(*self._skills_locator) + skills = self.find_elements(*self._skills_locator) return [skills[i].text for i in range(0, len(skills))] @property def delete_skill_buttons(self): - return self.selenium.find_elements(*self._delete_skill_buttons_locator) + return self.find_elements(*self._delete_skill_buttons_locator) def select_random_year(self): return self.select_year(random.choice(self.years_values[1:])) @@ -137,7 +134,7 @@ class EditProfile(Base): urls = [] for element in locs: - url = self.selenium.find_element(*element).get_attribute('href') + url = self.find_element(*element).get_attribute('href') urls.append(url) return urls diff --git a/pages/group_info_page.py b/pages/group_info_page.py index 68eec89..7f6d35c 100644 --- a/pages/group_info_page.py +++ b/pages/group_info_page.py @@ -1,11 +1,9 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. - from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as expected from pages.base import Base @@ -16,16 +14,20 @@ class GroupInfoPage(Base): _description_locator = (By.CSS_SELECTOR, '.group-description') _irc_channel_locator = (By.ID, 'group-irc') + def wait_for_page_to_load(self): + self.wait.until(lambda _: self.find_element(By.CSS_SELECTOR, 'html.js body#group-show')) + return self + def delete_group(self): - self.wait_for_element_visible(*self._delete_group_button) - self.selenium.find_element(*self._delete_group_button).click() + self.wait.until(expected.visibility_of_element_located( + self._delete_group_button)).click() from pages.groups_page import GroupsPage - return GroupsPage(self.base_url, self.selenium) + return GroupsPage(self.selenium, self.base_url) @property def description(self): - return self.selenium.find_element(*self._description_locator).text + return self.find_element(*self._description_locator).text @property def irc_channel(self): - return self.selenium.find_element(*self._irc_channel_locator).text + return self.find_element(*self._irc_channel_locator).text diff --git a/pages/groups_page.py b/pages/groups_page.py index b2d6f4c..8ca75bd 100644 --- a/pages/groups_page.py +++ b/pages/groups_page.py @@ -1,11 +1,9 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. - from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as expected from pages.base import Base from pages.create_group_page import CreateGroupPage @@ -17,11 +15,12 @@ class GroupsPage(Base): _alert_message_locator = (By.CSS_SELECTOR, '.alert-info') def click_create_group_main_button(self): - self.selenium.find_element(*self._create_group_main_button).click() - return CreateGroupPage(self.base_url, self.selenium) + self.find_element(*self._create_group_main_button).click() + return CreateGroupPage(self.selenium, self.base_url) def wait_for_alert_message(self): - self.wait_for_element_visible(*self._alert_message_locator) + self.wait.until(expected.visibility_of_element_located( + self._alert_message_locator)) def is_group_deletion_alert_present(self): - return self.is_element_visible(*self._alert_message_locator) + return self.is_element_displayed(*self._alert_message_locator) diff --git a/pages/home_page.py b/pages/home_page.py index 5e2772d..502e848 100644 --- a/pages/home_page.py +++ b/pages/home_page.py @@ -1,11 +1,8 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import WebDriverWait from pages.base import Base @@ -15,28 +12,18 @@ class Home(Base): _groups_link_locator = (By.CSS_SELECTOR, 'section.groups > a') _functional_areas_link_locator = (By.CSS_SELECTOR, 'section.functional-areas > a') - def __init__(self, base_url, selenium, open_url=True): - Base.__init__(self, base_url, selenium) - if open_url: - self.selenium.get(self.base_url) - @property def is_groups_link_visible(self): - return self.is_element_visible(*self._groups_link_locator) + return self.is_element_displayed(*self._groups_link_locator) @property def is_functional_areas_link_visible(self): - return self.is_element_visible(*self._functional_areas_link_locator) - - def go_to_localized_settings_page(self, non_US): - self.get_relative_path("/" + non_US + "/user/edit/") - from pages.settings import Settings - return Settings(self.base_url, self.selenium) + return self.is_element_displayed(*self._functional_areas_link_locator) def wait_for_user_login(self): # waits to see if user gets logged back in # if not then all ok try: - WebDriverWait(self.selenium, self.timeout).until(lambda s: self.is_user_loggedin) + self.wait.until(lambda s: self.is_user_loggedin) except Exception: pass diff --git a/pages/invite.py b/pages/invite.py index b9cd57c..5eae560 100644 --- a/pages/invite.py +++ b/pages/invite.py @@ -1,10 +1,7 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. - from selenium.webdriver.common.by import By from pages.base import Base @@ -19,13 +16,13 @@ class Invite(Base): @property def error_text_message(self): - return self.selenium.find_element(*self._error_text_locator).text + return self.find_element(*self._error_text_locator).text def invite(self, email, reason=''): - email_field = self.selenium.find_element(*self._recipient_field_locator) + email_field = self.find_element(*self._recipient_field_locator) email_field.send_keys(email) - reason_field = self.selenium.find_element(*self._vouch_reason_field_locator) + reason_field = self.find_element(*self._vouch_reason_field_locator) reason_field.send_keys(reason) - self.selenium.find_element(*self._send_invite_button_locator).click() + self.find_element(*self._send_invite_button_locator).click() from pages.invite_success import InviteSuccess - return InviteSuccess(self.base_url, self.selenium) + return InviteSuccess(self.selenium, self.base_url) diff --git a/pages/invite_success.py b/pages/invite_success.py index 88d1d30..b94a95b 100644 --- a/pages/invite_success.py +++ b/pages/invite_success.py @@ -1,10 +1,7 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. - from selenium.webdriver.common.by import By from pages.base import Base @@ -16,4 +13,4 @@ class InviteSuccess(Base): @property def success_message(self): - return self.selenium.find_element(*self._success_message_locator).text + return self.find_element(*self._success_message_locator).text diff --git a/pages/link_crawler.py b/pages/link_crawler.py index 71a5dc0..3207b24 100644 --- a/pages/link_crawler.py +++ b/pages/link_crawler.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/pages/location_search_results.py b/pages/location_search_results.py index 50faa92..e527fc0 100644 --- a/pages/location_search_results.py +++ b/pages/location_search_results.py @@ -1,15 +1,13 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. from random import randrange +from pypom import Region from selenium.webdriver.common.by import By from pages.base import Base -from pages.page import PageRegion class LocationSearchResults(Base): @@ -19,26 +17,25 @@ class LocationSearchResults(Base): @property def title(self): - return self.selenium.find_element(*self._results_title_locator).text + return self.find_element(*self._results_title_locator).text @property def results_count(self): - return len(self.selenium.find_elements(*self._result_item_locator)) + return len(self.find_elements(*self._result_item_locator)) @property def search_results(self): - return [self.SearchResult(self.base_url, self.selenium, el) for el in - self.selenium.find_elements(*self._result_item_locator)] + return [self.SearchResult(self, el) for el in self.find_elements(*self._result_item_locator)] def get_random_profile(self): random_index = randrange(self.results_count) return self.search_results[random_index].open_profile_page() - class SearchResult(PageRegion): + class SearchResult(Region): _profile_page_link_locator = (By.CSS_SELECTOR, 'img') def open_profile_page(self): - self._root_element.find_element(*self._profile_page_link_locator).click() + self.find_element(*self._profile_page_link_locator).click() from pages.profile import Profile - return Profile(self.base_url, self.selenium) + return Profile(self.page.selenium, self.page.base_url) diff --git a/pages/page.py b/pages/page.py deleted file mode 100644 index 1c1976f..0000000 --- a/pages/page.py +++ /dev/null @@ -1,102 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -import time - -from selenium.common.exceptions import (ElementNotVisibleException, - NoSuchElementException, - TimeoutException) -from selenium.webdriver.support.ui import WebDriverWait - - -class Page(object): - - def __init__(self, base_url, selenium): - self.base_url = base_url - self.selenium = selenium - self.timeout = 60 - - @property - def is_the_current_page(self): - if self._page_title: - WebDriverWait(self.selenium, self.timeout).until(lambda s: s.title) - - assert self._page_title == self.selenium.title - return True - - def scroll_to_element(self, element): - self.selenium.execute_script("return arguments[0].scrollIntoView();", element) - - def get_url_current_page(self): - WebDriverWait(self.selenium, self.timeout).until(lambda s: s.title) - return self.selenium.current_url - - def is_element_present(self, *locator): - self.selenium.implicitly_wait(0) - try: - self.selenium.find_element(*locator) - return True - except NoSuchElementException: - return False - finally: - # set back to where you once belonged - self.selenium.implicitly_wait(10) - - def wait_for_element_visible(self, *locator): - count = 0 - while not self.is_element_visible(*locator): - time.sleep(1) - count += 1 - if count == self.timeout: - raise Exception(':'.join(locator) + " is not visible") - - def wait_for_element_not_visible(self, *locator): - count = 0 - while self.is_element_visible(*locator): - time.sleep(1) - count += 1 - if count == self.timeout: - raise Exception(':'.join(locator) + " is still visible") - - def wait_for_element_present(self, *locator): - """Wait for an element to become present.""" - self.selenium.implicitly_wait(0) - try: - WebDriverWait(self.selenium, self.timeout).until( - lambda s: s.find_element(*locator)) - finally: - # set back to where you once belonged - self.selenium.implicitly_wait(10) - - def wait_for_element_not_present(self, *locator): - """Wait for an element to become not present.""" - self.selenium.implicitly_wait(0) - try: - WebDriverWait(self.selenium, self.timeout).until( - lambda s: len(s.find_elements(*locator)) < 1) - return True - except TimeoutException: - return False - finally: - # set back to where you once belonged - self.selenium.implicitly_wait(10) - - def is_element_visible(self, *locator): - try: - return self.selenium.find_element(*locator).is_displayed() - except (NoSuchElementException, ElementNotVisibleException): - return False - - def return_to_previous_page(self): - self.selenium.back() - - def get_relative_path(self, url): - self.selenium.get(u'%s%s' % (self.base_url, url)) - - -class PageRegion(Page): - - def __init__(self, base_url, selenium, root_element): - Page.__init__(self, base_url, selenium) - self._root_element = root_element diff --git a/pages/profile.py b/pages/profile.py index ec58591..b721d5d 100644 --- a/pages/profile.py +++ b/pages/profile.py @@ -1,18 +1,15 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. - from selenium.webdriver.common.by import By from selenium.webdriver.support.select import Select -from selenium.webdriver.support.ui import WebDriverWait from pages.base import Base class Profile(Base): + URL_TEMPLATE = '/{locale}/u/{username}' _profile_photo_locator = (By.CSS_SELECTOR, '#profile-stats > div.profile-photo img') _name_locator = (By.CSS_SELECTOR, 'h1.p-name') @@ -31,86 +28,85 @@ class Profile(Base): _profile_message_locator = (By.CSS_SELECTOR, '.alert') _view_as_locator = (By.ID, 'view-privacy-mode') - def __init__(self, base_url, selenium): - Base.__init__(self, base_url, selenium) - WebDriverWait(self.selenium, self.timeout).until( - lambda s: self.is_element_visible(*self._profile_photo_locator)) + def wait_for_page_to_load(self): + self.wait.until(lambda _: self.find_element(By.CSS_SELECTOR, 'html.js body#profile')) + return self def view_profile_as(self, view_as): - element = self.selenium.find_element(*self._view_as_locator) + element = self.find_element(*self._view_as_locator) select = Select(element) select.select_by_visible_text(view_as) @property def name(self): - return self.selenium.find_element(*self._name_locator).text + return self.find_element(*self._name_locator).text @property def biography(self): - return self.selenium.find_element(*self._biography_locator).text + return self.find_element(*self._biography_locator).text @property def email(self): - return self.selenium.find_element(*self._email_locator).text + return self.find_element(*self._email_locator).text @property def irc_nickname(self): - return self.selenium.find_element(*self._irc_nickname_locator).text + return self.find_element(*self._irc_nickname_locator).text @property def website(self): - return self.selenium.find_element(*self._website_locator).text + return self.find_element(*self._website_locator).text @property def vouched_by(self): - return self.selenium.find_element(*self._vouched_by_locator).text + return self.find_element(*self._vouched_by_locator).text @property def skills(self): - return self.selenium.find_element(*self._skills_locator).text.split('\n')[1] + return self.find_element(*self._skills_locator).text.split('\n')[1] @property def groups(self): - return self.selenium.find_element(*self._groups_locator).text.split('\n')[1] + return self.find_element(*self._groups_locator).text.split('\n')[1] @property def location(self): - return self.selenium.find_element(*self._location_locator).text + return self.find_element(*self._location_locator).text @property def city(self): - return self.selenium.find_element(*self._city_locator).text + return self.find_element(*self._city_locator).text @property def region(self): - return self.selenium.find_element(*self._region_locator).text + return self.find_element(*self._region_locator).text @property def country(self): - return self.selenium.find_element(*self._country_locator).text + return self.find_element(*self._country_locator).text def click_profile_city_filter(self): - self.selenium.find_element(*self._city_locator).click() + self.find_element(*self._city_locator).click() from location_search_results import LocationSearchResults - return LocationSearchResults(self.base_url, self.selenium) + return LocationSearchResults(self.selenium, self.base_url) def click_profile_region_filter(self,): - self.selenium.find_element(*self._region_locator).click() + self.find_element(*self._region_locator).click() from location_search_results import LocationSearchResults - return LocationSearchResults(self.base_url, self.selenium) + return LocationSearchResults(self.selenium, self.base_url) def click_profile_country_filter(self): - self.selenium.find_element(*self._country_locator).click() + self.find_element(*self._country_locator).click() from location_search_results import LocationSearchResults - return LocationSearchResults(self.base_url, self.selenium) + return LocationSearchResults(self.selenium, self.base_url) @property def languages(self): - return self.selenium.find_element(*self._languages_locator).text.split('\n')[1] + return self.find_element(*self._languages_locator).text.split('\n')[1] @property def profile_message(self): - return self.selenium.find_element(*self._profile_message_locator).text + return self.find_element(*self._profile_message_locator).text @property def is_groups_present(self): diff --git a/pages/register.py b/pages/register.py index c0d4a03..1ac6201 100644 --- a/pages/register.py +++ b/pages/register.py @@ -1,12 +1,9 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. - from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as expected from pages.base import Base @@ -32,62 +29,65 @@ class Register(Base): _city_results_list_locator = (By.CSS_SELECTOR, '#select2-id_city-results > li.select2-results__option--highlighted') _first_city_search_result_locator = (By.CSS_SELECTOR, '#select2-id_city-results > li.select2-results__option--highlighted:first-child') + def wait_for_page_to_load(self): + self.wait.until(lambda _: self.find_element(By.CSS_SELECTOR, 'html.js body#edit-profile')) + return self + @property def error_message(self): - return self.selenium.find_element(*self._error_locator).text + return self.find_element(*self._error_locator).text def set_full_name(self, full_name): - element = self.selenium.find_element(*self._full_name_field_locator) + element = self.find_element(*self._full_name_field_locator) element.send_keys(full_name) @property def privacy_error_message(self): - return self.selenium.find_element(*self._privacy_error_message_locator).text + return self.find_element(*self._privacy_error_message_locator).text def select_country(self, country): - self.selenium.find_element(*self._country_countainer_locator).click() - self.selenium.find_element(*self._input_locator).send_keys(country) - self.wait_for_element_present(*self._first_country_search_result_locator) - countries_list = self.selenium.find_elements(*self._country_results_list_locator) + self.find_element(*self._country_countainer_locator).click() + self.find_element(*self._input_locator).send_keys(country) + self.wait.until(expected.presence_of_element_located( + self._first_country_search_result_locator)) + countries_list = self.find_elements(*self._country_results_list_locator) country_item = next(item for item in countries_list if country == item.text) country_item.click() def select_region(self, region): - self.selenium.find_element(*self._region_container_locator).click() - self.selenium.find_element(*self._input_locator).send_keys(region) - self.wait_for_element_present(*self._first_region_search_result_locator) - regions_list = self.selenium.find_elements(*self._region_results_list_locator) + self.find_element(*self._region_container_locator).click() + self.find_element(*self._input_locator).send_keys(region) + self.wait.until(expected.presence_of_element_located( + self._first_region_search_result_locator)) + regions_list = self.find_elements(*self._region_results_list_locator) region_item = next(item for item in regions_list if region in item.text) region_item.click() def select_city(self, city): - self.selenium.find_element(*self._city_container_locator).click() - self.selenium.find_element(*self._input_locator).send_keys(city) - self.wait_for_element_present(*self._first_city_search_result_locator) - cities_list = self.selenium.find_elements(*self._city_results_list_locator) + self.find_element(*self._city_container_locator).click() + self.find_element(*self._input_locator).send_keys(city) + self.wait.until(expected.presence_of_element_located( + self._first_city_search_result_locator)) + cities_list = self.find_elements(*self._city_results_list_locator) city_item = next(item for item in cities_list if city in item.text) city_item.click() def check_privacy(self): - self.selenium.find_element(*self._privacy_locator).click() + self.find_element(*self._privacy_locator).click() def check_recaptcha(self): recaptcha_iframe_locator = (By.CSS_SELECTOR, '.g-recaptcha iframe') - recaptcha_iframe = self.selenium.find_element(*recaptcha_iframe_locator) + recaptcha_iframe = self.find_element(*recaptcha_iframe_locator) self.selenium.switch_to_frame(recaptcha_iframe) - - recaptcha_checkbox = self.selenium.find_element(*self._recaptcha_checkbox_locator) - self.scroll_to_element(recaptcha_checkbox) - recaptcha_checkbox.click() - WebDriverWait(self.selenium, self.timeout).until( - lambda s: self.selenium.find_element(*self._recaptcha_checkbox_checked) - ) + self.wait.until(expected.visibility_of_element_located( + self._recaptcha_checkbox_locator)).click() + self.wait.until(lambda s: self.find_element(*self._recaptcha_checkbox_checked)) self.selenium.switch_to_default_content() def click_create_profile_button(self, leavepage=True): - self.selenium.find_element(*self._create_profile_button_locator).click() + self.find_element(*self._create_profile_button_locator).click() if not leavepage: return self else: from pages.profile import Profile - return Profile(self.base_url, self.selenium) + return Profile(self.selenium, self.base_url) diff --git a/pages/search.py b/pages/search.py index 04abc76..19550f9 100644 --- a/pages/search.py +++ b/pages/search.py @@ -1,14 +1,12 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. - +from pypom import Region from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as expected from pages.base import Base -from pages.page import PageRegion class Search(Base): @@ -24,61 +22,60 @@ class Search(Base): _last_page_number_locator = (By.CSS_SELECTOR, '#pagination-form select option:last-child') _group_name_locator = (By.CSS_SELECTOR, '.group-name') + def wait_for_page_to_load(self): + self.wait.until(lambda _: self.find_element(By.CSS_SELECTOR, 'html.js body#search')) + return self + @property def results_count(self): - return len(self.selenium.find_elements(*self._result_locator)) + return len(self.find_elements(*self._result_locator)) @property def number_of_pages(self): - element = self.selenium.find_element(*self._last_page_number_locator) + element = self.find_element(*self._last_page_number_locator) return element.get_attribute('text') @property def no_results_message_head(self): - return self.selenium.find_element(*self._no_results_locator_head).text + return self.find_element(*self._no_results_locator_head).text @property def no_results_message_body(self): - return self.selenium.find_element(*self._no_results_locator_body).text + return self.find_element(*self._no_results_locator_body).text @property def advanced_options_shown(self): - return self.is_element_visible(*self._advanced_options_locator) + return self.is_element_displayed(*self._advanced_options_locator) def toggle_advanced_options(self): - self.selenium.find_element(*self._advanced_options_button_locator).click() + self.find_element(*self._advanced_options_button_locator).click() def check_non_vouched_only(self): - self.selenium.find_element(*self._non_vouched_only_checkbox_locator).click() + self.find_element(*self._non_vouched_only_checkbox_locator).click() def check_with_photos_only(self): - self.selenium.find_element(*self._with_photos_only_checkbox_locator).click() + self.find_element(*self._with_photos_only_checkbox_locator).click() @property def search_results(self): - return [self.SearchResult(self.base_url, self.selenium, el) for el in - self.selenium.find_elements(*self._result_locator)] + return [self.SearchResult(self, el) for el in self.find_elements(*self._result_locator)] def open_group(self, name): - self.wait_for_element_visible(*self._search_button_locator) - groups_names = self.selenium.find_elements(*self._group_name_locator) - for group in groups_names: - if group.get_attribute('title') == name: - group.click() + self.wait.until(expected.visibility_of_element_located( + (By.CSS_SELECTOR, '.group-name[title="{}"]'.format(name)))).click() from pages.group_info_page import GroupInfoPage - group_info_page = GroupInfoPage(self.base_url, self.selenium) - return group_info_page + return GroupInfoPage(self.selenium, self.base_url).wait_for_page_to_load() - class SearchResult(PageRegion): + class SearchResult(Region): _profile_page_link_locator = (By.CSS_SELECTOR, 'li a') _name_locator = (By.CSS_SELECTOR, '.result .details h2') def open_profile_page(self): - self._root_element.find_element(*self._profile_page_link_locator).click() + self.find_element(*self._profile_page_link_locator).click() from pages.profile import Profile - return Profile(self.base_url, self.selenium) + return Profile(self.page.selenium, self.page.base_url).wait_for_page_to_load() @property def name(self): - return self._root_element.find_element(*self._name_locator).text + return self.find_element(*self._name_locator).text diff --git a/pages/settings.py b/pages/settings.py index c94e6a9..2f30a6e 100644 --- a/pages/settings.py +++ b/pages/settings.py @@ -1,21 +1,22 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. import random +from pypom import Region from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys +from selenium.webdriver.support import expected_conditions as expected from selenium.webdriver.support.select import Select from pages.base import Base from pages.groups_page import GroupsPage -from pages.page import PageRegion class Settings(Base): + URL_TEMPLATE = '{locale}/user/edit' + _profile_tab_locator = (By.ID, 'profile') _profile_button_locator = (By.CSS_SELECTOR, '#profile-tab > a') @@ -33,34 +34,29 @@ class Settings(Base): @property def profile(self): - self.wait_for_element_present(*self._profile_button_locator) - self.selenium.find_element(*self._profile_button_locator).click() - return self.ProfileTab(self.base_url, self.selenium, - self.selenium.find_element(*self._profile_tab_locator)) + self.wait.until(expected.presence_of_element_located( + self._profile_button_locator)).click() + return self.ProfileTab(self, self.find_element(*self._profile_tab_locator)) @property def you_and_mozilla(self): - self.selenium.find_element(*self._you_and_mozilla_button_locator).click() - return self.YouAndMozilla(self.base_url, self.selenium, - self.selenium.find_element(*self._you_and_mozilla_tab_locator)) + self.find_element(*self._you_and_mozilla_button_locator).click() + return self.YouAndMozilla(self, self.find_element(*self._you_and_mozilla_tab_locator)) @property def groups(self): - self.selenium.find_element(*self._groups_button_locator).click() - return self.Groups(self.base_url, self.selenium, - self.selenium.find_element(*self._groups_tab_locator)) + self.find_element(*self._groups_button_locator).click() + return self.Groups(self, self.find_element(*self._groups_tab_locator)) @property def external_accounts(self): - self.selenium.find_element(*self._external_accounts_button_locator).click() - return self.ExternalAccountsTab(self.base_url, self.selenium, - self.selenium.find_element(*self._external_accounts_tab_locator)) + self.find_element(*self._external_accounts_button_locator).click() + return self.ExternalAccountsTab(self, self.find_element(*self._external_accounts_tab_locator)) @property def developer(self): - self.selenium.find_element(*self._developer_button_locator).click() - return self.DeveloperTab(self.base_url, self.selenium, - self.selenium.find_element(*self._developer_tab_locator)) + self.find_element(*self._developer_button_locator).click() + return self.DeveloperTab(self, self.find_element(*self._developer_tab_locator)) def create_group(self, group_name): groups = self.groups.click_find_group_link() @@ -69,66 +65,64 @@ class Settings(Base): group = create_group.click_create_group_submit() return group - class ProfileTab(PageRegion): + class ProfileTab(Region): _basic_info_form_locator = (By.CSS_SELECTOR, 'form.edit-profile:nth-child(1)') _skills_form_locator = (By.CSS_SELECTOR, 'form.edit-profile:nth-child(3)') _delete_account_form_locator = (By.CSS_SELECTOR, 'div.panel-danger') @property def basic_information(self): - return self.EditProfileForm(self.base_url, self.selenium, - self._root_element.find_element(*self._basic_info_form_locator)) + return self.EditProfileForm(self.page, self.find_element(*self._basic_info_form_locator)) @property def skills(self): - skill_form = self.SkillsForm(self.base_url, self.selenium, - self._root_element.find_element(*self._skills_form_locator)) - return skill_form + return self.SkillsForm(self.page, self.find_element(*self._skills_form_locator)) @property def delete_account(self): - return self.DeleteAccount(self.base_url, self.selenium, - self._root_element.find_element(*self._delete_account_form_locator)) + return self.DeleteAccount(self.page, self.find_element(*self._delete_account_form_locator)) - class EditProfileForm (PageRegion): + class EditProfileForm (Region): _full_name_field_locator = (By.ID, 'id_full_name') _bio_field_locator = (By.ID, 'id_bio') _update_locator = (By.ID, 'form-submit-basic') def set_full_name(self, full_name): - element = self._root_element.find_element(*self._full_name_field_locator) + element = self.find_element(*self._full_name_field_locator) element.clear() element.send_keys(full_name) def set_bio(self, biography): - element = self._root_element.find_element(*self._bio_field_locator) + element = self.find_element(*self._bio_field_locator) element.clear() element.send_keys(biography) def click_update(self): - self._root_element.find_element(*self._update_locator).click() - self.wait_for_element_not_present(*self._update_locator) - self.wait_for_element_present(*self._update_locator) + el = self.find_element(*self._update_locator) + el.click() + self.wait.until(expected.staleness_of(el)) + self.wait.until(expected.presence_of_element_located( + self._update_locator)) - class DeleteAccount(PageRegion): + class DeleteAccount(Region): _delete_acknowledgement_locator = (By.CSS_SELECTOR, '#delete-checkbox') _delete_profile_button_locator = (By.ID, 'delete-profile') def check_acknowledgement(self): - self._root_element.find_element(*self._delete_acknowledgement_locator).click() + self.find_element(*self._delete_acknowledgement_locator).click() @property def is_delete_button_enabled(self): - return 'disabled' not in self._root_element.find_element(*self._delete_profile_button_locator).get_attribute('class') + return 'disabled' not in self.find_element(*self._delete_profile_button_locator).get_attribute('class') def click_delete_profile(self): - self._root_element.find_element(*self._delete_profile_button_locator).click() + self.find_element(*self._delete_profile_button_locator).click() from pages.confirm_profile_delete import ConfirmProfileDelete - return ConfirmProfileDelete(self.base_url, self.selenium) + return ConfirmProfileDelete(self.page.selenium, self.page.base_url) - class SkillsForm(PageRegion): + class SkillsForm(Region): _skills_locator = (By.CSS_SELECTOR, '#skills .select2-selection__choice') _skills_field_locator = (By.CSS_SELECTOR, '#skills input') _delete_skill_buttons_locator = (By.CSS_SELECTOR, '#skills .select2-selection__choice__remove') @@ -138,36 +132,36 @@ class Settings(Base): @property def skills(self): # Return skills list with leading `x` button stripped - skills = self._root_element.find_elements(*self._skills_locator) + skills = self.find_elements(*self._skills_locator) return [skills[i].text[1:] for i in range(0, len(skills))] def add_skill(self, skill_name): - element = self._root_element.find_element(*self._skills_field_locator) + element = self.find_element(*self._skills_field_locator) element.send_keys(skill_name) - self.wait_for_element_present(*self._skills_first_result_locator) + self.wait.until(expected.presence_of_element_located( + self._skills_first_result_locator)) element.send_keys(Keys.RETURN) @property def delete_skill_buttons(self): - return self._root_element.find_elements(*self._delete_skill_buttons_locator) + return self.find_elements(*self._delete_skill_buttons_locator) def delete_skill(self, skill): skill_index = self.skills.index(skill) self.delete_skill_buttons[skill_index].click() def click_update(self): - self._root_element.find_element(*self._update_locator).click() + self.find_element(*self._update_locator).click() - class YouAndMozilla(PageRegion): + class YouAndMozilla(Region): _contributions_form_locator = (By.CSS_SELECTOR, 'form.edit-profile:nth-child(1)') @property def contributions(self): - return self.Contributions(self.base_url, self.selenium, - self._root_element.find_element(*self._contributions_form_locator)) + return self.Contributions(self.page, self.find_element(*self._contributions_form_locator)) - class Contributions(PageRegion): + class Contributions(Region): _select_month_locator = (By.ID, 'id_date_mozillian_month') _select_year_locator = (By.ID, 'id_date_mozillian_year') @@ -178,34 +172,34 @@ class Settings(Base): _update_locator = (By.ID, 'form-submit-contribution') def select_month(self, option_month): - element = self._root_element.find_element(*self._select_month_locator) + element = self.find_element(*self._select_month_locator) select = Select(element) select.select_by_value(option_month) def select_year(self, option_year): - element = self._root_element.find_element(*self._select_year_locator) + element = self.find_element(*self._select_year_locator) select = Select(element) select.select_by_value(option_year) @property def month(self): # Return selected month text - return self._root_element.find_element(*self._selected_month_locator).text + return self.find_element(*self._selected_month_locator).text @property def year(self): # Return selected year text - return self._root_element.find_element(*self._selected_year_locator).text + return self.find_element(*self._selected_year_locator).text @property def months_values(self): # Return all month values - return [month.get_attribute('value') for month in self._root_element.find_elements(*self._month_locator)] + return [month.get_attribute('value') for month in self.find_elements(*self._month_locator)] @property def years_values(self): # Return all year values - return [year.get_attribute('value') for year in self._root_element.find_elements(*self._year_locator)] + return [year.get_attribute('value') for year in self.find_elements(*self._year_locator)] def select_random_month(self): return self.select_month(random.choice(self.months_values[1:])) @@ -214,73 +208,76 @@ class Settings(Base): return self.select_year(random.choice(self.years_values[1:])) def click_update(self): - self._root_element.find_element(*self._update_locator).click() - self.wait_for_element_not_present(*self._update_locator) - self.wait_for_element_present(*self._update_locator) + el = self.find_element(*self._update_locator) + el.click() + self.wait.until(expected.staleness_of(el)) + self.wait.until(expected.presence_of_element_located( + self._update_locator)) - class Groups(PageRegion): + class Groups(Region): _find_group_page = (By.PARTIAL_LINK_TEXT, 'find the group') @property def is_find_group_link_visible(self): - return self.is_element_visible(*self._find_group_page) + return self.is_element_displayed(*self._find_group_page) def click_find_group_link(self): - self.selenium.find_element(*self._find_group_page).click() - return GroupsPage(self.base_url, self.selenium) + self.find_element(*self._find_group_page).click() + return GroupsPage(self.page.selenium, self.page.base_url) - class ExternalAccountsTab(PageRegion): + class ExternalAccountsTab(Region): _external_accounts_form_locator = (By.CSS_SELECTOR, '#extaccounts > form > div:nth-child(2)') _irc_form_locator = (By.CSS_SELECTOR, '#extaccounts > form > div:nth-child(3)') @property def external_accounts_form(self): - return self.ExternalAccounts(self.base_url, self.selenium, - self._root_element.find_element(*self._external_accounts_form_locator)) + return self.ExternalAccounts(self.page, self.find_element(*self._external_accounts_form_locator)) @property def irc_form(self): - return self.Irc(self.base_url, self.selenium, self._root_element.find_element(*self._irc_form_locator)) + return self.Irc(self.page, self.find_element(*self._irc_form_locator)) - class ExternalAccounts(PageRegion): + class ExternalAccounts(Region): _add_account_locator = (By.ID, 'accounts-addfield') _account_row_locator = (By.CSS_SELECTOR, 'div.externalaccount-fieldrow') @property def is_displayed(self): - return self._root_element.is_displayed() + return self.root.is_displayed() def count_external_accounts(self): - return len(self._root_element.find_elements(*self._account_row_locator)) + return len(self.find_elements(*self._account_row_locator)) def click_add_account(self): - self._root_element.find_element(*self._add_account_locator).click() + self.find_element(*self._add_account_locator).click() - class Irc(PageRegion): + class Irc(Region): _irc_nickname_locator = (By.ID, 'id_ircname') _update_locator = (By.ID, 'form-submit-irc') @property def nickname(self): - return self._root_element.find_element(*self._irc_nickname_locator).get_attribute('value') + return self.find_element(*self._irc_nickname_locator).get_attribute('value') @property def is_displayed(self): - return self._root_element.is_displayed() + return self.root.is_displayed() def update_nickname(self, new_nickname): - element = self._root_element.find_element(*self._irc_nickname_locator) + element = self.find_element(*self._irc_nickname_locator) element.clear() element.send_keys(new_nickname) def click_update(self): - self._root_element.find_element(*self._update_locator).click() - self.wait_for_element_not_present(*self._update_locator) - self.wait_for_element_present(*self._update_locator) + el = self.find_element(*self._update_locator) + el.click() + self.wait.until(expected.staleness_of(el)) + self.wait.until(expected.presence_of_element_located( + self._update_locator)) - class DeveloperTab(PageRegion): + class DeveloperTab(Region): _services_bugzilla_locator = (By.ID, 'services-bugzilla-url') _services_mozilla_reps_locator = (By.ID, 'services-mozilla-reps') @@ -290,7 +287,7 @@ class Settings(Base): urls = [] for element in locs: - url = self._root_element.find_element(*element).get_attribute('href') + url = self.find_element(*element).get_attribute('href') urls.append(url) return urls diff --git a/requirements/tests.txt b/requirements/tests.txt index ab488c0..33e51c5 100644 --- a/requirements/tests.txt +++ b/requirements/tests.txt @@ -1,5 +1,6 @@ BeautifulSoup==3.2.1 mozlog==3.5 +PyPOM==1.2.0 pytest==3.2.5 pytest-metadata==1.5.0 pytest-selenium==1.11.2 diff --git a/tests/conftest.py b/tests/conftest.py index 4935170..51cdd93 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -24,13 +24,6 @@ def capabilities(request, capabilities): return capabilities -@pytest.fixture -def selenium(selenium): - selenium.implicitly_wait(10) - selenium.maximize_window() - return selenium - - @pytest.fixture def new_email(): return 'mozillians_{0}@restmail.net'.format(uuid.uuid1()) diff --git a/tests/test_about_page.py b/tests/test_about_page.py index 46639db..8d31dae 100644 --- a/tests/test_about_page.py +++ b/tests/test_about_page.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -14,7 +12,7 @@ class TestAboutPage: @pytest.mark.nondestructive def test_about_page(self, base_url, selenium): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() about_mozillians_page = home_page.footer.click_about_link() assert about_mozillians_page.is_privacy_section_present assert about_mozillians_page.is_get_involved_section_present diff --git a/tests/test_account.py b/tests/test_account.py index 1d8637d..54c2505 100644 --- a/tests/test_account.py +++ b/tests/test_account.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -15,7 +13,7 @@ class TestAccount: @pytest.mark.credentials @pytest.mark.nondestructive def test_login_logout(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) assert home_page.header.is_logout_menu_item_present home_page.header.click_logout_menu_item() @@ -24,10 +22,10 @@ class TestAccount: @pytest.mark.credentials @pytest.mark.nondestructive def test_logout_verify_bid(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) assert home_page.header.is_logout_menu_item_present - home_page.logout_using_url() + selenium.get(base_url + '/logout') home_page.wait_for_user_login() assert home_page.is_sign_in_button_present diff --git a/tests/test_group.py b/tests/test_group.py index e653d56..fb5c854 100644 --- a/tests/test_group.py +++ b/tests/test_group.py @@ -14,7 +14,7 @@ class TestGroup: @pytest.mark.credentials def test_group_description_edit(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) # Create a new group @@ -41,7 +41,7 @@ class TestGroup: @pytest.mark.credentials def test_group_deletion_confirmation(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) # Create a new group @@ -59,7 +59,7 @@ class TestGroup: @pytest.mark.credentials def test_group_type_change(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) # Create a new group @@ -75,7 +75,7 @@ class TestGroup: @pytest.mark.credentials def test_group_invitations(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) # Create a new group diff --git a/tests/test_invite.py b/tests/test_invite.py index 80e308c..c01f88b 100644 --- a/tests/test_invite.py +++ b/tests/test_invite.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -13,7 +11,7 @@ class TestInvite: @pytest.mark.credentials def test_inviting_an_invalid_email_address(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) invite_page = home_page.header.click_invite_menu_item() invite_page.invite("invalidmail") @@ -21,7 +19,7 @@ class TestInvite: @pytest.mark.credentials def test_invite(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) invite_page = home_page.header.click_invite_menu_item() email_address = "user@example.com" diff --git a/tests/test_profile.py b/tests/test_profile.py index 26f0fba..8cb169f 100644 --- a/tests/test_profile.py +++ b/tests/test_profile.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -11,6 +9,8 @@ from selenium.webdriver.common.by import By from pages.home_page import Home from pages.link_crawler import LinkCrawler +from pages.profile import Profile +from pages.settings import Settings class TestProfile: @@ -18,7 +18,7 @@ class TestProfile: @pytest.mark.credentials @pytest.mark.nondestructive def test_profile_deletion_confirmation(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) settings = home_page.header.click_settings_menu_item() @@ -37,7 +37,7 @@ class TestProfile: @pytest.mark.credentials def test_edit_profile_information(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) settings = home_page.header.click_settings_menu_item() current_time = str(time.time()).split('.')[0] @@ -61,7 +61,7 @@ class TestProfile: @pytest.mark.credentials def test_skill_addition(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) settings = home_page.header.click_settings_menu_item() @@ -77,7 +77,7 @@ class TestProfile: @pytest.mark.credentials def test_skill_deletion(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) settings = home_page.header.click_settings_menu_item() @@ -99,10 +99,10 @@ class TestProfile: @pytest.mark.credentials @pytest.mark.nondestructive def test_that_filter_by_city_works(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) - profile_page = home_page.open_user_profile(u'Mozillians.User') + profile_page = home_page.header.click_view_profile_menu_item() city = profile_page.city country = profile_page.country @@ -118,10 +118,10 @@ class TestProfile: @pytest.mark.credentials @pytest.mark.nondestructive def test_that_filter_by_region_works(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) - profile_page = home_page.open_user_profile(u'Mozillians.User') + profile_page = home_page.header.click_view_profile_menu_item() region = profile_page.region country = profile_page.country search_results_page = profile_page.click_profile_region_filter() @@ -136,10 +136,10 @@ class TestProfile: @pytest.mark.credentials @pytest.mark.nondestructive def test_that_filter_by_country_works(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) - profile_page = home_page.open_user_profile(u'Mozillians.User') + profile_page = home_page.header.click_view_profile_menu_item() country = profile_page.country search_results_page = profile_page.click_profile_country_filter() expected_results_title = u'Mozillians in %s' % country @@ -152,9 +152,9 @@ class TestProfile: @pytest.mark.credentials def test_that_non_us_user_can_set_get_involved_date(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) - settings = home_page.go_to_localized_settings_page("es") + settings = Settings(selenium, base_url, locale='es').open() contributions = settings.you_and_mozilla.contributions selected_date = contributions.month + contributions.year contributions.select_random_month() @@ -164,7 +164,7 @@ class TestProfile: profile_page = home_page.header.click_view_profile_menu_item() assert "Tu perfil" == profile_page.profile_message - settings = home_page.go_to_localized_settings_page("es") + settings = home_page.header.click_settings_menu_item() contributions = settings.you_and_mozilla.contributions assert selected_date != contributions.month + contributions.year @@ -172,7 +172,7 @@ class TestProfile: def test_that_user_can_create_and_delete_group(self, base_url, selenium, vouched_user): group_name = (time.strftime('%x-%X')) - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) settings = home_page.header.click_settings_menu_item() groups = settings.groups.click_find_group_link() @@ -198,7 +198,7 @@ class TestProfile: # User has certain fields preset to values to run the test properly # groups - private # belongs to at least one group - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(private_user['email']) profile_page = home_page.header.click_view_profile_menu_item() @@ -208,14 +208,13 @@ class TestProfile: @pytest.mark.credentials @pytest.mark.nondestructive def test_private_groups_field_when_not_logged_in(self, base_url, selenium, private_user): - home_page = Home(base_url, selenium) - profile_page = home_page.open_user_profile(private_user['name']) - assert not profile_page.is_groups_present + page = Profile(selenium, base_url, username=private_user['name']).open() + assert not page.is_groups_present @pytest.mark.credentials @pytest.mark.nondestructive def test_that_links_in_the_services_page_return_200_code(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) settings = home_page.header.click_settings_menu_item() @@ -236,7 +235,7 @@ class TestProfile: @pytest.mark.credentials @pytest.mark.nondestructive def test_that_user_can_view_external_accounts(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) settings = home_page.header.click_settings_menu_item() @@ -245,7 +244,7 @@ class TestProfile: @pytest.mark.credentials def test_that_user_can_add_external_account(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) settings = home_page.header.click_settings_menu_item() @@ -257,7 +256,7 @@ class TestProfile: @pytest.mark.credentials def test_that_user_can_modify_external_accounts_irc_nickname(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) settings = home_page.header.click_settings_menu_item() @@ -281,7 +280,7 @@ class TestProfile: @pytest.mark.credentials @pytest.mark.nondestructive def test_new_user_cannot_see_groups_or_functional_areas(self, base_url, selenium, unvouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(unvouched_user['email']) assert not home_page.header.is_groups_menu_item_present diff --git a/tests/test_redirects.py b/tests/test_redirects.py index 1910f01..77253b5 100644 --- a/tests/test_redirects.py +++ b/tests/test_redirects.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/tests/test_register.py b/tests/test_register.py index d40b5b6..a04dab8 100644 --- a/tests/test_register.py +++ b/tests/test_register.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -10,7 +8,7 @@ from pages.home_page import Home class TestRegister: def test_profile_creation(self, base_url, selenium, new_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() profile = home_page.create_new_user(new_user['email']) # Click recaptcha box @@ -37,7 +35,7 @@ class TestRegister: assert 'Mountain View, California, United States' == profile_page.location def test_creating_profile_without_checking_privacy_policy_checkbox(self, base_url, selenium, new_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() profile = home_page.create_new_user(new_user['email']) profile.set_full_name("User that doesn't like policy") diff --git a/tests/test_search.py b/tests/test_search.py index 44c6c35..121f949 100644 --- a/tests/test_search.py +++ b/tests/test_search.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -18,7 +16,7 @@ class TestSearch: @pytest.mark.credentials @pytest.mark.nondestructive def test_that_search_returns_results_for_email_substring(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) search_page = home_page.header.search_for(u'@mozilla.com', loggedin=True) assert search_page.results_count > 0 @@ -27,7 +25,7 @@ class TestSearch: @pytest.mark.nondestructive def test_that_search_returns_results_for_first_name(self, base_url, selenium, vouched_user): query = u'Matt' - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) search_page = home_page.header.search_for(query, loggedin=True) assert search_page.results_count > 0 @@ -39,7 +37,7 @@ class TestSearch: @pytest.mark.credentials @pytest.mark.nondestructive def test_that_search_returns_results_for_irc_nickname(self, base_url, selenium, vouched_user): - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) search_page = home_page.header.search_for(u'mbrandt', loggedin=True) assert search_page.results_count > 0 @@ -50,7 +48,7 @@ class TestSearch: @pytest.mark.nondestructive def test_search_for_not_existing_mozillian_when_logged_in(self, base_url, selenium, vouched_user): query = u'Qwerty' - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() home_page.login(vouched_user['email']) search_page = home_page.header.search_for(query, loggedin=True) assert 0 == search_page.results_count @@ -58,7 +56,7 @@ class TestSearch: @pytest.mark.nondestructive def test_search_for_not_existing_mozillian_when_not_logged_in(self, base_url, selenium): query = u'Qwerty' - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() search_page = home_page.header.search_for(query) assert 0 == search_page.results_count @@ -67,6 +65,6 @@ class TestSearch: # Searching for empty string redirects to the Search page # with publicly available profiles query = u'' - home_page = Home(base_url, selenium) + home_page = Home(selenium, base_url).open() search_page = home_page.header.search_for(query) assert search_page.results_count == 0