~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
17
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.
18
    errors,
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
19
    mail_client,
20
    tests,
21
    urlutils,
3921.2.9 by Aaron Bentley
Update test to pass under LANG=C
22
    osutils,
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
23
    )
24
2790.2.1 by Keir Mierle
Add Mutt as a supported client email program. Also rearranges various listings
25
class TestMutt(tests.TestCase):
26
27
    def test_commandline(self):
28
        mutt = mail_client.Mutt(None)
4416.1.1 by Edwin Grubbs
Added ability to pass the body into mutt.
29
        commandline = mutt._get_compose_commandline(
30
            None, None, 'file%', body="hello")
31
        # The temporary filename is randomly generated, so it is not matched.
32
        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
33
        commandline = mutt._get_compose_commandline('jrandom@example.org',
34
                                                     'Hi there!', None)
4292.1.1 by Jelmer Vernooij
Mutt requires -- before the recipient address if -a is being used.
35
        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
36
                         commandline)
37
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.
38
    def test_commandline_is_8bit(self):
39
        mutt = mail_client.Mutt(None)
40
        cmdline = mutt._get_compose_commandline(u'jrandom@example.org',
41
            u'Hi there!', u'file%')
42
        self.assertEqual(
4292.1.1 by Jelmer Vernooij
Mutt requires -- before the recipient address if -a is being used.
43
            ['-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.
44
            cmdline)
45
        for item in cmdline:
46
            self.assertFalse(isinstance(item, unicode),
47
                'Command-line item %r is unicode!' % item)
48
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
49
50
class TestThunderbird(tests.TestCase):
51
52
    def test_commandline(self):
2681.1.9 by Aaron Bentley
Add support for mail-from-editor
53
        tbird = mail_client.Thunderbird(None)
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
54
        commandline = tbird._get_compose_commandline(None, None,
55
                                                     'file%')
56
        self.assertEqual(['-compose', "attachment='%s'" %
57
                          urlutils.local_path_to_url('file%')], commandline)
58
        commandline = tbird._get_compose_commandline('jrandom@example.org',
4098.5.1 by Aaron Bentley
Allow specifying body for t-bird, evo and xdg
59
                                                     'Hi there!', None,
60
                                                     "bo'dy")
61
        self.assertEqual(['-compose', "body=bo%27dy,"
62
                                      "subject='Hi there!',"
63
                                      "to='jrandom@example.org'"],
64
                                      commandline)
2681.2.1 by Lukáš Lalinsky
Support for Evolution mail client.
65
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).
66
    def test_commandline_is_8bit(self):
67
        # test for bug #139318
68
        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.
69
        cmdline = tbird._get_compose_commandline(u'jrandom@example.org',
70
            u'Hi there!', u'file%')
71
        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).
72
            ("attachment='%s'," % urlutils.local_path_to_url('file%')) +
73
            "subject='Hi there!',to='jrandom@example.org'",
74
            ], cmdline)
75
        for item in cmdline:
76
            self.assertFalse(isinstance(item, unicode),
77
                'Command-line item %r is unicode!' % item)
78
2681.2.1 by Lukáš Lalinsky
Support for Evolution mail client.
79
3324.4.1 by Xavier Maillard
Replace mail-mode call with compose-mail from GNU Emacs.
80
class TestEmacsMail(tests.TestCase):
3302.6.1 by Xavier Maillard
Add mail-mode GNU Emacs mail package as a mail_client option.
81
82
    def test_commandline(self):
3324.4.1 by Xavier Maillard
Replace mail-mode call with compose-mail from GNU Emacs.
83
        eclient = mail_client.EmacsMail(None)
84
85
        commandline = eclient._get_compose_commandline(None, 'Hi there!', None)
86
        self.assertEqual(['--eval', '(compose-mail nil "Hi there!")'],
87
                         commandline)
