From e66b356f900bc9899a5506378163ffaadd4a32b5 Mon Sep 17 00:00:00 2001 From: Folker Bernitt Date: Wed, 27 Jan 2016 13:56:41 +0100 Subject: Add a login multi user functional test - Issue #576 - Extended AppTestClient with multi user support --- service/pixelated/application.py | 21 +++-- service/pixelated/resources/auth.py | 16 +--- service/pixelated/resources/login_resource.py | 19 ++++- service/test/functional/features/environment.py | 17 ++-- service/test/functional/features/login.feature | 28 +++++++ service/test/functional/features/steps/common.py | 6 ++ service/test/functional/features/steps/compose.py | 1 - .../test/functional/features/steps/data_setup.py | 25 +++++- service/test/functional/features/steps/login.py | 34 ++++++++ .../test/functional/features/steps/mail_list.py | 1 + service/test/integration/test_multi_user_login.py | 1 + .../test/support/integration/app_test_client.py | 92 +++++++++++++++++++--- .../test/support/integration/multi_user_client.py | 13 +-- service/test/unit/resources/test_login_resource.py | 4 +- service/test/unit/test_application.py | 4 +- 15 files changed, 228 insertions(+), 54 deletions(-) create mode 100644 service/test/functional/features/login.feature create mode 100644 service/test/functional/features/steps/login.py diff --git a/service/pixelated/application.py b/service/pixelated/application.py index e273612d..c7833367 100644 --- a/service/pixelated/application.py +++ b/service/pixelated/application.py @@ -30,7 +30,7 @@ from pixelated.adapter.welcome_mail import add_welcome_mail from pixelated.config import arguments from pixelated.config import logger from pixelated.config.leap import initialize_leap_single_user, init_monkeypatches, initialize_leap_provider -from pixelated.config.services import Services +from pixelated.config import services from pixelated.config.site import PixelatedSite from pixelated.resources.auth import LeapPasswordChecker, PixelatedRealm, PixelatedAuthSessionWrapper, SessionChecker from pixelated.resources.login_resource import LoginResource @@ -49,6 +49,7 @@ class ServicesFactory(object): return user_id in self._services_by_user def services(self, user_id): + print self._services_by_user.keys() return self._services_by_user[user_id] def log_out_user(self, user_id): @@ -60,6 +61,13 @@ class ServicesFactory(object): def add_session(self, user_id, services): self._services_by_user[user_id] = services + @defer.inlineCallbacks + def create_services_from(self, leap_session): + _services = services.Services(leap_session) + yield _services.setup() + + self._services_by_user[leap_session.user_auth.uuid] = _services + class SingleUserServicesFactory(object): def __init__(self, mode): @@ -82,13 +90,13 @@ class UserAgentMode(object): def start_user_agent_in_single_user_mode(root_resource, services_factory, leap_home, leap_session): log.info('Bootstrap done, loading services for user %s' % leap_session.user_auth.username) - services = Services(leap_session) - yield services.setup() + _services = services.Services(leap_session) + yield _services.setup() if leap_session.fresh_account: yield add_welcome_mail(leap_session.mail_store) - services_factory.add_session(leap_session.user_auth.uuid, services) + services_factory.add_session(leap_session.user_auth.uuid, _services) root_resource.initialize() @@ -166,8 +174,9 @@ def _start_in_multi_user_mode(args, root_resource, services_factory): return defer.succeed(None) -def set_up_protected_resources(root_resource, provider, services_factory): - checker = LeapPasswordChecker(provider) +def set_up_protected_resources(root_resource, provider, services_factory, checker=None): + if not checker: + checker = LeapPasswordChecker(provider) session_checker = SessionChecker() anonymous_resource = LoginResource(services_factory) diff --git a/service/pixelated/resources/auth.py b/service/pixelated/resources/auth.py index 2d31316b..4eb6bd02 100644 --- a/service/pixelated/resources/auth.py +++ b/service/pixelated/resources/auth.py @@ -94,21 +94,7 @@ class SessionChecker(object): class LeapUser(object): def __init__(self, leap_session): - self._leap_session = leap_session - - @defer.inlineCallbacks - def start_services(self, services_factory): - _services = services.Services(self._leap_session) - yield _services.setup() - - if self._leap_session.fresh_account: - yield add_welcome_mail(self._leap_session.mail_store) - - services_factory.add_session(self._leap_session.user_auth.uuid, _services) - - def init_http_session(self, request): - session = IPixelatedSession(request.getSession()) - session.user_uuid = self._leap_session.user_auth.uuid + self.leap_session = leap_session class PixelatedRealm(object): diff --git a/service/pixelated/resources/login_resource.py b/service/pixelated/resources/login_resource.py index 8a18046c..065d71e7 100644 --- a/service/pixelated/resources/login_resource.py +++ b/service/pixelated/resources/login_resource.py @@ -27,7 +27,8 @@ from twisted.web.static import File from twisted.web.template import Element, XMLFile, renderElement, renderer, tags from twisted.python.filepath import FilePath -from pixelated.resources import BaseResource, UnAuthorizedResource +from pixelated.adapter.welcome_mail import add_welcome_mail +from pixelated.resources import BaseResource, UnAuthorizedResource, IPixelatedSession log = logging.getLogger(__name__) @@ -122,5 +123,17 @@ class LoginResource(BaseResource): creds = credentials.UsernamePassword(username, password) iface, leap_user, logout = yield self._portal.login(creds, None, IResource) - yield leap_user.start_services(self._services_factory) - leap_user.init_http_session(request) + yield self._initialize_after_login(self._services_factory, leap_user) + self._init_http_session(request, leap_user) + + @defer.inlineCallbacks + def _initialize_after_login(self, services_factory, leap_user): + session = leap_user.leap_session + yield services_factory.create_services_from(session) + + if session.fresh_account: + yield add_welcome_mail(session.mail_store) + + def _init_http_session(self, request, leap_user): + session = IPixelatedSession(request.getSession()) + session.user_uuid = leap_user.leap_session.user_auth.uuid diff --git a/service/test/functional/features/environment.py b/service/test/functional/features/environment.py index a41329dd..847322ff 100644 --- a/service/test/functional/features/environment.py +++ b/service/test/functional/features/environment.py @@ -19,6 +19,8 @@ import uuid from crochet import setup, wait_for from leap.common.events.server import ensure_server from twisted.internet import defer + +from pixelated.application import UserAgentMode from test.support.dispatcher.proxy import Proxy from test.support.integration import AppTestClient from selenium import webdriver @@ -31,21 +33,26 @@ setup() @wait_for(timeout=5.0) -def start_app_test_client(client): - ensure_server() - return client.start_client() +def start_app_test_client(client, mode): + return client.start_client(mode=mode) def before_all(context): + ensure_server() logging.disable('INFO') client = AppTestClient() - start_app_test_client(client) + start_app_test_client(client, UserAgentMode(is_single_user=True)) client.listenTCP() proxy = Proxy(proxy_port='8889', app_port='4567') FeaturesResource.DISABLED_FEATURES.append('autoRefresh') context.client = client context.call_to_terminate_proxy = proxy.run_on_a_thread() + multi_user_client = AppTestClient() + start_app_test_client(multi_user_client, UserAgentMode(is_single_user=False)) + multi_user_client.listenTCP(port=MULTI_USER_PORT) + context.multi_user_client = multi_user_client + def after_all(context): context.call_to_terminate_proxy() @@ -57,7 +64,7 @@ def before_feature(context, feature): context.browser.set_window_size(1280, 1024) context.browser.implicitly_wait(DEFAULT_IMPLICIT_WAIT_TIMEOUT_IN_S) context.browser.set_page_load_timeout(60) # wait for data - context.browser.get('http://localhost:8889/') + context.browser.get(HOMEPAGE_URL) def after_step(context, step): diff --git a/service/test/functional/features/login.feature b/service/test/functional/features/login.feature new file mode 100644 index 00000000..9a353d74 --- /dev/null +++ b/service/test/functional/features/login.feature @@ -0,0 +1,28 @@ +# +# Copyright (c) 2014 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . + +Feature: login and logout + As a user of Pixelated + I want to log in to my account + So I can see my emails + + Scenario: Existing user logs into his account + Given Account for user username exists + And I have a mail for username in my inbox + When I open the login page + And I enter username and password as credentials + And I click on the login button + Then I have mails diff --git a/service/test/functional/features/steps/common.py b/service/test/functional/features/steps/common.py index 9a547375..fb5698f0 100644 --- a/service/test/functional/features/steps/common.py +++ b/service/test/functional/features/steps/common.py @@ -26,6 +26,12 @@ TIMEOUT_IN_S = 20 DEFAULT_IMPLICIT_WAIT_TIMEOUT_IN_S = 10.0 +HOMEPAGE_URL = 'http://localhost:8889/' + +MULTI_USER_PORT = 4568 + +MULTI_USER_URL = 'http://localhost:%d/' % MULTI_USER_PORT + class ImplicitWait(object): def __init__(self, context, timeout=5.0): diff --git a/service/test/functional/features/steps/compose.py b/service/test/functional/features/steps/compose.py index f0bed86e..67b1bd51 100644 --- a/service/test/functional/features/steps/compose.py +++ b/service/test/functional/features/steps/compose.py @@ -21,7 +21,6 @@ from common import * @when('I compose a message with') def impl(context): - take_screenshot(context, '/tmp/screenshot.jpeg') toggle = context.browser.find_element_by_id('compose-mails-trigger') toggle.click() diff --git a/service/test/functional/features/steps/data_setup.py b/service/test/functional/features/steps/data_setup.py index fb825aba..167acf9a 100644 --- a/service/test/functional/features/steps/data_setup.py +++ b/service/test/functional/features/steps/data_setup.py @@ -17,6 +17,7 @@ from uuid import uuid4 from test.support.integration import MailBuilder from behave import given from common import wait_for_condition +from crochet import wait_for @given('I have a mail in my inbox') @@ -24,8 +25,30 @@ def add_mail_impl(context): subject = 'Hi! This the subject %s' % uuid4() input_mail = MailBuilder().with_subject(subject).build_input_mail() - context.client.add_mail_to_inbox(input_mail) + context.client.add_mail_to_inbox(input_mail) wait_for_condition(context, lambda _: context.client.search_engine.search(subject)[1] > 0, poll_frequency=0.1) context.last_subject = subject + + +@given('I have a mail for {username} in my inbox') +def add_mail_to_user_inbox(context, username): + subject = 'Hi! This the subject %s' % uuid4() + + input_mail = MailBuilder().with_subject(subject).build_input_mail() + + context.multi_user_client.add_mail_to_user_inbox(input_mail, username) + wait_for_condition(context, lambda _: context.multi_user_client.account_for(username).search_engine.search(subject)[1] > 0, poll_frequency=0.1) + + context.last_subject = subject + + +@wait_for(timeout=10.0) +def add_multi_user_account(context, username): + return context.multi_user_client.create_user('username') + + +@given(u'Account for user {username} exists') +def add_account(context, username): + add_multi_user_account(context, username) diff --git a/service/test/functional/features/steps/login.py b/service/test/functional/features/steps/login.py new file mode 100644 index 00000000..3c80e819 --- /dev/null +++ b/service/test/functional/features/steps/login.py @@ -0,0 +1,34 @@ +# +# Copyright (c) 2016 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . +from behave import when, then +from common import * + + +@when(u'I open the login page') +def login_page(context): + context.browser.get(MULTI_USER_URL + '/login') + + +@when(u'I enter {username} and {password} as credentials') +def enter_credentials(context, username, password): + fill_by_css_selector(context, 'input#email', username) + fill_by_css_selector(context, 'input#password', password) + + +@when(u'I click on the login button') +def click_login(context): + login_button = wait_until_element_is_visible_by_locator(context, (By.CSS_SELECTOR, 'input[name="login"]')) + login_button.click() diff --git a/service/test/functional/features/steps/mail_list.py b/service/test/functional/features/steps/mail_list.py index 1b850578..d19de6cd 100644 --- a/service/test/functional/features/steps/mail_list.py +++ b/service/test/functional/features/steps/mail_list.py @@ -76,6 +76,7 @@ def impl(context): @given('I have mails') +@then(u'I have mails') def impl(context): emails = wait_until_elements_are_visible_by_locator(context, (By.CSS_SELECTOR, '#mail-list li span a')) assert len(emails) > 0 diff --git a/service/test/integration/test_multi_user_login.py b/service/test/integration/test_multi_user_login.py index c571cf29..029d6f26 100644 --- a/service/test/integration/test_multi_user_login.py +++ b/service/test/integration/test_multi_user_login.py @@ -33,6 +33,7 @@ class MultiUserLoginTest(MultiUserClient, SoledadTestBase): @defer.inlineCallbacks def test_logged_in_users_sees_resources(self): response, login_request = yield self.login() + yield response mail = load_mail_from_file('mbox00000000') mail_id = yield self._create_mail_in_soledad(mail) expected_mail_dict = {'body': u'Dignissimos ducimus veritatis. Est tenetur consequatur quia occaecati. Vel sit sit voluptas.\n\nEarum distinctio eos. Accusantium qui sint ut quia assumenda. Facere dignissimos inventore autem sit amet. Pariatur voluptatem sint est.\n\nUt recusandae praesentium aspernatur. Exercitationem amet placeat deserunt quae consequatur eum. Unde doloremque suscipit quia.\n\n', 'header': {u'date': u'Tue, 21 Apr 2015 08:43:27 +0000 (UTC)', u'to': [u'carmel@murazikortiz.name'], u'x-tw-pixelated-tags': u'nite, macro, trash', u'from': u'darby.senger@zemlak.biz', u'subject': u'Itaque consequatur repellendus provident sunt quia.'}, 'ident': mail_id, 'status': [], 'tags': [], 'textPlainBody': u'Dignissimos ducimus veritatis. Est tenetur consequatur quia occaecati. Vel sit sit voluptas.\n\nEarum distinctio eos. Accusantium qui sint ut quia assumenda. Facere dignissimos inventore autem sit amet. Pariatur voluptatem sint est.\n\nUt recusandae praesentium aspernatur. Exercitationem amet placeat deserunt quae consequatur eum. Unde doloremque suscipit quia.\n\n', 'mailbox': u'inbox', 'attachments': [], 'security_casing': {'imprints': [{'state': 'no_signature_information'}], 'locks': []}} diff --git a/service/test/support/integration/app_test_client.py b/service/test/support/integration/app_test_client.py index baf05e2a..e841cfe5 100644 --- a/service/test/support/integration/app_test_client.py +++ b/service/test/support/integration/app_test_client.py @@ -16,6 +16,7 @@ import json import multiprocessing from leap.mail.adaptors.soledad import SoledadMailAdaptor +from leap.srp_session import SRPSession from mockito import mock import os import shutil @@ -31,9 +32,13 @@ from twisted.internet import reactor, defer from twisted.internet.defer import succeed from twisted.web.resource import getChildForRequest # from twisted.web.server import Site as PixelatedSite +from zope.interface import implementer +from twisted.cred import checkers, credentials from pixelated.adapter.mailstore.leap_attachment_store import LeapAttachmentStore from pixelated.adapter.services.feedback_service import FeedbackService -from pixelated.application import ServicesFactory, UserAgentMode, SingleUserServicesFactory +from pixelated.application import ServicesFactory, UserAgentMode, SingleUserServicesFactory, set_up_protected_resources +from pixelated.bitmask_libraries.config import LeapConfig +from pixelated.bitmask_libraries.session import LeapSession from pixelated.config.site import PixelatedSite from pixelated.adapter.mailstore import LeapMailStore @@ -53,17 +58,17 @@ class AppTestAccount(object): INDEX_KEY = '\xde3?\x87\xff\xd9\xd3\x14\xf0\xa7>\x1f%C{\x16.\\\xae\x8c\x13\xa7\xfb\x04\xd4]+\x8d_\xed\xd1\x8d\x0bI' \ '\x8a\x0e\xa4tm\xab\xbf\xb4\xa5\x99\x00d\xd5w\x9f\x18\xbc\x1d\xd4_W\xd2\xb6\xe8H\x83\x1b\xd8\x9d\xad' - def __init__(self, user_id): + def __init__(self, user_id, leap_home): self._user_id = user_id + self._leap_home = leap_home self._uuid = str(uuid.uuid4()) self._mail_address = '%s@pixelated.org' % user_id - self._tmp_dir = TempDir() self._soledad = None self._services = None @defer.inlineCallbacks def start(self): - soledad_test_folder = os.path.join(self._tmp_dir.name, self._uuid) + soledad_test_folder = os.path.join(self._leap_home, self._uuid) self.soledad = yield initialize_soledad(tempdir=soledad_test_folder, uuid=self._uuid) self.search_engine = SearchEngine(self.INDEX_KEY, user_home=soledad_test_folder) self.keymanager = mock() @@ -99,7 +104,8 @@ class AppTestAccount(object): return self._services def cleanup(self): - self._tmp_dir.dissolve() + soledad_test_folder = os.path.join(self._leap_home, self._uuid) + shutil.rmtree(soledad_test_folder) def _initialize_imap_account(self): account_ready_cb = defer.Deferred() @@ -115,19 +121,56 @@ class AppTestAccount(object): return mail_sender +@implementer(checkers.ICredentialsChecker) +class StubSRPChecker(object): + credentialInterfaces = ( + credentials.IUsernamePassword, + ) + + def __init__(self, leap_provider, credentials={}): + self._leap_provider = leap_provider + self._credentials = credentials.copy() + + def add_user(self, username, password): + self._credentials[username] = password + + def requestAvatarId(self, credentials): + leap_auth = SRPSession(credentials.username, uuid.uuid4(), uuid.uuid4(), uuid.uuid4()) + return defer.succeed(LeapSession(self._leap_provider, leap_auth, None, None, None, None)) + + +class StubServicesFactory(ServicesFactory): + + def __init__(self, accounts, mode): + super(StubServicesFactory, self).__init__(mode=mode) + self._accounts = accounts + + @defer.inlineCallbacks + def create_services_from(self, leap_session): + account = self._accounts[leap_session.user_auth.username] + self._services_by_user[leap_session.user_auth.uuid] = account.services + yield defer.succeed(None) + + class AppTestClient(object): INDEX_KEY = '\xde3?\x87\xff\xd9\xd3\x14\xf0\xa7>\x1f%C{\x16.\\\xae\x8c\x13\xa7\xfb\x04\xd4]+\x8d_\xed\xd1\x8d\x0bI' \ '\x8a\x0e\xa4tm\xab\xbf\xb4\xa5\x99\x00d\xd5w\x9f\x18\xbc\x1d\xd4_W\xd2\xb6\xe8H\x83\x1b\xd8\x9d\xad' ACCOUNT = 'test' MAIL_ADDRESS = 'test@pixelated.org' + def _initialize(self): + self._tmp_dir = TempDir() + self.accounts = {} + @defer.inlineCallbacks - def start_client(self): - self._test_account = AppTestAccount(self.ACCOUNT) + def start_client(self, mode=UserAgentMode(is_single_user=True)): + self._initialize() + self._mode = mode + self._test_account = AppTestAccount(self.ACCOUNT, self._tmp_dir.name) yield self._test_account.start() - self.cleanup = lambda: self._test_account.cleanup() + self.cleanup = lambda: self._tmp_dir.dissolve() # copy fields for single user tests self.soledad = self._test_account.soledad @@ -142,12 +185,29 @@ class AppTestClient(object): self.mail_service = self._test_account.mail_service self.account = self._test_account.account - self.service_factory = SingleUserServicesFactory(UserAgentMode(is_single_user=True)) - services = self._test_account.services - self.service_factory.add_session('someuserid', services) + if mode.is_single_user: + self.service_factory = SingleUserServicesFactory(mode) + services = self._test_account.services + self.service_factory.add_session('someuserid', services) + + self.resource = RootResource(self.service_factory) + self.resource.initialize() + else: + self.service_factory = StubServicesFactory(self.accounts, mode) + provider = mock() + provider.config = LeapConfig(self._tmp_dir.name) + + self.resource = set_up_protected_resources(RootResource(self.service_factory), provider, self.service_factory, checker=StubSRPChecker(provider)) - self.resource = RootResource(self.service_factory) - self.resource.initialize() + @defer.inlineCallbacks + def create_user(self, account_name): + if self._mode.is_single_user: + raise Exception('Not supported in single user mode') + + account = AppTestAccount(account_name, self._tmp_dir.name) + yield account.start() + + self.accounts[account_name] = account def _render(self, request, as_json=True): def get_str(_str): @@ -204,6 +264,12 @@ class AppTestClient(object): mail = yield self.mail_store.add_mail('INBOX', input_mail.raw) defer.returnValue(mail) + def account_for(self, username): + return self.accounts[username] + + def add_mail_to_user_inbox(self, input_mail, username): + return self.account_for(username).mail_store.add_mail('INBOX', input_mail.raw) + @defer.inlineCallbacks def add_multiple_to_mailbox(self, num, mailbox='', flags=[], tags=[], to='recipient@to.com', cc='recipient@cc.com', bcc='recipient@bcc.com'): mails = [] diff --git a/service/test/support/integration/multi_user_client.py b/service/test/support/integration/multi_user_client.py index af314fdf..2aa7d3ff 100644 --- a/service/test/support/integration/multi_user_client.py +++ b/service/test/support/integration/multi_user_client.py @@ -35,22 +35,23 @@ from pixelated.adapter.mailstore.searchable_mailstore import SearchableMailStore from pixelated.adapter.search import SearchEngine from pixelated.adapter.services.draft_service import DraftService from pixelated.bitmask_libraries.session import LeapSession, LeapSessionFactory -from pixelated.config import services as config_services +import pixelated.config.services # from pixelated.config.services import Services from pixelated.resources.auth import LeapPasswordChecker, SessionChecker, PixelatedRealm, PixelatedAuthSessionWrapper from pixelated.resources.login_resource import LoginResource from pixelated.resources.root_resource import RootResource from test.support.integration import AppTestClient from test.support.integration.app_test_client import initialize_soledad, AppTestAccount - +import test.support.mockito from test.support.test_helper import request_mock class MultiUserClient(AppTestClient): @defer.inlineCallbacks - def start_client(self): - self._test_account = AppTestAccount('test') + def start_client(self, mode=UserAgentMode(is_single_user=True)): + self._initialize() + self._test_account = AppTestAccount('test', self._tmp_dir.name) yield self._test_account.start() @@ -74,9 +75,9 @@ class MultiUserClient(AppTestClient): leap_session.fresh_account = False self._set_leap_srp_auth(username, password) + when(leap_session).initial_sync().thenAnswer(lambda: defer.succeed(None)) when(LeapSessionFactory).create(username, password).thenReturn(leap_session) - when(config_services).Services(leap_session).thenReturn(self._test_account.services) - # when(Services).setup().thenReturn(defer.succeed('mocked so irrelevant')) + when(pixelated.config.services).Services(ANY()).thenReturn(self._test_account.services) request = request_mock(path='/login', method="POST", body={'username': username, 'password': password}) return self._render(request, as_json=False) diff --git a/service/test/unit/resources/test_login_resource.py b/service/test/unit/resources/test_login_resource.py index 1f9a7c6a..1ccc530d 100644 --- a/service/test/unit/resources/test_login_resource.py +++ b/service/test/unit/resources/test_login_resource.py @@ -88,6 +88,7 @@ class TestLoginPOST(unittest.TestCase): config.leap_home = 'some_folder' leap_session.config = config leap_session.fresh_account = False + self.leap_session = leap_session self.leap_user = LeapUser(leap_session) @patch('twisted.web.util.redirectTo') @@ -99,8 +100,7 @@ class TestLoginPOST(unittest.TestCase): def assert_login_setup_service_for_user(_): verify(self.portal).login(ANY(), None, IResource) - self.assertTrue(mock_service_setup.called) - verify(self.services_factory).add_session('some_user_uuid', ANY()) + verify(self.services_factory).create_services_from(self.leap_session) mock_redirect.assert_called_once_with('/', self.request) self.assertTrue(self.resource.is_logged_in(self.request)) diff --git a/service/test/unit/test_application.py b/service/test/unit/test_application.py index a0eb9986..5f7f9c74 100644 --- a/service/test/unit/test_application.py +++ b/service/test/unit/test_application.py @@ -38,7 +38,7 @@ class ApplicationTest(unittest.TestCase): @patch('leap.common.events.client') @patch('pixelated.application.reactor') - @patch('pixelated.application.Services') + @patch('pixelated.application.services.Services') def test_that_start_user_agent_binds_to_tcp_port_if_no_ssl_options(self, services_mock, reactor_mock, _): # FIXME patch something closer, instead of leap.common app_mock = MagicMock() @@ -56,7 +56,7 @@ class ApplicationTest(unittest.TestCase): @patch('leap.common.events.client') @patch('pixelated.application.reactor') - @patch('pixelated.application.Services') + @patch('pixelated.application.services.Services') def test_that_start_user_agent_binds_to_ssl_if_ssl_options(self, services_mock, reactor_mock, _): # FIXME patch something closer, instead of leap.common app_mock = MagicMock() -- cgit v1.2.3