1import webbrowser
2import unittest
3import os
4import sys
5import subprocess
6from unittest import mock
7from test import support
8
9
10URL = 'http://www.example.com'
11CMD_NAME = 'test'
12
13
14class PopenMock(mock.MagicMock):
15
16    def poll(self):
17        return 0
18
19    def wait(self, seconds=None):
20        return 0
21
22
23class CommandTestMixin:
24
25    def _test(self, meth, *, args=[URL], kw={}, options, arguments):
26        """Given a web browser instance method name along with arguments and
27        keywords for same (which defaults to the single argument URL), creates
28        a browser instance from the class pointed to by self.browser, calls the
29        indicated instance method with the indicated arguments, and compares
30        the resulting options and arguments passed to Popen by the browser
31        instance against the 'options' and 'args' lists.  Options are compared
32        in a position independent fashion, and the arguments are compared in
33        sequence order to whatever is left over after removing the options.
34
35        """
36        popen = PopenMock()
37        support.patch(self, subprocess, 'Popen', popen)
38        browser = self.browser_class(name=CMD_NAME)
39        getattr(browser, meth)(*args, **kw)
40        popen_args = subprocess.Popen.call_args[0][0]
41        self.assertEqual(popen_args[0], CMD_NAME)
42        popen_args.pop(0)
43        for option in options:
44            self.assertIn(option, popen_args)
45            popen_args.pop(popen_args.index(option))
46        self.assertEqual(popen_args, arguments)
47
48
49class GenericBrowserCommandTest(CommandTestMixin, unittest.TestCase):
50
51    browser_class = webbrowser.GenericBrowser
52
53    def test_open(self):
54        self._test('open',
55                   options=[],
56                   arguments=[URL])
57
58
59class BackgroundBrowserCommandTest(CommandTestMixin, unittest.TestCase):
60
61    browser_class = webbrowser.BackgroundBrowser
62
63    def test_open(self):
64        self._test('open',
65                   options=[],
66                   arguments=[URL])
67
68
69class ChromeCommandTest(CommandTestMixin, unittest.TestCase):
70
71    browser_class = webbrowser.Chrome
72
73    def test_open(self):
74        self._test('open',
75                   options=[],
76                   arguments=[URL])
77
78    def test_open_with_autoraise_false(self):
79        self._test('open', kw=dict(autoraise=False),
80                   options=[],
81                   arguments=[URL])
82
83    def test_open_new(self):
84        self._test('open_new',
85                   options=['--new-window'],
86                   arguments=[URL])
87
88    def test_open_new_tab(self):
89        self._test('open_new_tab',
90                   options=[],
91                   arguments=[URL])
92
93
94class MozillaCommandTest(CommandTestMixin, unittest.TestCase):
95
96    browser_class = webbrowser.Mozilla
97
98    def test_open(self):
99        self._test('open',
100                   options=[],
101                   arguments=[URL])
102
103    def test_open_with_autoraise_false(self):
104        self._test('open', kw=dict(autoraise=False),
105                   options=[],
106                   arguments=[URL])
107
108    def test_open_new(self):
109        self._test('open_new',
110                   options=[],
111                   arguments=['-new-window', URL])
112
113    def test_open_new_tab(self):
114        self._test('open_new_tab',
115                   options=[],
116                   arguments=['-new-tab', URL])
117
118
119class NetscapeCommandTest(CommandTestMixin, unittest.TestCase):
120
121    browser_class = webbrowser.Netscape
122
123    def test_open(self):
124        self._test('open',
125                   options=['-raise', '-remote'],
126                   arguments=['openURL({})'.format(URL)])
127
128    def test_open_with_autoraise_false(self):
129        self._test('open', kw=dict(autoraise=False),
130                   options=['-noraise', '-remote'],
131                   arguments=['openURL({})'.format(URL)])
132
133    def test_open_new(self):
134        self._test('open_new',
135                   options=['-raise', '-remote'],
136                   arguments=['openURL({},new-window)'.format(URL)])
137
138    def test_open_new_tab(self):
139        self._test('open_new_tab',
140                   options=['-raise', '-remote'],
141                   arguments=['openURL({},new-tab)'.format(URL)])
142
143
144class GaleonCommandTest(CommandTestMixin, unittest.TestCase):
145
146    browser_class = webbrowser.Galeon
147
148    def test_open(self):
149        self._test('open',
150                   options=['-n'],
151                   arguments=[URL])
152
153    def test_open_with_autoraise_false(self):
154        self._test('open', kw=dict(autoraise=False),
155                   options=['-noraise', '-n'],
156                   arguments=[URL])
157
158    def test_open_new(self):
159        self._test('open_new',
160                   options=['-w'],
161                   arguments=[URL])
162
163    def test_open_new_tab(self):
164        self._test('open_new_tab',
165                   options=['-w'],
166                   arguments=[URL])
167
168
169class OperaCommandTest(CommandTestMixin, unittest.TestCase):
170
171    browser_class = webbrowser.Opera
172
173    def test_open(self):
174        self._test('open',
175                   options=[],
176                   arguments=[URL])
177
178    def test_open_with_autoraise_false(self):
179        self._test('open', kw=dict(autoraise=False),
180                   options=[],
181                   arguments=[URL])
182
183    def test_open_new(self):
184        self._test('open_new',
185                   options=['--new-window'],
186                   arguments=[URL])
187
188    def test_open_new_tab(self):
189        self._test('open_new_tab',
190                   options=[],
191                   arguments=[URL])
192
193
194class ELinksCommandTest(CommandTestMixin, unittest.TestCase):
195
196    browser_class = webbrowser.Elinks
197
198    def test_open(self):
199        self._test('open', options=['-remote'],
200                           arguments=['openURL({})'.format(URL)])
201
202    def test_open_with_autoraise_false(self):
203        self._test('open',
204                   options=['-remote'],
205                   arguments=['openURL({})'.format(URL)])
206
207    def test_open_new(self):
208        self._test('open_new',
209                   options=['-remote'],
210                   arguments=['openURL({},new-window)'.format(URL)])
211
212    def test_open_new_tab(self):
213        self._test('open_new_tab',
214                   options=['-remote'],
215                   arguments=['openURL({},new-tab)'.format(URL)])
216
217
218class BrowserRegistrationTest(unittest.TestCase):
219
220    def setUp(self):
221        # Ensure we don't alter the real registered browser details
222        self._saved_tryorder = webbrowser._tryorder
223        webbrowser._tryorder = []
224        self._saved_browsers = webbrowser._browsers
225        webbrowser._browsers = {}
226
227    def tearDown(self):
228        webbrowser._tryorder = self._saved_tryorder
229        webbrowser._browsers = self._saved_browsers
230
231    def _check_registration(self, preferred):
232        class ExampleBrowser:
233            pass
234
235        expected_tryorder = []
236        expected_browsers = {}
237
238        self.assertEqual(webbrowser._tryorder, expected_tryorder)
239        self.assertEqual(webbrowser._browsers, expected_browsers)
240
241        webbrowser.register('Example1', ExampleBrowser)
242        expected_tryorder = ['Example1']
243        expected_browsers['example1'] = [ExampleBrowser, None]
244        self.assertEqual(webbrowser._tryorder, expected_tryorder)
245        self.assertEqual(webbrowser._browsers, expected_browsers)
246
247        instance = ExampleBrowser()
248        if preferred is not None:
249            webbrowser.register('example2', ExampleBrowser, instance,
250                                preferred=preferred)
251        else:
252            webbrowser.register('example2', ExampleBrowser, instance)
253        if preferred:
254            expected_tryorder = ['example2', 'Example1']
255        else:
256            expected_tryorder = ['Example1', 'example2']
257        expected_browsers['example2'] = [ExampleBrowser, instance]
258        self.assertEqual(webbrowser._tryorder, expected_tryorder)
259        self.assertEqual(webbrowser._browsers, expected_browsers)
260
261    def test_register(self):
262        self._check_registration(preferred=False)
263
264    def test_register_default(self):
265        self._check_registration(preferred=None)
266
267    def test_register_preferred(self):
268        self._check_registration(preferred=True)
269
270
271class ImportTest(unittest.TestCase):
272    def test_register(self):
273        webbrowser = support.import_fresh_module('webbrowser')
274        self.assertIsNone(webbrowser._tryorder)
275        self.assertFalse(webbrowser._browsers)
276
277        class ExampleBrowser:
278            pass
279        webbrowser.register('Example1', ExampleBrowser)
280        self.assertTrue(webbrowser._tryorder)
281        self.assertEqual(webbrowser._tryorder[-1], 'Example1')
282        self.assertTrue(webbrowser._browsers)
283        self.assertIn('example1', webbrowser._browsers)
284        self.assertEqual(webbrowser._browsers['example1'], [ExampleBrowser, None])
285
286    def test_get(self):
287        webbrowser = support.import_fresh_module('webbrowser')
288        self.assertIsNone(webbrowser._tryorder)
289        self.assertFalse(webbrowser._browsers)
290
291        with self.assertRaises(webbrowser.Error):
292            webbrowser.get('fakebrowser')
293        self.assertIsNotNone(webbrowser._tryorder)
294
295    def test_synthesize(self):
296        webbrowser = support.import_fresh_module('webbrowser')
297        name = os.path.basename(sys.executable).lower()
298        webbrowser.register(name, None, webbrowser.GenericBrowser(name))
299        webbrowser.get(sys.executable)
300
301    def test_environment(self):
302        webbrowser = support.import_fresh_module('webbrowser')
303        try:
304            browser = webbrowser.get().name
305        except (webbrowser.Error, AttributeError) as err:
306            self.skipTest(str(err))
307        with support.EnvironmentVarGuard() as env:
308            env["BROWSER"] = browser
309            webbrowser = support.import_fresh_module('webbrowser')
310            webbrowser.get()
311
312    def test_environment_preferred(self):
313        webbrowser = support.import_fresh_module('webbrowser')
314        try:
315            webbrowser.get()
316            least_preferred_browser = webbrowser.get(webbrowser._tryorder[-1]).name
317        except (webbrowser.Error, AttributeError, IndexError) as err:
318            self.skipTest(str(err))
319
320        with support.EnvironmentVarGuard() as env:
321            env["BROWSER"] = least_preferred_browser
322            webbrowser = support.import_fresh_module('webbrowser')
323            self.assertEqual(webbrowser.get().name, least_preferred_browser)
324
325        with support.EnvironmentVarGuard() as env:
326            env["BROWSER"] = sys.executable
327            webbrowser = support.import_fresh_module('webbrowser')
328            self.assertEqual(webbrowser.get().name, sys.executable)
329
330
331if __name__=='__main__':
332    unittest.main()
333