3302.6.1 by Xavier Maillard
Add mail-mode GNU Emacs mail package as a mail_client option.
88
89
        commandline = eclient._get_compose_commandline('jrandom@example.org',
3324.4.1 by Xavier Maillard
Replace mail-mode call with compose-mail from GNU Emacs.
90
                                                       'Hi there!', None)
91
        self.assertEqual(['--eval',
92
                          '(compose-mail "jrandom@example.org" "Hi there!")'],
93
                         commandline)
94
95
        # We won't be able to know the temporary file name at this stage
96
        # so we can't raise an assertion with assertEqual
97
        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.
98
        if eclient.elisp_tmp_file is not None:
99
            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.
100
        commandline = ' '.join(cmdline)
101
        self.assertContainsRe(commandline, '--eval')
102
        self.assertContainsRe(commandline, '(compose-mail nil nil)')
103
        self.assertContainsRe(commandline, '(load .*)')
104
        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.
105
106
    def test_commandline_is_8bit(self):
3324.4.1 by Xavier Maillard
Replace mail-mode call with compose-mail from GNU Emacs.
107
        eclient = mail_client.EmacsMail(None)
3302.6.1 by Xavier Maillard
Add mail-mode GNU Emacs mail package as a mail_client option.
108
        commandline = eclient._get_compose_commandline(u'jrandom@example.org',
109
            u'Hi there!', u'file%')
4659.2.1 by Vincent Ladeuil
Cleanup emacs-bzr-send-XXXXXX.el leaks in /tmp during selftest.
110
        if eclient.elisp_tmp_file is not None:
111
            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.
112
        for item in commandline:
113
            self.assertFalse(isinstance(item, unicode),
114
                'Command-line item %r is unicode!' % item)
115
116
2681.1.23 by Aaron Bentley
Add support for xdg-email
117
class TestXDGEmail(tests.TestCase):
118
119
    def test_commandline(self):
120
        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.
121
        self.assertRaises(errors.NoMailAddressSpecified,
122
                          xdg_email._get_compose_commandline,
123
                          None, None, 'file%')
124
        commandline = xdg_email._get_compose_commandline(
125
            'jrandom@example.org', None, 'file%')
126
        self.assertEqual(['jrandom@example.org', '--attach', 'file%'],
127
                         commandline)
2681.1.23 by Aaron Bentley
Add support for xdg-email
128
        commandline = xdg_email._get_compose_commandline(
4098.5.1 by Aaron Bentley
Allow specifying body for t-bird, evo and xdg
129
            'jrandom@example.org', 'Hi there!', None, "bo'dy")
130
        self.assertEqual(['jrandom@example.org', '--subject', 'Hi there!',
131
                          '--body', "bo'dy"], commandline)
2681.1.23 by Aaron Bentley
Add support for xdg-email
132
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.
133
    def test_commandline_is_8bit(self):
134
        xdg_email = mail_client.XDGEmail(None)
135
        cmdline = xdg_email._get_compose_commandline(u'jrandom@example.org',
136
            u'Hi there!', u'file%')
137
        self.assertEqual(
138
            ['jrandom@example.org', '--subject', 'Hi there!',
139
             '--attach', 'file%'],
140
            cmdline)
141
        for item in cmdline:
142
            self.assertFalse(isinstance(item, unicode),
143
                'Command-line item %r is unicode!' % item)
144
2681.1.23 by Aaron Bentley
Add support for xdg-email
145
2681.2.1 by Lukáš Lalinsky
Support for Evolution mail client.
146
class TestEvolution(tests.TestCase):
147
148
    def test_commandline(self):
149
        evo = mail_client.Evolution(None)
150
        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
151
        self.assertEqual(['mailto:?attach=file%25'], commandline)
2681.2.1 by Lukáš Lalinsky
Support for Evolution mail client.
152
        commandline = evo._get_compose_commandline('jrandom@example.org',
4098.5.1 by Aaron Bentley
Allow specifying body for t-bird, evo and xdg
153
                                                   'Hi there!', None, 'bo&dy')
