From 7013966e310f9f9135b526ac447fc0718cb32139 Mon Sep 17 00:00:00 2001 From: Denis Costa Date: Fri, 25 Nov 2016 11:50:32 -0200 Subject: Update behave and selenium See: https://github.com/pixelated/project-issues/issues/380 --- service/test_requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/test_requirements.txt b/service/test_requirements.txt index b6b704c7..ae9443dd 100644 --- a/service/test_requirements.txt +++ b/service/test_requirements.txt @@ -1,5 +1,5 @@ -behave==1.2.4 -selenium==2.44.0 +behave==1.2.5 +selenium==3.0.1 mock==2.0.0 httmock==1.2.2 mockito==0.5.2 -- cgit v1.2.3 From a55252190f83a678e3b74c841e24512e78041b5a Mon Sep 17 00:00:00 2001 From: Denis Costa Date: Fri, 25 Nov 2016 11:59:40 -0200 Subject: Changes print from command to function See: https://github.com/pixelated/project-issues/issues/380 --- service/test/functional/features/steps/common.py | 2 +- service/test/functional/features/steps/mail_list.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/service/test/functional/features/steps/common.py b/service/test/functional/features/steps/common.py index ccad842c..a7800ee8 100644 --- a/service/test/functional/features/steps/common.py +++ b/service/test/functional/features/steps/common.py @@ -186,7 +186,7 @@ def get_console_log(context): for entry in logs: msg = entry['message'] if not (msg.startswith('x off') or msg.startswith('<- on')): - print entry['message'] + print(entry['message']) def create_email(context): diff --git a/service/test/functional/features/steps/mail_list.py b/service/test/functional/features/steps/mail_list.py index 82faa7af..8ac9cb6b 100644 --- a/service/test/functional/features/steps/mail_list.py +++ b/service/test/functional/features/steps/mail_list.py @@ -18,7 +18,7 @@ from selenium.common.exceptions import NoSuchElementException def find_current_mail(context): - print 'searching for mail [%s]' % context.current_mail_id + print('searching for mail [%s]' % context.current_mail_id) return find_element_by_id(context, '%s' % context.current_mail_id) -- cgit v1.2.3 From 4fd50e650bbfa474f77daf63a44e08b6cb039679 Mon Sep 17 00:00:00 2001 From: Denis Costa Date: Fri, 25 Nov 2016 13:55:02 -0200 Subject: Improves imports See: https://github.com/pixelated/project-issues/issues/380 --- service/test/functional/features/environment.py | 16 ++++++++-------- .../test/functional/features/steps/attachments.py | 21 +++++++++++++-------- service/test/functional/features/steps/common.py | 9 +++++++-- service/test/functional/features/steps/compose.py | 7 ++++++- service/test/functional/features/steps/mail_list.py | 16 ++++++++++++++-- service/test/functional/features/steps/mail_view.py | 12 +++++++++++- service/test/functional/features/steps/search.py | 6 ++++-- service/test/functional/features/steps/tag_list.py | 10 +++++++++- 8 files changed, 72 insertions(+), 25 deletions(-) diff --git a/service/test/functional/features/environment.py b/service/test/functional/features/environment.py index 77efc499..00480e68 100644 --- a/service/test/functional/features/environment.py +++ b/service/test/functional/features/environment.py @@ -13,23 +13,23 @@ # # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . -import uuid import os +import uuid -from selenium import webdriver from crochet import setup, wait_for - +from leap.common.events.server import ensure_server +from selenium import webdriver from twisted.internet import defer from twisted.logger import globalLogBeginner, textFileLogObserver, Logger -from test.support.integration import AppTestClient -from steps.common import * - -from leap.common.events.server import ensure_server - from pixelated.application import UserAgentMode from pixelated.config.site import PixelatedSite from pixelated.resources.features_resource import FeaturesResource +from test.support.integration import AppTestClient +from steps.common import ( + DEFAULT_IMPLICIT_WAIT_TIMEOUT_IN_S, + HOMEPAGE_URL, + MULTI_USER_PORT) setup() diff --git a/service/test/functional/features/steps/attachments.py b/service/test/functional/features/steps/attachments.py index 28d88343..90812d2c 100644 --- a/service/test/functional/features/steps/attachments.py +++ b/service/test/functional/features/steps/attachments.py @@ -13,16 +13,21 @@ # # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . -from email.mime.application import MIMEApplication -from time import sleep -from leap.bitmask.mail.mail import Message -from common import * -from test.support.integration import MailBuilder -from behave import given -from crochet import wait_for -from uuid import uuid4 from email.MIMEMultipart import MIMEMultipart +from email.mime.application import MIMEApplication from email.mime.text import MIMEText +from uuid import uuid4 + +from behave import given, then, when +from crochet import wait_for +from selenium.webdriver.common.by import By + +from common import ( + fill_by_css_selector, + find_element_by_css_selector, + find_elements_by_css_selector, + page_has_css, + wait_until_element_is_visible_by_locator) @given(u'I have a mail with an attachment in my inbox') diff --git a/service/test/functional/features/steps/common.py b/service/test/functional/features/steps/common.py index a7800ee8..4ffe40ce 100644 --- a/service/test/functional/features/steps/common.py +++ b/service/test/functional/features/steps/common.py @@ -13,11 +13,16 @@ # # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . + +import time + +from selenium.common.exceptions import ( + StaleElementReferenceException, + TimeoutException) from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait -from selenium.common.exceptions import TimeoutException, StaleElementReferenceException -import time + from test.support.integration import MailBuilder LOADING = 'loading' diff --git a/service/test/functional/features/steps/compose.py b/service/test/functional/features/steps/compose.py index 67b1bd51..c72b25e2 100644 --- a/service/test/functional/features/steps/compose.py +++ b/service/test/functional/features/steps/compose.py @@ -16,7 +16,12 @@ from time import sleep from behave import when -from common import * +from selenium.webdriver.common.by import By + +from common import ( + fill_by_css_selector, + wait_until_element_is_visible_by_locator, + find_element_by_css_selector) @when('I compose a message with') diff --git a/service/test/functional/features/steps/mail_list.py b/service/test/functional/features/steps/mail_list.py index 8ac9cb6b..7c880e8f 100644 --- a/service/test/functional/features/steps/mail_list.py +++ b/service/test/functional/features/steps/mail_list.py @@ -13,8 +13,20 @@ # # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . -from common import * -from selenium.common.exceptions import NoSuchElementException + +from behave import when, then, given +from selenium.common.exceptions import TimeoutException +from selenium.webdriver.common.by import By + +from common import ( + ImplicitWait, + execute_ignoring_staleness, + find_element_by_id, + mail_list_with_subject_exists, + wait_for_condition, + wait_for_loading_to_finish, + wait_until_element_is_visible_by_locator, + wait_until_elements_are_visible_by_locator) def find_current_mail(context): diff --git a/service/test/functional/features/steps/mail_view.py b/service/test/functional/features/steps/mail_view.py index 2db6dfc5..88ee5c5a 100644 --- a/service/test/functional/features/steps/mail_view.py +++ b/service/test/functional/features/steps/mail_view.py @@ -13,8 +13,18 @@ # # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . + +from behave import then, when from selenium.webdriver.common.keys import Keys -from common import * +from selenium.webdriver.common.by import By + +from common import ( + click_button, + find_element_by_css_selector, + find_elements_by_css_selector, + reply_subject, + wait_until_button_is_visible, + wait_until_element_is_visible_by_locator) @then('I see that the subject reads \'{subject}\'') diff --git a/service/test/functional/features/steps/search.py b/service/test/functional/features/steps/search.py index 879e834d..5a6d2d1c 100644 --- a/service/test/functional/features/steps/search.py +++ b/service/test/functional/features/steps/search.py @@ -13,10 +13,12 @@ # # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . -from selenium.webdriver import ActionChains +from behave import when, then +from selenium.webdriver import ActionChains from selenium.webdriver.common.keys import Keys -from common import * + +from common import find_element_by_css_selector, find_elements_by_css_selector @when('I search for a mail with the words "{search_term}"') diff --git a/service/test/functional/features/steps/tag_list.py b/service/test/functional/features/steps/tag_list.py index 8550a886..b9adea0a 100644 --- a/service/test/functional/features/steps/tag_list.py +++ b/service/test/functional/features/steps/tag_list.py @@ -13,7 +13,15 @@ # # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . -from common import * +from behave import when +from selenium.common.exceptions import TimeoutException +from selenium.webdriver.common.by import By + +from common import ( + find_element_by_class_name, + find_element_by_id, + wait_for_user_alert_to_disapear, + wait_until_element_is_visible_by_locator) def click_first_element_with_class(context, classname): -- cgit v1.2.3 From fcd6cdc105da48d36aaffb2d7fec5653b773d597 Mon Sep 17 00:00:00 2001 From: Denis Costa Date: Fri, 25 Nov 2016 13:56:56 -0200 Subject: Removes unused variable See: https://github.com/pixelated/project-issues/issues/380 --- service/test/functional/features/steps/attachments.py | 1 - 1 file changed, 1 deletion(-) diff --git a/service/test/functional/features/steps/attachments.py b/service/test/functional/features/steps/attachments.py index 90812d2c..7a80c34f 100644 --- a/service/test/functional/features/steps/attachments.py +++ b/service/test/functional/features/steps/attachments.py @@ -112,6 +112,5 @@ def click_remove_icon(context): @then(u'I should not see it attached') def assert_attachment_removed(context): - attachments_list_ul = find_elements_by_css_selector(context, '#attachment-list-item') attachments_list_li = context.browser.find_elements(By.CSS_SELECTOR, '#attachment-list-item li a') assert len(attachments_list_li) == 0 -- cgit v1.2.3 From 708225d9c41f13b714286a755c22e0f31d6ef4c7 Mon Sep 17 00:00:00 2001 From: Denis Costa Date: Fri, 25 Nov 2016 14:57:50 -0200 Subject: Removes commented code See: https://github.com/pixelated/project-issues/issues/380 --- service/test/functional/features/environment.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/service/test/functional/features/environment.py b/service/test/functional/features/environment.py index 00480e68..614741d7 100644 --- a/service/test/functional/features/environment.py +++ b/service/test/functional/features/environment.py @@ -65,8 +65,6 @@ def after_all(context): def before_feature(context, feature): - # context.browser = webdriver.Chrome() - # context.browser = webdriver.Firefox() context.browser = webdriver.PhantomJS() context.browser.set_window_size(1280, 1024) context.browser.implicitly_wait(DEFAULT_IMPLICIT_WAIT_TIMEOUT_IN_S) -- cgit v1.2.3 From 60c9020a11a88e07cb63ede737791bbeb8bbe6ec Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Mon, 28 Nov 2016 16:31:48 -0200 Subject: Convert URL constants to behave's userdata Behave 1.2.5 introduces user-specific configuration data, which can be used to override default values. See: https://github.com/pixelated/project-issues/issues/380 --- service/test/functional/features/environment.py | 14 ++++++++------ service/test/functional/features/steps/common.py | 8 -------- service/test/functional/features/steps/login.py | 3 +-- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/service/test/functional/features/environment.py b/service/test/functional/features/environment.py index 614741d7..c98609f8 100644 --- a/service/test/functional/features/environment.py +++ b/service/test/functional/features/environment.py @@ -26,10 +26,7 @@ from pixelated.application import UserAgentMode from pixelated.config.site import PixelatedSite from pixelated.resources.features_resource import FeaturesResource from test.support.integration import AppTestClient -from steps.common import ( - DEFAULT_IMPLICIT_WAIT_TIMEOUT_IN_S, - HOMEPAGE_URL, - MULTI_USER_PORT) +from steps.common import DEFAULT_IMPLICIT_WAIT_TIMEOUT_IN_S setup() @@ -46,6 +43,11 @@ def start_app_test_client(client, mode): def before_all(context): + userdata = context.config.userdata + context.homepage_url = userdata.get('homepage_url', 'http://localhost:8889') + context.multi_user_port = userdata.getint('multi_user_port', default=4568) + context.multi_user_url = userdata.get('multi_user_url', 'http://localhost:4568') + ensure_server() PixelatedSite.disable_csp_requests() client = AppTestClient() @@ -56,7 +58,7 @@ def before_all(context): multi_user_client = AppTestClient() start_app_test_client(multi_user_client, UserAgentMode(is_single_user=False)) - multi_user_client.listenTCP(port=MULTI_USER_PORT) + multi_user_client.listenTCP(port=context.multi_user_port) context.multi_user_client = multi_user_client @@ -69,7 +71,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(HOMEPAGE_URL) + context.browser.get(context.homepage_url) def after_step(context, step): diff --git a/service/test/functional/features/steps/common.py b/service/test/functional/features/steps/common.py index 4ffe40ce..bbceb015 100644 --- a/service/test/functional/features/steps/common.py +++ b/service/test/functional/features/steps/common.py @@ -25,18 +25,10 @@ from selenium.webdriver.support.wait import WebDriverWait from test.support.integration import MailBuilder -LOADING = 'loading' - 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/login.py b/service/test/functional/features/steps/login.py index 2a653030..d1840900 100644 --- a/service/test/functional/features/steps/login.py +++ b/service/test/functional/features/steps/login.py @@ -21,13 +21,12 @@ from selenium.webdriver.common.by import By from common import ( fill_by_css_selector, find_element_by_css_selector, - MULTI_USER_URL, wait_until_element_is_visible_by_locator) @when(u'I open the login page') def login_page(context): - context.browser.get(MULTI_USER_URL + '/login') + context.browser.get(context.multi_user_url + '/login') @when(u'I enter {username} and {password} as credentials') -- cgit v1.2.3 From d662fa63a0a7f7f2ae31cf1968f61db8b6240a5a Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Tue, 29 Nov 2016 16:16:44 -0200 Subject: Remove twisted loggers from behave tests The twisted loggers were capturing outputs and preventing debug with pdb --- service/test/functional/features/environment.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/service/test/functional/features/environment.py b/service/test/functional/features/environment.py index c98609f8..33e0f5fe 100644 --- a/service/test/functional/features/environment.py +++ b/service/test/functional/features/environment.py @@ -20,7 +20,6 @@ from crochet import setup, wait_for from leap.common.events.server import ensure_server from selenium import webdriver from twisted.internet import defer -from twisted.logger import globalLogBeginner, textFileLogObserver, Logger from pixelated.application import UserAgentMode from pixelated.config.site import PixelatedSite @@ -30,12 +29,6 @@ from steps.common import DEFAULT_IMPLICIT_WAIT_TIMEOUT_IN_S setup() -observers = [textFileLogObserver(open(os.devnull, 'w'))] - -globalLogBeginner.beginLoggingTo(observers) - -Logger('twisted') - @wait_for(timeout=5.0) def start_app_test_client(client, mode): -- cgit v1.2.3 From b07f0748a4cff3a3310327a9182d9458d0983613 Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Tue, 29 Nov 2016 16:38:58 -0200 Subject: Add support for parameterization on error We added debug on error, default to false and save screenshots, default to true --- service/test/functional/features/environment.py | 31 +++++++++++++++---------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/service/test/functional/features/environment.py b/service/test/functional/features/environment.py index 33e0f5fe..b7dbba3f 100644 --- a/service/test/functional/features/environment.py +++ b/service/test/functional/features/environment.py @@ -14,7 +14,8 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . import os -import uuid +import re +import time from crochet import setup, wait_for from leap.common.events.server import ensure_server @@ -68,12 +69,23 @@ def before_feature(context, feature): def after_step(context, step): - if step.status == 'failed': - id = str(uuid.uuid4()) - os.chdir("screenshots") - context.browser.save_screenshot('failed ' + str(step.name) + '_' + id + ".png") - save_source(context, 'failed ' + str(step.name) + '_' + id + ".html") - os.chdir("../") + _debug_on_error(context, step) + _save_screenshot(context, step) + + +def _debug_on_error(context, step): + if step.status == 'failed' and context.config.userdata.getbool("debug"): + import pdb + pdb.post_mortem(step.exc_traceback) + + +def _save_screenshot(context, step): + if (step.status == 'failed' and + context.config.userdata.getbool("screenshots", True)): + timestamp = time.strftime("%Y-%m-%d-%H-%M-%S") + filename = re.sub('\W', '-', timestamp + ' failed ' + str(step.name)) + filepath = os.path.join('screenshots', filename + '.png') + context.browser.save_screenshot(filepath) def after_feature(context, feature): @@ -92,8 +104,3 @@ def cleanup_all_mails(context): yield context.client.mail_store.delete_mail(mail.ident) return _delete_all_mails() - - -def save_source(context, filename='/tmp/source.html'): - with open(filename, 'w') as out: - out.write(context.browser.page_source.encode('utf8')) -- cgit v1.2.3 From cb95c9442032fc04f4530f2690f22611445c7565 Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Tue, 29 Nov 2016 20:01:53 -0200 Subject: Improve atomicity of checkbox operations We were getting too much errors like "Element is no longer attached to the DOM". See: https://github.com/pixelated/project-issues/issues/381 --- .../test/functional/features/steps/mail_list.py | 26 ++++++++++------------ 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/service/test/functional/features/steps/mail_list.py b/service/test/functional/features/steps/mail_list.py index 7c880e8f..23724bf2 100644 --- a/service/test/functional/features/steps/mail_list.py +++ b/service/test/functional/features/steps/mail_list.py @@ -22,6 +22,7 @@ from common import ( ImplicitWait, execute_ignoring_staleness, find_element_by_id, + find_element_by_css_selector, mail_list_with_subject_exists, wait_for_condition, wait_for_loading_to_finish, @@ -90,31 +91,28 @@ 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-entry__item')) + emails = wait_until_elements_are_visible_by_locator(context, (By.CSS_SELECTOR, '.mail-list-entry')) assert len(emails) > 0 @when('I mark the first unread email as read') def impl(context): - emails = wait_until_elements_are_visible_by_locator(context, (By.CSS_SELECTOR, '.mail-list-entry')) + mail_id = find_element_by_css_selector( + context, '.mail-list-entry:not(.status-read)').get_attribute('id') + + find_element_by_css_selector(context, '#%s input' % mail_id).click() + find_element_by_id(context, 'mark-selected-as-read').click() - for email in emails: - if 'status-read' not in email.get_attribute('class'): - context.current_mail_id = email.get_attribute('id') # we need to get the mail id before manipulating the page - email.find_element_by_tag_name('input').click() - find_element_by_id(context, 'mark-selected-as-read').click() - break - wait_until_elements_are_visible_by_locator(context, (By.CSS_SELECTOR, '#%s.status-read' % context.current_mail_id)) + find_element_by_css_selector(context, '#%s.status-read' % mail_id) @when('I delete the email') def impl(context): - def last_email(): - return wait_until_element_is_visible_by_locator(context, (By.CSS_SELECTOR, '.mail-list-entry')) - mail = last_email() - context.current_mail_id = mail.get_attribute('id') - mail.find_element_by_tag_name('input').click() + mail_id = find_element_by_css_selector(context, '.mail-list-entry').get_attribute('id') + + find_element_by_css_selector(context, '#%s input' % mail_id).click() find_element_by_id(context, 'delete-selected').click() + _wait_for_mail_list_to_be_empty(context) -- cgit v1.2.3 From cf55bf8e3657a13b230cd56787e0c941b2a596e9 Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Wed, 30 Nov 2016 11:39:16 -0200 Subject: Setup browser before_all method See: https://github.com/pixelated/project-issues/issues/381 --- service/test/functional/features/environment.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/service/test/functional/features/environment.py b/service/test/functional/features/environment.py index b7dbba3f..ce880a87 100644 --- a/service/test/functional/features/environment.py +++ b/service/test/functional/features/environment.py @@ -37,6 +37,11 @@ def start_app_test_client(client, mode): def before_all(context): + context.browser = webdriver.PhantomJS() + 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 + userdata = context.config.userdata context.homepage_url = userdata.get('homepage_url', 'http://localhost:8889') context.multi_user_port = userdata.getint('multi_user_port', default=4568) @@ -57,17 +62,19 @@ def before_all(context): def after_all(context): + context.browser.quit() context.client.stop() def before_feature(context, feature): - context.browser = webdriver.PhantomJS() - 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(context.homepage_url) +def after_feature(context, feature): + cleanup_all_mails(context) + context.last_mail = None + + def after_step(context, step): _debug_on_error(context, step) _save_screenshot(context, step) @@ -88,11 +95,6 @@ def _save_screenshot(context, step): context.browser.save_screenshot(filepath) -def after_feature(context, feature): - context.browser.quit() - - cleanup_all_mails(context) - context.last_mail = None @wait_for(timeout=10.0) -- cgit v1.2.3 From 61c288d889eef16a012a721d0fddab33467c861e Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Wed, 30 Nov 2016 11:40:27 -0200 Subject: Extract slugify method --- service/test/functional/features/environment.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/service/test/functional/features/environment.py b/service/test/functional/features/environment.py index ce880a87..b03c506e 100644 --- a/service/test/functional/features/environment.py +++ b/service/test/functional/features/environment.py @@ -90,11 +90,13 @@ def _save_screenshot(context, step): if (step.status == 'failed' and context.config.userdata.getbool("screenshots", True)): timestamp = time.strftime("%Y-%m-%d-%H-%M-%S") - filename = re.sub('\W', '-', timestamp + ' failed ' + str(step.name)) + filename = _slugify('{} failed {}'.format(timestamp, str(step.name))) filepath = os.path.join('screenshots', filename + '.png') context.browser.save_screenshot(filepath) +def _slugify(string_): + return re.sub('\W', '-', string_) @wait_for(timeout=10.0) -- cgit v1.2.3 From bd6280ddb415d5c949234e314a1fd4ffab927732 Mon Sep 17 00:00:00 2001 From: Renata Nobre Date: Wed, 30 Nov 2016 14:11:23 -0200 Subject: Update README.md Adding waffle badge, this way the community can follow what we are doing :) --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index eb3c44c1..a3232039 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ Pixelated User Agent [![Build Status](https://snap-ci.com/pixelated/pixelated-user-agent/branch/master/build_image)](https://snap-ci.com/pixelated/pixelated-user-agent/branch/master) [ ![Coverage Status](https://coveralls.io/repos/pixelated/pixelated-user-agent/badge.svg?branch=master)](https://coveralls.io/r/pixelated/pixelated-user-agent?branch=master) +[![Stories in Dev](https://badge.waffle.io/pixelated/pixelated-user-agent.svg?label=2%20-%20Development&title=Developing)](http://waffle.io/pixelated/pixelated-user-agent) The Pixelated User Agent is the mail client of the Pixelated ecosystem. It is composed of two parts, a web interface written in JavaScript ([FlightJS](https://flightjs.github.io/)) and a Python API that interacts with a LEAP Provider, the e-mail platform that Pixelated is built on. @@ -261,3 +262,5 @@ For people who want to run the user agent on docker container can use the Docker ## How to translate the user interface See: [Contributor's Guide](https://github.com/pixelated/pixelated-user-agent/blob/master/CONTRIBUTING.md#translating-ui) + + -- cgit v1.2.3 From ab17f819d5b724b45927e559de7c5dc796cb7fa6 Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Wed, 30 Nov 2016 14:17:37 -0200 Subject: Extract user agent initialization Now the initialization and mocking of the user agent run only when using localhost. See: https://github.com/pixelated/project-issues/issues/381 --- service/test/functional/features/environment.py | 43 ++++++++++++++-------- .../test/functional/features/steps/attachments.py | 2 +- service/test/functional/features/steps/common.py | 2 +- .../test/functional/features/steps/data_setup.py | 4 +- 4 files changed, 31 insertions(+), 20 deletions(-) diff --git a/service/test/functional/features/environment.py b/service/test/functional/features/environment.py index b03c506e..981fd33e 100644 --- a/service/test/functional/features/environment.py +++ b/service/test/functional/features/environment.py @@ -40,34 +40,45 @@ def before_all(context): context.browser = webdriver.PhantomJS() 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.set_page_load_timeout(60) userdata = context.config.userdata - context.homepage_url = userdata.get('homepage_url', 'http://localhost:8889') - context.multi_user_port = userdata.getint('multi_user_port', default=4568) - context.multi_user_url = userdata.get('multi_user_url', 'http://localhost:4568') + context.host = userdata.get('host', 'http://localhost') + if 'localhost' in context.host: + _mock_user_agent(context) + + +def _mock_user_agent(context): ensure_server() PixelatedSite.disable_csp_requests() - client = AppTestClient() - start_app_test_client(client, UserAgentMode(is_single_user=True)) - client.listenTCP(port=8889) FeaturesResource.DISABLED_FEATURES.append('autoRefresh') - context.client = client - multi_user_client = AppTestClient() - start_app_test_client(multi_user_client, UserAgentMode(is_single_user=False)) - multi_user_client.listenTCP(port=context.multi_user_port) - context.multi_user_client = multi_user_client + context.single_user_url = _define_url(8889) + context.single_user_client = _start_user_agent(8889, is_single_user=True) + + context.multi_user_url = _define_url(4568) + context.multi_user_client = _start_user_agent(4568, is_single_user=False) + + +def _start_user_agent(port, is_single_user): + client = AppTestClient() + start_app_test_client(client, UserAgentMode(is_single_user=is_single_user)) + client.listenTCP(port=port) + return client + + +def _define_url(port): + return 'http://localhost:{port}'.format(port=port) def after_all(context): context.browser.quit() - context.client.stop() + context.single_user_client.stop() def before_feature(context, feature): - context.browser.get(context.homepage_url) + context.browser.get(context.single_user_url) def after_feature(context, feature): @@ -103,8 +114,8 @@ def _slugify(string_): def cleanup_all_mails(context): @defer.inlineCallbacks def _delete_all_mails(): - mails = yield context.client.mail_store.all_mails() + mails = yield context.single_user_client.mail_store.all_mails() for mail in mails: - yield context.client.mail_store.delete_mail(mail.ident) + yield context.single_user_client.mail_store.delete_mail(mail.ident) return _delete_all_mails() diff --git a/service/test/functional/features/steps/attachments.py b/service/test/functional/features/steps/attachments.py index 7a80c34f..43948016 100644 --- a/service/test/functional/features/steps/attachments.py +++ b/service/test/functional/features/steps/attachments.py @@ -51,7 +51,7 @@ def build_mail_with_attachment(subject): @wait_for(timeout=10.0) def load_mail_into_soledad(context, mail): - return context.client.mail_store.add_mail('INBOX', mail.as_string()) + return context.single_user_client.mail_store.add_mail('INBOX', mail.as_string()) @then(u'I see the mail has an attachment') diff --git a/service/test/functional/features/steps/common.py b/service/test/functional/features/steps/common.py index bbceb015..c3916313 100644 --- a/service/test/functional/features/steps/common.py +++ b/service/test/functional/features/steps/common.py @@ -188,4 +188,4 @@ def get_console_log(context): def create_email(context): input_mail = MailBuilder().build_input_mail() - context.client.add_mail_to_inbox(input_mail) + context.single_user_client.add_mail_to_inbox(input_mail) diff --git a/service/test/functional/features/steps/data_setup.py b/service/test/functional/features/steps/data_setup.py index 167acf9a..3d28baed 100644 --- a/service/test/functional/features/steps/data_setup.py +++ b/service/test/functional/features/steps/data_setup.py @@ -26,8 +26,8 @@ def add_mail_impl(context): input_mail = MailBuilder().with_subject(subject).build_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.single_user_client.add_mail_to_inbox(input_mail) + wait_for_condition(context, lambda _: context.single_user_client.search_engine.search(subject)[1] > 0, poll_frequency=0.1) context.last_subject = subject -- cgit v1.2.3 From b6f60fd007efc84ef7cc2b63988448a61bbeb8d2 Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Wed, 30 Nov 2016 17:36:39 -0200 Subject: Add sign up smoke test See: https://github.com/pixelated/project-issues/issues/381 --- service/test/functional/features/environment.py | 20 ++++++++--- service/test/functional/features/smoke.feature | 37 +++++++++++++++++++ service/test/functional/features/steps/login.py | 2 +- service/test/functional/features/steps/signup.py | 45 ++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 5 deletions(-) create mode 100644 service/test/functional/features/smoke.feature create mode 100644 service/test/functional/features/steps/signup.py diff --git a/service/test/functional/features/environment.py b/service/test/functional/features/environment.py index 981fd33e..efbf3412 100644 --- a/service/test/functional/features/environment.py +++ b/service/test/functional/features/environment.py @@ -16,6 +16,7 @@ import os import re import time +from urlparse import urlparse from crochet import setup, wait_for from leap.common.events.server import ensure_server @@ -45,8 +46,16 @@ def before_all(context): userdata = context.config.userdata context.host = userdata.get('host', 'http://localhost') + if not context.host.startswith('http'): + context.host = 'https://{}'.format(context.host) + + hostname = urlparse(context.host).hostname + context.signup_url = 'https://{}/signup'.format(hostname) + context.login_url = 'https://mail.{}/login'.format(hostname) + if 'localhost' in context.host: _mock_user_agent(context) + context.login_url = context.multi_user_url + '/login' def _mock_user_agent(context): @@ -74,16 +83,19 @@ def _define_url(port): def after_all(context): context.browser.quit() - context.single_user_client.stop() + if 'localhost' in context.host: + context.single_user_client.stop() def before_feature(context, feature): - context.browser.get(context.single_user_url) + if 'localhost' in context.host: + context.browser.get(context.single_user_url) def after_feature(context, feature): - cleanup_all_mails(context) - context.last_mail = None + if 'localhost' in context.host: + cleanup_all_mails(context) + context.last_mail = None def after_step(context, step): diff --git a/service/test/functional/features/smoke.feature b/service/test/functional/features/smoke.feature new file mode 100644 index 00000000..3a9378e4 --- /dev/null +++ b/service/test/functional/features/smoke.feature @@ -0,0 +1,37 @@ +# +# 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 . + +@smoke @wip +Feature: sign up, login and logout + As a visitor of Pixelated + I want to sign up + So I can log in to my account and see the welcome email + + Scenario: Visitor creates his account + Given a user is accessing the signup page + When I enter username, password and password confirmation + And I click on the signup button + Then I should see the user control panel + + Scenario: Existing user logs into his account + Given a user is accessing the login page + #And I have a mail for username in my inbox + And I enter username and password as credentials + And I click on the login button + Then I should see the fancy interstitial + Then I have mails + When I logout + Then I should see the login page diff --git a/service/test/functional/features/steps/login.py b/service/test/functional/features/steps/login.py index d1840900..a8db6f49 100644 --- a/service/test/functional/features/steps/login.py +++ b/service/test/functional/features/steps/login.py @@ -26,7 +26,7 @@ from common import ( @when(u'I open the login page') def login_page(context): - context.browser.get(context.multi_user_url + '/login') + context.browser.get(context.login_url) @when(u'I enter {username} and {password} as credentials') diff --git a/service/test/functional/features/steps/signup.py b/service/test/functional/features/steps/signup.py new file mode 100644 index 00000000..1252017c --- /dev/null +++ b/service/test/functional/features/steps/signup.py @@ -0,0 +1,45 @@ +# +# 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 . + +import uuid +from behave import given, then, when + +from common import ( + fill_by_css_selector, + find_element_by_css_selector) + + +@given(u'a user is accessing the signup page') # noqa +def step_impl(context): + context.browser.get(context.signup_url) + + +@when(u'I enter username, password and password confirmation') # noqa +def step_impl(context): + fill_by_css_selector(context, '#srp_username', 'testuser_{}'.format(uuid.uuid4())) + fill_by_css_selector(context, '#srp_password', 'password') + fill_by_css_selector(context, '#srp_password_confirmation', 'password') + + +@when(u'I click on the signup button') # noqa +def step_impl(context): + find_element_by_css_selector(context, 'button[type=submit]').click() + + +@then(u'I should see the user control panel') # noqa +def step_impl(context): + text = find_element_by_css_selector(context, 'h1').text + assert text == 'user control panel' -- cgit v1.2.3 From a8a7362054f4b49ea1fbc00fe7b556e6e6ea4590 Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Wed, 30 Nov 2016 19:07:56 -0200 Subject: Add timeout to find by css selector See: https://github.com/pixelated/project-issues/issues/381 --- service/test/functional/features/steps/common.py | 20 +++++++------------- service/test/functional/features/steps/signup.py | 4 ++-- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/service/test/functional/features/steps/common.py b/service/test/functional/features/steps/common.py index c3916313..2fd2ec4f 100644 --- a/service/test/functional/features/steps/common.py +++ b/service/test/functional/features/steps/common.py @@ -66,15 +66,9 @@ def wait_until_elements_are_visible_by_locator(context, locator_tuple, timeout=T return context.browser.find_elements(locator_tuple[0], locator_tuple[1]) -def wait_until_elements_are_visible_by_xpath(context, locator_tuple, timeout=TIMEOUT_IN_S): - wait = WebDriverWait(context.browser, timeout) - wait.until(EC.presence_of_all_elements_located(locator_tuple)) - return context.browser.find_elements(locator_tuple[0], locator_tuple[1]) - - def wait_until_element_is_visible_by_locator(context, locator_tuple, timeout=TIMEOUT_IN_S): wait = WebDriverWait(context.browser, timeout) - wait.until(EC.visibility_of_element_located(locator_tuple)) + wait.until(EC.presence_of_element_located(locator_tuple)) return context.browser.find_element(locator_tuple[0], locator_tuple[1]) @@ -88,8 +82,8 @@ def fill_by_xpath(context, xpath, text): field.send_keys(text) -def fill_by_css_selector(context, css_selector, text): - field = find_element_by_css_selector(context, css_selector) +def fill_by_css_selector(context, css_selector, text, timeout=TIMEOUT_IN_S): + field = find_element_by_css_selector(context, css_selector, timeout=timeout) field.send_keys(text) @@ -118,8 +112,8 @@ def find_element_by_id(context, id): return wait_until_element_is_visible_by_locator(context, (By.ID, id)) -def find_element_by_css_selector(context, css_selector): - return wait_until_element_is_visible_by_locator(context, (By.CSS_SELECTOR, css_selector)) +def find_element_by_css_selector(context, css_selector, timeout=TIMEOUT_IN_S): + return wait_until_element_is_visible_by_locator(context, (By.CSS_SELECTOR, css_selector), timeout=timeout) def find_element_by_class_name(context, class_name): @@ -130,8 +124,8 @@ def find_elements_by_css_selector(context, css_selector, timeout=TIMEOUT_IN_S): return wait_until_elements_are_visible_by_locator(context, (By.CSS_SELECTOR, css_selector), timeout=timeout) -def find_elements_by_xpath(context, xpath): - return wait_until_elements_are_visible_by_xpath(context, (By.XPATH, xpath)) +def find_elements_by_xpath(context, xpath, timeout=TIMEOUT_IN_S): + return wait_until_elements_are_visible_by_locator(context, (By.XPATH, xpath), timeout=timeout) def find_element_containing_text(context, text, element_type='*'): diff --git a/service/test/functional/features/steps/signup.py b/service/test/functional/features/steps/signup.py index 1252017c..1558004b 100644 --- a/service/test/functional/features/steps/signup.py +++ b/service/test/functional/features/steps/signup.py @@ -18,6 +18,7 @@ import uuid from behave import given, then, when from common import ( + element_should_have_content, fill_by_css_selector, find_element_by_css_selector) @@ -41,5 +42,4 @@ def step_impl(context): @then(u'I should see the user control panel') # noqa def step_impl(context): - text = find_element_by_css_selector(context, 'h1').text - assert text == 'user control panel' + element_should_have_content(context, 'h1', 'user control panel') -- cgit v1.2.3 From 8372b0127343df96cbe1ca33477ea0f197a873be Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Wed, 30 Nov 2016 19:11:57 -0200 Subject: Add username to behave context See: https://github.com/pixelated/project-issues/issues/381 --- service/test/functional/features/environment.py | 3 +++ service/test/functional/features/smoke.feature | 3 +-- service/test/functional/features/steps/login.py | 13 ++++++------- service/test/functional/features/steps/signup.py | 3 +-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/service/test/functional/features/environment.py b/service/test/functional/features/environment.py index efbf3412..b51323fa 100644 --- a/service/test/functional/features/environment.py +++ b/service/test/functional/features/environment.py @@ -17,6 +17,7 @@ import os import re import time from urlparse import urlparse +import uuid from crochet import setup, wait_for from leap.common.events.server import ensure_server @@ -52,10 +53,12 @@ def before_all(context): hostname = urlparse(context.host).hostname context.signup_url = 'https://{}/signup'.format(hostname) context.login_url = 'https://mail.{}/login'.format(hostname) + context.username = 'testuser_{}'.format(uuid.uuid4()) if 'localhost' in context.host: _mock_user_agent(context) context.login_url = context.multi_user_url + '/login' + context.username = 'username' def _mock_user_agent(context): diff --git a/service/test/functional/features/smoke.feature b/service/test/functional/features/smoke.feature index 3a9378e4..1839539e 100644 --- a/service/test/functional/features/smoke.feature +++ b/service/test/functional/features/smoke.feature @@ -28,8 +28,7 @@ Feature: sign up, login and logout Scenario: Existing user logs into his account Given a user is accessing the login page - #And I have a mail for username in my inbox - And I enter username and password as credentials + When I enter username and password as credentials And I click on the login button Then I should see the fancy interstitial Then I have mails diff --git a/service/test/functional/features/steps/login.py b/service/test/functional/features/steps/login.py index a8db6f49..e773c0b1 100644 --- a/service/test/functional/features/steps/login.py +++ b/service/test/functional/features/steps/login.py @@ -15,15 +15,14 @@ # along with Pixelated. If not, see . import time -from behave import when, then -from selenium.webdriver.common.by import By +from behave import given, when, then from common import ( fill_by_css_selector, - find_element_by_css_selector, - wait_until_element_is_visible_by_locator) + find_element_by_css_selector) +@given(u'a user is accessing the login page') @when(u'I open the login page') def login_page(context): context.browser.get(context.login_url) @@ -31,13 +30,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', username) + fill_by_css_selector(context, 'input#email', context.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 = find_element_by_css_selector(context, 'input[name="login"]') login_button.click() @@ -53,7 +52,7 @@ def _wait_for_interstitial_to_reload(): @when(u'I logout') def click_logout(context): - logout_button = wait_until_element_is_visible_by_locator(context, (By.CSS_SELECTOR, 'ul#logout')) + logout_button = find_element_by_css_selector(context, 'ul#logout') logout_button.click() diff --git a/service/test/functional/features/steps/signup.py b/service/test/functional/features/steps/signup.py index 1558004b..43480666 100644 --- a/service/test/functional/features/steps/signup.py +++ b/service/test/functional/features/steps/signup.py @@ -14,7 +14,6 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . -import uuid from behave import given, then, when from common import ( @@ -30,7 +29,7 @@ def step_impl(context): @when(u'I enter username, password and password confirmation') # noqa def step_impl(context): - fill_by_css_selector(context, '#srp_username', 'testuser_{}'.format(uuid.uuid4())) + fill_by_css_selector(context, '#srp_username', context.username) fill_by_css_selector(context, '#srp_password', 'password') fill_by_css_selector(context, '#srp_password_confirmation', 'password') -- cgit v1.2.3 From 76ad8f023dfabb25e93f771e44164b06004cd7a4 Mon Sep 17 00:00:00 2001 From: Denis Costa Date: Wed, 30 Nov 2016 22:20:23 -0200 Subject: Removes unused function See: https://github.com/pixelated/project-issues/issues/381 --- service/test/functional/features/steps/common.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/service/test/functional/features/steps/common.py b/service/test/functional/features/steps/common.py index 2fd2ec4f..f2cab1a6 100644 --- a/service/test/functional/features/steps/common.py +++ b/service/test/functional/features/steps/common.py @@ -91,11 +91,6 @@ def take_screenshot(context, filename): context.browser.save_screenshot(filename) -def dump_source_to(context, filename): - with open(filename, 'w') as out: - out.write(context.browser.page_source.encode('utf8')) - - def page_has_css(context, css): try: find_element_by_css_selector(context, css) -- cgit v1.2.3 From a62d42cbf8c1fcf1785ddb21f374beb58231a2f5 Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Thu, 1 Dec 2016 15:58:18 -0200 Subject: Add support to use different webdrivers See: https://github.com/pixelated/project-issues/issues/381 --- service/test/functional/features/environment.py | 29 ++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/service/test/functional/features/environment.py b/service/test/functional/features/environment.py index b51323fa..a30f3221 100644 --- a/service/test/functional/features/environment.py +++ b/service/test/functional/features/environment.py @@ -30,6 +30,11 @@ from pixelated.resources.features_resource import FeaturesResource from test.support.integration import AppTestClient from steps.common import DEFAULT_IMPLICIT_WAIT_TIMEOUT_IN_S + +class UnsuportedWebDriverError(Exception): + pass + + setup() @@ -39,11 +44,7 @@ def start_app_test_client(client, mode): def before_all(context): - context.browser = webdriver.PhantomJS() - context.browser.set_window_size(1280, 1024) - context.browser.implicitly_wait(DEFAULT_IMPLICIT_WAIT_TIMEOUT_IN_S) - context.browser.set_page_load_timeout(60) - + _setup_webdriver(context) userdata = context.config.userdata context.host = userdata.get('host', 'http://localhost') @@ -61,6 +62,24 @@ def before_all(context): context.username = 'username' +def _setup_webdriver(context): + browser = context.config.userdata.get('webdriver', 'phantomjs') + supported_webdrivers = { + 'phantomjs': webdriver.PhantomJS, + 'firefox': webdriver.Firefox, + 'chrome': webdriver.Chrome, + } + + try: + context.browser = supported_webdrivers[browser]() + except KeyError: + raise UnsuportedWebDriverError('{} is not a supported webdriver'.format(browser)) + + context.browser.set_window_size(1280, 1024) + context.browser.implicitly_wait(DEFAULT_IMPLICIT_WAIT_TIMEOUT_IN_S) + context.browser.set_page_load_timeout(60) + + def _mock_user_agent(context): ensure_server() PixelatedSite.disable_csp_requests() -- cgit v1.2.3 From ae32177eae55df41c91b83119c6beec91daa9e23 Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Thu, 1 Dec 2016 16:02:35 -0200 Subject: Fix logout button reference to work on Firefox See: https://github.com/pixelated/project-issues/issues/381 --- service/test/functional/features/steps/login.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/service/test/functional/features/steps/login.py b/service/test/functional/features/steps/login.py index e773c0b1..367228f8 100644 --- a/service/test/functional/features/steps/login.py +++ b/service/test/functional/features/steps/login.py @@ -36,13 +36,12 @@ def enter_credentials(context, username, password): @when(u'I click on the login button') def click_login(context): - login_button = find_element_by_css_selector(context, 'input[name="login"]') - login_button.click() + find_element_by_css_selector(context, 'input[name="login"]').click() @then(u'I should see the fancy interstitial') def step_impl(context): - assert find_element_by_css_selector(context, 'section#hive-section') + find_element_by_css_selector(context, 'section#hive-section') _wait_for_interstitial_to_reload() @@ -52,10 +51,9 @@ def _wait_for_interstitial_to_reload(): @when(u'I logout') def click_logout(context): - logout_button = find_element_by_css_selector(context, 'ul#logout') - logout_button.click() + find_element_by_css_selector(context, '#logout-form div').click() @then(u'I should see the login page') def see_login_page(context): - assert find_element_by_css_selector(context, 'form#login_form') + find_element_by_css_selector(context, 'form#login_form') -- cgit v1.2.3 From e4fd5581c91e97940fe893eda42a8f200d1e8d22 Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Thu, 1 Dec 2016 16:08:22 -0200 Subject: Increase interstitial timeout We need a bigger timeout in order to test remotely See: https://github.com/pixelated/project-issues/issues/381 --- service/test/functional/features/steps/login.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/test/functional/features/steps/login.py b/service/test/functional/features/steps/login.py index 367228f8..b5e88608 100644 --- a/service/test/functional/features/steps/login.py +++ b/service/test/functional/features/steps/login.py @@ -46,7 +46,7 @@ def step_impl(context): def _wait_for_interstitial_to_reload(): - time.sleep(6) + time.sleep(10) @when(u'I logout') -- cgit v1.2.3 From 8b26f3f40e3f5d04a02528c81616a231d8f8428a Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Thu, 1 Dec 2016 17:20:36 -0200 Subject: [#849] Change unauthorized message --- service/pixelated/resources/login_resource.py | 4 ++-- service/test/integration/test_multi_user_login.py | 2 +- service/test/unit/resources/test_login_resource.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/service/pixelated/resources/login_resource.py b/service/pixelated/resources/login_resource.py index aadc435e..ed0cb54e 100644 --- a/service/pixelated/resources/login_resource.py +++ b/service/pixelated/resources/login_resource.py @@ -145,10 +145,10 @@ class LoginResource(BaseResource): self._complete_bootstrap(user_auth, request) def render_error(error): - log.info('Login Error for %s' % request.args['username'][0]) + log.info('Login error for %s' % request.args['username'][0]) log.info('%s' % error) request.setResponseCode(UNAUTHORIZED) - return self._render_template(request, 'Invalid credentials') + return self._render_template(request, 'Invalid username or password') d = self._handle_login(request) d.addCallbacks(render_response, render_error) diff --git a/service/test/integration/test_multi_user_login.py b/service/test/integration/test_multi_user_login.py index af2a81ac..fe456583 100644 --- a/service/test/integration/test_multi_user_login.py +++ b/service/test/integration/test_multi_user_login.py @@ -51,4 +51,4 @@ class MultiUserLoginTest(MultiUserSoledadTestBase): response, login_request = self.app_test_client.login('username', 'wrong_password') response_str = yield response self.assertEqual(401, login_request.responseCode) - self.assertIn('Invalid credentials', login_request.written) + self.assertIn('Invalid username or password', login_request.written) diff --git a/service/test/unit/resources/test_login_resource.py b/service/test/unit/resources/test_login_resource.py index d3d7ba64..45036f8d 100644 --- a/service/test/unit/resources/test_login_resource.py +++ b/service/test/unit/resources/test_login_resource.py @@ -206,7 +206,7 @@ class TestLoginPOST(unittest.TestCase): 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 credentials', written_response) + self.assertIn('Invalid username or password', written_response) self.assertFalse(mock_user_bootstrap_setup.called) self.assertFalse(self.resource.get_session(self.request).is_logged_in()) -- cgit v1.2.3 From a8b7f37fc8087407408cb65b76fdcd7686c8d87c Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Fri, 2 Dec 2016 11:45:01 -0200 Subject: Add support to run ipdb on error See: https://github.com/pixelated/project-issues/issues/381 --- service/test/functional/features/environment.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/service/test/functional/features/environment.py b/service/test/functional/features/environment.py index a30f3221..d49016b6 100644 --- a/service/test/functional/features/environment.py +++ b/service/test/functional/features/environment.py @@ -127,8 +127,12 @@ def after_step(context, step): def _debug_on_error(context, step): if step.status == 'failed' and context.config.userdata.getbool("debug"): - import pdb - pdb.post_mortem(step.exc_traceback) + try: + import ipdb + ipdb.post_mortem(step.exc_traceback) + except ImportError: + import pdb + pdb.post_mortem(step.exc_traceback) def _save_screenshot(context, step): -- cgit v1.2.3 From 31ac4ebd4f734fc4e438af504a318b4eb7ce627c Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Fri, 2 Dec 2016 13:00:03 -0200 Subject: Finish first smoke test See: https://github.com/pixelated/project-issues/issues/381 --- service/go | 2 +- service/test/functional/features/smoke.feature | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/service/go b/service/go index 7df9111b..8ceae7db 100755 --- a/service/go +++ b/service/go @@ -119,7 +119,7 @@ function runFunctionalTests { echo "Executing Functional Tests on headless PhantomJS." removeZmqCertificates echo "You should execute it on Debian box for more similar results with CI environment." - behave --tags ~@wip test/functional/features + behave --tags ~@wip --tags ~@smoke test/functional/features echo "Done." } diff --git a/service/test/functional/features/smoke.feature b/service/test/functional/features/smoke.feature index 1839539e..724c680c 100644 --- a/service/test/functional/features/smoke.feature +++ b/service/test/functional/features/smoke.feature @@ -14,7 +14,7 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . -@smoke @wip +@smoke Feature: sign up, login and logout As a visitor of Pixelated I want to sign up -- cgit v1.2.3 From 0dd71ff7c3a895e774205231c23720ee7313ad39 Mon Sep 17 00:00:00 2001 From: NavaL Date: Fri, 2 Dec 2016 16:44:36 +0100 Subject: [#625, #851] fixing log typo and adding test making sure encryption error does propagate to mails resources --- service/pixelated/resources/mails_resource.py | 6 +++--- .../test/unit/adapter/services/test_mail_sender.py | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/service/pixelated/resources/mails_resource.py b/service/pixelated/resources/mails_resource.py index 79b8ae4d..93070dd6 100644 --- a/service/pixelated/resources/mails_resource.py +++ b/service/pixelated/resources/mails_resource.py @@ -67,7 +67,7 @@ class MailsDeleteResource(Resource): def render_POST(self, request): def response_failed(failure): - log.error(failure, 'something failed') + log.error('something failed: %s' % failure.getErrorMessage()) request.finish() idents = json.loads(request.content.read())['idents'] @@ -175,7 +175,7 @@ class MailsResource(BaseResource): if isinstance(error.value, SMTPDownException): respond_json_deferred({'message': str(error.value)}, request, status_code=503) else: - log.error(error, 'error occurred while sending') + log.error('error occurred while sending: %s' % error.getErrorMessage()) respond_json_deferred({'message': 'an error occurred while sending'}, request, status_code=422) deferred = self._handle_post(request) @@ -185,7 +185,7 @@ class MailsResource(BaseResource): def render_PUT(self, request): def onError(error): - log.error(error, 'error saving draft') + log.error('error saving draft: %s' % error.getErrorMessage()) respond_json_deferred("", request, status_code=422) deferred = self._handle_put(request) diff --git a/service/test/unit/adapter/services/test_mail_sender.py b/service/test/unit/adapter/services/test_mail_sender.py index 4daa7f24..23951214 100644 --- a/service/test/unit/adapter/services/test_mail_sender.py +++ b/service/test/unit/adapter/services/test_mail_sender.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . from leap.bitmask.mail.outgoing.service import OutgoingMail +from mock import patch from twisted.mail.smtp import User from twisted.trial import unittest @@ -103,6 +104,25 @@ class MailSenderTest(unittest.TestCase): for recipient in flatten([input_mail.to, input_mail.cc, input_mail.bcc]): self.assertTrue(recipient in e.email_error_map) + @defer.inlineCallbacks + def test_keymanager_encrypt_problem_raises_exception(self): + input_mail = InputMail.from_dict(mail_dict(), from_address='pixelated@org') + + when(OutgoingMail)._maybe_attach_key(any(), any(), any()).thenReturn( + defer.succeed(None)) + when(OutgoingMail)._fix_headers(any(), any(), any()).thenReturn( + defer.succeed((None, mock()))) + when(self._keymanager_mock).encrypt(any(), any(), sign=any(), + fetch_remote=any()).thenReturn(defer.fail(Exception('pretend key expired'))) + + with patch('leap.bitmask.mail.outgoing.service.emit_async'): + try: + yield self.sender.sendmail(input_mail) + self.fail('Exception expected!') + except MailSenderException, e: + for recipient in flatten([input_mail.to, input_mail.cc, input_mail.bcc]): + self.assertTrue(recipient in e.email_error_map) + @defer.inlineCallbacks def test_iterates_over_recipients_and_send_whitout_bcc_field(self): input_mail = InputMail.from_dict(mail_dict(), from_address='pixelated@org') -- cgit v1.2.3