diff options
Diffstat (limited to 'service/test')
-rw-r--r-- | service/test/functional/features/environment.py | 2 | ||||
-rw-r--r-- | service/test/functional/features/steps/attachments.py | 10 | ||||
-rw-r--r-- | service/test/functional/features/steps/common.py | 2 | ||||
-rw-r--r-- | service/test/functional/features/steps/compose.py | 6 | ||||
-rw-r--r-- | service/test/functional/features/steps/login.py | 6 | ||||
-rw-r--r-- | service/test/functional/features/steps/tag_list.py | 21 | ||||
-rw-r--r-- | service/test/integration/test_multi_user_login.py | 9 | ||||
-rw-r--r-- | service/test/support/integration/app_test_client.py | 6 | ||||
-rw-r--r-- | service/test/unit/resources/test_backup_account_resource.py (renamed from service/test/unit/resources/test_account_recovery_resource.py) | 8 | ||||
-rw-r--r-- | service/test/unit/resources/test_helpers.py | 7 | ||||
-rw-r--r-- | service/test/unit/resources/test_login_resource.py | 113 |
11 files changed, 130 insertions, 60 deletions
diff --git a/service/test/functional/features/environment.py b/service/test/functional/features/environment.py index d49016b6..821a762b 100644 --- a/service/test/functional/features/environment.py +++ b/service/test/functional/features/environment.py @@ -63,7 +63,7 @@ def before_all(context): def _setup_webdriver(context): - browser = context.config.userdata.get('webdriver', 'phantomjs') + browser = context.config.userdata.get('webdriver', 'chrome') supported_webdrivers = { 'phantomjs': webdriver.PhantomJS, 'firefox': webdriver.Firefox, diff --git a/service/test/functional/features/steps/attachments.py b/service/test/functional/features/steps/attachments.py index 8852b787..37fabb6a 100644 --- a/service/test/functional/features/steps/attachments.py +++ b/service/test/functional/features/steps/attachments.py @@ -13,6 +13,8 @@ # # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see <http://www.gnu.org/licenses/>. +import os + from email.MIMEMultipart import MIMEMultipart from email.mime.application import MIMEApplication from email.mime.text import MIMEText @@ -67,8 +69,10 @@ def find_icon(context): def upload_big_file(context): base_dir = "test/functional/features/files/" fname = "over_5mb.data" + path = os.path.abspath(os.path.join(base_dir, fname)) + context.browser.execute_script("$('#fileupload').removeAttr('hidden');") - fill_by_css_selector(context, '#fileupload', base_dir + fname) + fill_by_css_selector(context, '#fileupload', path) find_element_by_css_selector(context, '#upload-error-message') @@ -97,7 +101,9 @@ def should_not_show_upload_error_message(context): def upload_attachment(context): base_dir = "test/functional/features/files/" fname = "5mb.data" - fill_by_css_selector(context, '#fileupload', base_dir + fname) + path = os.path.abspath(os.path.join(base_dir, fname)) + + fill_by_css_selector(context, '#fileupload', path) attachment_list_item = find_element_by_css_selector(context, '#attachment-list-item li a') assert attachment_list_item.text == "%s (5.00 Mb)" % fname diff --git a/service/test/functional/features/steps/common.py b/service/test/functional/features/steps/common.py index edfe2a50..3e1e995e 100644 --- a/service/test/functional/features/steps/common.py +++ b/service/test/functional/features/steps/common.py @@ -61,7 +61,7 @@ def _wait_until_elements_are_visible_by_locator(context, locator_tuple, timeout= def _wait_until_element_is_visible_by_locator(context, locator_tuple, timeout=TIMEOUT_IN_S): wait = WebDriverWait(context.browser, timeout) - wait.until(EC.presence_of_element_located(locator_tuple)) + wait.until(EC.visibility_of_element_located(locator_tuple)) return context.browser.find_element(locator_tuple[0], locator_tuple[1]) diff --git a/service/test/functional/features/steps/compose.py b/service/test/functional/features/steps/compose.py index 1dab1b6d..1b90052e 100644 --- a/service/test/functional/features/steps/compose.py +++ b/service/test/functional/features/steps/compose.py @@ -19,7 +19,9 @@ from behave import when from common import ( fill_by_css_selector, - find_element_by_css_selector) + find_element_by_css_selector, + find_element_by_id +) @when('I compose a message with') @@ -52,7 +54,7 @@ def send_impl(context): @when(u'I toggle the cc and bcc fields') def collapse_cc_bcc_fields(context): - cc_and_bcc_chevron = find_element_by_css_selector(context, '#cc-bcc-collapse') + cc_and_bcc_chevron = find_element_by_id(context, 'cc-bcc-collapse') cc_and_bcc_chevron.click() diff --git a/service/test/functional/features/steps/login.py b/service/test/functional/features/steps/login.py index 6ee521e9..9ce37370 100644 --- a/service/test/functional/features/steps/login.py +++ b/service/test/functional/features/steps/login.py @@ -29,13 +29,13 @@ def login_page(context): @when(u'I enter {username} and {password} as credentials') def enter_credentials(context, username, password): - fill_by_css_selector(context, 'input#email', context.username) - fill_by_css_selector(context, 'input#password', password) + fill_by_css_selector(context, 'input[name="username"]', context.username) + fill_by_css_selector(context, 'input[name="password"]', password) @when(u'I click on the login button') def click_login(context): - find_element_by_css_selector(context, 'input[name="login"]').click() + find_element_by_css_selector(context, 'button[type="submit"]').click() @then(u'I should see the fancy interstitial') diff --git a/service/test/functional/features/steps/tag_list.py b/service/test/functional/features/steps/tag_list.py index daea416d..e3382a61 100644 --- a/service/test/functional/features/steps/tag_list.py +++ b/service/test/functional/features/steps/tag_list.py @@ -14,11 +14,10 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see <http://www.gnu.org/licenses/>. from behave import when -from selenium.common.exceptions import TimeoutException +from selenium.common.exceptions import TimeoutException, StaleElementReferenceException from common import ( find_element_by_class_name, - find_element_by_id, find_element_by_css_selector, wait_for_user_alert_to_disapear) @@ -37,12 +36,11 @@ def expand_side_nav(context): if is_side_nav_expanded(context): return - toggle = find_element_by_class_name(context, 'side-nav-toggle') - toggle.click() + find_element_by_css_selector(context, '.side-nav-toggle-icon i').click() @when('I select the tag \'{tag}\'') -def impl(context, tag): +def select_tag(context, tag): wait_for_user_alert_to_disapear(context) expand_side_nav(context) @@ -53,23 +51,14 @@ def impl(context, tag): try: find_element_by_css_selector(context, '#tag-%s' % tag) - e = find_element_by_id(context, 'tag-%s' % tag) + e = find_element_by_css_selector(context, '#tag-%s .tag-label' % tag) e.click() find_element_by_css_selector(context, ".mail-list-entry__item[href*='%s']" % tag) success = True - except TimeoutException: + except (TimeoutException, StaleElementReferenceException): pass finally: try_again -= 1 assert success - - -@when('I am in \'{tag}\'') -def impl(context, tag): - expand_side_nav(context) - - find_element_by_css_selector(context, '#tag-%s' % tag) - e = find_element_by_id(context, 'tag-%s' % tag) - assert "selected" in e.get_attribute("class") diff --git a/service/test/integration/test_multi_user_login.py b/service/test/integration/test_multi_user_login.py index fe456583..04cceec3 100644 --- a/service/test/integration/test_multi_user_login.py +++ b/service/test/integration/test_multi_user_login.py @@ -13,7 +13,6 @@ # # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -from mock import patch from twisted.internet import defer @@ -47,8 +46,8 @@ class MultiUserLoginTest(MultiUserSoledadTestBase): self.assertEquals(val, response[key]) @defer.inlineCallbacks - def test_wrong_credentials_cannot_access_resources(self): + def test_wrong_credentials_is_redirected_to_login(self): response, login_request = self.app_test_client.login('username', 'wrong_password') - response_str = yield response - self.assertEqual(401, login_request.responseCode) - self.assertIn('Invalid username or password', login_request.written) + yield response + self.assertEqual(302, login_request.responseCode) + self.assertIn('/login?auth-error', login_request.responseHeaders.getRawHeaders('location')) diff --git a/service/test/support/integration/app_test_client.py b/service/test/support/integration/app_test_client.py index d52c85c0..538cf633 100644 --- a/service/test/support/integration/app_test_client.py +++ b/service/test/support/integration/app_test_client.py @@ -429,8 +429,6 @@ def initialize_soledad(tempdir, uuid): def __call__(self): return self - Soledad._shared_db = MockSharedDB() - _soledad = Soledad( uuid, passphrase, @@ -438,8 +436,8 @@ def initialize_soledad(tempdir, uuid): local_db_path, server_url, cert_file, - defer_encryption=False, - syncable=False) + shared_db=MockSharedDB() + ) yield SoledadMailAdaptor().initialize_store(_soledad) diff --git a/service/test/unit/resources/test_account_recovery_resource.py b/service/test/unit/resources/test_backup_account_resource.py index 01ffaed2..21ae5aab 100644 --- a/service/test/unit/resources/test_account_recovery_resource.py +++ b/service/test/unit/resources/test_backup_account_resource.py @@ -20,18 +20,18 @@ from mock import MagicMock, patch from twisted.trial import unittest from twisted.web.test.requesthelper import DummyRequest -from pixelated.resources.account_recovery_resource import AccountRecoveryResource +from pixelated.resources.backup_account_resource import BackupAccountResource from test.unit.resources import DummySite -class TestAccountRecoveryResource(unittest.TestCase): +class TestBackupAccountResource(unittest.TestCase): def setUp(self): self.services_factory = MagicMock() - self.resource = AccountRecoveryResource(self.services_factory) + self.resource = BackupAccountResource(self.services_factory) self.web = DummySite(self.resource) def test_get(self): - request = DummyRequest(['/recovery']) + request = DummyRequest(['/backup-account']) request.method = 'GET' d = self.web.get(request) diff --git a/service/test/unit/resources/test_helpers.py b/service/test/unit/resources/test_helpers.py index e21c5373..6c456f51 100644 --- a/service/test/unit/resources/test_helpers.py +++ b/service/test/unit/resources/test_helpers.py @@ -18,6 +18,7 @@ from twisted.trial import unittest import re from pixelated.resources import respond_json, respond_json_deferred +from pixelated.resources import get_public_static_folder, get_protected_static_folder from test.unit.resources import DummySite from twisted.web.test.requesthelper import DummyRequest @@ -44,3 +45,9 @@ class TestHelpers(unittest.TestCase): self.assertEqual(b"{\"test\": \"yep\"}", request.written[0]) self.assertEqual([b"application/json"], request.responseHeaders.getRawHeaders("Content-Type")) + + def test_getting_public_folder_returns_path(self): + self.assertIn('web-ui/dist/public', get_public_static_folder()) + + def test_getting_protected_folder_returns_path(self): + self.assertIn('web-ui/dist/protected', get_protected_static_folder()) diff --git a/service/test/unit/resources/test_login_resource.py b/service/test/unit/resources/test_login_resource.py index cec57123..733583a3 100644 --- a/service/test/unit/resources/test_login_resource.py +++ b/service/test/unit/resources/test_login_resource.py @@ -23,7 +23,7 @@ from twisted.internet import defer from twisted.trial import unittest from twisted.web.test.requesthelper import DummyRequest -from pixelated.resources.login_resource import LoginResource +from pixelated.resources.login_resource import LoginResource, LoginStatusResource from pixelated.resources.login_resource import parse_accept_language from test.unit.resources import DummySite @@ -87,23 +87,15 @@ class TestLoginResource(unittest.TestCase): d = self.web.get(request) - def assert_form_rendered(_): + def assert_login_page_rendered(_): self.assertEqual(200, request.responseCode) - form_action = 'action="/login"' - form_method = 'method="post"' - input_username = 'name="username"' - input_password = 'name="password"' - input_submit = 'name="login"' + title = 'Pixelated - Login' default_disclaimer = 'Some disclaimer' written_response = ''.join(request.written) - self.assertIn(form_action, written_response) - self.assertIn(form_method, written_response) - self.assertIn(input_password, written_response) - self.assertIn(input_submit, written_response) - self.assertIn(input_username, written_response) + self.assertIn(title, written_response) self.assertIn(default_disclaimer, written_response) - d.addCallback(assert_form_rendered) + d.addCallback(assert_login_page_rendered) return d def _write(self, filename, content): @@ -211,22 +203,23 @@ class TestLoginPOST(unittest.TestCase): return d @patch('pixelated.config.leap.BootstrapUserServices.setup') + @patch('twisted.web.util.redirectTo') @patch('pixelated.authentication.Authenticator.authenticate') - def test_should_return_form_back_with_error_message_when_login_fails(self, mock_authenticate, - mock_user_bootstrap_setup): + def test_should_redirect_to_login_with_error_flag_when_login_fails(self, mock_authenticate, + mock_redirect, + mock_user_bootstrap_setup): mock_authenticate.side_effect = UnauthorizedLogin() + mock_redirect.return_value = "mocked redirection" d = self.web.get(self.request) - def assert_error_response_and_user_services_not_setup(_): + def assert_redirected_to_login(_): mock_authenticate.assert_called_once_with(self.username, self.password) - self.assertEqual(401, self.request.responseCode) - written_response = ''.join(self.request.written) - self.assertIn('Invalid username or password', written_response) + mock_redirect.assert_called_once_with('/login?auth-error', self.request) self.assertFalse(mock_user_bootstrap_setup.called) self.assertFalse(self.resource.get_session(self.request).is_logged_in()) - d.addCallback(assert_error_response_and_user_services_not_setup) + d.addCallback(assert_redirected_to_login) return d @patch('pixelated.config.leap.BootstrapUserServices.setup') @@ -238,7 +231,7 @@ class TestLoginPOST(unittest.TestCase): def assert_interstitial_in_response(_): mock_authenticate.assert_called_once_with(self.username, self.password) - interstitial_js_in_template = '<script src="startup-assets/Interstitial.js"></script>' + interstitial_js_in_template = '<script src="/public/interstitial.js"></script>' self.assertIn(interstitial_js_in_template, self.request.written[0]) d.addCallback(assert_interstitial_in_response) @@ -259,7 +252,7 @@ class TestLoginPOST(unittest.TestCase): @patch('pixelated.config.leap.BootstrapUserServices.setup') @patch('pixelated.authentication.Authenticator.authenticate') - def test_successful_adds_cookies_to_indicat_logged_in_status_when_services_are_loaded(self, mock_authenticate, mock_user_bootstrap_setup): + def test_successful_adds_cookies_to_indicate_logged_in_status_when_services_are_loaded(self, mock_authenticate, mock_user_bootstrap_setup): mock_authenticate.return_value = self.user_auth irrelevant = None mock_user_bootstrap_setup.return_value = defer.succeed(irrelevant) @@ -271,3 +264,79 @@ class TestLoginPOST(unittest.TestCase): d.addCallback(assert_login_setup_service_for_user) return d + + @patch('pixelated.resources.session.PixelatedSession.login_started') + @patch('pixelated.authentication.Authenticator.authenticate') + def test_session_adds_login_started_status_after_authentication(self, mock_authenticate, mock_login_started): + mock_authenticate.return_value = self.user_auth + + d = self.web.get(self.request) + + def assert_login_started_called(_): + mock_login_started.assert_called_once() + + d.addCallback(assert_login_started_called) + return d + + @patch('pixelated.resources.session.PixelatedSession.login_successful') + @patch('pixelated.config.leap.BootstrapUserServices.setup') + @patch('pixelated.authentication.Authenticator.authenticate') + def test_session_adds_login_successful_status_when_services_setup_finishes(self, mock_authenticate, mock_user_bootstrap_setup, mock_login_successful): + mock_authenticate.return_value = self.user_auth + mock_user_bootstrap_setup.return_value = defer.succeed(None) + + d = self.web.get(self.request) + + def assert_login_successful_called(_): + mock_login_successful.assert_called_once() + + d.addCallback(assert_login_successful_called) + return d + + @patch('pixelated.resources.session.PixelatedSession.login_error') + @patch('pixelated.config.leap.BootstrapUserServices.setup') + @patch('pixelated.authentication.Authenticator.authenticate') + def test_session_adds_login_error_status_when_services_setup_gets_error(self, mock_authenticate, mock_user_bootstrap_setup, mock_login_error): + mock_authenticate.return_value = self.user_auth + mock_user_bootstrap_setup.return_value = defer.fail(Exception('Could not setup user services')) + + d = self.web.get(self.request) + + def assert_login_error_called(_): + mock_login_error.assert_called_once() + + d.addCallback(assert_login_error_called) + return d + + +class TestLoginStatus(unittest.TestCase): + def setUp(self): + self.services_factory = mock() + self.resource = LoginStatusResource(self.services_factory) + self.web = DummySite(self.resource) + + self.request = DummyRequest(['/status']) + + def test_login_status_completed_when_single_user(self): + self.services_factory.mode = mock() + self.services_factory.mode.is_single_user = True + d = self.web.get(self.request) + + def assert_login_completed(_): + self.assertIn('completed', self.request.written[0]) + + d.addCallback(assert_login_completed) + return d + + @patch('pixelated.resources.session.PixelatedSession.check_login_status') + def test_login_status_when_multi_user_returns_check_login_status(self, mock_login_status): + self.services_factory.mode = mock() + self.services_factory.mode.is_single_user = False + mock_login_status.return_value = 'started' + d = self.web.get(self.request) + + def assert_login_completed(_): + self.assertIn('started', self.request.written[0]) + + d.addCallback(assert_login_completed) + return d |