154
        self.assertEqual(['mailto:jrandom@example.org?body=bo%26dy&'
155
                          'subject=Hi%20there%21'], commandline)
2681.1.21 by Aaron Bentley
Refactor prompt generation to make it testable, test it with unicode
156
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.
157
    def test_commandline_is_8bit(self):
158
        evo = mail_client.Evolution(None)
159
        cmdline = evo._get_compose_commandline(u'jrandom@example.org',
160
            u'Hi there!', u'file%')
161
        self.assertEqual(
162
            ['mailto:jrandom@example.org?attach=file%25&subject=Hi%20there%21'
163
            ],
164
            cmdline)
165
        for item in cmdline:
166
            self.assertFalse(isinstance(item, unicode),
167
                'Command-line item %r is unicode!' % item)
168
2681.1.21 by Aaron Bentley
Refactor prompt generation to make it testable, test it with unicode
169
2681.5.2 by ghigo
update docs and tests
170
class TestKMail(tests.TestCase):
171
172
    def test_commandline(self):
2681.1.35 by Aaron Bentley
Rename test var evo => kmail
173
        kmail = mail_client.KMail(None)
174
        commandline = kmail._get_compose_commandline(None, None, 'file%')
2681.5.2 by ghigo
update docs and tests
175
        self.assertEqual(['--attach', 'file%'], commandline)
2681.1.35 by Aaron Bentley
Rename test var evo => kmail
176
        commandline = kmail._get_compose_commandline('jrandom@example.org',
177
                                                     'Hi there!', None)
2681.5.2 by ghigo
update docs and tests
178
        self.assertEqual(['-s', 'Hi there!', 'jrandom@example.org'],
179
                         commandline)
180
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.
181
    def test_commandline_is_8bit(self):
182
        kmail = mail_client.KMail(None)
183
        cmdline = kmail._get_compose_commandline(u'jrandom@example.org',
184
            u'Hi there!', u'file%')
185
        self.assertEqual(
186
            ['-s', 'Hi there!', '--attach', 'file%', 'jrandom@example.org'],
187
            cmdline)
188
        for item in cmdline:
189
            self.assertFalse(isinstance(item, unicode),
190
                'Command-line item %r is unicode!' % item)
191
2681.5.2 by ghigo
update docs and tests
192
3921.2.3 by Gavin Panella
Tests for the Claws mail client.
193
class TestClaws(tests.TestCase):
194
195
    def test_commandline(self):
196
        claws = mail_client.Claws(None)
3921.2.4 by Gavin Panella
Use the --attach option, and don't specify a From: header.
197
        commandline = claws._get_compose_commandline(
4401.2.2 by Barry Warsaw
Much simpler approach to support From: in Claws, after discussion with
198
            'jrandom@example.org', None, 'file%')
3921.2.4 by Gavin Panella
Use the --attach option, and don't specify a From: header.
199
        self.assertEqual(
4401.2.2 by Barry Warsaw
Much simpler approach to support From: in Claws, after discussion with
200
            ['--compose', 'mailto:jrandom@example.org?', '--attach', 'file%'],
201
            commandline)
3921.2.4 by Gavin Panella
Use the --attach option, and don't specify a From: header.
202
        commandline = claws._get_compose_commandline(
203
            'jrandom@example.org', 'Hi there!', None)
204
        self.assertEqual(
205
            ['--compose',
206
             'mailto:jrandom@example.org?subject=Hi%20there%21'],
3921.2.3 by Gavin Panella
Tests for the Claws mail client.
207
            commandline)
208
209
    def test_commandline_is_8bit(self):
210
        claws = mail_client.Claws(None)
211
        cmdline = claws._get_compose_commandline(
3921.2.7 by Gavin Panella
Use a non-ascii character in test_commandline_is_8bit.
212
            u'jrandom@example.org', u'\xb5cosm of fun!', u'file%')
