class Login(Base): """Set up the login page locators and functions.""" _confirm_password_locator = (By.NAME, 'confirmPassword') _continue_locator = (By.CSS_SELECTOR, 'button.{}'.format( munged_class_name('button'))) _create_account_locator = (By.ID, 'homepage-linkaccount-action-create') _fxa_sign_in_locator = (By.CLASS_NAME, '{}'.format( munged_class_name('normal-theme'))) _get_started_button_locator = (By.CLASS_NAME, '{}'.format( munged_class_name('primary-theme'))) _welcome_locator = (By.CLASS_NAME, '{}'.format( munged_class_name('intro'))) def wait_for_page_to_load(self): """Page load wait.""" self.wait.until( lambda s: s.find_element(*self._welcome_locator).is_displayed()) return self def click_get_started(self): """Click get started button.""" self.find_element(*self._get_started_button_locator).click() self.selenium.switch_to.window(self.selenium.window_handles[-1]) return Home(self.selenium, self.base_url).wait_for_page_to_load() def sign_in(self, email, password): """Fxa sign in.""" self.find_element(*self._fxa_sign_in_locator).click() self.fxa_sign_in(email, password) self.selenium.switch_to.window(self.selenium.window_handles[-1]) return Home(self.selenium, self.base_url).wait_for_page_to_load()
class EntryDetail(Region): """Entry detail locators and functions.""" _delete_entry_locator = (By.CSS_SELECTOR, 'article div menu ' 'button.{}:nth-child(2)'.format( munged_class_name('button'))) _delete_entry_modal_locator = (By.CSS_SELECTOR, '.ReactModal__Content--after-open ' 'menu button.{}'.format( munged_class_name('button'))) _title_locator = (By.CLASS_NAME, '{}'.format(munged_class_name('first-label'))) _title_text_locator = (By.CLASS_NAME, '{}'.format(munged_class_name('field-text'))) @property def title(self): """Entry title.""" title = self.find_element(*self._title_locator) return title.find_element(*self._title_text_locator).text def delete(self): """Delete an entry from the lockbox.""" self.find_element(*self._delete_entry_locator).click() self.find_element(*self._delete_entry_modal_locator).click()
class EntryDetail(Region): """Contain the locators and actions for a specific entry.""" _root_locator = (By.CLASS_NAME, '{}'.format( munged_class_name('panel-body'))) _entry_name_locator = (By.CSS_SELECTOR, '.{}'.format( munged_class_name('field-text'))) @property def title(self): """Entry title.""" with self.selenium.context(self.selenium.CONTEXT_CHROME): return self.find_element(*self._entry_name_locator).text
class Entry(Region): """Contain the locators and actions regarding a single entry.""" _entry_title_locator = (By.CLASS_NAME, '{}'.format( munged_class_name('title'))) _entry_subtitle_locator = (By.CLASS_NAME, '{}'.format( munged_class_name('subtitle'))) @property def title(self): """Entry title.""" with self.selenium.context(self.selenium.CONTEXT_CHROME): return self.find_element(*self._entry_title_locator).text @property def subtitle(self): """Entry Subtitle.""" with self.selenium.context(self.selenium.CONTEXT_CHROME): return self.find_element(*self._entry_subtitle_locator).text def click(self): """Click on the entry.""" with self.selenium.context(self.selenium.CONTEXT_CHROME): self.find_element(*self._entry_title_locator).click() return self.EntryDetail(self) class EntryDetail(Region): """Contain the locators and actions for a specific entry.""" _root_locator = (By.CLASS_NAME, '{}'.format( munged_class_name('panel-body'))) _entry_name_locator = (By.CSS_SELECTOR, '.{}'.format( munged_class_name('field-text'))) @property def title(self): """Entry title.""" with self.selenium.context(self.selenium.CONTEXT_CHROME): return self.find_element(*self._entry_name_locator).text
class Entry(Region): """Entry specific locators and functions.""" _name_locator = (By.CSS_SELECTOR, 'div.{}'.format( munged_class_name('title'))) @property def name(self): """Return the name of the entry.""" return self.find_element(*self._name_locator).text def click(self): """Click on the entry.""" self.root.click() return self.EntryDetail(self) class EntryDetail(Region): """Entry detail locators and functions.""" _delete_entry_locator = (By.CSS_SELECTOR, 'article div menu ' 'button.{}:nth-child(2)'.format( munged_class_name('button'))) _delete_entry_modal_locator = (By.CSS_SELECTOR, '.ReactModal__Content--after-open ' 'menu button.{}'.format( munged_class_name('button'))) _title_locator = (By.CLASS_NAME, '{}'.format( munged_class_name('first-label'))) _title_text_locator = (By.CLASS_NAME, '{}'.format( munged_class_name('field-text'))) _site_name_locator = (By.CSS_SELECTOR, 'article div form ' 'input[name="title"]') _website_address_locator = (By.CSS_SELECTOR, 'article div form ' 'input[name="origin"]') _username_locator = (By.CSS_SELECTOR, 'article div form ' 'input[name="username"]') _password_locator = (By.CSS_SELECTOR, 'article div form ' 'input[name="password"]') _note_locator = (By.CSS_SELECTOR, 'article div form ' 'textarea[name="notes"]') _save_entry_locator = (By.CSS_SELECTOR, 'article div form menu' 'button.{}'.format(munged_class_name('button'))) _save_entry_locator = (By.CSS_SELECTOR, 'article div form menu button[type="submit"]') def set_site_name(self, site_name): """Set the entry site name.""" field = self.find_element(*self._site_name_locator) field.send_keys(site_name) def set_website(self, url): """Set the entry website.""" field = self.find_element(*self._website_address_locator) field.send_keys(url) def set_username(self, username): """Set the entry username.""" field = self.find_element(*self._username_locator) field.send_keys(username) def set_password(self, password): """Set the entry password.""" field = self.find_element(*self._password_locator) field.send_keys(password) def set_note(self, note): """Set the entry note.""" field = self.find_element(*self._note_locator) field.send_keys(note) @property def title(self): """Entry title.""" title = self.find_element(*self._title_locator) return title.find_element(*self._title_text_locator).text def save(self): """Save the entry.""" self.find_element(*self._save_entry_locator).click() def delete(self): """Delete an entry from the lockbox.""" self.find_element(*self._delete_entry_locator).click() self.find_element(*self._delete_entry_modal_locator).click()
class Home(Base): """Contain the locators and actions relating to the home page.""" _modal_portal_locator = (By.CLASS_NAME, 'ReactModalPortal') _entries_locator = (By.CSS_SELECTOR, 'ul li div.{}'.format( munged_class_name('item-summary'))) _delete_entry_locator = (By.CSS_SELECTOR, 'article div menu ' 'button.{}'.format(munged_class_name( 'normal-theme'))) _delete_entry_modal_locator = (By.CSS_SELECTOR, '.ReactModal__Content--after-open ' 'menu button.{}'.format( munged_class_name('button'))) _new_entry_locator = (By.CSS_SELECTOR, 'section menu ' 'button.{}:nth-child(1)'.format( munged_class_name('button'))) _sign_in_locator = (By.CSS_SELECTOR, '.{} .{}'.format( munged_class_name('link'), munged_class_name('puffy-size'))) @property def door_hanger(self): """Interaction with the door hanger.""" from pages.door_hanger import DoorHanger return DoorHanger(self) def wait_for_page_to_load(self): """Wait for page to load.""" self.wait.until( lambda s: s.find_element(*self._modal_portal_locator)) return self @property def lockie(self): """Lockie image locator.""" return self.find_element(*self._lockie_locator).text def create_new_entry(self, site_name='', url='', username='', password='', note=''): """Create and save a new entry.""" current_entries = len(self.entries) self.find_element(*self._new_entry_locator).click() entry = self.entries[0].click() entry.set_site_name(site_name) entry.set_website(url) entry.set_username(username) entry.set_password(password) entry.set_note(note) entry.save() self.wait.until(lambda _: len(self.entries) != current_entries) def delete_entry(self): """Delete an entry from lockbox.""" self.find_element(*self._delete_entry_locator).click() self.find_element(*self._delete_entry_modal_locator).click() self.wait.until(lambda _: len(self.entries) == 0) def sign_in(self, user, password): """Sign in with fxa.""" els = self.find_elements(*self._sign_in_locator) els[1].click() self.fxa_sign_in(user, password) self.wait.until( EC.invisibility_of_element_located(self._sign_in_locator)) def sign_in_button_is_displayed(self): """Check if sign in button is displayed.""" try: self.find_elements(*self._sign_in_locator)[-1] except Exception: return False return True @property def entries(self): """List of current entries.""" els = self.find_elements(*self._entries_locator) return [Entry(self, el) for el in els]
class EntryDetail(Region): """Entry detail locators and functions.""" _entry_detail_locator = (By.CSS_SELECTOR, 'section article') _edit_entry_locator = (By.CSS_SELECTOR, 'article div div menu button:first-child') _delete_entry_locator = (By.CSS_SELECTOR, 'article div menu ' 'button.{}:nth-child(2)'.format( munged_class_name('button'))) _delete_entry_modal_locator = (By.CSS_SELECTOR, '.ReactModal__Content--after-open ' 'menu button.{}'.format( munged_class_name('button'))) _title_locator = (By.CLASS_NAME, '{}'.format(munged_class_name('first-label'))) _title_text_locator = (By.CLASS_NAME, '{}'.format(munged_class_name('field-text'))) _site_name_locator = (By.CSS_SELECTOR, 'article div form ' 'input[name="title"]') _website_address_locator = (By.CSS_SELECTOR, 'article div form ' 'input[name="origin"]') _username_locator = (By.CSS_SELECTOR, 'article div form ' 'input[name="username"]') _password_locator = (By.CSS_SELECTOR, 'article div form ' 'input[name="password"]') _note_locator = (By.CSS_SELECTOR, 'article div form ' 'textarea[name="notes"]') _save_entry_locator = (By.CSS_SELECTOR, 'article div form menu' 'button.{}'.format(munged_class_name('button'))) _save_entry_locator = (By.CSS_SELECTOR, 'article div form menu button[type="submit"]') def set_site_name(self, site_name): """Set the entry site name.""" field = self.find_element(*self._site_name_locator) field.send_keys(site_name) def set_site_url(self, site_url): """Set the entry site URL.""" field = self.find_element(*self._website_address_locator) field.send_keys(site_url) def set_username(self, username): """Set the entry username.""" field = self.find_element(*self._username_locator) field.send_keys(username) def set_password(self, password): """Set the entry password.""" field = self.find_element(*self._password_locator) field.send_keys(password) def set_note(self, note): """Set the entry note.""" field = self.find_element(*self._note_locator) field.send_keys(note) @property def title(self): """Entry title.""" title = self.find_element(*self._title_locator) return title.find_element(*self._title_text_locator).text @property def site_url(self): """Entry site URL.""" url = self.find_element(*self._website_address_locator) return url.get_attribute('value') @property def username(self): """Entry username.""" username = self.find_element(*self._username_locator) return username.get_attribute('value') @property def password(self): """Entry site URL.""" password = self.find_element(*self._password_locator) return password.get_attribute('value') @property def note(self): """Entry site URL.""" note = self.find_element(*self._note_locator) return note.get_attribute('value') def save(self): """Save the entry.""" self.find_element(*self._save_entry_locator).click() from time import sleep sleep(5) def edit(self): """Delete an entry from the lockbox.""" self.find_element(*self._edit_entry_locator).click() def delete(self): """Delete an entry from the lockbox.""" self.find_element(*self._delete_entry_locator).click() self.find_element(*self._delete_entry_modal_locator).click()
class DoorHanger(Region): """Contain the locators and actions relating to the door habger.""" _entry_list = (By.CLASS_NAME, '{}'.format( munged_class_name('item-summary'))) _manage_button_locator = (By.CLASS_NAME, '{}'.format( munged_class_name('ghost-theme'))) _panel_locator = (By.CSS_SELECTOR, '#PanelUI-webext-lockbox_mozilla_' + 'com-browser-action-view') _lockbox_button_locator = (By.ID, 'lockbox_mozilla_com-browser-action') _xul_browser_locator = (By.CLASS_NAME, 'webextension-popup-browser') def _open_and_switch_to_hanger(self): """Open the door hanger and switch to it.""" with self.selenium.context(self.selenium.CONTEXT_CHROME): self.find_element(*self._lockbox_button_locator).click() self.wait.until( lambda s: s.find_element(*self._panel_locator).is_displayed()) panel = self.find_element(*self._panel_locator) hanger = panel.find_element(*self._xul_browser_locator) self.selenium.switch_to_frame(hanger) def find_entrys(self): """Find all entrys.""" self._open_and_switch_to_hanger() with self.selenium.context(self.selenium.CONTEXT_CHROME): els = self.selenium.find_elements(*self._entry_list) return [self.Entry(self) for el in els] def click_manage(self): """Click the manage button.""" self._open_and_switch_to_hanger() with self.selenium.context(self.selenium.CONTEXT_CHROME): self.find_element(*self._manage_button_locator).click() class Entry(Region): """Contain the locators and actions regarding a single entry.""" _entry_title_locator = (By.CLASS_NAME, '{}'.format( munged_class_name('title'))) _entry_subtitle_locator = (By.CLASS_NAME, '{}'.format( munged_class_name('subtitle'))) @property def title(self): """Entry title.""" with self.selenium.context(self.selenium.CONTEXT_CHROME): return self.find_element(*self._entry_title_locator).text @property def subtitle(self): """Entry Subtitle.""" with self.selenium.context(self.selenium.CONTEXT_CHROME): return self.find_element(*self._entry_subtitle_locator).text def click(self): """Click on the entry.""" with self.selenium.context(self.selenium.CONTEXT_CHROME): self.find_element(*self._entry_title_locator).click() return self.EntryDetail(self) class EntryDetail(Region): """Contain the locators and actions for a specific entry.""" _root_locator = (By.CLASS_NAME, '{}'.format( munged_class_name('panel-body'))) _entry_name_locator = (By.CSS_SELECTOR, '.{}'.format( munged_class_name('field-text'))) @property def title(self): """Entry title.""" with self.selenium.context(self.selenium.CONTEXT_CHROME): return self.find_element(*self._entry_name_locator).text