blob: 6e5765e445410558ea847c1d7af7d233e1b4dd41 [file] [log] [blame]
>>> import mechanize
>>> from mechanize._response import test_response
>>> from test_browser import TestBrowser2, make_mock_handler
Opening a new response should close the old one.
>>> class TestHttpHandler(mechanize.BaseHandler):
... def http_open(self, request):
... return test_response(url=request.get_full_url())
>>> class TestHttpBrowser(TestBrowser2):
... handler_classes = TestBrowser2.handler_classes.copy()
... handler_classes["http"] = TestHttpHandler
... default_schemes = ["http"]
>>> def response_impl(response):
... return response.wrapped.fp.__class__.__name__
>>> br = TestHttpBrowser()
>>> r = br.open("http://example.com")
>>> print response_impl(r)
StringI
>>> r2 = br.open("http://example.com")
>>> print response_impl(r2)
StringI
>>> print response_impl(r)
eofresponse
So should .set_response()
>>> br.set_response(test_response())
>>> print response_impl(r2)
eofresponse
.visit_response() works very similarly to .open()
>>> br = TestHttpBrowser()
>>> r = br.open("http://example.com")
>>> r2 = test_response(url="http://example.com/2")
>>> print response_impl(r2)
StringI
>>> br.visit_response(r2)
>>> print response_impl(r)
eofresponse
>>> br.geturl() == br.request.get_full_url() == "http://example.com/2"
True
>>> junk = br.back()
>>> br.geturl() == br.request.get_full_url() == "http://example.com"
True
.back() may reload if the complete response was not read. If so, it
should return the new response, not the old one
>>> class ReloadCheckBrowser(TestHttpBrowser):
... reloaded = False
... def reload(self):
... self.reloaded = True
... return TestHttpBrowser.reload(self)
>>> br = ReloadCheckBrowser()
>>> old = br.open("http://example.com")
>>> junk = br.open("http://example.com/2")
>>> new = br.back()
>>> br.reloaded
True
>>> new.wrapped is not old.wrapped
True
Warn early about some mistakes setting a response object
>>> import StringIO
>>> br = TestBrowser2()
>>> br.set_response("blah")
Traceback (most recent call last):
...
ValueError: not a response object
>>> br.set_response(StringIO.StringIO())
Traceback (most recent call last):
...
ValueError: not a response object
.open() without an appropriate scheme handler should fail with
URLError
>>> br = TestBrowser2()
>>> br.open("http://example.com")
Traceback (most recent call last):
...
URLError: <urlopen error unknown url type: http>
Reload after failed .open() should fail due to failure to open, not
with BrowserStateError
>>> br.reload()
Traceback (most recent call last):
...
URLError: <urlopen error unknown url type: http>
.clear_history() should do what it says on the tin. Note that the
history does not include the current response!
>>> br = TestBrowser2()
>>> br.add_handler(make_mock_handler(test_response)([("http_open", None)]))
>>> br.response() is None
True
>>> len(br._history._history)
0
>>> r = br.open("http://example.com/1")
>>> br.response() is not None
True
>>> len(br._history._history)
0
>>> br.clear_history()
>>> br.response() is not None
True
>>> len(br._history._history)
0
>>> r = br.open("http://example.com/2")
>>> br.response() is not None
True
>>> len(br._history._history)
1
>>> br.clear_history()
>>> br.response() is not None
True
>>> len(br._history._history)
0
.open()ing a Request with False .visit does not affect Browser state.
Redirections during such a non-visiting request should also be
non-visiting.
>>> from mechanize import BrowserStateError, Request, HTTPRedirectHandler
>>> from test_urllib2 import MockHTTPHandler
>>> def make_browser_with_redirect():
... br = TestBrowser2()
... hh = MockHTTPHandler(302, "Location: http://example.com/\r\n\r\n")
... br.add_handler(hh)
... br.add_handler(HTTPRedirectHandler())
... return br
>>> def raises(exc_class, fn, *args, **kwds):
... try:
... fn(*args, **kwds)
... except exc_class, exc:
... return True
... return False
>>> def test_state(br):
... return (br.request is None and
... br.response() is None and
... raises(BrowserStateError, br.back)
... )
>>> br = make_browser_with_redirect()
>>> test_state(br)
True
>>> req = Request("http://example.com")
>>> req.visit = False
>>> r = br.open(req)
>>> test_state(br)
True
.open_novisit() mutates the request object
>>> br = make_browser_with_redirect()
>>> test_state(br)
True
>>> req = Request("http://example.com")
>>> print req.visit
None
>>> r = br.open_novisit(req)
>>> test_state(br)
True
>>> req.visit
False
...in fact, any redirection (but not refresh), proxy request, basic or
digest auth request, or robots.txt request should be non-visiting,
even if .visit is True:
>>> from test_urllib2 import MockPasswordManager
>>> def test_one_visit(handlers):
... br = TestBrowser2()
... for handler in handlers: br.add_handler(handler)
... req = Request("http://example.com")
... req.visit = True
... br.open(req)
... return br
>>> def test_state(br):
... # XXX the _history._history check is needed because of the weird
... # throwing-away of history entries by .back() where response is
... # None, which makes the .back() check insufficient to tell if a
... # history entry was .add()ed. I don't want to change this until
... # post-stable.
... return (
... br.response() and
... br.request and
... len(br._history._history) == 0 and
... raises(BrowserStateError, br.back))
>>> hh = MockHTTPHandler(302, "Location: http://example.com/\r\n\r\n")
>>> br = test_one_visit([hh, HTTPRedirectHandler()])
>>> test_state(br)
True
>>> class MockPasswordManager:
... def add_password(self, realm, uri, user, password): pass
... def find_user_password(self, realm, authuri): return '', ''
>>> ah = mechanize.HTTPBasicAuthHandler(MockPasswordManager())
>>> hh = MockHTTPHandler(
... 401, 'WWW-Authenticate: Basic realm="realm"\r\n\r\n')
>>> test_state(test_one_visit([hh, ah]))
True
>>> ph = mechanize.ProxyHandler(dict(http="proxy.example.com:3128"))
>>> ah = mechanize.ProxyBasicAuthHandler(MockPasswordManager())
>>> hh = MockHTTPHandler(
... 407, 'Proxy-Authenticate: Basic realm="realm"\r\n\r\n')
>>> test_state(test_one_visit([ph, hh, ah]))
True
XXX Can't really fix this one properly without significant changes --
the refresh should go onto the history *after* the call, but currently
all redirects, including refreshes, are done by recursive .open()
calls, which gets the history wrong in this case. Will have to wait
until after stable release:
#>>> hh = MockHTTPHandler(
#... "refresh", 'Location: http://example.com/\r\n\r\n')
#>>> br = test_one_visit([hh, HTTPRedirectHandler()])
#>>> br.response() is not None
#True
#>>> br.request is not None
#True
#>>> r = br.back()
XXX digest, robots
.global_form() is separate from the other forms (partly for backwards-
compatibility reasons).
>>> from mechanize._response import test_response
>>> br = TestBrowser2()
>>> html = """\
... <html><body>
... <input type="text" name="a" />
... <form><input type="text" name="b" /></form>
... </body></html>
... """
>>> response = test_response(html, headers=[("Content-type", "text/html")])
>>> br.global_form()
Traceback (most recent call last):
BrowserStateError: not viewing any document
>>> br.set_response(response)
>>> br.global_form().find_control(nr=0).name
'a'
>>> len(list(br.forms()))
1
>>> iter(br.forms()).next().find_control(nr=0).name
'b'
.select_form() works with the global form
>>> from mechanize._response import test_html_response
>>> br = TestBrowser2()
>>> br.visit_response(test_html_response("""\
... <html><head><title></title></head><body>
... <input type="text" name="a" value="b"></input>
... <form>
... <input type="text" name="p" value="q"></input>
... </form>
... </body></html>"""))
>>> def has_a(form):
... try:
... form.find_control(name="a")
... except mechanize.ControlNotFoundError:
... return False
... else:
... return True
>>> br.select_form(predicate=has_a)
>>> br.form.find_control(name="a").value
'b'