~bzr-pqm/bzr/bzr.dev

2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
1
# Copyright (C) 2007 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
16
3921.2.9 by Aaron Bentley
Update test to pass under LANG=C
17
import urllib
18
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
19
from bzrlib import (
3042.1.2 by Lukáš Lalinský
Don't use None as address in TestXDGEmail and add a test to check if it raises NoMailAddressSpecified with None.
20
    errors,
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
21
    mail_client,
22
    tests,
23
    urlutils,
3921.2.9 by Aaron Bentley
Update test to pass under LANG=C
24
    osutils,
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
25
    )
26
2790.2.1 by Keir Mierle
Add Mutt as a supported client email program. Also rearranges various listings
27
class TestMutt(tests.TestCase):
28
29
    def test_commandline(self):
30
        mutt = mail_client.Mutt(None)
4416.1.1 by Edwin Grubbs
Added ability to pass the body into mutt.
31
        commandline = mutt._get_compose_commandline(
32
            None, None, 'file%', body="hello")
33
        # The temporary filename is randomly generated, so it is not matched.
34
        self.assertEqual(['-a', 'file%', '-i'], commandline[:-1])
2790.2.1 by Keir Mierle
Add Mutt as a supported client email program. Also rearranges various listings
35
        commandline = mutt._get_compose_commandline('jrandom@example.org',
36
                                                     'Hi there!', None)
4292.1.1 by Jelmer Vernooij
Mutt requires -- before the recipient address if -a is being used.
37
        self.assertEqual(['-s', 'Hi there!', '--', 'jrandom@example.org'],
2790.2.1 by Keir Mierle
Add Mutt as a supported client email program. Also rearranges various listings
38
                         commandline)
39
3234.2.6 by Alexander Belchenko
because every mail client has different rules to compose command line we should encode arguments to 8 bit string only when needed.
40
    def test_commandline_is_8bit(self):
41
        mutt = mail_client.Mutt(None)
42
        cmdline = mutt._get_compose_commandline(u'jrandom@example.org',
43
            u'Hi there!', u'file%')
44
        self.assertEqual(
4292.1.1 by Jelmer Vernooij
Mutt requires -- before the recipient address if -a is being used.
45
            ['-s', 'Hi there!', '-a', 'file%', '--', 'jrandom@example.org'],
3234.2.6 by Alexander Belchenko
because every mail client has different rules to compose command line we should encode arguments to 8 bit string only when needed.
46
            cmdline)
47
        for item in cmdline:
48
            self.assertFalse(isinstance(item, unicode),
49
                'Command-line item %r is unicode!' % item)
50
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
51
52
class TestThunderbird(tests.TestCase):
53
54
    def test_commandline(self):
2681.1.9 by Aaron Bentley
Add support for mail-from-editor
55
        tbird = mail_client.Thunderbird(None)
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
56
        commandline = tbird._get_compose_commandline(None, None,
57
                                                     'file%')
58
        self.assertEqual(['-compose', "attachment='%s'" %
59
                          urlutils.local_path_to_url('file%')], commandline)
60
        commandline = tbird._get_compose_commandline('jrandom@example.org',
4098.5.1 by Aaron Bentley
Allow specifying body for t-bird, evo and xdg
61
                                                     'Hi there!', None,
62
                                                     "bo'dy")
63
        self.assertEqual(['-compose', "body=bo%27dy,"
64
                                      "subject='Hi there!',"
65
                                      "to='jrandom@example.org'"],
66
                                      commandline)
2681.2.1 by Lukáš Lalinsky
Support for Evolution mail client.
67
3234.2.3 by Alexander Belchenko
mail_client.py: provide new private method ExternalMailClient._get_compose_8bit_commandline to make bug #139318 testable (as Aaron requested).
68
    def test_commandline_is_8bit(self):
69
        # test for bug #139318
70
        tbird = mail_client.Thunderbird(None)
3234.2.6 by Alexander Belchenko
because every mail client has different rules to compose command line we should encode arguments to 8 bit string only when needed.
71
        cmdline = tbird._get_compose_commandline(u'jrandom@example.org',
72
            u'Hi there!', u'file%')
73
        self.assertEqual(['-compose',
3234.2.3 by Alexander Belchenko
mail_client.py: provide new private method ExternalMailClient._get_compose_8bit_commandline to make bug #139318 testable (as Aaron requested).
74
            ("attachment='%s'," % urlutils.local_path_to_url('file%')) +
75
            "subject='Hi there!',to='jrandom@example.org'",
76
            ], cmdline)
77
        for item in cmdline:
78
            self.assertFalse(isinstance(item, unicode),
79
                'Command-line item %r is unicode!' % item)