6379.4.2 by Jelmer Vernooij
Add urlutils.quote / urlutils.unquote.
213
        subject_string = urlutils.quote(
3921.2.9 by Aaron Bentley
Update test to pass under LANG=C
214
            u'\xb5cosm of fun!'.encode(osutils.get_user_encoding(), 'replace'))
3921.2.3 by Gavin Panella
Tests for the Claws mail client.
215
        self.assertEqual(
216
            ['--compose',
3921.2.9 by Aaron Bentley
Update test to pass under LANG=C
217
             '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.
218
             '--attach',
219
             'file%'],
3921.2.3 by Gavin Panella
Tests for the Claws mail client.
220
            cmdline)
221
        for item in cmdline:
222
            self.assertFalse(isinstance(item, unicode),
223
                'Command-line item %r is unicode!' % item)
224
4401.2.2 by Barry Warsaw
Much simpler approach to support From: in Claws, after discussion with
225
    def test_with_from(self):
226
        claws = mail_client.Claws(None)
227
        cmdline = claws._get_compose_commandline(
228
            u'jrandom@example.org', None, None, None, u'qrandom@example.com')
229
        self.assertEqual(
230
            ['--compose',
231
             'mailto:jrandom@example.org?from=qrandom%40example.com'],
232
            cmdline)
233
234
    def test_to_required(self):
235
        claws = mail_client.Claws(None)
236
        self.assertRaises(errors.NoMailAddressSpecified,
237
                          claws._get_compose_commandline,
238
                          None, None, 'file%')
239
4401.2.3 by Barry Warsaw
Add test for including body text for Claws.
240
    def test_with_body(self):
241
        claws = mail_client.Claws(None)
242
        cmdline = claws._get_compose_commandline(
243
            u'jrandom@example.org', None, None, 'This is some body text')
244
        self.assertEqual(
245
            ['--compose',
246
             'mailto:jrandom@example.org?body=This%20is%20some%20body%20text'],
247
            cmdline)
248
3921.2.3 by Gavin Panella
Tests for the Claws mail client.
249
2681.1.21 by Aaron Bentley
Refactor prompt generation to make it testable, test it with unicode
250
class TestEditor(tests.TestCase):
251
252
    def test_get_merge_prompt_unicode(self):
253
        """Prompt, to and subject are unicode, the attachement is binary"""
254
        editor = mail_client.Editor(None)
255
        prompt = editor._get_merge_prompt(u'foo\u1234',
256
                                        u'bar\u1234',
257
                                        u'baz\u1234',
258
                                        u'qux\u1234'.encode('utf-8'))
259
        self.assertContainsRe(prompt, u'foo\u1234(.|\n)*bar\u1234'
260
                              u'(.|\n)*baz\u1234(.|\n)*qux\u1234')
261
        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
262
263
264
class DummyMailClient(object):
265
266
    def compose_merge_request(self, *args, **kwargs):
267
        self.args = args
268
        self.kwargs = kwargs
269
270
271
class DefaultMailDummyClient(mail_client.DefaultMail):
272
273
    def __init__(self):
274
        self.client = DummyMailClient()
275
276
    def _mail_client(self):
277
        return self.client
278
279
280
class TestDefaultMail(tests.TestCase):
281
282
    def test_compose_merge_request(self):
283
        client = DefaultMailDummyClient()
284
        to = "a@b.com"
285
        subject = "[MERGE]"
286
        directive = "directive",
287
        basename = "merge"
288
        client.compose_merge_request(to, subject, directive,
289
                                     basename=basename)
290
        dummy_client = client.client
291
        self.assertEqual(dummy_client.args, (to, subject, directive))
4098.5.10 by Aaron Bentley
Fix test case.
292
        self.assertEqual(dummy_client.kwargs,
293
                         {"basename": basename, 'body': None})