1+ import io
2+ import os
13import webbrowser
24import unittest
3- import os
45import sys
56import subprocess
67from unittest import mock
@@ -47,6 +48,14 @@ def _test(self, meth, *, args=[URL], kw={}, options, arguments):
4748 popen_args .pop (popen_args .index (option ))
4849 self .assertEqual (popen_args , arguments )
4950
51+ def test_reject_dash_prefixes (self ):
52+ browser = self .browser_class (name = CMD_NAME )
53+ with self .assertRaisesRegex (
54+ ValueError ,
55+ r"^Invalid URL \(leading dash disallowed\): '--key=val http.*'$"
56+ ):
57+ browser .open (f"--key=val { URL } " )
58+
5059
5160class GenericBrowserCommandTest (CommandTestMixin , unittest .TestCase ):
5261
@@ -57,11 +66,6 @@ def test_open(self):
5766 options = [],
5867 arguments = [URL ])
5968
60- def test_reject_dash_prefixes (self ):
61- browser = self .browser_class (name = CMD_NAME )
62- with self .assertRaises (ValueError ):
63- browser .open (f"--key=val { URL } " )
64-
6569
6670class BackgroundBrowserCommandTest (CommandTestMixin , unittest .TestCase ):
6771
@@ -222,6 +226,73 @@ def test_open_new_tab(self):
222226 arguments = ['openURL({},new-tab)' .format (URL )])
223227
224228
229+ class MockPopenPipe :
230+ def __init__ (self , cmd , mode ):
231+ self .cmd = cmd
232+ self .mode = mode
233+ self .pipe = io .StringIO ()
234+ self ._closed = False
235+
236+ def write (self , buf ):
237+ self .pipe .write (buf )
238+
239+ def close (self ):
240+ self ._closed = True
241+ return None
242+
243+
244+ @unittest .skipUnless (sys .platform == "darwin" , "macOS specific test" )
245+ class MacOSXOSAScriptTest (unittest .TestCase ):
246+ def setUp (self ):
247+ # Ensure that 'BROWSER' is not set to 'open' or something else.
248+ # See: https://github.com/python/cpython/issues/131254.
249+ ctx = os_helper .EnvironmentVarGuard ()
250+ env = ctx .__enter__ ()
251+ self .addCleanup (ctx .__exit__ )
252+ env .unset ("BROWSER" )
253+
254+ support .patch (self , os , "popen" , self .mock_popen )
255+ self .browser = webbrowser .MacOSXOSAScript ("default" )
256+
257+ def mock_popen (self , cmd , mode ):
258+ self .popen_pipe = MockPopenPipe (cmd , mode )
259+ return self .popen_pipe
260+
261+ def test_default (self ):
262+ browser = webbrowser .get ()
263+ assert isinstance (browser , webbrowser .MacOSXOSAScript )
264+ self .assertEqual (browser ._name , "default" )
265+
266+ def test_default_open (self ):
267+ url = "https://python.org"
268+ self .browser .open (url )
269+ self .assertTrue (self .popen_pipe ._closed )
270+ self .assertEqual (self .popen_pipe .cmd , "osascript" )
271+ script = self .popen_pipe .pipe .getvalue ()
272+ self .assertEqual (script .strip (), f'open location "{ url } "' )
273+
274+ def test_url_quote (self ):
275+ self .browser .open ('https://python.org/"quote"' )
276+ script = self .popen_pipe .pipe .getvalue ()
277+ self .assertEqual (
278+ script .strip (), 'open location "https://python.org/%22quote%22"'
279+ )
280+
281+ def test_explicit_browser (self ):
282+ browser = webbrowser .MacOSXOSAScript ("safari" )
283+ browser .open ("https://python.org" )
284+ script = self .popen_pipe .pipe .getvalue ()
285+ self .assertIn ('tell application "safari"' , script )
286+ self .assertIn ('open location "https://python.org"' , script )
287+
288+ def test_reject_dash_prefixes (self ):
289+ with self .assertRaisesRegex (
290+ ValueError ,
291+ r"^Invalid URL \(leading dash disallowed\): '--key=val http.*'$"
292+ ):
293+ self .browser .open (f"--key=val { URL } " )
294+
295+
225296class BrowserRegistrationTest (unittest .TestCase ):
226297
227298 def setUp (self ):
0 commit comments