~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%')
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%')
110
        for item in commandline:
111
            self.assertFalse(isinstance(item, unicode),
112
                'Command-line item %r is unicode!' % item)
113
114
2681.1.23 by Aaron Bentley
Add support for xdg-email
115
class TestXDGEmail(tests.TestCase):
116
117
    def test_commandline(self):
118
        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.
119
        self.assertRaises(errors.NoMailAddressSpecified,
120
                          xdg_email._get_compose_commandline,
121
                          None, None, 'file%')
122
        commandline = xdg_email._get_compose_commandline(
123
            'jrandom@example.org', None, 'file%')
124
        self.assertEqual(['jrandom@example.org', '--attach', 'file%'],
125
                         commandline)
2681.1.23 by Aaron Bentley
Add support for xdg-email
126
        commandline = xdg_email._get_compose_commandline(
4098.5.1 by Aaron Bentley
Allow specifying body for t-bird, evo and xdg
127
            'jrandom@example.org', 'Hi there!', None, "bo'dy")
128
        self.assertEqual(['jrandom@example.org', '--subject', 'Hi there!',
129
                          '--body', "bo'dy"], commandline)
2681.1.23 by Aaron Bentley
Add support for xdg-email
130
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.
131
    def test_commandline_is_8bit(self):
132
        xdg_email = mail_client.XDGEmail(None)
133
        cmdline = xdg_email._get_compose_commandline(u'jrandom@example.org',
134
            u'Hi there!', u'file%')
135
        self.assertEqual(
136
            ['jrandom@example.org', '--subject', 'Hi there!',
137
             '--attach', 'file%'],
138
            cmdline)
139
        for item in cmdline:
140
            self.assertFalse(isinstance(item, unicode),
141
                'Command-line item %r is unicode!' % item)
142
2681.1.23 by Aaron Bentley
Add support for xdg-email
143
2681.2.1 by Lukáš Lalinsky
Support for Evolution mail client.
144
class TestEvolution(tests.TestCase):
145
146
    def test_commandline(self):
147
        evo = mail_client.Evolution(None)
148
        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
149
        self.assertEqual(['mailto:?attach=file%25'], commandline)
2681.2.1 by Lukáš Lalinsky
Support for Evolution mail client.
150
        commandline = evo._get_compose_commandline('jrandom@example.org',
4098.5.1 by Aaron Bentley
Allow specifying body for t-bird, evo and xdg
151
                                                   'Hi there!', None, 'bo&dy')
152
        self.assertEqual(['mailto:jrandom@example.org?body=bo%26dy&'
153
                          'subject=Hi%20there%21'], commandline)
2681.1.21 by Aaron Bentley
Refactor prompt generation to make it testable, test it with unicode
154
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.
155
    def test_commandline_is_8bit(self):
156
        evo = mail_client.Evolution(None)
157
        cmdline = evo._get_compose_commandline(u'jrandom@example.org',
158
            u'Hi there!', u'file%')
159
        self.assertEqual(
160
            ['mailto:jrandom@example.org?attach=file%25&subject=Hi%20there%21'
161
            ],
162
            cmdline)
163
        for item in cmdline:
164
            self.assertFalse(isinstance(item, unicode),
165
                'Command-line item %r is unicode!' % item)
166
2681.1.21 by Aaron Bentley
Refactor prompt generation to make it testable, test it with unicode
167
2681.5.2 by ghigo
update docs and tests
168
class TestKMail(tests.TestCase):
169
170
    def test_commandline(self):
2681.1.35 by Aaron Bentley
Rename test var evo => kmail
171
        kmail = mail_client.KMail(None)
172
        commandline = kmail._get_compose_commandline(None, None, 'file%')
2681.5.2 by ghigo
update docs and tests
173
        self.assertEqual(['--attach', 'file%'], commandline)
2681.1.35 by Aaron Bentley
Rename test var evo => kmail
174
        commandline = kmail._get_compose_commandline('jrandom@example.org',
175
                                                     'Hi there!', None)
2681.5.2 by ghigo
update docs and tests
176
        self.assertEqual(['-s', 'Hi there!', 'jrandom@example.org'],
177
                         commandline)
178
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.
179
    def test_commandline_is_8bit(self):
180
        kmail = mail_client.KMail(None)
181
        cmdline = kmail._get_compose_commandline(u'jrandom@example.org',
182
            u'Hi there!', u'file%')
183
        self.assertEqual(
184
            ['-s', 'Hi there!', '--attach', 'file%', 'jrandom@example.org'],
185
            cmdline)
186
        for item in cmdline:
187
            self.assertFalse(isinstance(item, unicode),
188
                'Command-line item %r is unicode!' % item)
189
2681.5.2 by ghigo
update docs and tests
190
3921.2.3 by Gavin Panella
Tests for the Claws mail client.
191
class TestClaws(tests.TestCase):
192
193
    def test_commandline(self):
194
        claws = mail_client.Claws(None)