80
2681.2.1 by Lukáš Lalinsky
Support for Evolution mail client.
81
3324.4.1 by Xavier Maillard
Replace mail-mode call with compose-mail from GNU Emacs.
82
class TestEmacsMail(tests.TestCase):
3302.6.1 by Xavier Maillard
Add mail-mode GNU Emacs mail package as a mail_client option.
83
84
    def test_commandline(self):
3324.4.1 by Xavier Maillard
Replace mail-mode call with compose-mail from GNU Emacs.
85
        eclient = mail_client.EmacsMail(None)
86
87
        commandline = eclient._get_compose_commandline(None, 'Hi there!', None)
88
        self.assertEqual(['--eval', '(compose-mail nil "Hi there!")'],
89
                         commandline)
3302.6.1 by Xavier Maillard
Add mail-mode GNU Emacs mail package as a mail_client option.
90
91
        commandline = eclient._get_compose_commandline('jrandom@example.org',
3324.4.1 by Xavier Maillard
Replace mail-mode call with compose-mail from GNU Emacs.
92
                                                       'Hi there!', None)
93
        self.assertEqual(['--eval',
94
                          '(compose-mail "jrandom@example.org" "Hi there!")'],
95
                         commandline)
96
97
        # We won't be able to know the temporary file name at this stage
98
        # so we can't raise an assertion with assertEqual
99
        cmdline = eclient._get_compose_commandline(None, None, 'file%')
4659.2.1 by Vincent Ladeuil
Cleanup emacs-bzr-send-XXXXXX.el leaks in /tmp during selftest.
100
        if eclient.elisp_tmp_file is not None:
101
            self.addCleanup(osutils.delete_any, eclient.elisp_tmp_file)
3324.4.1 by Xavier Maillard
Replace mail-mode call with compose-mail from GNU Emacs.
102
        commandline = ' '.join(cmdline)
103
        self.assertContainsRe(commandline, '--eval')
104
        self.assertContainsRe(commandline, '(compose-mail nil nil)')
105
        self.assertContainsRe(commandline, '(load .*)')
106
        self.assertContainsRe(commandline, '(bzr-add-mime-att \"file%\")')
3302.6.1 by Xavier Maillard
Add mail-mode GNU Emacs mail package as a mail_client option.
107
108
    def test_commandline_is_8bit(self):
3324.4.1 by Xavier Maillard
Replace mail-mode call with compose-mail from GNU Emacs.
109
        eclient = mail_client.EmacsMail(None)
3302.6.1 by Xavier Maillard
Add mail-mode GNU Emacs mail package as a mail_client option.
110
        commandline = eclient._get_compose_commandline(u'jrandom@example.org',
111
            u'Hi there!', u'file%')
4659.2.1 by Vincent Ladeuil
Cleanup emacs-bzr-send-XXXXXX.el leaks in /tmp during selftest.
112
        if eclient.elisp_tmp_file is not None:
113
            self.addCleanup(osutils.delete_any, eclient.elisp_tmp_file)
3302.6.1 by Xavier Maillard
Add mail-mode GNU Emacs mail package as a mail_client option.
114
        for item in commandline:
115
            self.assertFalse(isinstance(item, unicode),
116
                'Command-line item %r is unicode!' % item)
117
118
2681.1.23 by Aaron Bentley
Add support for xdg-email
119
class TestXDGEmail(tests.TestCase):
120
121
    def test_commandline(self):
122
        xdg_email = mail_client.XDGEmail(None)
3042.1.2 by Lukáš Lalinský
Don't use None as address in TestXDGEmail and add a test to check if it raises NoMailAddressSpecified with None.
123
        self.assertRaises(errors.NoMailAddressSpecified,
124
                          xdg_email._get_compose_commandline,
125
                          None, None, 'file%')
126
        commandline = xdg_email._get_compose_commandline(
127
            'jrandom@example.org', None, 'file%')
128
        self.assertEqual(['jrandom@example.org', '--attach', 'file%'],
129
                         commandline)
2681.1.23 by Aaron Bentley
Add support for xdg-email
130
        commandline = xdg_email._get_compose_commandline(
4098.5.1 by Aaron Bentley
Allow specifying body for t-bird, evo and xdg
131
            'jrandom@example.org', 'Hi there!', None, "bo'dy")
132
        self.assertEqual(['jrandom@example.org', '--subject', 'Hi there!',
133
                          '--body', "bo'dy"], commandline)
2681.1.23 by Aaron Bentley
Add support for xdg-email
134
3234.2.6 by Alexander Belchenko
because every mail client has different rules to compose command line we should encode arguments to 8 bit string only when needed.
135
    def test_commandline_is_8bit(self):
136
        xdg_email = mail_client.XDGEmail(None)
