aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorVadim Rutkovsky <vrutkovs@redhat.com>2014-03-21 23:15:00 +0800
committerVadim Rutkovsky <vrutkovs@redhat.com>2014-03-25 16:46:23 +0800
commit399b1a6fc593a9c5e692923120346e0386f578e5 (patch)
tree0ce0730706208dfb3f34cd2c4b7335aa3872491f /tests
parenta9b96e5ae15d13d204e7bef5da283bb34154d9c8 (diff)
downloadgsoc2013-evolution-399b1a6fc593a9c5e692923120346e0386f578e5.tar
gsoc2013-evolution-399b1a6fc593a9c5e692923120346e0386f578e5.tar.gz
gsoc2013-evolution-399b1a6fc593a9c5e692923120346e0386f578e5.tar.bz2
gsoc2013-evolution-399b1a6fc593a9c5e692923120346e0386f578e5.tar.lz
gsoc2013-evolution-399b1a6fc593a9c5e692923120346e0386f578e5.tar.xz
gsoc2013-evolution-399b1a6fc593a9c5e692923120346e0386f578e5.tar.zst
gsoc2013-evolution-399b1a6fc593a9c5e692923120346e0386f578e5.zip
Add installed tests using --enable-installed-tests switch
https://bugzilla.gnome.org/show_bug.cgi?id=726832
Diffstat (limited to 'tests')
-rw-r--r--tests/common_steps.py223
-rw-r--r--tests/environment.py46
-rw-r--r--tests/shortcuts.feature135
-rw-r--r--tests/steps/initial_setup_steps.py138
-rw-r--r--tests/steps/steps.py122
5 files changed, 664 insertions, 0 deletions
diff --git a/tests/common_steps.py b/tests/common_steps.py
new file mode 100644
index 0000000000..3752142f9d
--- /dev/null
+++ b/tests/common_steps.py
@@ -0,0 +1,223 @@
+# -*- coding: UTF-8 -*-
+from dogtail.utils import isA11yEnabled, enableA11y
+if isA11yEnabled() is False:
+ enableA11y(True)
+
+from time import time, sleep
+from functools import wraps
+from os import strerror, errno, kill, system
+from signal import signal, alarm, SIGALRM, SIGKILL
+from subprocess import Popen
+from behave import step
+from gi.repository import GLib, Gio
+
+from dogtail.rawinput import keyCombo, absoluteMotion, pressKey
+from dogtail.tree import root
+from dogtail.utils import run
+from unittest import TestCase
+
+
+# Create a dummy unittest class to have nice assertions
+class dummy(TestCase):
+ def runTest(self): # pylint: disable=R0201
+ assert True
+
+
+def wait_until(my_lambda, element, timeout=30, period=0.25):
+ """
+ This function keeps running lambda with specified params until the result is True
+ or timeout is reached
+ Sample usages:
+ * wait_until(lambda x: x.name != 'Loading...', context.app)
+ Pause until window title is not 'Loading...'.
+ Return False if window title is still 'Loading...'
+ Throw an exception if window doesn't exist after default timeout
+
+ * wait_until(lambda element, expected: x.text == expected, element, ('Expected text'))
+ Wait until element text becomes the expected (passed to the lambda)
+
+ """
+ exception_thrown = None
+ mustend = int(time()) + timeout
+ while int(time()) < mustend:
+ try:
+ if my_lambda(element):
+ return True
+ except Exception as e:
+ # If lambda has thrown the exception we'll re-raise it later
+ # and forget about if lambda passes
+ exception_thrown = e
+ sleep(period)
+ if exception_thrown:
+ raise exception_thrown
+ else:
+ return False
+
+
+class TimeoutError(Exception):
+ """
+ Timeout exception class for limit_execution_time_to function
+ """
+ pass
+
+
+def limit_execution_time_to(
+ seconds=10, error_message=strerror(errno.ETIME)):
+ """
+ Decorator to limit function execution to specified limit
+ """
+ def decorator(func):
+ def _handle_timeout(signum, frame):
+ raise TimeoutError(error_message)
+
+ def wrapper(*args, **kwargs):
+ signal(SIGALRM, _handle_timeout)
+ alarm(seconds)
+ try:
+ result = func(*args, **kwargs)
+ finally:
+ alarm(0)
+ return result
+
+ return wraps(func)(wrapper)
+
+ return decorator
+
+
+class App(object):
+ """
+ This class does all basic events with the app
+ """
+ def __init__(
+ self, appName, shortcut='<Control><Q>', a11yAppName=None,
+ forceKill=True, parameters='', recordVideo=False):
+ """
+ Initialize object App
+ appName command to run the app
+ shortcut default quit shortcut
+ a11yAppName app's a11y name is different than binary
+ forceKill is the app supposed to be kill before/after test?
+ parameters has the app any params needed to start? (only for startViaCommand)
+ recordVideo start gnome-shell recording while running the app
+ """
+ self.appCommand = appName
+ self.shortcut = shortcut
+ self.forceKill = forceKill
+ self.parameters = parameters
+ self.internCommand = self.appCommand.lower()
+ self.a11yAppName = a11yAppName
+ self.recordVideo = recordVideo
+ self.pid = None
+
+ # a way of overcoming overview autospawn when mouse in 1,1 from start
+ pressKey('Esc')
+ absoluteMotion(100, 100, 2)
+
+ # attempt to make a recording of the test
+ if self.recordVideo:
+ keyCombo('<Control><Alt><Shift>R')
+
+ def isRunning(self):
+ """
+ Is the app running?
+ """
+ if self.a11yAppName is None:
+ self.a11yAppName = self.internCommand
+
+ # Trap weird bus errors
+ for attempt in xrange(0, 10):
+ try:
+ return self.a11yAppName in [x.name for x in root.applications()]
+ except GLib.GError:
+ continue
+ raise Exception("10 at-spi errors, seems that bus is blocked")
+
+ def kill(self):
+ """
+ Kill the app via 'killall'
+ """
+ if self.recordVideo:
+ keyCombo('<Control><Alt><Shift>R')
+
+ try:
+ kill(self.pid, SIGKILL)
+ except:
+ # Fall back to killall
+ Popen("killall " + self.appCommand, shell=True).wait()
+
+ def startViaCommand(self):
+ """
+ Start the app via command
+ """
+ if self.forceKill and self.isRunning():
+ self.kill()
+ assert not self.isRunning(), "Application cannot be stopped"
+
+ command = "%s %s" % (self.appCommand, self.parameters)
+ self.pid = run(command, timeout=1)
+
+ assert self.isRunning(), "Application failed to start"
+ return root.application(self.a11yAppName)
+
+ def closeViaShortcut(self):
+ """
+ Close the app via shortcut
+ """
+ if not self.isRunning():
+ raise Exception("App is not running")
+
+ keyCombo(self.shortcut)
+ assert not self.isRunning(), "Application cannot be stopped"
+
+
+@step(u'Start a new Evolution instance')
+def start_new_evolution_instance(context):
+ context.app = context.app_class.startViaCommand()
+
+
+def cleanup():
+ # Remove cached data and settings
+ folders = ['~/.local/share/evolution', '~/.cache/evolution', '~/.config/evolution']
+ for folder in folders:
+ system("rm -rf %s > /dev/null" % folder)
+
+ # Clean up goa data
+ system("rm -rf ~/.config/goa-1.0/accounts.conf")
+ system("killall goa-daemon 2&> /dev/null")
+
+ # Reset GSettings
+ schemas = [x for x in Gio.Settings.list_schemas() if 'evolution' in x.lower()]
+ for schema in schemas:
+ system("gsettings reset-recursively %s" % schema)
+
+ # Skip warning dialog
+ system("gsettings set org.gnome.evolution.shell skip-warning-dialog true")
+ # Show switcher buttons as icons (to minimize tree scrolling)
+ system("gsettings set org.gnome.evolution.shell buttons-style icons")
+
+
+
+def check_for_errors(context):
+ """Check that no error is displayed on Evolution UI"""
+ # Don't try to check for errors on dead app
+ if not context.app or context.app.dead:
+ return
+ alerts = context.app.findChildren(lambda x: x.roleName == 'alert')
+ if not alerts:
+ # alerts can also return None
+ return
+ alerts = filter(lambda x: x.showing, alerts)
+ if len(alerts) > 0:
+ labels = alerts[0].findChildren(lambda x: x.roleName == 'label')
+ messages = [x.name for x in labels]
+
+ if alerts[0].name != 'Error' and alerts[0].showing:
+ # Erase the configuration and start all over again
+ system("evolution --force-shutdown &> /dev/null")
+
+ # Remove previous data
+ folders = ['~/.local/share/evolution', '~/.cache/evolution', '~/.config/evolution']
+ for folder in folders:
+ system("rm -rf %s > /dev/null" % folder)
+
+ raise RuntimeError("Error occurred: %s" % messages)
diff --git a/tests/environment.py b/tests/environment.py
new file mode 100644
index 0000000000..2d6a09f479
--- /dev/null
+++ b/tests/environment.py
@@ -0,0 +1,46 @@
+# -*- coding: UTF-8 -*-
+
+from time import sleep
+from dogtail.utils import isA11yEnabled, enableA11y
+if not isA11yEnabled():
+ enableA11y(True)
+
+from common_steps import App, dummy, cleanup
+from dogtail.config import config
+
+
+def before_all(context):
+ """Setup evolution stuff
+ Being executed once before any test
+ """
+
+ try:
+ # Skip dogtail actions to print to stdout
+ config.logDebugToStdOut = False
+ config.typingDelay = 0.2
+
+ # Include assertion object
+ context.assertion = dummy()
+
+ # Cleanup existing data before any test
+ cleanup()
+
+ context.app_class = App('evolution')
+
+ except Exception as e:
+ print("Error in before_all: %s" % e.message)
+
+
+def after_scenario(context, scenario):
+ """Teardown for each scenario
+ Kill evolution (in order to make this reliable we send sigkill)
+ """
+ try:
+ # Stop evolution
+ context.app_class.kill()
+
+ # Make some pause after scenario
+ sleep(1)
+ except Exception as e:
+ # Stupid behave simply crashes in case exception has occurred
+ print("Error in after_scenario: %s" % e.message)
diff --git a/tests/shortcuts.feature b/tests/shortcuts.feature
new file mode 100644
index 0000000000..0f9989a06a
--- /dev/null
+++ b/tests/shortcuts.feature
@@ -0,0 +1,135 @@
+Feature: Shortcuts
+
+ Background:
+ * Open Evolution and setup fake account
+
+ @general_shortcuts
+ Scenario: Ctrl-Q to quit application - two instances
+ * Start a new Evolution instance
+ * Press "<Control>Q"
+ Then Evolution is closed
+
+ @general_shortcuts
+ Scenario: F1 to launch help
+ * Press "<F1>"
+ Then Help section "Evolution Mail and Calendar" is displayed
+
+ @general_shortcuts
+ Scenario: Shift-Ctrl-W to open a new window
+ * Press "<Control><Shift>W"
+ Then Evolution has 2 windows opened
+
+ @general_shortcuts
+ Scenario: Ctrl-W to close a window
+ * Press "<Control><Shift>W"
+ * Press "<Control>W"
+ Then Evolution has 1 window opened
+
+ @general_shortcuts
+ Scenario: Ctrl-Shift-S to open Preferences
+ * Press "<Control><Shift>S"
+ Then Preferences dialog is opened
+
+ @mail_shortcuts
+ Scenario: Mail: Ctrl-Shift-M to compose new message
+ * Open "Mail" section
+ * Press "<Control><Shift>M"
+ Then Message composer with title "Compose Message" is opened
+
+ @contacts_shortcuts
+ Scenario: Contacts: Ctrl-Shift-C to create new contact
+ * Open "Contacts" section
+ * Press "<Control><Shift>C"
+ Then Contact editor window is opened
+
+ @contacts_shortcuts
+ Scenario: Contacts: Ctrl-Shift-L to create new contact list
+ * Open "Contacts" section
+ * Press "<Control><Shift>L"
+ Then Contact List editor window is opened
+
+ @calendar_shortcuts
+ Scenario: Calendar: Ctrl-Shift-A to create new appointment
+ * Open "Calendar" section
+ * Press "<Control><Shift>A"
+ Then Event editor with title "Appointment - No Summary" is displayed
+
+ @calendar_shortcuts
+ Scenario: Calendar: Ctrl-Shift-E to create new meeting
+ * Open "Calendar" section
+ * Press "<Control><Shift>E"
+ Then Event editor with title "Meeting - No Summary" is displayed
+
+ @calendar_shortcuts
+ Scenario: Tasks: Ctrl-Shift-T to create new task
+ * Open "Tasks" section
+ * Press "<Control><Shift>T"
+ Then Task editor with title "Task - No Summary" is opened
+
+ @memos_shortcuts
+ Scenario: Memos: Ctrl-Shift-O to create new memo
+ * Open "Memos" section
+ * Press "<Control><Shift>O"
+ Then Memo editor with title "Memo - No Summary" is opened
+
+ @memos_shortcuts
+ Scenario: Memos: Ctrl-Shift-O to create new task
+ * Open "Memos" section
+ * Press "<Control><Shift>O"
+ Then Shared memo editor with title "Memo - No Summary" is opened
+
+ @view_shortcuts
+ Scenario Outline: Ctrl+<1-5> to switch views
+ * Press "<shortcut>"
+ Then "<section>" view is opened
+
+ Examples:
+ | shortcut | section |
+ | <Ctrl>1 | Mail |
+ | <Ctrl>2 | Contacts |
+ | <Ctrl>3 | Calendar |
+ | <Ctrl>4 | Tasks |
+ | <Ctrl>5 | Memos |
+
+ @menu_shortcuts
+ Scenario Outline: Menu shortcuts on all views
+ * Open "<section>" section
+ * Press "<shortcut>"
+ Then "<menu>" menu is opened
+
+ Examples:
+ | section | shortcut | menu |
+ | Mail | <Alt>F | File |
+ | Mail | <Alt>E | Edit |
+ | Mail | <Alt>V | View |
+ | Mail | <Alt>O | Folder |
+ | Mail | <Alt>M | Message |
+ | Mail | <Alt>S | Search |
+ | Mail | <Alt>H | Help |
+
+ | Contacts | <Alt>F | File |
+ | Contacts | <Alt>E | Edit |
+ | Contacts | <Alt>V | View |
+ | Contacts | <Alt>A | Actions |
+ | Contacts | <Alt>S | Search |
+ | Contacts | <Alt>H | Help |
+
+ | Calendar | <Alt>F | File |
+ | Calendar | <Alt>E | Edit |
+ | Calendar | <Alt>V | View |
+ | Calendar | <Alt>A | Actions |
+ | Calendar | <Alt>S | Search |
+ | Calendar | <Alt>H | Help |
+
+ | Tasks | <Alt>F | File |
+ | Tasks | <Alt>E | Edit |
+ | Tasks | <Alt>V | View |
+ | Tasks | <Alt>A | Actions |
+ | Tasks | <Alt>S | Search |
+ | Tasks | <Alt>H | Help |
+
+ | Memos | <Alt>F | File |
+ | Memos | <Alt>E | Edit |
+ | Memos | <Alt>V | View |
+ | Memos | <Alt>S | Search |
+ | Memos | <Alt>H | Help |
diff --git a/tests/steps/initial_setup_steps.py b/tests/steps/initial_setup_steps.py
new file mode 100644
index 0000000000..ec97e455e4
--- /dev/null
+++ b/tests/steps/initial_setup_steps.py
@@ -0,0 +1,138 @@
+# -*- coding: UTF-8 -*-
+from behave import step
+
+from common_steps import wait_until, check_for_errors
+from dogtail.tree import root
+from os import system
+from pyatspi import STATE_SENSITIVE
+from time import sleep
+
+
+@step(u'Open Evolution and setup fake account')
+def open_evolution_and_setup_fake_account(context):
+ system("evolution --force-shutdown 2&> /dev/null")
+ context.execute_steps(u'* Start a new Evolution instance')
+ window = context.app.child(roleName='frame')
+ if window.name == 'Evolution Account Assistant':
+ context.execute_steps(u"""
+ * Complete Welcome dialog in Evolution Account Assistant
+ * Complete Restore from Backup dialog in Evolution Account Assistant
+ * Complete Identity dialog setting name to "GNOME QE User" and email address to "test@test"
+ * Wait for account is being looked up dialog in Evolution Account Assistant
+ * Complete Receiving Email dialog of Evolution Account Assistant setting
+ | Field | Value |
+ | Server Type: | None |
+ * Complete Sending Email dialog of Evolution Account Assistant setting
+ | Field | Value |
+ | Server Type: | Sendmail |
+ * Complete Account Summary in Evolution Account Assistant
+ * Complete Done dialog in Evolution Account Assistant
+ """)
+ # Evo doesn't create default addressbook immidiately
+ # We should restart it
+ system("evolution --force-shutdown 2&> /dev/null")
+ context.execute_steps(u'* Start a new Evolution instance')
+
+
+@step(u'Complete Receiving Options in Evolution Account Assistant')
+@step(u'Complete Account Summary in Evolution Account Assistant')
+@step(u'Complete Restore from Backup dialog in Evolution Account Assistant')
+@step(u'Complete Welcome dialog in Evolution Account Assistant')
+def evo_account_assistant_dummy_dialogs(context):
+ # nothing to do here, skip it
+ window = context.app.child('Evolution Account Assistant')
+ click_continue(window)
+
+
+@step(u'Complete Identity dialog setting name to "{name}" and email address to "{email}"')
+def evo_account_assistant_identity_dialog(context, name, email):
+ # nothing to do here, skip it
+ window = context.app.child('Evolution Account Assistant')
+ window.childLabelled("Full Name:").text = name
+ window.childLabelled("Email Address:").text = email
+ click_continue(window)
+
+
+@step(u"Wait for account is being looked up dialog in Evolution Account Assistant")
+def wait_for_account_to_be_looked_up(context):
+ window = context.app.child('Evolution Account Assistant')
+ skip_lookup = window.findChildren(lambda x: x.name == 'Skip Lookup')
+ visible_skip_lookup = [x for x in skip_lookup if x.showing]
+ if len(visible_skip_lookup) > 0:
+ visible_skip_lookup = visible_skip_lookup[0]
+ assert wait_until(lambda x: not x.showing, visible_skip_lookup),\
+ "Skip Lookup button didn't dissappear"
+
+
+def click_continue(window):
+ # As initial wizard dialog creates a bunch of 'Continue' buttons
+ # We have to click to the visible and enabled one
+ button = None
+ for attempt in xrange(0, 10):
+ btns = window.findChildren(lambda x: x.name == 'Continue')
+ visible_and_enabled = [x for x in btns if x.showing and STATE_SENSITIVE in x.getState().getStates()]
+ if visible_and_enabled == []:
+ sleep(0.1)
+ continue
+ else:
+ button = visible_and_enabled[0]
+ break
+ button.click()
+
+
+@step(u'Complete {sending_or_receiving} Email dialog of Evolution Account Assistant setting')
+def evo_account_assistant_receiving_email_dialog_from_table(context, sending_or_receiving):
+ window = context.app.child('Evolution Account Assistant')
+ for row in context.table:
+ label = str(row['Field'])
+ value = str(row['Value'])
+ filler = window.child(roleName='filler', name='%s Email' % sending_or_receiving)
+ widgets = filler.findChildren(lambda x: x.showing)
+ visible_widgets = [x for x in widgets if x.labeller and x.labeller.name == label]
+ if len(visible_widgets) == 0:
+ raise RuntimeError("Cannot find visible widget labelled '%s'" % label)
+ widget = visible_widgets[0]
+ if widget.roleName == 'combo box':
+ if label != 'Port:':
+ widget.click()
+ widget.menuItem(value).click()
+ else:
+ # Port is a combobox, but you can type your port there
+ widget.textentry('').text = value
+ widget.textentry('').grab_focus()
+ widget.textentry('').keyCombo("<Enter>")
+ if widget.roleName == 'text':
+ widget.text = value
+
+ # Check for password here and accept self-generated certificate (if appears)
+ btns = window.findChildren(lambda x: x.name == 'Check for Supported Types')
+ visible_btns = [w for w in btns if w.showing]
+ if visible_btns == []:
+ click_continue(window)
+ return
+ visible_btns[0].click()
+
+ # Confirm all certificates by clicking 'Accept Permanently' until dialog is visible
+ apps = [x.name for x in root.applications()]
+ if 'evolution-user-prompter' in apps:
+ prompter = root.application('evolution-user-prompter')
+ dialog = prompter.child(roleName='dialog')
+ while dialog.showing:
+ if prompter.findChild(lambda x: x.name == 'Accept Permanently', retry=False, requireResult=False):
+ prompter.button('Accept Permanently').click()
+ else:
+ sleep(0.1)
+
+ # Wait until Cancel button disappears
+ cancel = filler.findChildren(lambda x: x.name == 'Cancel')[0]
+ while cancel.showing:
+ sleep(0.1)
+ check_for_errors(context)
+ click_continue(window)
+
+
+@step(u'Complete Done dialog in Evolution Account Assistant')
+def evo_account_assistant_done_dialog(context):
+ # nothing to do here, skip it
+ window = context.app.child('Evolution Account Assistant')
+ window.button('Apply').click()
diff --git a/tests/steps/steps.py b/tests/steps/steps.py
new file mode 100644
index 0000000000..dac984f5dc
--- /dev/null
+++ b/tests/steps/steps.py
@@ -0,0 +1,122 @@
+# -*- coding: UTF-8 -*-
+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 os import system
+
+
+@step(u'Help section "{name}" is displayed')
+def help_is_displayed(context, name):
+ try:
+ context.yelp = root.application('yelp')
+ frame = context.yelp.child(roleName='frame')
+ wait_until(lambda x: x.showing, frame)
+ sleep(1)
+ context.assertion.assertEquals(name, frame.name)
+ finally:
+ system("killall yelp")
+
+
+@step(u'Evolution has {num:d} window opened')
+@step(u'Evolution has {num:d} windows opened')
+def evolution_has_num_windows_opened(context, num):
+ windows = context.app.findChildren(lambda x: x.roleName == 'frame')
+ context.assertion.assertEqual(len(windows), num)
+
+
+@step(u'Preferences dialog is opened')
+def preferences_dialog_opened(context):
+ context.app.window('Evolution Preferences')
+
+
+@step(u'"{name}" view is opened')
+def view_is_opened(context, name):
+ if name != 'Mail':
+ window_name = context.app.children[0].name
+ context.assertion.assertEquals(window_name, "%s - Evolution" % name)
+ else:
+ # A special case for Mail
+ context.assertion.assertTrue(context.app.menu('Message').showing)
+
+
+@step(u'Open "{section_name}" section')
+def open_section_by_name(context, section_name):
+ context.app.menu('View').click()
+ context.app.menu('View').menu('Window').point()
+ context.app.menu('View').menu('Window').menuItem(section_name).click()
+
+
+@step(u'"{name}" menu is opened')
+def menu_is_opened(context, name):
+ sleep(0.5)
+ menu = context.app.menu(name)
+ children_displayed = [x.showing for x in menu.children]
+ context.assertion.assertTrue(True in children_displayed, "Menu '%s' is not opened" % name)
+
+
+@step(u'Press "{sequence}"')
+def press_button_sequence(context, sequence):
+ keyCombo(sequence)
+ sleep(0.5)
+
+
+@then(u'Evolution is closed')
+def evolution_is_closed(context):
+ assert wait_until(lambda x: x.dead, context.app),\
+ "Evolution window is opened"
+ context.assertion.assertFalse(context.app_class.isRunning(), "Evolution is in the process list")
+
+
+@step(u'Message composer with title "{name}" is opened')
+def message_composer_is_opened(context, name):
+ context.app.composer = context.app.window(name)
+
+
+@then(u'Contact editor window with title "{title}" is opened')
+def contact_editor_with_label_is_opened(context, title):
+ context.app.contact_editor = context.app.dialog(title)
+ context.assertion.assertIsNotNone(
+ context.app.contact_editor, "Contact Editor was not found")
+ context.assertion.assertTrue(
+ context.app.contact_editor.showing, "Contact Editor didn't appear")
+
+
+@then(u'Contact editor window is opened')
+def contact_editor_is_opened(context):
+ context.execute_steps(u'Then Contact editor window with title "Contact Editor" is opened')
+
+
+@then(u'Contact List editor window is opened')
+def contact_list_editor_is_opened(context):
+ context.execute_steps(
+ u'Then Contact List editor window with title "Contact List Editor" is opened')
+
+
+@then(u'Contact List editor window with title "{name}" is opened')
+def contact_list_editor__with_name_is_opened(context, name):
+ context.app.contact_list_editor = context.app.dialog(name)
+
+
+@step(u'Memo editor with title "{name}" is opened')
+def memo_editor_is_opened(context, name):
+ context.execute_steps(u'* Task editor with title "%s" is opened' % name)
+
+
+@step(u'Shared Memo editor with title "{name}" is opened')
+def shared_memo_editor_is_opened(context, name):
+ context.execute_steps(u'* Task editor with title "%s" is opened' % name)
+
+
+@step(u'Task editor with title "{title}" is opened')
+def task_editor_with_title_is_opened(context, title):
+ context.app.task_editor = context.app.window(title)
+ # Spoof event_editor for assigned tasks
+ if 'Assigned' in title:
+ context.app.event_editor = context.app.task_editor
+
+
+@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) \ No newline at end of file