3921.2.4 by Gavin Panella
Use the --attach option, and don't specify a From: header.
195
        commandline = claws._get_compose_commandline(
4401.2.2 by Barry Warsaw
Much simpler approach to support From: in Claws, after discussion with
196
            'jrandom@example.org', None, 'file%')
3921.2.4 by Gavin Panella
Use the --attach option, and don't specify a From: header.
197
        self.assertEqual(
4401.2.2 by Barry Warsaw
Much simpler approach to support From: in Claws, after discussion with
198
            ['--compose', 'mailto:jrandom@example.org?', '--attach', 'file%'],
199
            commandline)
3921.2.4 by Gavin Panella
Use the --attach option, and don't specify a From: header.
200
        commandline = claws._get_compose_commandline(
201
            'jrandom@example.org', 'Hi there!', None)
202
        self.assertEqual(
203
            ['--compose',
204
             'mailto:jrandom@example.org?subject=Hi%20there%21'],
3921.2.3 by Gavin Panella
Tests for the Claws mail client.
205
            commandline)
206
207
    def test_commandline_is_8bit(self):
208
        claws = mail_client.Claws(None)
209
        cmdline = claws._get_compose_commandline(
3921.2.7 by Gavin Panella
Use a non-ascii character in test_commandline_is_8bit.
210
            u'jrandom@example.org', u'\xb5cosm of fun!', u'file%')
3921.2.9 by Aaron Bentley
Update test to pass under LANG=C
211
        subject_string = urllib.quote(
212
            u'\xb5cosm of fun!'.encode(osutils.get_user_encoding(), 'replace'))
3921.2.3 by Gavin Panella
Tests for the Claws mail client.
213
        self.assertEqual(
214
            ['--compose',
3921.2.9 by Aaron Bentley
Update test to pass under LANG=C
215
             '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.
216
             '--attach',
217
             'file%'],
3921.2.3 by Gavin Panella
Tests for the Claws mail client.
218
            cmdline)
219
        for item in cmdline:
220
            self.assertFalse(isinstance(item, unicode),
221
                'Command-line item %r is unicode!' % item)
222
4401.2.2 by Barry Warsaw
Much simpler approach to support From: in Claws, after discussion with
223
    def test_with_from(self):
224
        claws = mail_client.Claws(None)
225
        cmdline = claws._get_compose_commandline(
226
            u'jrandom@example.org', None, None, None, u'qrandom@example.com')
227
        self.assertEqual(
228
            ['--compose',
229
             'mailto:jrandom@example.org?from=qrandom%40example.com'],
230
            cmdline)
231
232
    def test_to_required(self):
233
        claws = mail_client.Claws(None)
234
        self.assertRaises(errors.NoMailAddressSpecified,
235
                          claws._get_compose_commandline,
236
                          None, None, 'file%')
237
4401.2.3 by Barry Warsaw
Add test for including body text for Claws.
238
    def test_with_body(self):
239
        claws = mail_client.Claws(None)
240
        cmdline = claws._get_compose_commandline(
241
            u'jrandom@example.org', None, None, 'This is some body text')
242
        self.assertEqual(
243
            ['--compose',
244
             'mailto:jrandom@example.org?body=This%20is%20some%20body%20text'],
245
            cmdline)
246
3921.2.3 by Gavin Panella
Tests for the Claws mail client.
247
2681.1.21 by Aaron Bentley
Refactor prompt generation to make it testable, test it with unicode
248
class TestEditor(tests.TestCase):
249
250
    def test_get_merge_prompt_unicode(self):
251
        """Prompt, to and subject are unicode, the attachement is binary"""
252
        editor = mail_client.Editor(None)
253
        prompt = editor._get_merge_prompt(u'foo\u1234',
254
                                        u'bar\u1234',
255
                                        u'baz\u1234',
256
                                        u'qux\u1234'.encode('utf-8'))
257
        self.assertContainsRe(prompt, u'foo\u1234(.|\n)*bar\u1234'
258
                              u'(.|\n)*baz\u1234(.|\n)*qux\u1234')
259
        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
260
261
262
class DummyMailClient(object):
263
264
    def compose_merge_request(self, *args, **kwargs):
265
        self.args = args
266
        self.kwargs = kwargs
267
268
269
class DefaultMailDummyClient(mail_client.DefaultMail):
270
271
    def __init__(self):
272
        self.client = DummyMailClient()
273
274
    def _mail_client(self):
275
        return self.client
276
277
278
class TestDefaultMail(tests.TestCase):
279
280
    def test_compose_merge_request(self):
281
        client = DefaultMailDummyClient()
282
        to = "a@b.com"
283
        subject = "[MERGE]"
284
        directive = "directive",
285
        basename = "merge"
286
        client.compose_merge_request(to, subject, directive,
287
                                     basename=basename)
288
        dummy_client = client.client
289
        self.assertEqual(dummy_client.args, (to, subject, directive))
4098.5.10 by Aaron Bentley
Fix test case.
290
        self.assertEqual(dummy_client.kwargs,
291
                         {"basename": basename, 'body': None})