137
        cmdline = xdg_email._get_compose_commandline(u'jrandom@example.org',
138
            u'Hi there!', u'file%')
139
        self.assertEqual(
140
            ['jrandom@example.org', '--subject', 'Hi there!',
141
             '--attach', 'file%'],
142
            cmdline)
143
        for item in cmdline:
144
            self.assertFalse(isinstance(item, unicode),
145
                'Command-line item %r is unicode!' % item)
146
2681.1.23 by Aaron Bentley
Add support for xdg-email
147
2681.2.1 by Lukáš Lalinsky
Support for Evolution mail client.
148
class TestEvolution(tests.TestCase):
149
150
    def test_commandline(self):
151
        evo = mail_client.Evolution(None)
152
        commandline = evo._get_compose_commandline(None, None, 'file%')
2681.1.18 by Aaron Bentley
Refactor to increase code sharing, allow multiple command names for tbird
153
        self.assertEqual(['mailto:?attach=file%25'], commandline)
2681.2.1 by Lukáš Lalinsky
Support for Evolution mail client.
154
        commandline = evo._get_compose_commandline('jrandom@example.org',
4098.5.1 by Aaron Bentley
Allow specifying body for t-bird, evo and xdg
155
                                                   'Hi there!', None, 'bo&dy')
156
        self.assertEqual(['mailto:jrandom@example.org?body=bo%26dy&'
157
                          'subject=Hi%20there%21'], commandline)
2681.1.21 by Aaron Bentley
Refactor prompt generation to make it testable, test it with unicode
158
3234.2.6 by Alexander Belchenko
because every mail client has different rules to compose command line we should encode arguments to 8 bit string only when needed.
159
    def test_commandline_is_8bit(self):
160
        evo = mail_client.Evolution(None)
161
        cmdline = evo._get_compose_commandline(u'jrandom@example.org',
162
            u'Hi there!', u'file%')
163
        self.assertEqual(
164
            ['mailto:jrandom@example.org?attach=file%25&subject=Hi%20there%21'
165
            ],
166
            cmdline)
167
        for item in cmdline:
168
            self.assertFalse(isinstance(item, unicode),
169
                'Command-line item %r is unicode!' % item)
170
2681.1.21 by Aaron Bentley
Refactor prompt generation to make it testable, test it with unicode
171
2681.5.2 by ghigo
update docs and tests
172
class TestKMail(tests.TestCase):
173
174
    def test_commandline(self):
2681.1.35 by Aaron Bentley
Rename test var evo => kmail
175
        kmail = mail_client.KMail(None)
176
        commandline = kmail._get_compose_commandline(None, None, 'file%')
2681.5.2 by ghigo
update docs and tests
177
        self.assertEqual(['--attach', 'file%'], commandline)
2681.1.35 by Aaron Bentley
Rename test var evo => kmail
178
        commandline = kmail._get_compose_commandline('jrandom@example.org',
179
                                                     'Hi there!', None)
2681.5.2 by ghigo
update docs and tests
180
        self.assertEqual(['-s', 'Hi there!', 'jrandom@example.org'],
181
                         commandline)
182
3234.2.6 by Alexander Belchenko
because every mail client has different rules to compose command line we should encode arguments to 8 bit string only when needed.
183
    def test_commandline_is_8bit(self):
184
        kmail = mail_client.KMail(None)
185
        cmdline = kmail._get_compose_commandline(u'jrandom@example.org',
186
            u'Hi there!', u'file%')
187
        self.assertEqual(
188
            ['-s', 'Hi there!', '--attach', 'file%', 'jrandom@example.org'],
189
            cmdline)
190
        for item in cmdline:
191
            self.assertFalse(isinstance(item, unicode),
192
                'Command-line item %r is unicode!' % item)
193
2681.5.2 by ghigo
update docs and tests
194
3921.2.3 by Gavin Panella
Tests for the Claws mail client.
195
class TestClaws(tests.TestCase):
196
197
    def test_commandline(self):
198
        claws = mail_client.Claws(None)
3921.2.4 by Gavin Panella
Use the --attach option, and don't specify a From: header.
199
        commandline = claws._get_compose_commandline(
4401.2.2 by Barry Warsaw
Much simpler approach to support From: in Claws, after discussion with
200
            'jrandom@example.org', None, 'file%')
3921.2.4 by Gavin Panella
Use the --attach option, and don't specify a From: header.
201
        self.assertEqual(
4401.2.2 by Barry Warsaw
Much simpler approach to support From: in Claws, after discussion with
202
            ['--compose', 'mailto:jrandom@example.org?', '--attach', 'file%'],
203
            commandline)
