PK:Hfxapom/__init__.pyPK EH7 lg^^fxapom/fxapom.py # 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 string import random from datetime import datetime from fxa.core import Client from fxa.errors import ClientError from fxa.tests.utils import TestEmailAccount from selenium.webdriver.remote.webdriver import WebDriver # Constants for available FxA environments DEV_URL = 'https://stable.dev.lcip.org/auth/' PROD_URL = 'https://api.accounts.firefox.com/' TIMEOUT = 20 class AccountNotFoundException(Exception): pass class WebDriverFxA(object): def __init__(self, driver, timeout=TIMEOUT): self.driver = driver self.timeout = timeout def sign_in(self, email=None, password=None): """Signs in a user, either with the specified email address and password, or a returning user.""" if isinstance(self.driver, WebDriver): from pages.sign_in import SignIn else: from pages.marionette.sign_in import MarionetteSignIn as SignIn sign_in = SignIn(self.driver, self.timeout) sign_in.sign_in(email, password) class FxATestAccount: """A base test class that can be extended by other tests to include utility methods.""" password = ''.join([random.choice(string.letters) for i in range(8)]) def __init__(self, url=DEV_URL): """ Creates an FxATestAccount object, which includes a verified account. :param url: The url for the api host. Defaults to DEV_URL. """ self.url = url random_string = ''.join(random.choice(string.ascii_lowercase) for _ in range(12)) email_pattern = random_string + '@{hostname}' self.account = TestEmailAccount(email=email_pattern) self.client = Client(self.url) # Create and verify the Firefox account self.session = self.client.create_account(self.account.email, self.password) print 'fxapom created an account for email: %s at %s on %s' % ( self.account.email, self.url, datetime.now()) m = self.account.wait_for_email(lambda m: "x-verify-code" in m["headers"]) if not m: raise RuntimeError("Verification email was not received") self.session.verify_email_code(m["headers"]["x-verify-code"]) def __del__(self): """ Deletes the Firefox Account that was created during __init__. """ try: self.account.clear() self.client.destroy_account(self.email, self.password) print 'fxapom deleted the account for email: %s at %s on %s' % ( self.account.email, self.url, datetime.now()) except ClientError as err: # 'Unknown Account' error is ok - account already deleted # https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md#response-format if err.errno == 102: return raise def login(self): try: session = self.client.login(self.email, self.password) return session except ClientError as err: # 'Unknown Account' error is the only one we care about and will # cause us to throw a custom exception # https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md#response-format if err.errno == 102: raise AccountNotFoundException('FxA Account Not Found') raise @property def email(self): return self.account.email @property def is_verified(self): return self.session.get_email_status()['verified'] PK:Hfxapom/pages/__init__.pyPK EH#k]]fxapom/pages/base.py# 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 fxapom.fxapom import TIMEOUT from page import Page class Base(Page): def __init__(self, driver, timeout=TIMEOUT): super(Base, self).__init__(driver, timeout) self._main_window_handle = self.driver.current_window_handle def switch_to_main_window(self): self.driver.switch_to_window(self._main_window_handle) def close_window(self): self.driver.close() PK EHlągllfxapom/pages/page.py# 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.common.exceptions import NoSuchElementException from fxapom.fxapom import TIMEOUT class Page(object): def __init__(self, driver, timeout=TIMEOUT): self.driver = driver self.timeout = timeout def is_element_visible(self, *locator): try: return self.driver.find_element(*locator).is_displayed() except NoSuchElementException: return False PK EHt20$ $ fxapom/pages/sign_in.py# 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 EC from selenium.webdriver.support.ui import WebDriverWait as Wait from fxapom.fxapom import TIMEOUT from fxapom.pages.base import Base class SignIn(Base): _fox_logo_locator = (By.ID, 'fox-logo') _email_input_locator = (By.CSS_SELECTOR, '.input-row .email') _next_button_locator = (By.ID, 'email-button') _password_input_locator = (By.ID, 'password') _sign_in_locator = (By.ID, 'submit-btn') def __init__(self, driver, timeout=TIMEOUT): super(Base, self).__init__(driver, timeout) self._sign_in_window_handle = None self.popup = False self.check_for_popup(self.driver.window_handles) @property def login_password(self): """Get the value of the login password field.""" return self.driver.find_element(*self._password_input_locator).get_attribute('value') @login_password.setter def login_password(self, value): """Set the value of the login password field.""" password = self.driver.find_element(*self._password_input_locator) password.clear() password.send_keys(value) def click_next(self): self.driver.find_element(*self._next_button_locator).click() @property def email(self): """Get the value of the email field.""" return self.driver.find_element(*self._email_input_locator).get_attribute('value') @email.setter def email(self, value): """Set the value of the email field.""" email = Wait(self.driver, self.timeout).until( EC.visibility_of_element_located(self._email_input_locator)) email.clear() email.send_keys(value) def check_for_popup(self, handles): if len(handles) > 1: self.popup = True for handle in handles: self.driver.switch_to.window(handle) if self.is_element_visible(*self._fox_logo_locator): Wait(self.driver, self.timeout).until( EC.visibility_of_element_located(self._email_input_locator)) self._sign_in_window_handle = handle break else: raise Exception('Popup has not loaded') def click_sign_in(self): self.driver.find_element(*self._sign_in_locator).click() if self.popup: Wait(self.driver, self.timeout).until( lambda s: self._sign_in_window_handle not in self.driver.window_handles) self.switch_to_main_window() def sign_in(self, email, password): """Signs in using the specified email address and password.""" self.email = email self.login_password = password if self.is_element_visible(*self._next_button_locator): self.click_next() self.click_sign_in() PK EH#fxapom/pages/marionette/__init__.pyPK EHtuufxapom/pages/marionette/base.py# 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 fxapom.fxapom import TIMEOUT from fxapom.pages.marionette.page import Page class Base(Page): def __init__(self, driver, timeout=TIMEOUT): super(Page, self).__init__(driver, timeout) self._main_window_handle = self.driver.current_window_handle def switch_to_main_window(self): self.driver.switch_to_window(self._main_window_handle) def close_window(self): self.driver.close() PK EHnejjfxapom/pages/marionette/page.py# 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 marionette_driver.errors import NoSuchElementException from fxapom.fxapom import TIMEOUT class Page(object): def __init__(self, driver, timeout=TIMEOUT): self.driver = driver self.timeout = timeout def is_element_visible(self, *locator): try: return self.driver.find_element(*locator).is_displayed() except NoSuchElementException: return False PK EH\%R6 6 "fxapom/pages/marionette/sign_in.py# 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 marionette_driver import expected, Wait, By from fxapom.fxapom import TIMEOUT from fxapom.pages.marionette.base import Base class MarionetteSignIn(Base): _fox_logo_locator = (By.ID, 'fox-logo') _email_input_locator = (By.CSS_SELECTOR, '.input-row .email') _next_button_locator = (By.ID, 'email-button') _password_input_locator = (By.ID, 'password') _sign_in_locator = (By.ID, 'submit-btn') def __init__(self, driver, timeout=TIMEOUT): super(Base, self).__init__(driver, timeout) self._sign_in_window_handle = None self.popup = False self.check_for_popup(self.driver.window_handles) @property def email(self): """Get the value of the email field.""" return self.driver.find_element(*self._email_input_locator).get_attribute('value') @email.setter def email(self, value): """Set the value of the email field.""" email = Wait(self.driver, self.timeout).until( expected.element_present(*self._email_input_locator)) Wait(self.driver, self.timeout).until( expected.element_displayed(email)) email.clear() email.send_keys(value) @property def login_password(self): """Get the value of the login password field.""" return self.driver.find_element(*self._password_input_locator).get_attribute('value') @login_password.setter def login_password(self, value): """Set the value of the login password field.""" password = self.driver.find_element(*self._password_input_locator) password.clear() password.send_keys(value) def click_next(self): self.driver.find_element(*self._next_button_locator).click() def check_for_popup(self, handles): if len(self.driver.window_handles) > 1: self.popup = True for handle in handles: self.driver.switch_to.window(handle) if self.is_element_visible(*self._fox_logo_locator): Wait(self.driver, self.timeout).until( expected.element_displayed(*self._email_input_locator)) self._sign_in_window_handle = handle break else: raise Exception('Popup has not loaded') def click_sign_in(self): self.driver.find_element(*self._sign_in_locator).click() if self.popup: Wait(self.driver, self.timeout).until( lambda s: self._sign_in_window_handle not in self.driver.window_handles) self.switch_to_main_window() def sign_in(self, email, password): """Signs in using the specified email address and password.""" self.email = email self.login_password = password if self.is_element_visible(*self._next_button_locator): self.click_next() self.click_sign_in() PK EHtests/marionette/__init__.pyPK EH b9nntests/marionette/conftest.py# 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 pytest from marionette_driver import By, Wait from marionette_driver.marionette import Marionette @pytest.fixture def click_login(base_url, marionette, timeout): fxa_login_button_locator = (By.CSS_SELECTOR, 'button.signin') marionette.navigate('%s/' % base_url) Wait(marionette, timeout).until( lambda m: m.find_element(*fxa_login_button_locator).is_displayed()) marionette.find_element(*fxa_login_button_locator).click() @pytest.fixture def marionette(request): m = Marionette(bin=request.config.option.bin) m.start_session() m.set_prefs({'signon.rememberSignons': False}) request.addfinalizer(m.delete_session) return m PK EH;^^"tests/marionette/test_fxa_login.py# 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 marionette_driver import By, expected, Wait from fxapom.fxapom import WebDriverFxA class TestLogin(object): _fxa_logged_in_indicator_locator = (By.ID, 'loggedin') def test_user_can_sign_in(self, base_url, marionette, dev_account, click_login, timeout): fxa = WebDriverFxA(marionette, timeout) fxa.sign_in(dev_account.email, dev_account.password) # We sometimes need to wait longer than the standard 10 seconds logged_in = Wait(marionette, timeout).until( expected.element_present(*self._fxa_logged_in_indicator_locator)) Wait(marionette, timeout).until(expected.element_displayed(logged_in)) PK EHtests/webdriver/__init__.pyPK EH^Rvv!tests/webdriver/test_fxa_login.py# 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 EC from selenium.webdriver.support.ui import WebDriverWait as Wait from fxapom.fxapom import WebDriverFxA class TestLogin(object): _fxa_logged_in_indicator_locator = (By.ID, 'loggedin') def test_user_can_sign_in(self, selenium, dev_account, click_login, timeout): fxa = WebDriverFxA(selenium, timeout) fxa.sign_in(dev_account.email, dev_account.password) # We sometimes need to wait longer than the standard 10 seconds Wait(selenium, timeout).until( EC.visibility_of_element_located(self._fxa_logged_in_indicator_locator)) PKEH;$fxapom-1.7.dist-info/DESCRIPTION.rstFirefox Accounts Page Object Model ================================== `Selenium WebDriver `_ compatible page object model and utilities for `Firefox Accounts `_ .. image:: https://img.shields.io/pypi/l/fxapom.svg :target: https://github.com/mozilla/fxapom/blob/master/LICENSE :alt: License .. image:: https://img.shields.io/pypi/v/fxapom.svg :target: https://pypi.python.org/pypi/fxapom/ :alt: PyPI .. image:: https://img.shields.io/travis/mozilla/fxapom.svg :target: https://travis-ci.org/mozilla/fxapom/ :alt: Travis .. image:: https://img.shields.io/github/issues-raw/mozilla/fxapom.svg :target: https://github.com/mozilla/fxapom/issues :alt: Issues .. image:: https://img.shields.io/requires/github/mozilla/fxapom.svg :target: https://requires.io/github/mozilla/fxapom/requirements/?branch=master :alt: Requirements Overview -------- This package contains a utility to create a test Firefox Account on either the dev or prod instance of Firefox Accounts, as well as a set of page objects that can be used to interact with Firefox Accounts' sign in screens. Installation ------------ ``python setup.py develop`` **If running on a Mac, you may need the following before running the above command:** ``pip install cryptography`` Usage ----- To create a test Firefox Account, simply create an instance of the ``FxATestAccount`` object. You can pass the url for the Firefox Accounts API server into the constructor or, if you know you want to create a development Account, you can omit that argument. There are two constants available to you to specify the url for either the development environment or the production environment, which are: * ``fxapom.DEV_URL`` - the url for the development environment * ``fxapom.PROD_URL`` - the url for the production environment FxAPOM is now able to handle tests written using both Selenium WebDriver and Marionette. Based on the type of driver being used, the package will automatically handle the tests in the way best suited for that driver including all error handling. Example of creating an account on the development environment, using the default: .. code-block:: python from fxapom.fxapom import FxATestAccount account = FxATestAccount() Example of creating an account on the development environment, specifying the ``DEV_URL``: .. code-block:: python from fxapom.fxapom import DEV_URL, FxATestAccount account = FxATestAccount(DEV_URL) To sign in via Firefox Accounts, use the ``sign_in`` method in the ``WebDriverFxA`` object, passing in the email address and password: .. code-block:: python from fxapom.fxapom import WebDriverFxA fxa = WebDriverFxA(driver) fxa.sign_in(email_address, password) Note that we are passing ``driver`` into the constructor of ``WebDriverFxA``, which it then uses to interact with the Firefox Accounts web pages. This driver will be identified as either an instance of Selenium or Marionette and the tests will be handled accordingly. To create an account and then use it to sign in, use both tools described above: .. code-block:: python from fxapom.fxapom import FxATestAccount, WebDriverFxA account = FxATestAccount() fxa = WebDriverFxA(driver) fxa.sign_in(account.email, account.password) Running The Tests ----------------- * Install the requirements using ``pip install -r requirements.txt`` * Run the tests using a local Firefox browser via ``py.test --driver=Firefox tests`` Change Log ---------- 1.7 ^^^ * Added `Marionette ` functionality 1.6 ^^^ * Remove the requirement to pass ``base_url`` into pages in the page object model. * Update readme to remove outdated references to ``mozwebqa``. 1.5 ^^^ * Switch the test suite to use ``pytest-selenium`` * Remove implicit waits from the tests and page objects 1.4 ^^^ * Accounts created via ``FxATestAccount`` are now automatically deleted when the object leaves scope * The ``create_account`` method has been removed from ``FxATestAccount`` as accounts are now automatically created on instantiation * This is a **breaking change** 1.3.1 ^^^^^ * Change the README to ``rst`` format 1.3 ^^^ * Change FxATestAccount constructor to accept the url to the FxA API server * This is a **breaking change** 1.2 ^^^ * Update required version of PyFxA in setup.py to 0.0.5 1.1 ^^^ * Update required version of PyFxA in requirements.txt to 0.0.5 1.0 ^^^ * Initial release PKEHBJ"fxapom-1.7.dist-info/metadata.json{"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)", "Operating System :: POSIX", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS :: MacOS X", "Topic :: Software Development :: Testing", "Topic :: Utilities", "Programming Language :: Python", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7"], "extensions": {"python.details": {"contacts": [{"email": "mozwebqa@mozilla.org", "name": "Mozilla Web QA", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/mozilla/fxapom"}}}, "extras": [], "generator": "bdist_wheel (0.27.0)", "keywords": ["mozilla"], "license": "MPL 2.0", "metadata_version": "2.0", "name": "fxapom", "run_requires": [{"requires": ["PyFxA (==0.0.8)"]}], "summary": "Mozilla Firefox Accounts Page Object Model", "version": "1.7"}PKEHg "fxapom-1.7.dist-info/top_level.txtfxapom tests PKEHX\\fxapom-1.7.dist-info/WHEELWheel-Version: 1.0 Generator: bdist_wheel (0.27.0) Root-Is-Purelib: true Tag: py2-none-any PKEHtӑfxapom-1.7.dist-info/METADATAMetadata-Version: 2.0 Name: fxapom Version: 1.7 Summary: Mozilla Firefox Accounts Page Object Model Home-page: https://github.com/mozilla/fxapom Author: Mozilla Web QA Author-email: mozwebqa@mozilla.org License: MPL 2.0 Keywords: mozilla Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0) Classifier: Operating System :: POSIX Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: MacOS :: MacOS X Classifier: Topic :: Software Development :: Testing Classifier: Topic :: Utilities Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Requires-Dist: PyFxA (==0.0.8) Firefox Accounts Page Object Model ================================== `Selenium WebDriver `_ compatible page object model and utilities for `Firefox Accounts `_ .. image:: https://img.shields.io/pypi/l/fxapom.svg :target: https://github.com/mozilla/fxapom/blob/master/LICENSE :alt: License .. image:: https://img.shields.io/pypi/v/fxapom.svg :target: https://pypi.python.org/pypi/fxapom/ :alt: PyPI .. image:: https://img.shields.io/travis/mozilla/fxapom.svg :target: https://travis-ci.org/mozilla/fxapom/ :alt: Travis .. image:: https://img.shields.io/github/issues-raw/mozilla/fxapom.svg :target: https://github.com/mozilla/fxapom/issues :alt: Issues .. image:: https://img.shields.io/requires/github/mozilla/fxapom.svg :target: https://requires.io/github/mozilla/fxapom/requirements/?branch=master :alt: Requirements Overview -------- This package contains a utility to create a test Firefox Account on either the dev or prod instance of Firefox Accounts, as well as a set of page objects that can be used to interact with Firefox Accounts' sign in screens. Installation ------------ ``python setup.py develop`` **If running on a Mac, you may need the following before running the above command:** ``pip install cryptography`` Usage ----- To create a test Firefox Account, simply create an instance of the ``FxATestAccount`` object. You can pass the url for the Firefox Accounts API server into the constructor or, if you know you want to create a development Account, you can omit that argument. There are two constants available to you to specify the url for either the development environment or the production environment, which are: * ``fxapom.DEV_URL`` - the url for the development environment * ``fxapom.PROD_URL`` - the url for the production environment FxAPOM is now able to handle tests written using both Selenium WebDriver and Marionette. Based on the type of driver being used, the package will automatically handle the tests in the way best suited for that driver including all error handling. Example of creating an account on the development environment, using the default: .. code-block:: python from fxapom.fxapom import FxATestAccount account = FxATestAccount() Example of creating an account on the development environment, specifying the ``DEV_URL``: .. code-block:: python from fxapom.fxapom import DEV_URL, FxATestAccount account = FxATestAccount(DEV_URL) To sign in via Firefox Accounts, use the ``sign_in`` method in the ``WebDriverFxA`` object, passing in the email address and password: .. code-block:: python from fxapom.fxapom import WebDriverFxA fxa = WebDriverFxA(driver) fxa.sign_in(email_address, password) Note that we are passing ``driver`` into the constructor of ``WebDriverFxA``, which it then uses to interact with the Firefox Accounts web pages. This driver will be identified as either an instance of Selenium or Marionette and the tests will be handled accordingly. To create an account and then use it to sign in, use both tools described above: .. code-block:: python from fxapom.fxapom import FxATestAccount, WebDriverFxA account = FxATestAccount() fxa = WebDriverFxA(driver) fxa.sign_in(account.email, account.password) Running The Tests ----------------- * Install the requirements using ``pip install -r requirements.txt`` * Run the tests using a local Firefox browser via ``py.test --driver=Firefox tests`` Change Log ---------- 1.7 ^^^ * Added `Marionette ` functionality 1.6 ^^^ * Remove the requirement to pass ``base_url`` into pages in the page object model. * Update readme to remove outdated references to ``mozwebqa``. 1.5 ^^^ * Switch the test suite to use ``pytest-selenium`` * Remove implicit waits from the tests and page objects 1.4 ^^^ * Accounts created via ``FxATestAccount`` are now automatically deleted when the object leaves scope * The ``create_account`` method has been removed from ``FxATestAccount`` as accounts are now automatically created on instantiation * This is a **breaking change** 1.3.1 ^^^^^ * Change the README to ``rst`` format 1.3 ^^^ * Change FxATestAccount constructor to accept the url to the FxA API server * This is a **breaking change** 1.2 ^^^ * Update required version of PyFxA in setup.py to 0.0.5 1.1 ^^^ * Update required version of PyFxA in requirements.txt to 0.0.5 1.0 ^^^ * Initial release PKEHTfxapom-1.7.dist-info/RECORDfxapom/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 fxapom/fxapom.py,sha256=xyYPioz_Vi1EOaoErSDwvCykmsgT7g2Vkz066bO_bLw,3678 fxapom/pages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 fxapom/pages/base.py,sha256=UPKfBjPBxWCFB7xU1qPVaIfpisQarUUmeWHEJIIYVw8,605 fxapom/pages/page.py,sha256=I4koseZVG-p0wDu01Vrh7z7C37AIyrdEZhVDV1Sr-wg,620 fxapom/pages/sign_in.py,sha256=eeryCWdyCHIcDCoBq3Lqj8rL0BT3s1VwxGjwiC2CppE,3108 fxapom/pages/marionette/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 fxapom/pages/marionette/base.py,sha256=yZWtdun3EKsFwHzIBpqf8jIHNFgiiTtp01odphHfeU8,629 fxapom/pages/marionette/page.py,sha256=P1Oh34g2UxgPGKLoh8uh35GH4lDMrNf7KMjdnEy538o,618 fxapom/pages/marionette/sign_in.py,sha256=ENPJnBSR1XP3mMTo2CE02NrVXxO_s1fmSFvx_iGIofc,3126 fxapom-1.7.dist-info/DESCRIPTION.rst,sha256=R-nlTug08X3gP6gAJCeO66pvSY7gKIMAPUCuJF1aL_E,4543 fxapom-1.7.dist-info/METADATA,sha256=6YswjNyeMXgHX4OlBOHS4EWrPFCvy_Nc9I1LYi-Rduo,5374 fxapom-1.7.dist-info/RECORD,, fxapom-1.7.dist-info/WHEEL,sha256=NY1jXjYTzC-y18R7C1rLIlMfy-7M7rD-jBHtBp-diYk,92 fxapom-1.7.dist-info/metadata.json,sha256=OjGfTNxJbS3KzW8z4QSQvc8IYVsXXqXPljBKoa8XOaI,978 fxapom-1.7.dist-info/top_level.txt,sha256=ugIV1fMr_7qNF-keCGLxWjFM3CwOGKRwDUH6m7NMcJk,13 tests/marionette/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 tests/marionette/conftest.py,sha256=nl_zqN47Lxr_yh7YQUdDnAKdrL1J1Ke5JnalRadsxeo,878 tests/marionette/test_fxa_login.py,sha256=HZhcRtfRB23sI0Pka2-O7f8Yihu-it9gZic3z3IT5Ek,862 tests/webdriver/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 tests/webdriver/test_fxa_login.py,sha256=_6lZFjVArEguJsRlGe-WSQMoEh5DBg03iQQq6xWpLrI,886 PK:Hfxapom/__init__.pyPK EH7 lg^^0fxapom/fxapom.pyPK:Hfxapom/pages/__init__.pyPK EH#k]]fxapom/pages/base.pyPK EHlągllfxapom/pages/page.pyPK EHt20$ $ fxapom/pages/sign_in.pyPK EH#x fxapom/pages/marionette/__init__.pyPK EHtuu fxapom/pages/marionette/base.pyPK EHnejjk#fxapom/pages/marionette/page.pyPK EH\%R6 6 "&fxapom/pages/marionette/sign_in.pyPK EH2tests/marionette/__init__.pyPK EH b9nn2tests/marionette/conftest.pyPK EH;^^"j6tests/marionette/test_fxa_login.pyPK EH:tests/webdriver/__init__.pyPK EH^Rvv!A:tests/webdriver/test_fxa_login.pyPKEH;$=fxapom-1.7.dist-info/DESCRIPTION.rstPKEHBJ"Ofxapom-1.7.dist-info/metadata.jsonPKEHg " Tfxapom-1.7.dist-info/top_level.txtPKEHX\\VTfxapom-1.7.dist-info/WHEELPKEHtӑTfxapom-1.7.dist-info/METADATAPKEHT#jfxapom-1.7.dist-info/RECORDPKq