Add installed tests using --enable-installed-tests switch

https://bugzilla.gnome.org/show_bug.cgi?id=726832
This commit is contained in:
Vadim Rutkovsky
2014-03-21 16:15:00 +01:00
parent a9b96e5ae1
commit 399b1a6fc5
8 changed files with 810 additions and 0 deletions

View File

@ -147,4 +147,9 @@ DISTCHECK_CONFIGURE_FLAGS = \
--disable-weather \
--with-help
@BEHAVE_INSTALLED_TESTS_RULE@
INSTALLED_TESTS=general_shortcuts mail_shortcuts contacts_shortcuts \
calendar_shortcuts memos_shortcuts view_shortcuts menu_shortcuts
INSTALLED_TESTS_TYPE=session-exclusive
-include $(top_srcdir)/git.mk

View File

@ -1411,6 +1411,11 @@ if test "$with_catalog" = "yes"; then
fi
AM_CONDITIONAL(GLADE_CATALOG, test "x$with_catalog" != "xno")
dnl ********************************************
dnl Installed tests
dnl ********************************************
BEHAVE_INSTALLED_TESTS
dnl ******************************
dnl Makefiles
dnl ******************************
@ -1592,4 +1597,5 @@ echo "
Highlight support: $msg_text_highlight
Plugins: $msg_plugins
User documentation: $with_help
Installed tests: $enable_installed_tests
"

135
m4/behave-installed-test.m4 Normal file
View File