3921.2.4 by Gavin Panella
Use the --attach option, and don't specify a From: header.
204
        commandline = claws._get_compose_commandline(
205
            'jrandom@example.org', 'Hi there!', None)
206
        self.assertEqual(
207
            ['--compose',
208
             'mailto:jrandom@example.org?subject=Hi%20there%21'],
3921.2.3 by Gavin Panella
Tests for the Claws mail client.
209
            commandline)
210
211
    def test_commandline_is_8bit(self):
212
        claws = mail_client.Claws(None)
213
        cmdline = claws._get_compose_commandline(
3921.2.7 by Gavin Panella
Use a non-ascii character in test_commandline_is_8bit.
214
            u'jrandom@example.org', u'\xb5cosm of fun!', u'file%')
3921.2.9 by Aaron Bentley
Update test to pass under LANG=C
215
        subject_string = urllib.quote(
216
            u'\xb5cosm of fun!'.encode(osutils.get_user_encoding(), 'replace'))
3921.2.3 by Gavin Panella
Tests for the Claws mail client.
217
        self.assertEqual(
218
            ['--compose',
3921.2.9 by Aaron Bentley
Update test to pass under LANG=C
219
             'mailto:jrandom@example.org?subject=%s' % subject_string,
3921.2.4 by Gavin Panella
Use the --attach option, and don't specify a From: header.
220
             '--attach',
221
             'file%'],
3921.2.3 by Gavin Panella
Tests for the Claws mail client.
222
            cmdline)
223
        for item in cmdline:
224
            self.assertFalse(isinstance(item, unicode),
225
                'Command-line item %r is unicode!' % item)
226
4401.2.2 by Barry Warsaw
Much simpler approach to support From: in Claws, after discussion with
227
    def test_with_from(self):
228
        claws = mail_client.Claws(None)
229
        cmdline = claws._get_compose_commandline(
230
            u'jrandom@example.org', None, None, None, u'qrandom@example.com')
231
        self.assertEqual(
232
            ['--compose',
233
             'mailto:jrandom@example.org?from=qrandom%40example.com'],
234
            cmdline)
235
236
    def test_to_required(self):
237
        claws = mail_client.Claws(None)
238
        self.assertRaises(errors.NoMailAddressSpecified,
239
                          claws._get_compose_commandline,
240
                          None, None, 'file%')
241
4401.2.3 by Barry Warsaw
Add test for including body text for Claws.
242
    def test_with_body(self):
243
        claws = mail_client.Claws(None)
244
        cmdline = claws._get_compose_commandline(
245
            u'jrandom@example.org', None, None, 'This is some body text')
246
        self.assertEqual(
247
            ['--compose',
248
             'mailto:jrandom@example.org?body=This%20is%20some%20body%20text'],
249
            cmdline)
250
3921.2.3 by Gavin Panella
Tests for the Claws mail client.
251
2681.1.21 by Aaron Bentley
Refactor prompt generation to make it testable, test it with unicode
252
class TestEditor(tests.TestCase):
253
254
    def test_get_merge_prompt_unicode(self):
255
        """Prompt, to and subject are unicode, the attachement is binary"""
256
        editor = mail_client.Editor(None)
257
        prompt = editor._get_merge_prompt(u'foo\u1234',
258
                                        u'bar\u1234',
259
                                        u'baz\u1234',
260
                                        u'qux\u1234'.encode('utf-8'))
261
        self.assertContainsRe(prompt, u'foo\u1234(.|\n)*bar\u1234'
262
                              u'(.|\n)*baz\u1234(.|\n)*qux\u1234')
263
        editor._get_merge_prompt(u'foo', u'bar', u'baz', 'qux\xff')
3270.3.2 by James Westby
Add a smoke test to check that the DefaultMail client passes through
264
265
266
class DummyMailClient(object):
267
268
    def compose_merge_request(self, *args, **kwargs):
269
        self.args = args
270
        self.kwargs = kwargs
271
272
273
class DefaultMailDummyClient(mail_client.DefaultMail):
274
275
    def __init__(self):
276
        self.client = DummyMailClient()
277
278
    def _mail_client(self):
279
        return self.client
280
281
282
class TestDefaultMail(tests.TestCase):
283
284
    def test_compose_merge_request(self):
285
        client = DefaultMailDummyClient()
286
        to = "a@b.com"
287
        subject = "[MERGE]"
288
        directive = "directive",
289
        basename = "merge"
290
        client.compose_merge_request(to, subject, directive,
291
                                     basename=basename)
292
        dummy_client = client.client
293
        self.assertEqual(dummy_client.args, (to, subject, directive))
4098.5.10 by Aaron Bentley
Fix test case.
294
        self.assertEqual(dummy_client.kwargs,
295
                         {"basename": basename, 'body': None})