Skip to content

Commit b2fb67d

Browse files
committed
tests: update Thunderbird/Evolution interactions
Sync with app-linux-split-gpg, especially the following commits: a652de5 test: avoid false negative from sending status dialog 4bcba03 tests: update for Thunderbird 102 15fda8c tests: disable end-of-year message, and similar popups b9c13d0 tests: fix clicking top buttons in evolution d65f098 tests: use distribution's dogtail package 00394da tests: try harder to avoid donation prompt during tests 3bf5616 tests: update for Thunderbird 115 7477c2d tests: switch from smtpd to aiosmtpd 17f96e0 tests: handle both Save and Save All dialogs e46af5f tests: adjust for Thunderbird 128
1 parent bd30173 commit b2fb67d

3 files changed

Lines changed: 152 additions & 56 deletions

File tree

splitgpg2tests/tests.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -360,18 +360,18 @@ def setUp(self):
360360

361361
# run as root to not deal with /var/mail permission issues
362362
self.frontend.run(
363-
'touch /var/mail/user; chown user:user /var/mail/user', user='root',
363+
'mkdir -p Mail/new Mail/cur Mail/tmp',
364364
wait=True)
365365

366366
# SMTP configuration
367367
self.smtp_server = self.frontend.run(
368-
'python3 /usr/share/split-gpg2-tests/test_smtpd.py',
369-
user='root', passio_popen=True)
368+
'aiosmtpd -n -c aiosmtpd.handlers.Mailbox /home/user/Mail',
369+
passio_popen=True)
370370

