diff --git a/README.rst b/README.rst index 7e3c9e1..a0c81b0 100644 --- a/README.rst +++ b/README.rst @@ -2,3 +2,39 @@ Mozlotov ======== Mozilla-specific helpers for writing Molotov tests. + + +FXA +--- + +In order to use an API that requires a Firefox Account Bearer token, +you can use the **FXATestAccount** class. The class will create +a test user for you and provide a Bearer token. + +Example of Molotov integration: + +.. code-block:: python + + from molotov import global_setup, global_teardown setup + from mozlotov import FXATestAccount + + _FXA = [] + + @global_setup() + def create_accoun(args): + # creates the user and get a Bearer token + acct = FXATestAccount() + acct.create() + _FXA.append(acct) + + @global_teardown() + def destroy_account(): + # destroys the user + _FXA[0].cleanup() + + @setup() + async def init_test(worker_id, args): + # grab the Bearer token for the Molotov test + headers = {"Authorization": _FXA[0].authorization()} + return {'headers': headers} + diff --git a/mozlotov/__init__.py b/mozlotov/__init__.py index 373d726..833de46 100644 --- a/mozlotov/__init__.py +++ b/mozlotov/__init__.py @@ -1,2 +1,6 @@ - __version__ = '0.1' + +try: + from mozlotov._fxa import FXATestAccount # NOQA +except ImportError: + pass # NOQA diff --git a/mozlotov/_fxa.py b/mozlotov/_fxa.py new file mode 100644 index 0000000..098108f --- /dev/null +++ b/mozlotov/_fxa.py @@ -0,0 +1,50 @@ +import os +import functools.partials + +from fxa.__main__ import DEFAULT_CLIENT_ID +from fxa.core import Client +from fxa.tests.utils import TestEmailAccount +from fxa.tools.bearer import get_bearer_token + + +_FXA_SERVER = "https://api.accounts.firefox.com" +_FXA_OAUTH = "https://oauth.accounts.firefox.com/v1" +_PWD = 'MySecretPassword' + + +class FXATestAccount(object): + def __init__(self, server=_FXA_SERVER, oauth=_FXA_OAUTH, password=_PWD): + self.server = server + self.oauth = oauth + self.session = self.token = None + self.password = password + self.acct = TestEmailAccount() + self.client = Client(_FXA_SERVER) + + def _verify(self, session, response): + code = response["headers"].get('x-verify-code') + if code is None: + return False + session.verify_email_code(code) + return True + + def create(self): + session = self.client.create_account(self.acct.email, self.password) + m = self.acct.wait_for_email(functools.partial(self._verify, session)) + if m is None: + raise RuntimeError("verification email did not arrive") + + self.token = get_bearer_token(self.acct.email, self.password + account_server_url=self.server+"/v1", + oauth_server_url=self.oauth, + scopes=['sync:addon_storage'], + client_id=DEFAULT_CLIENT_ID) + + def cleanup(self): + self.acct.clear() + self.client.destroy_account(self.acct.email, self.password) + + def authorization(self): + if self.token is None: + raise RuntimeError("You need to call create() first") + return "Bearer %s" % self.token