1# -*- coding: UTF-8 -*- 2from behave import step, then 3from common_steps import wait_until 4from dogtail.predicate import GenericPredicate 5from dogtail.rawinput import keyCombo 6from time import time, sleep 7from gi.repository import GLib 8import pyatspi 9 10 11@step(u'Select "{name}" addressbook') 12def select_addressbook(context, name, password=None): 13 cells = context.app.findChildren( 14 GenericPredicate(name=name, roleName='table cell')) 15 visible_cells = filter(lambda x: x.showing, cells) 16 if visible_cells == []: 17 raise RuntimeError("Cannot find addressbook '%s'" % name) 18 visible_cells[0].click() 19 # Wait for addressbook to load 20 try: 21 spinner = context.app.findChild( 22 GenericPredicate(name='Spinner'), retry=False, requireResult=False) 23 if spinner: 24 start_time = time() 25 while spinner.showing: 26 sleep(1) 27 if (time() - start_time) > 180: 28 raise RuntimeError("Contacts take too long to synchronize") 29 except (GLib.GError, TypeError): 30 pass 31 32 33@step(u'Change categories view to "{category}"') 34def change_categories_view(context, category): 35 labels = context.app.findChildren( 36 lambda x: x.labeller.name == 'Show:' and x.showing) 37 if labels == []: 38 raise RuntimeError("Cannot find category switcher") 39 labels[0].combovalue = category 40 41 42@step(u'Delete selected contact') 43def delete_selected_contact(context): 44 context.app.menu('Edit').click() 45 mnu = context.app.menu('Edit').menuItem("Delete Contact") 46 if pyatspi.STATE_ENABLED in mnu.getState().getStates(): 47 context.app.menu('Edit').menuItem("Delete Contact").click() 48 49 alert = context.app.child(roleName='alert', name='Question') 50 alert.button('Delete').click() 51 context.execute_steps(u"* Wait for email to synchronize") 52 53 54@step(u'Delete all contacts containing "{part}"') 55def delete_all_contacts_containing(context, part): 56 context.app.search_bar.grab_focus() 57 for attempts in range(0, 10): 58 try: 59 context.app.search_bar.text = part 60 break 61 except (GLib.GError, AttributeError): 62 sleep(0.1) 63 continue 64 keyCombo("<Enter>") 65 context.execute_steps(u"* Wait for email to synchronize") 66 context.app.search_bar.grab_focus() 67 keyCombo("<Tab>") 68 sleep(3) 69 heading = context.app.findChild( 70 GenericPredicate(roleName='heading'), 71 retry=False, requireResult=False) 72 if heading: 73 keyCombo("<Control>a") 74 context.execute_steps(u"* Delete selected contact") 75 sleep(3) 76 77 78@step(u'Create a new contact') 79def create_a_new_contact(context): 80 context.app.menu('File').click() 81 context.app.menu('File').menu('New').point() 82 context.app.menu('File').menu('New').menuItem("Contact").click() 83 context.execute_steps(u"Then Contact editor window is opened") 84 85 86def get_element_by_name(contact_editor, name, section=None): 87 """Get a field object by name in section (if specified)""" 88 element = None 89 if section: 90 panel = contact_editor.findChild( 91 GenericPredicate(roleName='panel', name=section), retry=False, requireResult=False) 92 if not panel: 93 # Other section is not a panel, but a toggle button 94 panel = contact_editor.child(roleName='toggle button', name=section) 95 element = panel.childLabelled(name) 96 else: 97 label = contact_editor.findChild( 98 GenericPredicate(label=name), retry=False, requireResult=False) 99 if not label: 100 # In case childLabelled is missing 101 # Find a filler with this name and get its text child 102 element = contact_editor.child( 103 roleName='filler', name=name).child(roleName='text') 104 else: 105 element = contact_editor.childLabelled(name) 106 if element: 107 return element 108 else: 109 raise RuntimeError("Cannot find element named '%s' in section '%s'" % ( 110 name, section)) 111 112 113@step(u'Set "{field_name}" in contact editor to "{field_value}"') 114def set_field_to_value(context, field_name, field_value): 115 element = get_element_by_name(context.app.contact_editor, field_name) 116 if element.roleName == "text": 117 element.text = field_value 118 elif element.roleName == "combo box": 119 if element.combovalue != field_value: 120 element.combovalue = field_value 121 122 123@step(u'Save the contact') 124def save_contact(context): 125 context.app.contact_editor.button('Save').click() 126 assert wait_until(lambda x: not x.showing, context.app.contact_editor),\ 127 "Contact Editor was not hidden" 128 assert wait_until(lambda x: x.dead, context.app.contact_editor),\ 129 "Contact Editor was not closed" 130 context.app.contact_editor = None 131 132 133@step(u'Refresh addressbook') 134def refresh_addressbook(context): 135 #Clear the search 136 icons = context.app.search_bar.findChildren(lambda x: x.roleName == 'icon') 137 if icons != []: 138 icons[-1].click() 139 else: 140 for attempts in range(0, 10): 141 try: 142 context.app.search_bar.text = '' 143 break 144 except (GLib.GError, AttributeError): 145 sleep(0.1) 146 continue 147 context.app.search_bar.grab_focus() 148 keyCombo('<Enter>') 149 context.execute_steps(u"* Wait for email to synchronize") 150 151 152@step(u'Select "{contact_name}" contact list') 153@step(u'Select "{contact_name}" contact') 154def select_contact_with_name(context, contact_name): 155 # heading shows the name of currently selected contact 156 # We have to keep on pressing Tab to select the next contact 157 # Until we meet the first contact 158 # WARNING - what if we will have two identical contacts? 159 fail = False 160 selected_contact = None 161 162 # HACK 163 # To make the contact table appear 164 # we need to focus on search window 165 # and send Tabs to have the first contact focused 166 context.app.search_bar.grab_focus() 167 sleep(0.1) 168 # Switch to 'Any field contains' (not reachable in 3.6) 169 icons = context.app.search_bar.findChildren(GenericPredicate(roleName='icon')) 170 171 if icons != []: 172 icons[0].click() 173 wait_until(lambda x: x.findChildren( 174 GenericPredicate(roleName='check menu item', name='Any field contains')) != [], 175 context.app) 176 context.app.menuItem('Any field contains').click() 177 for attempts in range(0, 10): 178 try: 179 context.app.search_bar.text = contact_name 180 break 181 except (GLib.GError, AttributeError): 182 sleep(0.1) 183 continue 184 keyCombo("<Enter>") 185 context.app.search_bar.grab_focus() 186 187 keyCombo("<Tab>") 188 first_contact_name = context.app.child(roleName='heading').text 189 190 while True: 191 selected_contact = context.app.child(roleName='heading') 192 if selected_contact.text == contact_name: 193 fail = False 194 break 195 keyCombo("<Tab>") 196 # Wait until contact data is being rendered 197 sleep(1) 198 if first_contact_name == selected_contact.text: 199 fail = True 200 break 201 202 context.assertion.assertFalse( 203 fail, "Can't find contact named '%s'" % contact_name) 204 context.selected_contact_text = selected_contact.text 205 206 207@step(u'Open contact editor for selected contact') 208def open_contact_editor_for_selected_contact(context): 209 context.app.menu('File').click() 210 context.app.menu('File').menuItem('Open Contact').click() 211 context.execute_steps(u""" 212 Then Contact editor window with title "Contact Editor - %s" is opened 213 """ % context.selected_contact_text) 214 215 216@then(u'"{field}" property is set to "{expected}"') 217def property_in_contact_window_is_set_to(context, field, expected): 218 element = get_element_by_name(context.app.contact_editor, field) 219 actual = None 220 if element.roleName == "text": 221 actual = element.text 222 elif element.roleName == "combo box": 223 actual = element.combovalue 224 if actual == '': 225 actual = element.textentry('').text 226 assert unicode(actual) == expected, "Incorrect value" 227 228 229def get_combobox_textbox_object(contact_editor, section, scroll_to_bottom=True): 230 """Get a list of paired 'combobox-textbox' objects in contact editor""" 231 section_names = { 232 'Ims': 'Instant Messaging', 233 'Phones': 'Telephone', 234 'Emails': 'Email'} 235 section = section_names[section.capitalize()] 236 lbl = contact_editor.child(roleName='toggle button', name=section) 237 panel = lbl.findAncestor(GenericPredicate(roleName='filler')) 238 textboxes = panel.findChildren(GenericPredicate(roleName='text')) 239 240 # Scroll to the bottom of the page if needed 241 pagetab = panel.findAncestor(GenericPredicate(roleName='page tab')) 242 for scroll in pagetab.findChildren(lambda x: x.roleName == 'scroll bar'): 243 if scroll_to_bottom: 244 scroll.value = scroll.maxValue 245 else: 246 scroll.value = 0 247 248 # Expand section if button exists 249 button = panel.findChild( 250 GenericPredicate(roleName='push button', name=section), 251 retry=False, requireResult=False) 252 # Expand button if any of textboxes is not visible 253 if button and (False in [x.showing for x in textboxes]): 254 button.click() 255 256 comboboxes = panel.findChildren(GenericPredicate(roleName='combo box')) 257 258 # Rearrange comboboxes and textboxes according to their position 259 result = [] 260 for combo in comboboxes: 261 combo_row = combo.position[1] 262 matching_textboxes = [ 263 x for x in textboxes 264 if ((x.position[1] - combo_row) == 0) and (x.position[0] > combo.position[0])] 265 if (matching_textboxes != []): 266 correct_textbox = min(matching_textboxes, key=lambda x: x.position[0]) 267 result.append((combo, correct_textbox)) 268 269 comboboxes = [x[0] for x in result][::-1] 270 textboxes = [x[1] for x in result][::-1] 271 272 return (textboxes, comboboxes, button) 273 274 275@step(u'Set {section} in contact editor to') 276def set_contact_emails_to_value(context, section): 277 (textboxes, comboboxes, collapse_button) = get_combobox_textbox_object( 278 context.app.contact_editor, section) 279 280 # clear existing data 281 for textbox in textboxes: 282 textbox.text = "" 283 284 for index, row in enumerate(context.table.rows): 285 # Check that we have sufficient amount of textboxes 286 # If not - click plus buttons until we have enough 287 if index == len(textboxes): 288 textboxes[0].parent.child(roleName="push button").click() 289 (textboxes, comboboxes, collapse_button) = get_combobox_textbox_object( 290 context.app.contact_editor, section) 291 textboxes[index].text = row['Value'] 292 if comboboxes[index].combovalue != row['Field']: 293 comboboxes[index].combovalue = row['Field'] 294 295 296@then(u'{section} are set to') 297def emails_are_set_to(context, section): 298 (textboxes, comboboxes, collapse_button) = get_combobox_textbox_object( 299 context.app.contact_editor, section, section == 'IMs') 300 301 actual = [] 302 for index, textbox in enumerate(textboxes): 303 combo_value = textbox.text 304 if combo_value.strip() != '': 305 type_value = comboboxes[index].combovalue 306 actual.append({'Field': unicode(type_value), 'Value': unicode(combo_value)}) 307 actual = sorted(actual) 308 309 expected = [] 310 for row in context.table: 311 expected.append({'Field': row['Field'], 'Value': row['Value']}) 312 expected = sorted(expected) 313 314 assert actual == expected, "Incorrect %s value:\nexpected:%s\n but was:%s" % ( 315 row['Field'], expected, actual) 316 317 318@step(u'Tick "Wants to receive HTML mail" checkbox') 319def tick_checkbox(context): 320 context.app.contact_editor.childNamed("Wants to receive HTML mail").click() 321 322 323@step(u'"Wants to receive HTML mail" checkbox is ticked') 324def checkbox_is_ticked(context): 325 check_state = context.app.childNamed("Wants to receive HTML mail").checked 326 assert check_state, "Incorrect checkbox state" 327 328 329@step(u'Switch to "{name}" tab in contact editor') 330def switch_to_tab(context, name): 331 context.app.contact_editor.tab(name).click() 332 333 334@step(u'Set the following properties in contact editor') 335def set_properties(context): 336 for row in context.table.rows: 337 context.execute_steps(u""" 338 * Set "%s" in contact editor to "%s" 339 """ % (row['Field'], row['Value'])) 340 341 342@step(u'The following properties in contact editor are set') 343def verify_properties(context): 344 for row in context.table.rows: 345 context.execute_steps(u""" 346 Then "%s" property is set to "%s" 347 """ % (row['Field'], row['Value'])) 348 349 350@step(u'Set the following properties in "{section}" section of contact editor') 351def set_properties_in_section(context, section): 352 for row in context.table.rows: 353 context.execute_steps(u""" 354 * Set "%s" in "%s" section of contact editor to "%s" 355 """ % (row['Field'], section, row['Value'])) 356 357 358@step(u'The following properties in "{section}" section of contact editor are set') 359def verify_properties_in_section(context, section): 360 for row in context.table.rows: 361 context.execute_steps(u""" 362 Then "%s" property in "%s" section is set to "%s" 363 """ % (row['Field'], section, row['Value'])) 364 365 366@step(u'Set the following note for the contact') 367def set_note_for_contact(context): 368 context.app.contact_editor.child( 369 roleName='page tab', name='Notes').textentry('').text = context.text 370 371 372@then(u'The following note is set for the contact') 373def verify_note_set_for_contact(context): 374 actual = context.app.contact_editor.child( 375 roleName='page tab', name='Notes').textentry('').text 376 expected = context.text 377 assert actual == expected,\ 378 "Incorrect note value:\nexpected:%s\n but was:%s" % (expected, actual) 379 380 381@step(u'Set "{field_name}" in "{section}" section of contact editor to "{field_value}"') 382def set_field_in_section_to_value(context, field_name, section, field_value): 383 element = get_element_by_name( 384 context.app.contact_editor, field_name, section=section) 385 if element.roleName == "text": 386 element.text = field_value 387 elif element.roleName == "combo box": 388 element.combovalue = field_value 389