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