From 5dd7be0ff1a59c82a9343eb9bfecab7df566509b Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Sun, 10 Nov 2019 11:11:04 +0000 Subject: [PATCH] Invalidate caches in Browser.goBack() Most of the cached attributes invalidated by Browser._changed() were based on the response, so it makes more sense to invalidate them from Browser._setResponse. This means that Browser.goBack() now invalidates these caches, so subsequent uses of methods such as Browser.getLink() work properly. _req_content_type is an exception to this: this is a property of the request, set by Browser.post(), and it still makes sense to clear this in Browser._preparedRequest(). Fixes #83. --- CHANGES.rst | 4 +- src/zope/testbrowser/browser.py | 4 +- src/zope/testbrowser/tests/test_browser.py | 46 ++++++++++++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index a4c8e0e..2746b9d 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,7 +5,9 @@ CHANGES 5.4.1 (unreleased) ------------------ -- Nothing changed yet. +- Fix a bug where ``browser.goBack()`` did not invalidate caches, so + subsequent queries could use data from the wrong response. See `issue 83 + `_. 5.4.0 (2019-11-01) diff --git a/src/zope/testbrowser/browser.py b/src/zope/testbrowser/browser.py index f518f2b..54796d1 100644 --- a/src/zope/testbrowser/browser.py +++ b/src/zope/testbrowser/browser.py @@ -310,6 +310,7 @@ def _submit(self, form, name=None, index=None, coord=None, **args): def _setResponse(self, response): self._response = response + self._changed() def getLink(self, text=None, url=None, id=None, index=0): """See zope.testbrowser.interfaces.IBrowser""" @@ -475,7 +476,6 @@ def _changed(self): self._contents = None self._controls = {} self.__html = None - self._req_content_type = None @contextmanager def _preparedRequest(self, url): @@ -510,7 +510,7 @@ def _preparedRequest(self, url): yield kwargs - self._changed() + self._req_content_type = None self.timer.stop() def _absoluteUrl(self, url): diff --git a/src/zope/testbrowser/tests/test_browser.py b/src/zope/testbrowser/tests/test_browser.py index c29744e..4c40f25 100644 --- a/src/zope/testbrowser/tests/test_browser.py +++ b/src/zope/testbrowser/tests/test_browser.py @@ -425,6 +425,52 @@ def test_reload_after_post(): """ +def test_goBack_changes_cached_html(self): + """ + goBack() causes the browser to clear its cached parsed HTML, so queries + that rely on that use the correct response. + + >>> app = TestApp() + >>> browser = Browser(wsgi_app=app) + >>> app.set_next_response(b'''\ + ... + ... First page + ... link + ... + ... ''') + >>> browser.open('http://localhost/') + GET / HTTP/1.1 + ... + >>> browser.title + 'First page' + >>> browser.getLink('link').url + 'http://localhost/foo' + + >>> app.set_next_response(b'''\ + ... + ... Second page + ... link + ... + ... ''') + >>> browser.open('http://localhost/') + GET / HTTP/1.1 + ... + >>> browser.title + 'Second page' + >>> browser.getLink('link').url + 'http://localhost/bar' + + After going back, queries once again return answers based on the first + response. + + >>> browser.goBack() + >>> browser.title + 'First page' + >>> browser.getLink('link').url + 'http://localhost/foo' + """ + + def test_button_without_name(self): """ This once blew up.