From f28906c1c417800f5823dc937a7671a04d14193c Mon Sep 17 00:00:00 2001 From: Duda Dornelles Date: Thu, 9 Oct 2014 12:20:18 +0200 Subject: moving fake-service features to service, getting rid of setup.py test requires and getting them into test_requirements.txt --- service/test/functional/features/steps/__init__.py | 0 service/test/functional/features/steps/common.py | 98 +++++++++++++++++++ service/test/functional/features/steps/compose.py | 69 +++++++++++++ .../test/functional/features/steps/mail_list.py | 72 ++++++++++++++ .../test/functional/features/steps/mail_view.py | 107 +++++++++++++++++++++ service/test/functional/features/steps/search.py | 34 +++++++ service/test/functional/features/steps/tag_list.py | 34 +++++++ 7 files changed, 414 insertions(+) create mode 100644 service/test/functional/features/steps/__init__.py create mode 100644 service/test/functional/features/steps/common.py create mode 100644 service/test/functional/features/steps/compose.py create mode 100644 service/test/functional/features/steps/mail_list.py create mode 100644 service/test/functional/features/steps/mail_view.py create mode 100644 service/test/functional/features/steps/search.py create mode 100644 service/test/functional/features/steps/tag_list.py (limited to 'service/test/functional/features/steps') diff --git a/service/test/functional/features/steps/__init__.py b/service/test/functional/features/steps/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/service/test/functional/features/steps/common.py b/service/test/functional/features/steps/common.py new file mode 100644 index 00000000..6574d551 --- /dev/null +++ b/service/test/functional/features/steps/common.py @@ -0,0 +1,98 @@ +# +# 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 . +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 NoSuchElementException +from hamcrest import * + + +def wait_until_element_is_invisible_by_locator(context, locator_tuple): + wait = WebDriverWait(context.browser, 10) + wait.until(EC.invisibility_of_element_located(locator_tuple)) + + +def wait_for_user_alert_to_disapear(context): + wait_until_element_is_invisible_by_locator(context, (By.ID, 'user-alerts')) + + +def wait_until_element_is_visible_by_locator(context, locator_tuple): + wait = WebDriverWait(context.browser, 10) + wait.until(EC.visibility_of_element_located(locator_tuple)) + + +def fill_by_xpath(context, xpath, text): + field = context.browser.find_element_by_xpath(xpath) + field.send_keys(text) + + +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) + return True + except NoSuchElementException: + return False + + +def find_element_by_xpath(context, xpath): + return context.browser.find_element_by_xpath(xpath) + + +def find_element_by_css_selector(context, css_selector): + return context.browser.find_element_by_css_selector(css_selector) + + +def find_elements_by_css_selector(context, css_selector): + return context.browser.find_elements_by_css_selector(css_selector) + + +def find_element_containing_text(context, text, element_type='*'): + return context.browser.find_element_by_xpath("//%s[contains(.,'%s')]" % (element_type, text)) + + +def element_should_have_content(context, css_selector, content): + e = find_element_by_css_selector(context, css_selector) + assert_that(e.text, equal_to(content)) + + +def wait_until_button_is_visible(context, title): + wait = WebDriverWait(context.browser, 10) + locator_tuple = (By.XPATH, ("//%s[contains(.,'%s')]" % ('button', title))) + wait.until(EC.visibility_of_element_located(locator_tuple)) + + +def click_button(context, title, element='button'): + button = find_element_containing_text(context, title, element_type=element) + button.click() + + +def mail_subject(context): + e = find_element_by_css_selector(context, '#mail-view .subject') + return e.text + + +def reply_subject(context): + e = find_element_by_css_selector(context, '#reply-subject') + return e.text diff --git a/service/test/functional/features/steps/compose.py b/service/test/functional/features/steps/compose.py new file mode 100644 index 00000000..5a61a8e5 --- /dev/null +++ b/service/test/functional/features/steps/compose.py @@ -0,0 +1,69 @@ +# +# 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 . +from behave import given, when +from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.wait import WebDriverWait +from time import sleep +from common import * +from hamcrest import * + + +@given('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() + + for row in context.table: + fill_by_xpath(context, '//*[@id="subject"]', row['subject']) + fill_by_xpath(context, '//*[@id="text-box"]', row['body']) + + +@given("for the '{recipients_field}' field I type '{to_type}' and chose the first contact that shows") +def choose_impl(context, recipients_field, to_type): + browser = context.browser + browser.find_element_by_css_selector('#recipients-to-area span input.tt-input').click() + recipients_field = recipients_field.lower() + css_selector = '#recipients-%s-area' % recipients_field + recipients_element = browser.find_element_by_css_selector(css_selector) + recipients_element.find_element_by_css_selector('.tt-input').send_keys(to_type) + wait_until_element_is_visible_by_locator(context, (By.CSS_SELECTOR, '.tt-dropdown-menu div div')) + browser.find_element_by_css_selector('.tt-dropdown-menu div div').click() + + +@then("for the '{recipients_field}' field I type '{to_type}' and chose the first contact that shows") +def choose_impl(context, recipients_field, to_type): + recipients_field = recipients_field.lower() + browser = context.browser + field = browser.find_element_by_css_selector('#recipients-%s-area .tt-input' % recipients_field) + field.send_keys(to_type) + sleep(1) + find_element_by_css_selector(context, '.tt-dropdown-menu div div').click() + + +@given('I save the draft') +def save_impl(context): + context.browser.find_element_by_id('draft-button').click() + + +@when('I open the saved draft and send it') +def send_impl(context): + context.execute_steps(u"when I select the tag 'drafts'") + context.execute_steps(u"when I open the first mail in the mail list") + assert_that(is_not(page_has_css(context, '#send-button[disabled]'))) + click_button(context, 'Send') + element_should_have_content(context, '#user-alerts', 'Your message was sent!') diff --git a/service/test/functional/features/steps/mail_list.py b/service/test/functional/features/steps/mail_list.py new file mode 100644 index 00000000..2d57099b --- /dev/null +++ b/service/test/functional/features/steps/mail_list.py @@ -0,0 +1,72 @@ +# +# 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 . +import re +from behave import * +from common import * + + +def find_current_mail(context): + return find_element_by_xpath(context, '//*[@id="mail-list"]/li[@id="mail-%s"]//a' % context.current_mail_id) + + +def check_current_mail_is_visible(context): + find_current_mail(context) + + +def open_current_mail(context): + e = find_current_mail(context) + e.click() + + +@then('I see that mail under the \'{tag}\' tag') +def impl(context, tag): + context.execute_steps("when I select the tag '%s'" % tag) + check_current_mail_is_visible(context) + + +@when('I open that mail') +def impl(context): + open_current_mail(context) + + +@when('I open the first mail in the mail list') +def impl(context): + elements = context.browser.find_elements_by_xpath('//*[@id="mail-list"]//a') + context.current_mail_id = elements[0].get_attribute('href').split('/')[-1] + elements[0].click() + + +@when('I open the first mail in the \'{tag}\'') +def impl(context, tag): + context.browser.execute_script('window.scrollBy(0, -200)') + context.execute_steps(u"When I select the tag '%s'" % tag) + context.execute_steps(u'When I open the first mail in the mail list') + + +@then('I open the mail I previously tagged') +def impl(context): + open_current_mail(context) + + +@then('I see the mail I sent') +def impl(context): + src = context.browser.page_source + assert_that(src, contains_string(context.reply_subject)) + + +@then('the deleted mail is there') +def impl(context): + check_current_mail_is_visible(context) diff --git a/service/test/functional/features/steps/mail_view.py b/service/test/functional/features/steps/mail_view.py new file mode 100644 index 00000000..98647958 --- /dev/null +++ b/service/test/functional/features/steps/mail_view.py @@ -0,0 +1,107 @@ +# +# 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 . +import re +from selenium.webdriver.common.keys import Keys +from behave import * +from common import * +from hamcrest import * +from time import sleep + + +@then('I see that the subject reads \'{subject}\'') +def impl(context, subject): + e = find_element_by_css_selector(context, '#mail-view .subject') + assert_that(e.text, equal_to(subject)) + + +@then('I see that the body reads \'{expected_body}\'') +def impl(context, expected_body): + e = find_element_by_css_selector(context, '#mail-view .bodyArea') + assert_that(e.text, equal_to(expected_body)) + + +@then('that email has the \'{tag}\' tag') +def impl(context, tag): + elements = find_elements_by_css_selector(context, '#mail-view .tagsArea .tag') + tags = [e.text for e in elements] + assert_that(tags, has_item(tag.upper())) + + +@when('I add the tag \'{tag}\' to that mail') +def impl(context, tag): + context.browser.execute_script("$('#new-tag-button').click();") + context.browser.execute_script("$('#new-tag-input').val('%s');" % tag) + e = find_element_by_css_selector(context, '#new-tag-input') + e.send_keys(Keys.ENTER) + + +@then('I reply to it') +def impl(context): + click_button(context, 'Reply') + click_button(context, 'Send') + context.reply_subject = reply_subject(context) + + +@then('I see if the mail has html content') +def impl(context): + e = find_element_by_css_selector(context, '#mail-view .bodyArea') + h2 = e.find_element_by_css_selector("h2[style*='color: #3f4944']") + assert_that(h2.text, contains_string('cborim')) + + +@when('I try to delete the first mail') +def impl(context): + context.execute_steps(u"When I open the first mail in the mail list") + find_element_by_css_selector(context, '#mail-view #view-more-actions').click() + context.browser.execute_script("$('#delete-button-top').click();") + + e = find_element_by_css_selector(context, '#user-alerts') + assert_that(e.text, equal_to('Your message was moved to trash!')) + + +@then('I choose to forward this mail') +def impl(context): + wait_until_button_is_visible(context, 'Forward') + click_button(context, 'Forward') + + +@then('I forward this mail') +def impl(context): + wait_until_button_is_visible(context, 'Send') + click_button(context, 'Send') + + +@then('I remove all tags') +def impl(context): + e = find_element_by_css_selector(context, '.tagsArea') + tags = e.find_elements_by_css_selector('.tag') + assert_that(len(tags), greater_than(0)) + for tag in tags: + tag.click() + + +@then('I choose to trash') +def impl(context): + context.browser.execute_script("$('button#view-more-actions').click()") + click_button(context, 'Trash this message', 'span') + + +@then('I see the mail has a cc and a bcc recipient') +def impl(context): + cc = find_element_by_css_selector(context, '.msg-header .cc') + bcc = find_element_by_css_selector(context, '.msg-header .bcc') + + assert_that(cc.text, matches_regexp('[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+')) diff --git a/service/test/functional/features/steps/search.py b/service/test/functional/features/steps/search.py new file mode 100644 index 00000000..cf97eb74 --- /dev/null +++ b/service/test/functional/features/steps/search.py @@ -0,0 +1,34 @@ +# +# 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 . +from selenium.webdriver.common.keys import Keys +from behave import * +from common import * +from hamcrest import * +from time import sleep + + +@when('I search for a mail with the words "{search_term}"') +def impl(context, search_term): + search_field = find_element_by_css_selector(context, '#search-trigger input[type="search"]') + search_field.send_keys(search_term) + search_field.send_keys(Keys.ENTER) + sleep(1) + + +@then('I see one or more mails in the search results') +def impl(context): + lis = find_elements_by_css_selector(context, '#mail-list li') + assert_that(len(lis), greater_than_or_equal_to(1)) diff --git a/service/test/functional/features/steps/tag_list.py b/service/test/functional/features/steps/tag_list.py new file mode 100644 index 00000000..e83ca2f1 --- /dev/null +++ b/service/test/functional/features/steps/tag_list.py @@ -0,0 +1,34 @@ +# +# 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 . +from behave import * +from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.wait import WebDriverWait +from common import * + + +def click_first_element_with_class(context, classname): + elements = context.browser.find_elements_by_class_name(classname) + elements[0].click() + + +@when('I select the tag \'{tag}\'') +def impl(context, tag): + wait_for_user_alert_to_disapear(context) + click_first_element_with_class(context, 'left-off-canvas-toggle') + context.browser.execute_script("window.scrollBy(0, -200)") + e = context.browser.find_element_by_xpath('//*[@id="tag-list"]/ul/li[contains(translate(., "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"), "%s")]' % tag) + e.click() -- cgit v1.2.3