@ -0,0 +1,135 @@
# How to use the installed tests m4
#
# Place BEHAVE_INSTALLED_TESTS somewhere in configure.ac
#
# Writing your Makefile.am
# ~~~~~~~~~~~~~~~~~~~~~~~~
#
# Somewhere in your Makefile.am in this test directory, you need to declare
# the following variables:
#
# INSTALLED_TESTS=list of tags for tests to install
# INSTALLED_TESTS_TYPE=session-exclusive
#
# First the list of tests which should be installed, followed by
# the type of test they should be configured as. The type can
# be 'session' or 'session-exclusive'
#
# More information about valid types can be found here:
# https://wiki.gnome.org/GnomeGoals/InstalledTests
#
# The last variable is optional, but can be useful to configure
# your test program to run in the installed environment as opposed
# to the normal `make check' run.
#
# Then place this somewhere in your Makefile.am
#
# @BEHAVE_INSTALLED_TESTS_RULE@
#
# And the following in configure.ac
#
# BEHAVE_INSTALLED_TESTS
#
# And that's it, now your unit tests will be installed along with
# a .test metadata file into $(pkglibexecdir) if --enable-installed-tests
# is passed to your configure script, and will be run automatically
# by the continuous integration servers.
#
# FIXME: Change the above link to point to real documentation, not
# a gnome goal page which might disappear at some point.
#
# BUGS: This macro hooks into install-exec-am and install-data-am
# which are internals of Automake. This is because Automake doesnt
# consider the regular install-exec-local / install-exec-hook or
# data install components unless variables have been setup for them
# in advance.
#
# This doesnt seem to present a problem, but it is depending on
# internals of Automake instead of clear documented API.
# Place this in configure.ac to enable
# the installed tests option.
AC_DEFUN([BEHAVE_INSTALLED_TESTS], [
AC_PREREQ([2.50])dnl
AC_REQUIRE([AM_NLS])dnl
AC_PROG_INSTALL
AC_PROG_MKDIR_P
AC_PROG_LIBTOOL
AC_ARG_ENABLE(installed-tests,
[AC_HELP_STRING([--enable-installed-tests],
[enable installed unit tests [default=no]])],,
[enable_installed_tests="no"])
AM_CONDITIONAL([BEHAVE_INSTALLED_TESTS_ENABLED],[test "x$enable_installed_tests" = "xyes"])
AC_SUBST([BEHAVE_INSTALLED_TESTS_ENABLED], [$enable_installed_tests])
# Define the rule for makefiles
BEHAVE_INSTALLED_TESTS_RULE='
ifeq ($(BEHAVE_INSTALLED_TESTS_ENABLED),yes)
install-exec-am: installed-tests-exec-hook
install-data-am: installed-tests-data-hook
uninstall-am: uninstall-tests-hook
META_DIRECTORY=${DESTDIR}/${datadir}/installed-tests/${PACKAGE}
EXEC_DIRECTORY=${DESTDIR}/${pkglibexecdir}/installed-tests
FINAL_TEST_ENVIRONMENT=
ifneq ($(INSTALLED_TESTS_ENVIRONMENT),)
FINAL_TEST_ENVIRONMENT="env $(INSTALLED_TESTS_ENVIRONMENT)"
endif
BEHAVE_FEATURES=$(notdir $(wildcard tests/*.feature))
BEHAVE_STEP_DEFINITION=$(notdir $(wildcard tests/steps/*.py))
BEHAVE_COMMON_FILES=environment.py common_steps.py
installed-tests-exec-hook:
@$(MKDIR_P) $(EXEC_DIRECTORY);
@for feature in $(BEHAVE_FEATURES); do \
$(LIBTOOL) --mode=install $(INSTALL) --mode=777 tests/$$feature $(EXEC_DIRECTORY);\
done
@for common_file in $(BEHAVE_COMMON_FILES); do \
$(LIBTOOL) --mode=install $(INSTALL) --mode=777 tests/$$common_file $(EXEC_DIRECTORY);\
done
@$(MKDIR_P) $(EXEC_DIRECTORY)/steps;
@for step_definition in $(BEHAVE_STEP_DEFINITION); do \
$(LIBTOOL) --mode=install $(INSTALL) --mode=777 tests/steps/$$step_definition $(EXEC_DIRECTORY)/steps;\
done
installed-tests-data-hook:
@$(MKDIR_P) $(META_DIRECTORY);
@for test in $(INSTALLED_TESTS); do \
echo "Installing $$test.test to $(META_DIRECTORY)"; \
echo m4_escape([[Test]]) > $(META_DIRECTORY)/$$test.test; \
echo "Exec=behave $(pkglibexecdir)/installed-tests -t $$test -k -f plain" \
>> $(META_DIRECTORY)/$$test.test; \
echo "Type=$(INSTALLED_TESTS_TYPE)" >> $(META_DIRECTORY)/$$test.test; \
done
uninstall-tests-hook:
@for feature in $(BEHAVE_FEATURES); do\
echo "Removing feature $(EXEC_DIRECTORY) $$feature";\
$(LIBTOOL) --mode=uninstall $(RM) $(EXEC_DIRECTORY)/$$feature;\
done
@for common_file in $(BEHAVE_COMMON_FILES); do\
echo "Removing feature $(EXEC_DIRECTORY) $$common_file";\
$(LIBTOOL) --mode=uninstall $(RM) $(EXEC_DIRECTORY)/$$common_file;\
done
@for step_definition in $(BEHAVE_STEP_DEFINITION); do\
echo "Removing feature $(EXEC_DIRECTORY)/steps $$step_definition";\
$(LIBTOOL) --mode=uninstall $(RM) $(EXEC_DIRECTORY)/steps/$$step_definition;\
done
@for test in $(INSTALLED_TESTS); do\
$(LIBTOOL) --mode=uninstall $(RM) $(META_DIRECTORY)/$$test.test;\
done
endif
'
# substitute @BEHAVE_INSTALLED_TESTS_RULE@ in Makefiles
AC_SUBST([BEHAVE_INSTALLED_TESTS_RULE])
m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([BEHAVE_INSTALLED_TESTS_RULE])])
])

223
tests/common_steps.py Normal file
View File

@ -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)

46
tests/environment.py Normal file
View File

@ -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)

135
tests/shortcuts.feature Normal file
View File

@ -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 |

View File

@ -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()

122
tests/steps/steps.py Normal file
View File

@ -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)