371371
# IMAP configuration
372372
self.imap_pw = "pass"
373373
self.frontend.run(
374-
'echo "mail_location=mbox:~/Mail:INBOX=/var/mail/%u" |\
374+
'echo "mail_location=maildir:~/Mail" |\
375375
sudo tee /etc/dovecot/conf.d/100-mail.conf', wait=True)
376376
self.frontend.run('sudo systemctl restart dovecot', wait=True)
377377
self.frontend.run( # set a user password because IMAP needs one for auth
@@ -422,6 +422,8 @@ def setup_tb_profile(self, setup_openpgp):
422422
user_pref("mail.identity.id1.useremail", "user@localhost");
423423
user_pref("mail.identity.id1.smtpServer", "smtp1");
424424
user_pref("mail.identity.id1.compose_html", false);
425+
user_pref("datareporting.policy.dataSubmissionEnabled", false); // avoid message popups
426+
user_pref("app.donation.eoy.version.viewed", 100); // avoid message popups
425427
"""
426428
imap_server = """
427429
user_pref("mail.server.server1.userName", "user");
@@ -542,11 +544,11 @@ def setUp(self):
542544

543545
# run as root to not deal with /var/mail permission issues
544546
self.frontend.run(
545-
'touch /var/mail/user; chown user /var/mail/user', user='root',
547+
'mkdir -p Mail/new Mail/cur Mail/tmp',
546548
wait=True)
547549
self.smtp_server = self.frontend.run(
548-
'python3 /usr/share/split-gpg2-tests/test_smtpd.py',
549-
user='root', passio_popen=True)
550+
'aiosmtpd -n -c aiosmtpd.handlers.Mailbox /home/user/Mail',
551+
passio_popen=True)
550552

551553
p = self.frontend.run(
552554
'PYTHONPATH=$HOME/dogtail python3 {} setup 2>&1'.format(

tests/test_evolution.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@ def open_accounts(app):
5858
def get_sibling_offset(node, offset):
5959
return node.parent.children[node.indexInParent+offset]
6060

61+
def get_sibling_button_maybe(button):
62+
try:
63+
# if there is a sibling button (without the name) that's the one that works
64+
button_sibling = button.parent.children[button.indexInParent + 1]
65+
if button_sibling.roleName == "push button":
66+
return button_sibling
67+
except KeyError:
68+
pass
69+
return button
70+
6171
def add_local_account(app):
6272
accounts_tab = None
6373
settings = None
@@ -78,16 +88,16 @@ def add_local_account(app):
7888
wizard.button('Next').doActionNamed('click')
7989
# Receiving Email tab
8090
time.sleep(2)
81-
wizard.menuItem('Local delivery').doActionNamed('click')
82-
wizard.childLabelled('Local Delivery File:').parent.button('(None)').\
91+
wizard.menuItem('Maildir-format mail directories').doActionNamed('click')
92+
wizard.childLabelled('Mail Directory:', showingOnly=True).parent.menuItem('Other…').\
8393
doActionNamed('click')
84-
file_chooser = app.child('Choose a local delivery file',
94+
file_chooser = app.child('Choose a Maildir mail directory',
8595
roleName='file chooser')
8696
file_chooser.child('File System Root').doActionNamed('click')
87-
file_chooser.child('var').doActionNamed('activate')
88-
file_chooser.child('spool').doActionNamed('activate')
89-
file_chooser.child('mail').doActionNamed('activate')
97+
file_chooser.child('home').doActionNamed('activate')
9098
file_chooser.child('user').doActionNamed('activate')
99+
file_chooser.child('Mail').doActionNamed('activate')
100+
file_chooser.button('Open').doActionNamed('click')
91101
time.sleep(1)
92102
wizard.button('Next').doActionNamed('click')
93103
# Receiving Options tab
@@ -138,7 +148,9 @@ def attach(app, compose_window, path):
138148
file_chooser.button('Attach').doActionNamed('click')
139149

140150
def send_email(app, sign=False, encrypt=False, inline=False, attachment=None):
141-
app.button('New').doActionNamed('click')
151+
new_button = app.button('New')
152+
new_button = get_sibling_button_maybe(new_button)
153+
new_button.doActionNamed('click')
142154
new_message = app.child('Compose Message', roleName='frame')
143155
new_message.textentry('To:').text = 'user@localhost,'
144156
new_message.childLabelled('Subject:').text = subject
@@ -160,8 +172,10 @@ def send_email(app, sign=False, encrypt=False, inline=False, attachment=None):
160172
new_message.button('Send').doActionNamed('click')
161173

162174
def receive_message(app, signed=False, encrypted=False, attachment=None):
163-
app.button('Send / Receive').doActionNamed('click')
164-
app.child(name='Inbox.*', roleName='table cell').doActionNamed('edit')
175+
send_receive = app.button('Send / Receive')
176+
send_receive = get_sibling_button_maybe(send_receive)
177+
send_receive.doActionNamed('click')
178+
app.child(name='Inbox .*', roleName='table cell').doActionNamed('edit')
165179
messages = app.child('Messages', roleName='panel')
166180
messages.child(subject).grabFocus()
167181
message = app.child('Evolution Mail Display', roleName='document web')

tests/test_thunderbird.py

Lines changed: 120 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ def wrapper(*args, **kwargs):
119119
func(*args, **kwargs)
120120
break # if successful
121121
except Exception as e:
122-
if retry == max_tries:
122+
if retry == max_tries-1:
123123
raise e
124124
else:
125125
print("failed during setup in {}.\n Retrying".format(
@@ -151,20 +151,27 @@ def export_pub_key():
151151

152152
@retry_if_failed(max_tries=3)
153153
def enter_imap_passwd(tb):
154-
# check new mail so client can realize IMAP requires entering a password
155-
get_messages(tb)
154+
try:
155+
pass_prompt = tb.app.findChild(orPredicate(
156+
GenericPredicate(name='Enter your password for user', roleName='frame'),
157+
GenericPredicate(name='Enter your password for user', roleName='dialog')
158+
))
159+
except tree.SearchError:
160+
# check new mail so client can realize IMAP requires entering a password
161+
get_messages(tb)
156162
# password entry
157163
pass_prompt = tb.app.findChild(orPredicate(
158164
GenericPredicate(name='Enter your password for user', roleName='frame'),
159165
GenericPredicate(name='Enter your password for user', roleName='dialog')
160166
))
161167
pass_textbox = pass_prompt.findChild(GenericPredicate(roleName='password text'))
162-
pass_textbox.text = tb.imap_pw
168+
pass_textbox.typeText(tb.imap_pw)
163169
pass_prompt.childNamed("Use Password Manager to remember this password.")\
164170
.doActionNamed('check')
165171
pass_prompt.findChild(orPredicate(
166172
GenericPredicate(name='OK', roleName='push button'), # tb < 91
167-
GenericPredicate(name='Sign in', roleName='push button')) # tb >= 91
173+
GenericPredicate(name='Sign in', roleName='push button'), # tb >= 91, tb < 128
174+
GenericPredicate(name='OK', roleName='button')) # tb >= 128
168175
).doActionNamed('press')
169176

170177
def accept_qubes_attachments(tb):
@@ -237,8 +244,14 @@ def configure_openpgp_account(tb):
237244
accept_dialog = tb.app.findChild(orPredicate(
238245
GenericPredicate(name='.*(%s).*' % keyid),
239246
GenericPredicate(name='.[0-9A-F]*%s' % keyid),
240-
)).parent
241-
accept_dialog.childNamed('OK').doActionNamed('press')
247+
GenericPredicate(name='ID: 0x%s' % keyid),
248+
)).parent.parent
249+
try:
250+
accept_dialog.childNamed("Accepted.*").doActionNamed("select")
251+
except tree.SearchError:
252+
# old TB
253+
pass
254+
accept_dialog.childNamed('OK|Import').doActionNamed('press')
242255
tb.app.childNamed('Success! Keys imported.*').childNamed('OK').doActionNamed(
243256
'press')
244257
doubleClick(*key_manager.findChild(
@@ -256,16 +269,37 @@ def configure_openpgp_account(tb):
256269

257270

258271
def get_messages(tb):
259-
tb.app.child(name='user@localhost',
260-
roleName='table row').doActionNamed('activate')
261-
tb.app.button('Get Messages').doActionNamed('press')
262-
tb.app.menuItem('Get All New Messages').doActionNamed('click')
263-
tb.app.child(name='Inbox.*', roleName='table row').doActionNamed(
264-
'activate')
272+
try:
273+
# TB >= 115
274+
try:
275+
# TB >= 128
276+
tb.app.child('Get Messages', roleName='button').doActionNamed('press')
277+
except tree.SearchError:
278+
# TB < 128
279+
tb.app.button('Get Messages').doActionNamed('press')
280+
tb.app.child(name='Inbox.*', roleName='tree item').doActionNamed(
281+
'activate')
282+
except tree.SearchError:
283+
# TB < 115
284+
tb.app.child(name='user@localhost',
285+
roleName='table row').doActionNamed('activate')
286+
tb.app.button('Get Messages').doActionNamed('press')
287+
tb.app.menuItem('Get All New Messages').doActionNamed('click')
288+
tb.app.child(name='Inbox.*', roleName='table row').doActionNamed(
289+
'activate')
290+
265291

266292
def attach(tb, compose_window, path):
267-
compose_window.button('Attach').button('Attach').doActionNamed('press')
268-
compose_window.button('Attach').menuItem('File.*').doActionNamed('click')
293+
try:
294+
# TB >= 128
295+
compose_window.child('Attach', roleName='button').\
296+
doActionNamed('press')
297+
compose_window.child('Attach', roleName='button').\
298+
menuItem('File.*').doActionNamed('click')
299+
except tree.SearchError:
300+
# TB < 128
301+
compose_window.button('Attach').button('Attach').doActionNamed('press')
302+
compose_window.button('Attach').menuItem('File.*').doActionNamed('click')
269303
# for some reason on some thunderbird versions do not expose 'Attach File'
270304
# dialog through accessibility API, use xdotool instead
271305
subprocess.check_call(
@@ -293,18 +327,25 @@ def attach(tb, compose_window, path):
293327

294328
def send_email(tb, sign=False, encrypt=False, inline=False, attachment=None):
295329
config.searchCutoffCount = 20
296-
write = tb.app.button('Write')
330+
try:
331+
# TB >= 128
332+
write = tb.app.child(name='New Message', roleName='button')
333+
except tree.SearchError:
334+
try:
335+
write = tb.app.button('New Message')
336+
except tree.SearchError:
337+
write = tb.app.button('Write')
297338
config.searchCutoffCount = defaultCutoffCount
298339
write.doActionNamed('press')
299340
compose = tb.app.child(name='Write: .*', roleName='frame')
300341
to_entry = compose.findChild(TBEntry(name='To'))
301-
to_entry.text = 'user@localhost'
342+
to_entry.typeText('user@localhost')
302343
# lets thunderbird settle down on default values (after filling recipients)
303344
time.sleep(1)
304345
subject_entry = compose.findChild(
305346
orPredicate(GenericPredicate(name='Subject:', roleName='entry'),
306347
TBEntry(name='Subject')))
307-
subject_entry.text = subject
348+
subject_entry.typeText(subject)
308349
try:
309350
compose_document = compose.child(roleName='document web')
310351
try:
@@ -315,18 +356,29 @@ def send_email(tb, sign=False, encrypt=False, inline=False, attachment=None):
315356
except tree.SearchError:
316357
compose.child(
317358
roleName='document frame').text = 'This is test message'
318-
security = compose.findChild(
319-
GenericPredicate(name='Security', roleName='push button'))
359+
try:
360+
# TB >= 128
361+
security = compose.findChild(
362+
GenericPredicate(name='Security|OpenPGP', roleName='button'))
363+
except tree.SearchError:
364+
# TB < 128
365+
security = compose.findChild(
366+
GenericPredicate(name='Security|OpenPGP', roleName='push button'))
320367
security.doActionNamed('press')
321-
sign_button = security.childNamed('Digitally Sign This Message')
322-
encrypt_button = security.childNamed('Require Encryption')
368+
sign_button = security.childNamed('Digitally Sign.*')
369+
encrypt_button = security.childNamed('Require Encryption|Encrypt')
323370
if sign_button.checked != sign:
324371
sign_button.doActionNamed('click')
325372
if encrypt_button.checked != encrypt:
326373
encrypt_button.doActionNamed('click')
327374
if attachment:
328375
attach(tb, compose, attachment)
329-
compose.button('Send').doActionNamed('press')
376+
try:
377+
# TB >= 128
378+
compose.child('Send', roleName='button').doActionNamed('press')
379+
except tree.SearchError:
380+
# TB < 128
381+
compose.button('Send').doActionNamed('press')
330382
config.searchCutoffCount = 5
331383
try:
332384
if encrypt:
@@ -363,16 +415,36 @@ def send_email(tb, sign=False, encrypt=False, inline=False, attachment=None):
363415

364416
def receive_message(tb, signed=False, encrypted=False, attachment=None):
365417
get_messages(tb)
366-
config.searchCutoffCount = 5
418+
if encrypted:
419+
config.searchCutoffCount = 5
420+
try:
421+
# TB >= 128
422+
tb.app.child(name='user[^,]*, .*, \.\.\..*',
423+
roleName='table row').doActionNamed('clickAncestor')
424+
except tree.SearchError:
425+
try:
426+
# TB >= 115
427+
tb.app.child(name='user[^,]*, .*, \.\.\..*',
428+
roleName='tree item').doActionNamed('activate')
429+
except tree.SearchError:
430+
# TB < 115
431+
tb.app.child(name='Encrypted Message .*|.*\.\.\. .*',
432+
roleName='table row').doActionNamed('activate')
433+
finally:
434+
config.searchCutoffCount = defaultCutoffCount
367435
try:
368-
tb.app.child(name='Encrypted Message .*|.*\.\.\. .*',
369-
roleName='table row').doActionNamed('activate')
436+
# TB >= 128
437+
tb.app.child(name='.*{}.*'.format(subject),
438+
roleName='table row').doActionNamed('clickAncestor')
370439
except tree.SearchError:
371-
pass
372-
finally:
373-
config.searchCutoffCount = defaultCutoffCount
374-
tb.app.child(name='.*{}.*'.format(subject),
375-
roleName='table row').doActionNamed('activate')
440+
try:
441+
# TB >= 115
442+
tb.app.child(name='.*{}.*'.format(subject),
443+
roleName='tree item').doActionNamed('activate')
444+
except tree.SearchError:
445+
# TB < 115
446+
tb.app.child(name='.*{}.*'.format(subject),
447+
roleName='table row').doActionNamed('activate')
376448
# wait a little to TB decrypt/check the message
377449
time.sleep(2)
378450
# dogtail always add '$' at the end of regexp; and also "Escape all
@@ -399,11 +471,10 @@ def receive_message(tb, signed=False, encrypted=False, attachment=None):
399471
# msg_body = msg.text
400472
config.searchCutoffCount = 5
401473
try:
402-
if signed or encrypted:
403-
tb.app.button('OpenPGP.*').doActionNamed('press')
404-
# 'Message Security - OpenPGP' is an internal label,
405-
# nested 2 levels into the popup
406-
message_security = tb.app.child('Message Security - OpenPGP')
474+
tb.app.button('OpenPGP.*').doActionNamed('press')
475+
# 'Message Security - OpenPGP' is an internal label,
476+
# nested 2 levels into the popup
477+
message_security = tb.app.child('Message Security - OpenPGP')
407478
except tree.SearchError:
408479
# alternative way of opening 'message security'
409480
keyCombo('<Control><Alt>s')
@@ -430,8 +501,14 @@ def receive_message(tb, signed=False, encrypted=False, attachment=None):
430501
attachment_size = attachment_label.parent.children[
431502
attachment_label.indexInParent + 1 + offset]
432503
assert attachment_size.text[0] != '0'
433-
attachment_save = attachment_label.parent.children[
434-
attachment_label.indexInParent + 2 + offset].button('Save.*')
504+
attachment_save_parent = attachment_label.parent.children[
505+
attachment_label.indexInParent + 2 + offset]
506+
try:
507+
# TB >= 128
508+
attachment_save = attachment_save_parent.child('Save.*', roleName='button')
509+
except tree.SearchError:
510+
# TB < 128
511+
attachment_save = attachment_save_parent.button('Save.*')
435512
try:
436513
# try child button first
437514
attachment_save.children[1].doActionNamed('press')
@@ -444,11 +521,14 @@ def receive_message(tb, signed=False, encrypted=False, attachment=None):
444521
# for some reasons some Thunderbird versions do not expose 'Attach File'
445522
# dialog through accessibility API, use xdotool instead
446523
save_as = tb.app.findChild(
447-
GenericPredicate(name='Save All Attachments',
524+
GenericPredicate(name='Save All Attachments|Save Attachment',
448525
roleName='file chooser'))
449526
click(*save_as.childNamed('Home').position)
450527
click(*save_as.childNamed('Desktop').position)
451-
save_as.childNamed('Open').doActionNamed('click')
528+
if save_as.name == 'Save Attachment':
529+
save_as.childNamed('Save').doActionNamed('click')
530+
else:
531+
save_as.childNamed('Open').doActionNamed('click')
452532
# save_as = tb.app.dialog('Save .*Attachment.*')
453533
# places = save_as.child(roleName='table',
454534
# name='Places')

0 commit comments

Comments
 (0)