2 Dogtail::Application.new('Thunderbird')
6 thunderbird_app.child(roleName: 'frame', recursive: false)
10 thunderbird_app.child('Account Setup - Mozilla Thunderbird', roleName: 'frame')
14 folder_view = thunderbird_main.child($config['Thunderbird']['address'],
15 roleName: 'tree item')
16 # Dogtail mangles the regexps we pass it, which we have to workaround,
17 # hence the suboptimal regexp below (the simpler /^Inbox( .*)?$/ would
18 # not work). For details, see
19 # https://gitlab.tails.boum.org/tails/tails/-/issues/19928#note_215864
20 folder_view.child(/^Inbox|Inbox (.*)$/, roleName: 'tree item')
23 When /^I start Thunderbird$/ do
24 workaround_pref_lines = [
25 # When we generate a random subject line it may contain one of the
26 # keywords that will make Thunderbird show an extra prompt when trying
27 # to send an email. Let's disable this feature.
28 'pref("mail.compose.attachment_reminder", false);',
30 workaround_pref_lines.each do |line|
31 $vm.file_append('/etc/thunderbird/pref/thunderbird.js', "#{line}\n")
36 When /^I have not configured an email account yet$/ do
37 conf_path = "/home/#{LIVE_USER}/.thunderbird/profile.default/prefs.js"
38 if $vm.file_exist?(conf_path)
39 thunderbird_prefs = $vm.file_content(conf_path).chomp
40 assert(!thunderbird_prefs.include?('mail.accountmanager.accounts'))
44 Then /^I am prompted to setup an email account$/ do
48 Then /^I cancel setting up an email account$/ do
49 thunderbird_wizard.button('Cancel').press
50 thunderbird_wizard.button('Exit Setup').press
53 Then /^I open Thunderbird's Add-ons Manager$/ do
54 # Make sure AppMenu is available, even if it seems hard to click its
55 # "Add-ons" menu + menu item...
56 thunderbird_main.button('AppMenu')
57 # ... then use keyboard shortcuts, with a little delay between both
58 # so that the menu has a chance to pop up:
59 @screen.press('alt', 't')
62 @thunderbird_addons = thunderbird_app.child(
63 'Add-ons Manager', roleName: 'document web'
67 Then /^I open the Extensions tab$/ do
68 # Sometimes the Add-on manager loads its GUI slowly, so that the
69 # tabs move around, creating a race where we might find the
70 # Extensions tab at one place but it has moved to another when we
71 # finally do the click.
74 .child('Extensions', roleName: 'page tab', retry: false).press
75 # Verify that we clicked correctly:
77 .child('Manage Your Extensions', roleName: 'heading', retry: false)
81 Then /^I see that no add-ons are enabled in Thunderbird$/ do
82 assert(!@thunderbird_addons.child?('Enabled', roleName: 'heading'))
85 When /^I enter my email credentials into the autoconfiguration wizard$/ do
86 address = $config['Thunderbird']['address']
87 name = address.split('@').first
88 hostname = address.split('@').last
89 password = $config['Thunderbird']['password']
91 # These tricks are needed because on Jenkins, the hostname of the test email
92 # server resolves to a RFC 1918 address (sysadmin#18044), which tor would not allow
93 # connecting to, and the firewall leak checker would make a fuss
95 allow_connecting_to_possibly_rfc1918_host(hostname)
97 thunderbird_wizard.child('Your full name', roleName: 'entry').grabFocus
99 thunderbird_wizard.child('Email address',
100 roleName: 'entry').grabFocus
101 @screen.paste(address)
102 thunderbird_wizard.child('Password', roleName: 'password text').grabFocus
103 @screen.paste(password)
104 thunderbird_wizard.button('Continue').press
105 # This button is shown if and only if a configuration has been found
106 try_for(120) { thunderbird_wizard.button('Done') }
109 Then /^the autoconfiguration wizard's choice for the (incoming|outgoing) server is secure (.+)$/ do |type, protocol|
110 type = type.capitalize
111 section = thunderbird_wizard.child(type, roleName: 'heading').parent
112 subsections = section.children(roleName: 'section')
113 assert(subsections.any? { |s| s.text == protocol })
114 assert(subsections.any? { |s| s.text == 'SSL/TLS' || s.text == 'STARTTLS' })
117 def wait_for_thunderbird_progress_bar_to_vanish
119 thunderbird_main.child(roleName: 'status bar', retry: false)
120 .child(roleName: 'progress bar', retry: false)
127 When /^I fetch my email$/ do
128 thunderbird_main.button('Get Messages').press
129 wait_for_thunderbird_progress_bar_to_vanish
132 When /^I accept the (?:autoconfiguration wizard's|manual) configuration$/ do
133 thunderbird_wizard.button('Done').press
135 # The password check can fail due to bad Tor circuits.
138 # Spam the button, even if it is disabled (while it is still
139 # testing the password).
140 thunderbird_wizard.button('Finish').press
148 # The account isn't fully created before we fetch our mail. For
149 # instance, if we'd try to send an email before this, yet another
150 # wizard will start, indicating (incorrectly) that we do not have an
151 # account set up yet. Normally we disable automatic fetching of email,
152 # and thus here we would immediately call "step 'I fetch my email'",
153 # but Thunderbird 68 will fetch email immediately for a newly created
154 # account despite our prefs (#17222), so here we first wait for this
155 # operation to complete. But that initial fetch is incomplete,
156 # e.g. only the INBOX folder is listed, so after that we fetch
157 # email manually: otherwise Thunderbird does not know about the "Sent"
158 # directory yet and sending email will fail when copying messages there.
159 wait_for_thunderbird_progress_bar_to_vanish
160 step 'I fetch my email'
163 When /^I select the autoconfiguration wizard's IMAP choice$/ do
164 thunderbird_wizard.child('IMAP (remote folders)', roleName: 'radio button').select
167 When /^I send an email to myself$/ do
168 thunderbird_main.button('New Message').press
169 compose_window = thunderbird_app.child('Write: (no subject) - Thunderbird')
170 compose_window.child('To', roleName: 'entry').grabFocus
171 @screen.paste($config['Thunderbird']['address'])
172 # The randomness of the subject will make it easier for us to later
173 # find *exactly* this email. This makes it safe to run several tests
175 @subject = "Automated test suite: #{random_alnum_string(32)}"
176 compose_window.child('Subject', roleName: 'entry').grabFocus
177 @screen.paste(@subject)
178 compose_window = thunderbird_app.child("Write: #{@subject} - Thunderbird")
179 compose_window.child('Message body', roleName: 'document web').grabFocus
181 compose_window.child('Composition Toolbar', roleName: 'tool bar')
182 .button('Send').press
183 try_for(120, delay: 2) do
184 !compose_window.exist?
188 Then /^I can find the email I sent to myself in my inbox$/ do
189 recovery_proc = proc { step 'I fetch my email' }
190 retry_tor(recovery_proc) do
191 thunderbird_inbox.activate
192 thunderbird_main.child('Quick Filter',
193 roleName: 'toggle button')
195 thunderbird_main.child('Filter these messages <Ctrl+Shift+K>',
198 @screen.paste(@subject)
199 message = thunderbird_main.child(
200 "#{$config['Thunderbird']['address'].split('@').first},.*, #{@subject}, Unread",
201 roleName: 'tree item'
205 thunderbird_main.button('Delete').press
209 Then(/^the screen keyboard works in Thunderbird$/) do
210 step 'I start Thunderbird'
211 osk_key = 'ScreenKeyboardKeyX.png'
212 thunderbird_x = 'ThunderbirdX.png'
215 thunderbird_x = 'ThunderbirdXRTL.png'
217 thunderbird_x = 'ThunderbirdXChinese.png'
219 osk_key = 'ScreenKeyboardKeyPersian.png'
220 thunderbird_x = 'ThunderbirdXPersian.png'
222 # We have to click to activate the screen keyboard (#19101),
223 # but we cannot do it with Dogtail so we have to use a picture.
224 @screen.wait('ThunderbirdTextEntry.png', 20).click
225 @screen.wait('ScreenKeyboard.png', 20)
226 @screen.wait(osk_key, 20).click
227 @screen.wait(thunderbird_x, 20)