diff options
author | Vadim Rutkovsky <vrutkovs@redhat.com> | 2014-04-24 21:19:23 +0800 |
---|---|---|
committer | Vadim Rutkovsky <vrutkovs@redhat.com> | 2014-04-25 02:47:28 +0800 |
commit | a13f453398b3f71d46c00cfecf331a4db93f0004 (patch) | |
tree | 57e2b14878e2ad250ba68f76fd4bd914bc67d74d /tests | |
parent | fdde33396195d6287e9b582e7ffe8a3bff453e84 (diff) | |
download | gsoc2013-evolution-a13f453398b3f71d46c00cfecf331a4db93f0004.tar gsoc2013-evolution-a13f453398b3f71d46c00cfecf331a4db93f0004.tar.gz gsoc2013-evolution-a13f453398b3f71d46c00cfecf331a4db93f0004.tar.bz2 gsoc2013-evolution-a13f453398b3f71d46c00cfecf331a4db93f0004.tar.lz gsoc2013-evolution-a13f453398b3f71d46c00cfecf331a4db93f0004.tar.xz gsoc2013-evolution-a13f453398b3f71d46c00cfecf331a4db93f0004.tar.zst gsoc2013-evolution-a13f453398b3f71d46c00cfecf331a4db93f0004.zip |
tests: add addressbook tests
Diffstat (limited to 'tests')
-rw-r--r-- | tests/addressbook.feature | 250 | ||||
-rw-r--r-- | tests/environment.py | 3 | ||||
-rw-r--r-- | tests/steps/addressbook_steps.py | 371 | ||||
-rw-r--r-- | tests/steps/steps.py | 34 |
4 files changed, 656 insertions, 2 deletions
diff --git a/tests/addressbook.feature b/tests/addressbook.feature new file mode 100644 index 0000000000..4e318e83df --- /dev/null +++ b/tests/addressbook.feature @@ -0,0 +1,250 @@ +Feature: Addressbook: File: Create contacts + + Background: + * Open Evolution and setup fake account + * Open "Contacts" section + * Select "Personal" addressbook + * Change categories view to "Any Category" + * Delete all contacts containing "Doe" + + @addressbook_contacts + Scenario: Create a simple contact + * Create a new contact + * Set "Full Name..." in contact editor to "John Doe" + * Save the contact + * Refresh addressbook + * Select "Doe, John" contact + * Open contact editor for selected contact + Then "Full Name..." property is set to "John Doe" + + @addressbook_contacts + Scenario: Create a contact with full data + * Create a new contact + * Set "Full Name..." in contact editor to "Jimmy Doe" + * Set "Nickname:" in contact editor to "Unknown" + * Set emails in contact editor to + | Field | Value | + | Work | jimmy.doe@company.com | + | Home | jimmy_doe_72@gmail.com | + | Other | jimmydoe72@yahoo.com | + | Other | xxjimmyxx@free_email.com | + * Tick "Wants to receive HTML mail" checkbox + * Set phones in contact editor to + | Field | Value | + | Assistant Phone | 123 | + | Business Phone | 234 | + | Business Fax | 345 | + | Callback Phone | 456 | + | Car Phone | 567 | + | Company Phone | 678 | + | Home Phone | 789 | + | Home Fax | 890 | + * Set IMs in contact editor to + | Field | Value | + | AIM | 123 | + | Jabber | 234 | + | Yahoo | 345 | + | Gadu-Gadu | 456 | + * Switch to "Personal Information" tab in contact editor + * Set the following properties in contact editor + | Field | Value | + | Home Page: | http://anna-doe.com | + | Blog: | http://blog.anna-doe.com | + | Calendar: | caldav://anna-doe.com/calendar.ics | + | Free/Busy: | http://anna-doe.com/free-busy | + | Video Chat: | http://anna-doe.com/video-chat | + | Profession: | QA Engineer | + | Title: | Dr. | + | Company: | Something Ltd. | + | Department: | Desktop QA | + | Manager: | John Doe | + | Assistant: | Anna Doe | + | Office: | 221b | + | Spouse: | Jack Doe | + * Switch to "Mailing Address" tab in contact editor + * Set the following properties in "Home" section of contact editor + | Field | Value | + | City: | Brno | + | Zip/Postal Code: | 61245 | + | State/Province: | Brno-Kralovo Pole | + | Country: | Czech Republic | + | PO Box: | 123456 | + | Address: | Purkynova 99/71 | + * Set the following properties in "Work" section of contact editor + | Field | Value | + | City: | Brno | + | Zip/Postal Code: | 61245 | + | State/Province: | Brno-Kralovo Pole | + | Country: | Czech Republic | + | PO Box: | 123456 | + | Address: | Purkynova 99/71 | + * Set the following properties in "Other" section of contact editor + | Field | Value | + | City: | Brno | + | Zip/Postal Code: | 61245 | + | State/Province: | Brno-Kralovo Pole | + | Country: | Czech Republic | + | PO Box: | 123456 | + | Address: | Purkynova 99/71 | + * Switch to "Notes" tab in contact editor + * Set the following note for the contact: + """ + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed dignissim gravida elit, nec facilisis augue commodo quis. + + Sed ac metus quis tellus aliquet posuere non quis elit. Quisque non ante congue urna blandit accumsan. + + In vitae ligula risus. Nunc venenatis leo vel leo facilisis porta. Nam sed magna urna, venenatis. + """ + * Refresh addressbook + * Select "Doe, Jimmy" contact + * Open contact editor for selected contact + Then "Nickname:" property is set to "Unknown" + And Emails are set to + | Field | Value | + | Work | jimmy.doe@company.com | + | Home | jimmy_doe_72@gmail.com | + | Other | jimmydoe72@yahoo.com | + | Other | xxjimmyxx@free_email.com | + And "Wants to receive HTML mail" checkbox is ticked + And Phones are set to + | Field | Value | + | Assistant Phone | 123 | + | Business Phone | 234 | + | Business Fax | 345 | + | Callback Phone | 456 | + | Car Phone | 567 | + | Company Phone | 678 | + | Home Phone | 789 | + | Home Fax | 890 | + And IMs are set to + | Field | Value | + | AIM | 123 | + | Jabber | 234 | + | Yahoo | 345 | + | Gadu-Gadu | 456 | + * Switch to "Personal Information" tab in contact editor + Then The following properties in contact editor are set + | Field | Value | + | Home Page: | http://anna-doe.com | + | Blog: | http://blog.anna-doe.com | + | Calendar: | caldav://anna-doe.com/calendar.ics | + | Free/Busy: | http://anna-doe.com/free-busy | + | Video Chat: | http://anna-doe.com/video-chat | + | Field | Value | + | Profession: | QA Engineer | + | Title: | Dr. | + | Company: | Something Ltd. | + | Department: | Desktop QA | + | Manager: | John Doe | + | Assistant: | Anna Doe | + | Office: | 221b | + | Spouse: | Jack Doe | + * Switch to "Mailing Address" tab in contact editor + Then The following properties in "Home" section of contact editor are set + | Field | Value | + | City: | Brno | + | Zip/Postal Code: | 61245 | + | State/Province: | Brno-Kralovo Pole | + | Country: | Czech Republic | + | PO Box: | 123456 | + | Address: | Purkynova 99/71 | + And The following properties in "Work" section of contact editor are set + | Field | Value | + | City: | Brno | + | Zip/Postal Code: | 61245 | + | State/Province: | Brno-Kralovo Pole | + | Country: | Czech Republic | + | PO Box: | 123456 | + | Address: | Purkynova 99/71 | + And The following properties in "Other" section of contact editor are set + | Field | Value | + | City: | Brno | + | Zip/Postal Code: | 61245 | + | State/Province: | Brno-Kralovo Pole | + | Country: | Czech Republic | + | PO Box: | 123456 | + | Address: | Purkynova 99/71 | + * Switch to "Notes" tab in contact editor + Then The following note is set for the contact: + """ + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed dignissim gravida elit, nec facilisis augue commodo quis. + + Sed ac metus quis tellus aliquet posuere non quis elit. Quisque non ante congue urna blandit accumsan. + + In vitae ligula risus. Nunc venenatis leo vel leo facilisis porta. Nam sed magna urna, venenatis. + """ + + @addressbook_contacts + Scenario: Create a contact with different "file under" field + * Create a new contact + * Set "Full Name..." in contact editor to "Jackie Doe" + * Set "File under:" in contact editor to "Jackie Doe" + * Save the contact + * Refresh addressbook + * Select "Jackie Doe" contact + * Open contact editor for selected contact + Then "Full Name..." property is set to "Jackie Doe" + + @addressbook_contacts + Scenario: Create a contact with all phones and IM set (part 2) + * Create a new contact + * Set "Full Name..." in contact editor to "Kevin Doe" + * Set IMs in contact editor to + | Field | Value | + | MSN | 123 | + | ICQ | 234 | + | GroupWise | 345 | + | Skype | 456 | + * Set phones in contact editor to + | Field | Value | + | ISDN | 123 | + | Mobile Phone | 234 | + | Other Phone | 345 | + | Other Fax | 456 | + | Pager | 567 | + | Primary Phone | 678 | + | Radio | 789 | + | Telex | 890 | + + * Save the contact + * Refresh addressbook + * Select "Doe, Kevin" contact + * Open contact editor for selected contact + Then Phones are set to + | Field | Value | + | ISDN | 123 | + | Mobile Phone | 234 | + | Other Phone | 345 | + | Other Fax | 456 | + | Pager | 567 | + | Primary Phone | 678 | + | Radio | 789 | + | Telex | 890 | + And IMs are set to + | Field | Value | + | MSN | 123 | + | ICQ | 234 | + | GroupWise | 345 | + | Skype | 456 | + + @addressbook_contacts + Scenario: Create a contact with all IM set (part 2) + * Create a new contact + * Set "Full Name..." in contact editor to "Mary Doe" + * Set IMs in contact editor to + | Field | Value | + | Twitter | 123 | + | ICQ | 234 | + | Jabber | 345 | + | Skype | 456 | + + * Save the contact + * Refresh addressbook + * Select "Doe, Mary" contact + * Open contact editor for selected contact + Then IMs are set to + | Field | Value | + | Twitter | 123 | + | ICQ | 234 | + | Jabber | 345 | + | Skype | 456 | diff --git a/tests/environment.py b/tests/environment.py index 76fe686380..a9098e6904 100644 --- a/tests/environment.py +++ b/tests/environment.py @@ -16,6 +16,9 @@ def before_all(context): """ try: + # Close running evo instances + os.system("evolution --force-shutdown > /dev/null") + # Skip dogtail actions to print to stdout config.logDebugToStdOut = False config.typingDelay = 0.2 diff --git a/tests/steps/addressbook_steps.py b/tests/steps/addressbook_steps.py new file mode 100644 index 0000000000..3249d3cff4 --- /dev/null +++ b/tests/steps/addressbook_steps.py @@ -0,0 +1,371 @@ +# -*- coding: UTF-8 -*- +from behave import step, then +from common_steps import wait_until +from dogtail.predicate import GenericPredicate +from dogtail.rawinput import keyCombo +from time import time, sleep +from gi.repository import GLib +import pyatspi + + +@step(u'Select "{name}" addressbook') +def select_addressbook(context, name, password=None): + cells = context.app.findChildren( + GenericPredicate(name=name, roleName='table cell')) + visible_cells = filter(lambda x: x.showing, cells) + if visible_cells == []: + raise RuntimeError("Cannot find addressbook '%s'" % name) + visible_cells[0].click() + # Wait for addressbook to load + try: + spinner = context.app.findChild( + GenericPredicate(name='Spinner'), retry=False, requireResult=False) + if spinner: + start_time = time() + while spinner.showing: + sleep(1) + if (time() - start_time) > 180: + raise RuntimeError("Contacts take too long to synchronize") + except (GLib.GError, TypeError): + pass + + +@step(u'Change categories view to "{category}"') +def change_categories_view(context, category): + labels = context.app.findChildren( + lambda x: x.labeller.name == 'Show:' and x.showing) + if labels == []: + raise RuntimeError("Cannot find category switcher") + labels[0].combovalue = category + + +@step(u'Delete selected contact') +def delete_selected_contact(context): + context.app.menu('Edit').click() + mnu = context.app.menu('Edit').menuItem("Delete Contact") + if pyatspi.STATE_ENABLED in mnu.getState().getStates(): + context.app.menu('Edit').menuItem("Delete Contact").click() + + alert = context.app.child(roleName='alert', name='Question') + alert.button('Delete').click() + context.execute_steps(u"* Wait for email to synchronize") + + +@step(u'Delete all contacts containing "{part}"') +def delete_all_contacts_containing(context, part): + context.app.search_bar.grab_focus() + for attempts in range(0, 10): + try: + context.app.search_bar.text = part + break + except (GLib.GError, AttributeError): + sleep(0.1) + continue + keyCombo("<Enter>") + context.execute_steps(u"* Wait for email to synchronize") + context.app.search_bar.grab_focus() + keyCombo("<Tab>") + sleep(3) + heading = context.app.findChild( + GenericPredicate(roleName='heading'), + retry=False, requireResult=False) + if heading: + keyCombo("<Control>a") + context.execute_steps(u"* Delete selected contact") + sleep(3) + + +@step(u'Create a new contact') +def create_a_new_contact(context): + context.app.menu('File').click() + context.app.menu('File').menu('New').point() + context.app.menu('File').menu('New').menuItem("Contact").click() + context.execute_steps(u"Then Contact editor window is opened") + + +def get_element_by_name(contact_editor, name, section=None): + """Get a field object by name in section (if specified)""" + element = None + if section: + panel = contact_editor.findChild( + GenericPredicate(roleName='panel', name=section), retry=False, requireResult=False) + if not panel: + # Other section is not a panel, but a toggle button + panel = contact_editor.child(roleName='toggle button', name=section) + element = panel.childLabelled(name) + else: + label = contact_editor.findChild( + GenericPredicate(label=name), retry=False, requireResult=False) + if not label: + # In case childLabelled is missing + # Find a filler with this name and get its text child + element = contact_editor.child( + roleName='filler', name=name).child(roleName='text') + else: + element = contact_editor.childLabelled(name) + if element: + return element + else: + raise RuntimeError("Cannot find element named '%s' in section '%s'" % ( + name, section)) + + +@step(u'Set "{field_name}" in contact editor to "{field_value}"') +def set_field_to_value(context, field_name, field_value): + element = get_element_by_name(context.app.contact_editor, field_name) + if element.roleName == "text": + element.text = field_value + elif element.roleName == "combo box": + if element.combovalue != field_value: + element.combovalue = field_value + + +@step(u'Save the contact') +def save_contact(context): + context.app.contact_editor.button('Save').click() + assert wait_until(lambda x: x.dead, context.app.contact_editor),\ + "Contact Editor was not closed" + context.app.contact_editor = None + + +@step(u'Refresh addressbook') +def refresh_addressbook(context): + #Clear the search + icons = context.app.search_bar.findChildren(lambda x: x.roleName == 'icon') + if icons != []: + icons[-1].click() + else: + for attempts in range(0, 10): + try: + context.app.search_bar.text = '' + break + except (GLib.GError, AttributeError): + sleep(0.1) + continue + context.app.search_bar.grab_focus() + keyCombo('<Enter>') + context.execute_steps(u"* Wait for email to synchronize") + + +@step(u'Select "{contact_name}" contact list') +@step(u'Select "{contact_name}" contact') +def select_contact_with_name(context, contact_name): + # heading shows the name of currently selected contact + # We have to keep on pressing Tab to select the next contact + # Until we meet the first contact + # WARNING - what if we will have two identical contacts? + fail = False + selected_contact = None + + # HACK + # To make the contact table appear + # we need to focus on search window + # and send Tabs to have the first contact focused + context.app.search_bar.grab_focus() + sleep(0.1) + # Switch to 'Any field contains' (not reachable in 3.6) + icons = context.app.search_bar.findChildren(GenericPredicate(roleName='icon')) + + if icons != []: + icons[0].click() + wait_until(lambda x: x.findChildren( + GenericPredicate(roleName='check menu item', name='Any field contains')) != [], + context.app) + context.app.menuItem('Any field contains').click() + for attempts in range(0, 10): + try: + context.app.search_bar.text = contact_name + break + except (GLib.GError, AttributeError): + sleep(0.1) + continue + keyCombo("<Enter>") + context.app.search_bar.grab_focus() + + keyCombo("<Tab>") + first_contact_name = context.app.child(roleName='heading').text + + while True: + selected_contact = context.app.child(roleName='heading') + if selected_contact.text == contact_name: + fail = False + break + keyCombo("<Tab>") + # Wait until contact data is being rendered + sleep(1) + if first_contact_name == selected_contact.text: + fail = True + break + + context.assertion.assertFalse( + fail, "Can't find contact named '%s'" % contact_name) + context.selected_contact_text = selected_contact.text + + +@step(u'Open contact editor for selected contact') +def open_contact_editor_for_selected_contact(context): + context.app.menu('File').click() + context.app.menu('File').menuItem('Open Contact').click() + context.execute_steps(u""" + Then Contact editor window with title "Contact Editor - %s" is opened + """ % context.selected_contact_text) + + +@then(u'"{field}" property is set to "{expected}"') +def property_in_contact_window_is_set_to(context, field, expected): + element = get_element_by_name(context.app.contact_editor, field) + actual = None + if element.roleName == "text": + actual = element.text + elif element.roleName == "combo box": + actual = element.combovalue + if actual == '': + actual = element.textentry('').text + assert unicode(actual) == expected, "Incorrect value" + + +def get_combobox_textbox_object(contact_editor, section): + """Get a list of paired 'combobox-textbox' objects in contact editor""" + section_names = { + 'Ims': 'Instant Messaging', + 'Phones': 'Telephone', + 'Emails': 'Email'} + section = section_names[section.capitalize()] + lbl = contact_editor.child(roleName='label', name=section) + panel = lbl.findAncestor(GenericPredicate(roleName='panel')) + textboxes = panel.findChildren(GenericPredicate(roleName='text')) + + # Expand section if button exists + button = panel.findChild( + GenericPredicate(roleName='push button', name=section), + retry=False, requireResult=False) + # Expand button if any of textboxes is not visible + if button and (False in [x.showing for x in textboxes]): + button.click() + + comboboxes = panel.findChildren(GenericPredicate(roleName='combo box')) + + # Rearrange comboboxes and textboxes according to their position + result = [] + for combo in comboboxes: + combo_row = combo.position[1] + matching_textboxes = [ + x for x in textboxes + if (x.position[1] == combo_row) and (x.position[0] > combo.position[0])] + correct_textbox = min(matching_textboxes, key=lambda x: x.position[0]) + result.append((combo, correct_textbox)) + + comboboxes = [x[0] for x in result] + textboxes = [x[1] for x in result] + + return (textboxes, comboboxes) + + +@step(u'Set {section} in contact editor to') +def set_contact_emails_to_value(context, section): + (textboxes, comboboxes) = get_combobox_textbox_object( + context.app.contact_editor, section) + + # clear existing data + for textbox in textboxes: + textbox.text = "" + + for index, row in enumerate(context.table.rows): + textboxes[index].text = row['Value'] + if comboboxes[index].combovalue != row['Field']: + comboboxes[index].combovalue = row['Field'] + + +@then(u'{section} are set to') +def emails_are_set_to(context, section): + (textboxes, comboboxes) = get_combobox_textbox_object( + context.app.contact_editor, section) + + actual = [] + for index, textbox in enumerate(textboxes): + combo_value = textbox.text + if combo_value.strip() != '': + type_value = comboboxes[index].combovalue + actual.append({'Field': unicode(type_value), 'Value': unicode(combo_value)}) + actual = sorted(actual) + + expected = [] + for row in context.table: + expected.append({'Field': row['Field'], 'Value': row['Value']}) + expected = sorted(expected) + + assert actual == expected, "Incorrect %s value:\nexpected:%s\n but was:%s" % ( + row['Field'], expected, actual) + + +@step(u'Tick "Wants to receive HTML mail" checkbox') +def tick_checkbox(context): + context.app.contact_editor.childNamed("Wants to receive HTML mail").click() + + +@step(u'"Wants to receive HTML mail" checkbox is ticked') +def checkbox_is_ticked(context): + check_state = context.app.childNamed("Wants to receive HTML mail").checked + assert check_state, "Incorrect checkbox state" + + +@step(u'Switch to "{name}" tab in contact editor') +def switch_to_tab(context, name): + context.app.contact_editor.tab(name).click() + + +@step(u'Set the following properties in contact editor') +def set_properties(context): + for row in context.table.rows: + context.execute_steps(u""" + * Set "%s" in contact editor to "%s" + """ % (row['Field'], row['Value'])) + + +@step(u'The following properties in contact editor are set') +def verify_properties(context): + for row in context.table.rows: + context.execute_steps(u""" + Then "%s" property is set to "%s" + """ % (row['Field'], row['Value'])) + + +@step(u'Set the following properties in "{section}" section of contact editor') +def set_properties_in_section(context, section): + for row in context.table.rows: + context.execute_steps(u""" + * Set "%s" in "%s" section of contact editor to "%s" + """ % (row['Field'], section, row['Value'])) + + +@step(u'The following properties in "{section}" section of contact editor are set') +def verify_properties_in_section(context, section): + for row in context.table.rows: + context.execute_steps(u""" + Then "%s" property in "%s" section is set to "%s" + """ % (row['Field'], section, row['Value'])) + + +@step(u'Set the following note for the contact') +def set_note_for_contact(context): + context.app.contact_editor.child( + roleName='page tab', name='Notes').textentry('').text = context.text + + +@then(u'The following note is set for the contact') +def verify_note_set_for_contact(context): + actual = context.app.contact_editor.child( + roleName='page tab', name='Notes').textentry('').text + expected = context.text + assert actual == expected,\ + "Incorrect note value:\nexpected:%s\n but was:%s" % (expected, actual) + + +@step(u'Set "{field_name}" in "{section}" section of contact editor to "{field_value}"') +def set_field_in_section_to_value(context, field_name, section, field_value): + element = get_element_by_name( + context.app.contact_editor, field_name, section=section) + if element.roleName == "text": + element.text = field_value + elif element.roleName == "combo box": + element.combovalue = field_value
\ No newline at end of file diff --git a/tests/steps/steps.py b/tests/steps/steps.py index 78b19d2f7f..2b36709d8e 100644 --- a/tests/steps/steps.py +++ b/tests/steps/steps.py @@ -3,9 +3,9 @@ from behave import step, then from common_steps import wait_until from dogtail.tree import root from dogtail.rawinput import keyCombo -from time import sleep +from time import sleep, time from os import system -from gi.repository import Gio +from gi.repository import Gio, GLib @step(u'Help section "{name}" is displayed') @@ -42,12 +42,23 @@ def view_is_opened(context, name): context.assertion.assertTrue(context.app.menu('Message').showing) +def get_visible_searchbar(context): + """Wait for searchbar to become visible""" + searchbars = context.app.findChildren(lambda x: x.labeller.name == 'Search:' and x.showing) + assert wait_until(lambda x: len(x) > 0, searchbars), "No visible searchbars found" + return searchbars[0] + + @step(u'Open "{section_name}" section') def open_section_by_name(context, section_name): + wait_until(lambda x: x.showing, context.app.menu('View')) context.app.menu('View').click() context.app.menu('View').menu('Window').point() context.app.menu('View').menu('Window').menuItem(section_name).click() + # Find a search bar + context.app.search_bar = get_visible_searchbar(context) + # Check that service required for this sections is running required_services = { 'Mail': 'org.gnome.evolution.dataserver.Sources', @@ -143,3 +154,22 @@ def task_editor_with_title_is_opened(context, title): @step(u'Event editor with title "{name}" is displayed') def event_editor_with_name_displayed(context, name): context.app.event_editor = context.app.window(name) + + +@step(u'Wait for email to synchronize') +def wait_for_mail_folder_to_synchronize(context): + # Wait until Google calendar is loaded + for attempt in range(0, 10): + start_time = time() + try: + spinners = context.app.findChildren(lambda x: x.name == 'Spinner') + for spinner in spinners: + try: + while spinner.showing: + sleep(0.1) + if (time() - start_time) > 180: + raise RuntimeError("Mail takes too long to synchronize") + except GLib.GError: + continue + except (GLib.GError, TypeError): + continue |