zopefoundation / zope.testbrowser Goto Github PK
View Code? Open in Web Editor NEWProgrammable browser for functional black-box tests
License: Other
Programmable browser for functional black-box tests
License: Other
IControl doesn't define readonly
, which looks like part of the API. (Although note that IListControl classes don't have readonly
properties.)
IControl.type has a list of values that doesn't mention textarea
. I also wonder how it would cope with HTML5 control types such as date
etc.
IControl doesn't have id
(and the implementation lacks it as well), which is sometimes rather inconvenient.
Building zope.testbrowser on my Fedora 18 machine with python-2.7.3 and virtualenv-1.9.1 from PyPI fails, using the enclosed buildout. This came up in #4 originally. This is the full stack trace:
nico@pesto $ bin/test
Running zope.testrunner.layer.UnitTests tests:
Set up zope.testrunner.layer.UnitTests in 0.000 seconds.
Failure in test /home/nico/src/zope.testbrowser/src/zope/testbrowser/README.txt
Failed doctest test for README.txt
File "/home/nico/src/zope.testbrowser/src/zope/testbrowser/README.txt", line 0
----------------------------------------------------------------------
File "/home/nico/src/zope.testbrowser/src/zope/testbrowser/README.txt", line 119, in README.txt
Failed example:
verifyObject(interfaces.IBrowser, browser)
Exception raised:
Traceback (most recent call last):
File "/usr/lib64/python2.7/doctest.py", line 1289, in __run
compileflags, 1) in test.globs
File "<doctest README.txt[20]>", line 1, in <module>
verifyObject(interfaces.IBrowser, browser)
File "/home/nico/src/zope.testbrowser/eggs/zope.interface-4.0.5-py2.7-linux-x86_64.egg/zope/interface/verify.py", line 105, in verifyObject
return _verify(iface, candidate, tentative, vtype='o')
File "/home/nico/src/zope.testbrowser/eggs/zope.interface-4.0.5-py2.7-linux-x86_64.egg/zope/interface/verify.py", line 55, in _verify
attr = getattr(candidate, name)
File "/home/nico/src/zope.testbrowser/src/zope/testbrowser/browser.py", line 299, in lastRequestPystones
return self.timer.elapsedPystones
File "/home/nico/src/zope.testbrowser/src/zope/testbrowser/browser.py", line 176, in elapsedPystones
return self.elapsedSeconds * self.pystonesPerSecond
File "/home/nico/src/zope.testbrowser/src/zope/testbrowser/browser.py", line 135, in pystonesPerSecond
from test import pystone
ImportError: cannot import name pystone
----------------------------------------------------------------------
File "/home/nico/src/zope.testbrowser/src/zope/testbrowser/README.txt", line 1380, in README.txt
Failed example:
browser.lastRequestPystones < 10000 # really big number for safety
Exception raised:
Traceback (most recent call last):
File "/usr/lib64/python2.7/doctest.py", line 1289, in __run
compileflags, 1) in test.globs
File "<doctest README.txt[388]>", line 1, in <module>
browser.lastRequestPystones < 10000 # really big number for safety
File "/home/nico/src/zope.testbrowser/src/zope/testbrowser/browser.py", line 299, in lastRequestPystones
return self.timer.elapsedPystones
File "/home/nico/src/zope.testbrowser/src/zope/testbrowser/browser.py", line 176, in elapsedPystones
return self.elapsedSeconds * self.pystonesPerSecond
File "/home/nico/src/zope.testbrowser/src/zope/testbrowser/browser.py", line 135, in pystonesPerSecond
from test import pystone
ImportError: cannot import name pystone
Ran 19 tests with 1 failures and 0 errors in 0.375 seconds.
Tearing down left over layers:
Tear down zope.testrunner.layer.UnitTests in 0.000 seconds.
When you load a page and then reload it and the server sends a 30x redirect for the 2nd response, the .reload() call will not follow redirects (nor raise exceptions for 4xx/5xx errors).
This is a regression from mechanize-based zope.testbrowser.
zope.testbrowser relies on BeautifulSoup's implementation of CSS selectors to query HTML nodes. The latest release of BeautifulSoup requires CSS selectors to follow the CSS spec in ways where previously it allowed lax values. Since zope.testbrowser doesn't actually follow the CSS spec (inadequate quoting), this causes problems like zopefoundation/zc.catalog#8.
One instance (from the above bug) is this line in getControlLabels():
forlbls = html.select('label[for=%s]' % controlid)
The %s should apparently be quoted with double quotes in case controlid
is not a valid CSS identifier.
Other instances of this may lurk. https://facelessuser.github.io/soupsieve/#beautiful-soup-differences has a list of things we should watch for.
To reproduce:
$ pip install zope.testbrowser==4.0.2
Output is:
Downloading/unpacking zope.testbrowser==4.0.2
Downloading zope.testbrowser-4.0.2.tar.gz (77kB): 77kB downloaded
Running setup.py egg_info for package zope.testbrowser
Downloading/unpacking mechanize>=0.2.0 (from zope.testbrowser==4.0.2)
Downloading mechanize-0.2.5.tar.gz (383kB): 383kB downloaded
Running setup.py egg_info for package mechanize
Requirement already satisfied (use --upgrade to upgrade): setuptools in /Users/flavia.carlette/.virtualenvs/test/lib/python2.7/site-packages/setuptools-0.6c11-py2.7.egg (from zope.testbrowser==4.0.2)
Downloading/unpacking zope.interface (from zope.testbrowser==4.0.2)
Downloading zope.interface-4.0.5.zip (173kB): 173kB downloaded
Running setup.py egg_info for package zope.interface
warning: no previously-included files matching '*.dll' found anywhere in distribution
warning: no previously-included files matching '*.pyc' found anywhere in distribution
warning: no previously-included files matching '*.pyo' found anywhere in distribution
warning: no previously-included files matching '*.so' found anywhere in distribution
Downloading/unpacking zope.schema (from zope.testbrowser==4.0.2)
Downloading zope.schema-4.3.2.zip (93kB): 93kB downloaded
Running setup.py egg_info for package zope.schema
warning: no previously-included files matching '*.dll' found anywhere in distribution
warning: no previously-included files matching '*.pyc' found anywhere in distribution
warning: no previously-included files matching '*.pyo' found anywhere in distribution
warning: no previously-included files matching '*.so' found anywhere in distribution
Downloading/unpacking pytz (from zope.testbrowser==4.0.2)
Could not find a version that satisfies the requirement pytz (from zope.testbrowser==4.0.2) (from versions: 2009r, 2008b, 2009f, 2008c, 2007g, 2011g, 2005m, 2011e, 2007f, 2011k, 2007k, 2006j, 2008h, 2008i, 2011e, 2008a, 2009e, 2006g, 2011j, 2010l, 2005m, 2008i, 2005k, 2008g, 2007c, 2007i, 2009l, 2009r, 2006j, 2011k, 2007d, 2006p, 2009i, 2009u, 2007i, 2009f, 2010g, 2008h, 2009a, 2007g, 2011e, 2006p, 2012b, 2010k, 2005r, 2007f, 2009l, 2009p, 2008c, 2009j, 2008g, 2010g, 2010h, 2011h, 2010k, 2007c, 2007d, 2011d, 2009l, 2011c, 2008a, 2005m, 2007k, 2009n, 2011d, 2013b, 2012h, 2010e, 2012d, 2012f, 2011n, 2011b, 2011j, 2008c, 2012j, 2007k, 2009f, 2009d, 2010e, 2010b, 2013b, 2011d, 2009p, 2008h, 2005r, 2009i, 2009n, 2009a, 2010k, 2008g, 2006g, 2008b, 2012c, 2009i, 2007g, 2012c, 2010h, 2011n, 2012g, 2007d, 2008a, 2009u, 2012g, 2010o, 2006p, 2010b, 2009u, 2012d, 2011k, 2012f, 2009a, 2007f, 2011h, 2010l, 2009j, 2011g, 2009g, 2009g, 2005r, 2011c, 2012g, 2009g, 2012d, 2009j, 2010o, 2007c, 2010g, 2006g, 2009d, 2010h, 2005k, 2006j, 2010b, 2009n, 2011g, 2011c, 2012b, 2009e, 2009d, 2011j, 2007i, 2012j, 2010l, 2009r, 2012h, 2010e, 2009p, 2008i, 2012f, 2009e, 2012b, 2011h, 2005k, 2008b, 2012c, 2010o, 2013b, 2012j, 2011n, 2004b)
Cleaning up...
No distributions matching the version for pytz (from zope.testbrowser==4.0.2)
Installing pytz==2013b
and then trying to install zope.testbrowser
again fixes the issue.
The soft hyphen or ­
-marker tell a web browser where it can break the word to start a new line and inserts a hyphen at the end of the splitted word. For example, ar­tic­le
may be rendered as article
or ar-\nticle
or artic-\nle
.
Since zope.testbrowser renders special markers like ­
or
, it would be necessary to insert a soft-hyphen into the expected text, so getLink
finds the text. However, how do you represent a special marker that renders to an empty string?
zope.testbrowser should probably just remove ­
markers when searching for a link or control.
The WebTest <= 1.3.4
version pin in latest stable zope.testbrowser release (4.0.3) is causing pain.
I thought pushing zope.testbrowser 5.0.0 out of the door would be a good way to fix this, but on second though, that would cause even more pain due to lack of 100% backwards compatibility.
So let's fix this and release 4.0.4.
The version pin exists because zope.testbrowser's tests fail when you get a newer WebTest. The test failures are all of the form
AssertionError: Iterator <listiterator object at 0x37d5e10> returned a non-<type 'str'> object: u"Hello world!\n\nHTTP_CONNECTION = 'close'\nHTTP...
in webtest.lint, and are caused by stdlib's wsgiref.simple_server.demo_app returning a Unicode response body. Why does it return a unicode body? Because it prints the wsgi environment into a StringIO. Why are there Unicode strings in the wsgi environment? Frog knows, but here they are:
(Pdb) pp environ
{'HTTP_CONNECTION': 'close',
'HTTP_HOST': 'localhost',
'HTTP_USER_AGENT': 'Python-urllib/2.7',
'PATH_INFO': '/',
'QUERY_STRING': '',
'REQUEST_METHOD': 'GET',
'SCRIPT_NAME': '',
'SERVER_NAME': 'localhost',
'SERVER_PORT': '80',
'SERVER_PROTOCOL': 'HTTP/1.0',
u'paste.testing': True,
u'paste.testing_variables': {},
u'paste.throw_errors': None,
'wsgi.errors': <webtest.lint.ErrorWrapper object at 0x7fdf4f6bbe10>,
'wsgi.input': <webtest.lint.InputWrapper object at 0x7fdf4f628090>,
'wsgi.multiprocess': False,
'wsgi.multithread': False,
'wsgi.run_once': False,
'wsgi.url_scheme': 'http',
'wsgi.version': (1, 0)}
(I see several open issues about compatibility with the old mechanize
-based test browser, so I hope this sort of thing is welcome.)
I'm in the process of migrating a large project (Launchpad) from old versions of zope.testbrowser
to version 5.x. One thorn in my side has been that in several places we do something like this:
edit_status_url = re.compile(r'1.0/\+bug/[0-9]+/\+editstatus')
browser.getLink(url=edit_status_url).click()
This worked with mechanize
because regexes were tested using .search
. However, zope.testbrowser
now tests them using .match
, so the above code has to be more like this:
edit_status_url = re.compile(r'.*/1.0/\+bug/[0-9]+/\+editstatus')
browser.getLink(url=edit_status_url).click()
I don't suppose it would be possible to go back to 4.x-compatible behaviour here?
Python 3.8 removed time.clock()
, which causes
Traceback (most recent call last):
...
Module zope.testbrowser.browser, line 483, in _preparedRequest
self.timer.start()
Module zope.testbrowser.browser, line 1420, in start
self.start_time = self._getTime()
Module zope.testbrowser.browser, line 1413, in _getTime
return time.clock()
AttributeError: module 'time' has no attribute 'clock'
The old mechanize-based zope.testbrowser behaved like this:
>>> print(browser.contents)
...
<input type="checkbox" id="closed" name="closed" value="on" />
...
>>> browser.getControl(name='closed').value
False
The new webtest-based zope.testbrowser returns []
instead of False
. Which is fine, I suppose, but I'd like this backwards incompatibility to be documented somewhere.
See #29 (comment)
Another of those mechanize-to-webtest compatibility issues:
>>> print(browser.contents)
...<label for="form.lead_reviewer">Reviewer</label>
<input class="hiddenType" id="form.lead_reviewer" name="form.lead_reviewer" type="hidden" value="" />
...
>>> browser.getControl('Reviewer').value = 'manager'
This used to work, now it fails with a LookupError.
(I'm fine with the change, <label>
pointing to a hidden field seems wrong, I'd just like this to be documented.)
I've seen variations on this, some of which end up in an error like
Failed example:
manager.reload()
Exception raised:
Traceback (most recent call last):
File "/usr/lib/python2.7/doctest.py", line 1315, in __run
compileflags, 1) in test.globs
File "<doctest invitations.txt[101]>", line 1, in <module>
manager.reload()
File "/home/mg/src/zopefoundation/zope.testbrowser/src/zope/testbrowser/browser.py", line 197, in reload
resp = self.testapp.request(req)
File "/home/mg/src/ivija/.tox/py27-latest/local/lib/python2.7/site-packages/webtest/app.py", line 581, in request
req = url_or_req.copy()
File "/home/mg/src/ivija/.tox/py27-latest/local/lib/python2.7/site-packages/webob/request.py", line 861, in copy
self.make_body_seekable()
File "/home/mg/src/ivija/.tox/py27-latest/local/lib/python2.7/site-packages/webob/request.py", line 929, in make_body_seekable
self.copy_body()
File "/home/mg/src/ivija/.tox/py27-latest/local/lib/python2.7/site-packages/webob/request.py", line 953, in copy_body
data = input.read(min(todo, 65535))
File "/home/mg/src/ivija/.tox/py27-latest/local/lib/python2.7/site-packages/webob/request.py", line 1544, in readinto
"(%d more bytes were expected)" % (self.remaining,)
DisconnectionError: The client disconnected while sending the body (79 more bytes were expected)
and some of which silently end up with a (that was actually a different bug, see #75)browser.contents
of ''
.
I get the impression that submitting a form and then calling reload()
in the old mechanize-based testbrowser used to replay the last POST request as a GET to the same URL.
I don't think that's a good idea either, so what I propose instead is to have zope.testbrowser explicitly raise a BrowserStateError() if you try to reload a POST.
The behaviour related to setting radio controls has changed in some cases.
I added a test case in master...fschulze:radio-master.
I added the same one for 4.0.4 in 4.0.4...fschulze:radio-4.0.4 to show that it works correctly with mechanize.
The following scenario error leads to an error:
browser.getControl()
is used to select a not existing control.This leads to a UnicodeDecodeError when zope.testbrowser tries to render the list of possible controls using the mechRepr
of the controls. The exception happens when joining the mechRepr
values of the controls because to a single string. The ones of the select options and text fields are unicode
while the one of the submit control is str
but contains a non-ASCII char.
Maybe they even show that the code is broken because zope.testbrowser.cookies.expiration_string
does not seem to work on Python 3, at least not the same way as in Python 2.
The NotImplementedError in https://github.com/zopefoundation/zope.testbrowser/blob/master/src/zope/testbrowser/browser.py#L769 breaks tests which expect a LookupError when there are controls that aren't covered in mechRepr. One example is an input element of type number
for which the ctrl class is webtest.forms.Field
. I'm not sure what the best fix here is. I'd say there should just be a fallback representation, but I'm not sure what it should look like. Maybe just as for webtest.forms.File
?
tox -e docs
fails for me. They pass for me (given #64) if I set LC_TIME=C instead of my usual lt_LT.UTF-8.
I suspect expires.strftime('%a, %d %b %Y %H:%M:%S GMT')
in zope.testbrowser.cookies is not really what we want to.
Given a form like
<input type="radio" name="selected" id="select-c1" value="c1" checked="checked" />
<label for="select-c1">Label 1</label>
<input type="radio" name="selected" id="select-c2" value="c2" />
<label for="select-c2">Label 2</label>
if you do browser.getControl('Label 1').click()
, it'll unselect the radio button.
This is not how browsers behave, and it does not match how the older mechanize-based zope.testbrowser used to behave. If you click on the selected radio button it should stay selected.
The changelog for version 5.0.0 should clearly document which zope.testbrowser APIs have disappeared, and what users are supposed to do when they upgrade their zope.testbrowser.
The following pseudocode sequence goes wrong with zope.testbrowser 5.4.0:
browser.open(...)
browser.getLink(...).click()
browser.title
browser.goBack()
browser.getLink(...)
The second call to getLink
incorrectly uses HTML from the previous response, cached by evaluating browser.title
.
Browser._html
and other related caches are invalidated by the Browser._changed
method, but this is only called from Browser._preparedRequest
; just navigating through history doesn't touch them. I think it would make a lot more sense to do the invalidation in Browser._setResponse
, since most of the cached properties are derived from the response.
mechanize
used to have this comment in its Referer header handling:
# See RFC 2616 14.36. The only times we know the source of the
# request URI has a URI associated with it are redirect, and
# Browser.click() / Browser.submit() / Browser.follow_link().
# Otherwise, it's the user's job to add any Referer header before
# .open()ing.
By contrast, if self.url
is set at the start of Browser._preparedRequest
, it just sets Referer to that. This means that if you do browser.open()
twice in a row, the second one gets its Referer set to the first URL.
mechanize
's behaviour was clearly more correct here. The RFC it quotes says: "The Referer field MUST NOT be sent if the Request-URI was obtained from a source that does not have its own URI, such as input from the user keyboard." In the context of a test browser, browser.open
is analogous to input from the user keyboard and should not result in sending a Referer header.
I ran into some very confusing test failures in Launchpad that I eventually tracked down to this. I hacked around it by doing browser._response = None
just before the relevant browser.open()
calls.
Given I have a form:
<form>
<select name="a">
<option value="b" selected="selected">b</option>
</select>
</form>
Trying to select something which is not an option using:
browser.getControl(name="a").displayValue = ['c']
silently ignores the unknown values. This results in no selected options in the example above.
I think in version 4.x an error was raised because there is no displayOption
with the required title. (But I currently do not have code at hand to check this as 4.x calls into mechanize
to select the value.)
The current behaviour is error prone for typos.
I propose to raise an exception (like KeyError
) in this case.
Any suggestions?
Given a form like
<select multiple name="select-multiple">
<option value="foo" />
<option value="bar" />
<option value="baz" />
</select>
if you find the ItemControl for foo
(call it item
) and set item.selected = True
twice in a row, zope.testbrowser ends up calling WebTest's MultipleSelect.value__set() with a list of values that contains duplicates, which in turn causes WebTest to raise
ValueError: Option(s) u'foo' not found (from u'foo', u'bar', u'baz')
Checkboxes become multiple controls that are handled together
when they are collected by Browser._findAllControls()
. Usually they all
have the same name. When there are other fields with the same
name โ or in a more normal and case multiple inputs with no name โ unexpected errors are possible.
Has anybody any idea how to fix this?
Those tests assert the expected behaviour but fail with the current implementation.
class TestsSameNameAndCheckboxes(unittest.TestCase):
"""Testing weird behaviour regarding checkboxes with the same name."""
def test_checkbox_controls_with_same_name_1(self):
"""A checkbox without name doesn't interfere with
throwing a LookupError. In this case, multiple input
fields are handled together but the checkbox is not
treated as that because the first input is a button.
"""
app = QuietTestApp()
browser = Browser(wsgi_app=app)
app.set_next_response(b'''\
<html><body>
<form action="." method="post" enctype="multipart/form-data">
<button type="button">Do Stuff</button>
<button type="button">Do Other Stuff</button>
<label for="checkbox">Label</label>
<input type="checkbox" id="checkbox">
</form></body></html>
''')
browser.open('http://localhost/')
with self.assertRaises(LookupError):
browser.getControl('Not There')
def test_checkbox_controls_with_same_name_2(self):
"""A checkbox is regognized as an ItemControl."""
app = QuietTestApp()
browser = Browser(wsgi_app=app)
app.set_next_response(b'''\
<html><body>
<form action="." method="post" enctype="multipart/form-data">
<button name="any" type="button">Do Stuff</button>
<button name="any" type="button">Do Other Stuff</button>
<label for="checkbox">Label</label>
<input name="any" type="checkbox" id="checkbox">
</form></body></html>
''')
browser.open('http://localhost/')
control = browser.getControl('Label')
assert isinstance(control, ItemControl)
def test_checkbox_controls_with_same_name_3(self):
"""A checkbox without name doesn't interfere with
throwing a LookupError. This time it seems to interpret the buttons
as options of the checkbox."""
app = QuietTestApp()
browser = Browser(wsgi_app=app)
app.set_next_response(b'''\
<html><body>
<form action="." method="post" enctype="multipart/form-data">
<label for="checkbox">Label</label>
<input type="checkbox" id="checkbox">
<button type="button">Do Stuff</button>
<button type="button">Do Other Stuff</button>
</form></body></html>
''')
browser.open('http://localhost/')
with self.assertRaises(LookupError):
browser.getControl('Not There')
.browser.SetattrErrorsMixin
prevents spelling errors when using certain classes in this packages. It maybe pre-date __slots__
(Python 2.2) which can be used to achieve the same goal.
The over_the_wire.txt test fails on the initial request too not only on the later request with a query string. Probably google changed the rules.
Probably we should skip/remove the on the wire tests at all because it's not what the testbrowser is used to do.
D:\git\zope\zope.testbrowser>bin\test.exe -pv1
Running tests at level 1
Running zope.testrunner.layer.UnitTests tests:
Set up zope.testrunner.layer.UnitTests in 0.000 seconds.
Running:
29/42 (69.0%) ... e\zope.testbrowser\src\zope\testbrowser\over_the_wire.txt
Failure in test d:\git\zope\zope.testbrowser\src\zope\testbrowser\over_the_wire.txt
Failed doctest test for over_the_wire.txt
File "d:\git\zope\zope.testbrowser\src\zope\testbrowser\over_the_wire.txt", line 0
----------------------------------------------------------------------
File "d:\git\zope\zope.testbrowser\src\zope\testbrowser\over_the_wire.txt", line 21, in over_the_wire.txt
Failed example:
browser.open('http://google.com/ncr')
Exception raised:
Traceback (most recent call last):
File "C:\Python27\lib\doctest.py", line 1289, in __run
compileflags, 1) in test.globs
File "<doctest over_the_wire.txt[3]>", line 1, in <module>
browser.open('http://google.com/ncr')
File "d:\git\zope\zope.testbrowser\src\zope\testbrowser\browser.py", line 244, in open
self._processRequest(url, make_request)
File "d:\git\zope\zope.testbrowser\src\zope\testbrowser\browser.py", line 266, in _processRequest
resp = make_request(reqargs)
File "d:\git\zope\zope.testbrowser\src\zope\testbrowser\browser.py", line 242, in <lambda>
make_request = lambda args: self.testapp.get(url, **args)
File "d:\home\.buildout\eggs\webtest-2.0.14-py2.7.egg\webtest\app.py", line 212, in get
expect_errors=expect_errors)
File "d:\git\zope\zope.testbrowser\src\zope\testbrowser\browser.py", line 81, in do_request
self._assertAllowed(req.url)
File "d:\git\zope\zope.testbrowser\src\zope\testbrowser\browser.py", line 78, in _assertAllowed
raise RobotExclusionError(url, 403, msg, [], None)
RobotExclusionError: HTTP Error 403: request disallowed by robots.txt
Ran 42 tests with 1 failures, 0 errors and 0 skipped in 1.626 seconds.
Tearing down left over layers:
Tear down zope.testrunner.layer.UnitTests in 0.000 seconds.
Tests with failures:
d:\git\zope\zope.testbrowser\src\zope\testbrowser\over_the_wire.txt
Would be nice if there was support in zope.testbrowser.
See for example https://mail.zope.org/pipermail/zope3-users/2008-May/007871.html
When will a release be available for the new wsgi app based 5.0.0 version? I'm asking because It looks very promising.
There's one test failure caused by webtest trying to guess the mimetype of the uploaded file because, apparently, Windows has never heard about CSV files.
This can be fixed by explicitly passing the MIME type to webtest.forms.Upload(filename, body, mimetype)
. This requires WebTest >= 2.0.8.
Here's another of those mechanize-to-webtest compatibility issues:
<a href="..."><span>My link</span></a>
used to be findable with browser.getLink('My link')
, since mechanize collects all nested text, but now it's not found anymore, since zope.testbrowser only looks at the directly contained text.
The old mechanize-based zope.testbrowser allowed the following:
>>> print(browser.contents)
...
<iframe width="..." height="..." src="http://localhost/style_preview.html"></iframe>
...
>>> browser.getLink(url='preview')
<Link text=None url='http://localhost/pdr/style_preview.html'>
>>> browser.getLink(url='preview').click()
The new WebTest-based zope.testbrowser does not treat iframes as links.
(I'm not arguing that it should, but maybe we want to add a note about this to the documentation and WONTFIX this bug?)
I saw there always following Location URL,
https://github.com/zopefoundation/zope.testbrowser/blob/master/src/zope/testbrowser/browser.py#L278
but previously in an older version, I used to browser.mech_browser.set_handle_redirect(False)
Is there any way to do something like this?
See https://travis-ci.org/zopefoundation/zope.testbrowser on the tab named "current"
Someone with admin permissions in this repository should be able to fix this.
e.g.,
zope/testbrowser/_compat.py:44: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
from collections import MutableMapping # noqa
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.