From e57d2be6ee9cfd0ce00eaa10275517c33857cd9a Mon Sep 17 00:00:00 2001 From: Joshua Fehler Date: Sun, 9 Jun 2024 20:08:37 -0400 Subject: [PATCH 1/2] Standardise LXML driver tests --- tests/base.py | 5 ++ tests/lxml_drivers.py | 128 ++++++++++++++++++++++++++++++++ tests/test_djangoclient.py | 116 +---------------------------- tests/test_flaskclient.py | 132 +-------------------------------- tests/test_webdriver.py | 6 -- tests/test_zopetestbrowser.py | 133 +--------------------------------- 6 files changed, 141 insertions(+), 379 deletions(-) create mode 100644 tests/lxml_drivers.py diff --git a/tests/base.py b/tests/base.py index ce7c872d7..dc43689bb 100644 --- a/tests/base.py +++ b/tests/base.py @@ -53,6 +53,11 @@ def get_new_browser(self): driver_name = self.browser.driver_name.lower() return get_browser(driver_name) + def test_should_support_with_statement(self): + browser = self.get_new_browser() + with browser as b: + assert b is not None + def test_can_open_page(self): """should be able to visit, get title and quit""" self.browser.visit(EXAMPLE_APP) diff --git a/tests/lxml_drivers.py b/tests/lxml_drivers.py new file mode 100644 index 000000000..8d0feaebc --- /dev/null +++ b/tests/lxml_drivers.py @@ -0,0 +1,128 @@ +import os + +import pytest + +from .fake_webapp import EXAMPLE_APP + + +class LxmlDriverTests: + def test_cant_switch_to_frame(self): + """lxml-based drivers should not be able to switch to frames""" + with pytest.raises(NotImplementedError) as err: + self.browser.get_iframe("frame_123") + self.fail() + + assert f"{self.browser.driver_name.lower()} doesn't support frames." == err.value.args[0] + + def test_attach_file(self): + """should provide a way to change file field value""" + file_path = os.path.join( + os.path.abspath(os.path.dirname(__file__)), + "mockfile.txt", + ) + self.browser.attach_file("file", file_path) + self.browser.find_by_name("upload").click() + + html = self.browser.html + assert "text/plain" in html + with open(file_path) as f: + assert f.read() in html + + def test_forward_to_none_page(self): + """lxml-based drivers should not fail when trying to forward to none""" + browser = self.get_new_browser() + browser.visit(EXAMPLE_APP) + browser.forward() + assert EXAMPLE_APP == browser.url + browser.quit() + + def test_can_clear_password_field_content(self): + """lxml-based drivers should not be able to clear""" + with pytest.raises(NotImplementedError): + self.browser.find_by_name("password").first.clear() + + def test_can_clear_tel_field_content(self): + """lxml-based drivers should not be able to clear""" + with pytest.raises(NotImplementedError): + self.browser.find_by_name("telephone").first.clear() + + def test_can_clear_text_field_content(self): + """lxml-based drivers should not be able to clear""" + with pytest.raises(NotImplementedError): + self.browser.find_by_name("query").first.clear() + + def test_can_clear_textarea_content(self): + """lxml-based drivers should not be able to clear""" + with pytest.raises(NotImplementedError): + self.browser.find_by_name("description").first.clear() + + def test_can_clear_search_content(self): + """lxml-based drivers should not be able to clear""" + with pytest.raises(NotImplementedError): + self.browser.find_by_name("search_keyword").first.clear() + + def test_can_clear_url_content(self): + """lxml-based drivers should not be able to clear""" + with pytest.raises(NotImplementedError): + self.browser.find_by_name("url_input").first.clear() + + def test_simple_type(self): + """ + lxml-based drivers won't support type method + because it doesn't interact with JavaScript + """ + with pytest.raises(NotImplementedError): + self.browser.type("query", "with type method") + + def test_simple_type_on_element(self): + """ + lxml-based drivers won't support type method + because it doesn't interact with JavaScript + """ + with pytest.raises(NotImplementedError): + self.browser.find_by_name("query").type("with type method") + + def test_slowly_typing(self): + """ + lxml-based drivers won't support type method + because it doesn't interact with JavaScript + """ + with pytest.raises(NotImplementedError): + self.browser.type("query", "with type method", slowly=True) + + def test_slowly_typing_on_element(self): + """ + lxml-based drivers won't support type method + on element because it doesn't interac with JavaScript + """ + with pytest.raises(NotImplementedError): + query = self.browser.find_by_name("query") + query.type("with type method", slowly=True) + + def test_cant_mouseover(self): + """lxml-based drivers should not be able to put the mouse over the element""" + with pytest.raises(NotImplementedError): + self.browser.find_by_css("#visible").mouse_over() + + def test_cant_mouseout(self): + """lxml-based drivers should not be able to mouse out of an element""" + with pytest.raises(NotImplementedError): + self.browser.find_by_css("#visible").mouse_out() + + def test_finding_all_links_by_non_ascii_text(self): + """lxml-based drivers should find links by non ascii text""" + non_ascii_encodings = { + "pangram_pl": "Jeżu klątw, spłódź Finom część gry hańb!", + "pangram_ja": "天 地 星 空", + "pangram_ru": "В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!", # NOQA RUF001 + "pangram_eo": "Laŭ Ludoviko Zamenhof bongustas freŝa ĉeĥa manĝaĵo kun spicoj.", + } + for key, text in non_ascii_encodings.items(): + link = self.browser.links.find_by_text(text) + assert key == link["id"] + + def test_links_with_nested_tags_xpath(self): + links = self.browser.find_by_xpath('//a/span[text()="first bar"]/..') + assert len(links) == 1, 'Found more than one link with a span with text "BAR ONE". %s' % [ + item.outer_html for item in links + ] diff --git a/tests/test_djangoclient.py b/tests/test_djangoclient.py index 0ae818642..4d5f3dbe5 100644 --- a/tests/test_djangoclient.py +++ b/tests/test_djangoclient.py @@ -11,7 +11,7 @@ from .base import BaseBrowserTests from .base import get_browser from .fake_webapp import EXAMPLE_APP -from splinter import Browser +from .lxml_drivers import LxmlDriverTests sys.path.append("tests/fake_django") @@ -21,7 +21,7 @@ django.setup() -class TestDjangoClientDriver(BaseBrowserTests): +class TestDjangoClientDriver(BaseBrowserTests, LxmlDriverTests): @pytest.fixture(autouse=True, scope="class") def setup_browser(self, request): request.cls.browser = get_browser("django") @@ -31,116 +31,6 @@ def setup_browser(self, request): def visit_example_app(self): self.browser.visit(EXAMPLE_APP) - def test_should_support_with_statement(self): - with Browser("django") as internet: - assert internet is not None - - def test_attach_file(self): - "should provide a way to change file field value" - file_path = os.path.join( - os.path.abspath(os.path.dirname(__file__)), - "mockfile.txt", - ) - self.browser.attach_file("file", file_path) - self.browser.find_by_name("upload").click() - - html = self.browser.html - assert "text/plain" in html - with open(file_path) as f: - assert f.read() in html - - def test_forward_to_none_page(self): - "should not fail when trying to forward to none" - browser = Browser("django") - browser.visit(EXAMPLE_APP) - browser.forward() - assert EXAMPLE_APP == browser.url - browser.quit() - - def test_can_clear_password_field_content(self): - "django should not be able to clear" - with pytest.raises(NotImplementedError): - self.browser.find_by_name("password").first.clear() - - def test_can_clear_tel_field_content(self): - "django should not be able to clear" - with pytest.raises(NotImplementedError): - self.browser.find_by_name("telephone").first.clear() - - def test_can_clear_text_field_content(self): - "django should not be able to clear" - with pytest.raises(NotImplementedError): - self.browser.find_by_name("query").first.clear() - - def test_cant_switch_to_frame(self): - "django driver should not be able to switch to frames" - with pytest.raises(NotImplementedError) as err: - self.browser.get_iframe("frame_123") - self.fail() - - assert "django doesn't support frames." == err.value.args[0] - - def test_simple_type(self): - """ - django won't support type method - because it doesn't interact with JavaScript - """ - with pytest.raises(NotImplementedError): - self.browser.type("query", "with type method") - - def test_simple_type_on_element(self): - """ - django won't support type method - because it doesn't interact with JavaScript - """ - with pytest.raises(NotImplementedError): - self.browser.find_by_name("query").type("with type method") - - def test_slowly_typing(self): - """ - django won't support type method - because it doesn't interact with JavaScript - """ - with pytest.raises(NotImplementedError): - self.browser.type("query", "with type method", slowly=True) - - def test_slowly_typing_on_element(self): - """ - django won't support type method - on element because it doesn't interac with JavaScript - """ - with pytest.raises(NotImplementedError): - query = self.browser.find_by_name("query") - query.type("with type method", slowly=True) - - def test_cant_mouseover(self): - "django should not be able to put the mouse over the element" - with pytest.raises(NotImplementedError): - self.browser.find_by_css("#visible").mouse_over() - - def test_cant_mouseout(self): - "django should not be able to mouse out of an element" - with pytest.raises(NotImplementedError): - self.browser.find_by_css("#visible").mouse_out() - - def test_links_with_nested_tags_xpath(self): - links = self.browser.find_by_xpath('//a/span[text()="first bar"]/..') - assert len(links) == 1, 'Found more than one link with a span with text "BAR ONE". %s' % [ - item.outer_html for item in links - ] - - def test_finding_all_links_by_non_ascii_text(self): - "should find links by non ascii text" - non_ascii_encodings = { - "pangram_pl": "Jeżu klątw, spłódź Finom część gry hańb!", - "pangram_ja": "天 地 星 空", - "pangram_ru": "В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!", # NOQA RUF001 - "pangram_eo": "Laŭ Ludoviko Zamenhof bongustas freŝa ĉeĥa manĝaĵo kun spicoj.", - } - for key, text in non_ascii_encodings.items(): - link = self.browser.links.find_by_text(text) - assert key == link["id"] - def test_cookies_extra_parameters(self): """Cookie can be created with extra parameters.""" timestamp = int(time.time() + 120) @@ -159,7 +49,7 @@ def setup_browser(self, request): request.cls.browser = get_browser("django", custom_headers=custom_headers) request.addfinalizer(request.cls.browser.quit) - def test_create_a_phantomjs_with_custom_headers(self): + def test_create_a_browser_with_custom_headers(self): self.browser.visit(EXAMPLE_APP + "headers") assert self.browser.is_text_present("X-Splinter-Customheaders-1: Hello") diff --git a/tests/test_flaskclient.py b/tests/test_flaskclient.py index 28dc02b25..e8ad3e97b 100644 --- a/tests/test_flaskclient.py +++ b/tests/test_flaskclient.py @@ -1,7 +1,6 @@ # Copyright 2014 splinter authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -import os import time import pytest @@ -10,10 +9,10 @@ from .base import get_browser from .fake_webapp import app from .fake_webapp import EXAMPLE_APP -from splinter import Browser +from .lxml_drivers import LxmlDriverTests -class TestFlaskClientDriver(BaseBrowserTests): +class TestFlaskClientDriver(BaseBrowserTests, LxmlDriverTests): @pytest.fixture(autouse=True, scope="class") def setup_browser(self, request): request.cls.browser = get_browser("flask", app=app, wait_time=0.1) @@ -23,138 +22,13 @@ def setup_browser(self, request): def visit_example_app(self, request): self.browser.visit(EXAMPLE_APP) - def test_should_support_with_statement(self): - with Browser("flask", app=app) as internet: - assert internet is not None - - def test_attach_file(self): - "should provide a way to change file field value" - file_path = os.path.join( - os.path.abspath(os.path.dirname(__file__)), - "mockfile.txt", - ) - self.browser.attach_file("file", file_path) - self.browser.find_by_name("upload").click() - - html = self.browser.html - assert "text/plain" in html - with open(file_path) as f: - assert f.read() in html - def test_serialize_select_mutiple(self): - "should serialize a select with multiple values into a list" + """should serialize a select with multiple values into a list""" self.browser.select("pets", ["cat", "dog"]) form = self.browser.find_by_name("send")._get_parent_form() data = self.browser.serialize(form) assert data["pets"] == ["cat", "dog"] - def test_forward_to_none_page(self): - "should not fail when trying to forward to none" - browser = Browser("flask", app=app) - browser.visit(EXAMPLE_APP) - browser.forward() - assert EXAMPLE_APP == browser.url - browser.quit() - - def test_can_clear_password_field_content(self): - "flask should not be able to clear" - with pytest.raises(NotImplementedError): - self.browser.find_by_name("password").first.clear() - - def test_can_clear_tel_field_content(self): - "flask should not be able to clear" - with pytest.raises(NotImplementedError): - self.browser.find_by_name("telephone").first.clear() - - def test_can_clear_text_field_content(self): - "flask should not be able to clear" - with pytest.raises(NotImplementedError): - self.browser.find_by_name("query").first.clear() - - def test_can_clear_textarea_content(self): - "flask should not be able to clear" - with pytest.raises(NotImplementedError): - self.browser.find_by_name("description").first.clear() - - def test_can_clear_search_content(self): - "flask should not be able to clear" - with pytest.raises(NotImplementedError): - self.browser.find_by_name("search_keyword").first.clear() - - def test_can_clear_url_content(self): - "flask should not be able to clear" - with pytest.raises(NotImplementedError): - self.browser.find_by_name("url_input").first.clear() - - def test_cant_switch_to_frame(self): - "flask should not be able to switch to frames" - with pytest.raises(NotImplementedError) as err: - self.browser.get_iframe("frame_123") - self.fail() - - assert "flask doesn't support frames." == err.value.args[0] - - def test_simple_type(self): - """ - flask won't support type method - because it doesn't interact with JavaScript - """ - with pytest.raises(NotImplementedError): - self.browser.type("query", "with type method") - - def test_simple_type_on_element(self): - """ - flask won't support type method - because it doesn't interact with JavaScript - """ - with pytest.raises(NotImplementedError): - self.browser.find_by_name("query").type("with type method") - - def test_slowly_typing(self): - """ - flask won't support type method - because it doesn't interact with JavaScript - """ - with pytest.raises(NotImplementedError): - self.browser.type("query", "with type method", slowly=True) - - def test_slowly_typing_on_element(self): - """ - flask won't support type method - on element because it doesn't interac with JavaScript - """ - with pytest.raises(NotImplementedError): - query = self.browser.find_by_name("query") - query.type("with type method", slowly=True) - - def test_cant_mouseover(self): - "flask should not be able to put the mouse over the element" - with pytest.raises(NotImplementedError): - self.browser.find_by_css("#visible").mouse_over() - - def test_cant_mouseout(self): - "flask should not be able to mouse out of an element" - with pytest.raises(NotImplementedError): - self.browser.find_by_css("#visible").mouse_out() - - def test_links_with_nested_tags_xpath(self): - links = self.browser.find_by_xpath('//a/span[text()="first bar"]/..') - assert len(links) == 1, 'Found more than one link with a span with text "BAR ONE". %s' % [ - item.outer_html for item in links - ] - - def test_finding_all_links_by_non_ascii_text(self): - "should find links by non ascii text" - non_ascii_encodings = { - "pangram_pl": "Jeżu klątw, spłódź Finom część gry hańb!", - "pangram_ja": "天 地 星 空", - "pangram_ru": "В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!", # NOQA RUF001 - "pangram_eo": "Laŭ Ludoviko Zamenhof bongustas freŝa ĉeĥa manĝaĵo kun spicoj.", - } - for key, text in non_ascii_encodings.items(): - link = self.browser.links.find_by_text(text) - assert key == link["id"] - def test_redirection_on_post(self): """ when submitting a form that POSTs to /redirected, diff --git a/tests/test_webdriver.py b/tests/test_webdriver.py index b8e026f1b..015e07fca 100644 --- a/tests/test_webdriver.py +++ b/tests/test_webdriver.py @@ -44,12 +44,6 @@ def test_attach_file(request, browser_name): assert str(f.read()) in html -@pytest.mark.parametrize("browser_name", supported_browsers) -def test_should_support_with_statement(browser_name): - with get_browser(browser_name): - pass - - @pytest.mark.parametrize("browser_name", supported_browsers) def test_browser_config(request, browser_name): """Splinter's drivers get the Config object when it's passed through the Browser function.""" diff --git a/tests/test_zopetestbrowser.py b/tests/test_zopetestbrowser.py index ed819cfb8..9dbee33db 100644 --- a/tests/test_zopetestbrowser.py +++ b/tests/test_zopetestbrowser.py @@ -1,17 +1,15 @@ # Copyright 2013 splinter authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -import os - import pytest from .base import BaseBrowserTests from .base import get_browser from .fake_webapp import EXAMPLE_APP -from splinter import Browser +from .lxml_drivers import LxmlDriverTests -class TestZopeTestBrowserDriver(BaseBrowserTests): +class TestZopeTestBrowserDriver(BaseBrowserTests, LxmlDriverTests): @pytest.fixture(autouse=True, scope="class") def setup_browser(self, request): request.cls.browser = get_browser("zope.testbrowser", wait_time=0.1) @@ -21,133 +19,6 @@ def setup_browser(self, request): def visit_example_app(self, request): self.browser.visit(EXAMPLE_APP) - def test_should_support_with_statement(self): - with Browser("zope.testbrowser"): - pass - - def test_attach_file(self): - "should provide a way to change file field value" - file_path = os.path.join( - os.path.abspath(os.path.dirname(__file__)), - "mockfile.txt", - ) - self.browser.attach_file("file", file_path) - self.browser.find_by_name("upload").click() - - html = self.browser.html - - assert "text/plain" in html - - with open(file_path) as f: - assert f.read() in html - - def test_forward_to_none_page(self): - "should not fail when trying to forward to none" - browser = Browser("zope.testbrowser") - browser.visit(EXAMPLE_APP) - browser.forward() - assert EXAMPLE_APP == browser.url - browser.quit() - - def test_cant_switch_to_frame(self): - "zope.testbrowser should not be able to switch to frames" - with pytest.raises(NotImplementedError) as err: - self.browser.get_iframe("frame_123") - self.fail() - - assert "zope.testbrowser doesn't support frames." == err.value.args[0] - - def test_simple_type(self): - """ - zope.testbrowser won't support type method - because it doesn't interact with JavaScript - """ - with pytest.raises(NotImplementedError): - self.browser.type("query", "with type method") - - def test_simple_type_on_element(self): - """ - zope.testbrowser won't support type method - because it doesn't interact with JavaScript - """ - with pytest.raises(NotImplementedError): - self.browser.find_by_name("query").type("with type method") - - def test_can_clear_password_field_content(self): - "zope.testbrowser should not be able to clear" - with pytest.raises(NotImplementedError): - self.browser.find_by_name("password").first.clear() - - def test_can_clear_tel_field_content(self): - "zope.testbrowser should not be able to clear" - with pytest.raises(NotImplementedError): - self.browser.find_by_name("telephone").first.clear() - - def test_can_clear_text_field_content(self): - "zope.testbrowser should not be able to clear" - with pytest.raises(NotImplementedError): - self.browser.find_by_name("query").first.clear() - - def test_can_clear_textarea_content(self): - "flask should not be able to clear" - with pytest.raises(NotImplementedError): - self.browser.find_by_name("description").first.clear() - - def test_can_clear_search_content(self): - "flask should not be able to clear" - with pytest.raises(NotImplementedError): - self.browser.find_by_name("search_keyword").first.clear() - - def test_can_clear_url_content(self): - "flask should not be able to clear" - with pytest.raises(NotImplementedError): - self.browser.find_by_name("url_input").first.clear() - - def test_slowly_typing(self): - """ - zope.testbrowser won't support type method - because it doesn't interact with JavaScript - """ - with pytest.raises(NotImplementedError): - self.browser.type("query", "with type method", slowly=True) - - def test_slowly_typing_on_element(self): - """ - zope.testbrowser won't support type method - on element because it doesn't interac with JavaScript - """ - with pytest.raises(NotImplementedError): - query = self.browser.find_by_name("query") - query.type("with type method", slowly=True) - - def test_cant_mouseover(self): - "zope.testbrowser should not be able to put the mouse over the element" - with pytest.raises(NotImplementedError): - self.browser.find_by_css("#visible").mouse_over() - - def test_cant_mouseout(self): - "zope.testbrowser should not be able to mouse out of an element" - with pytest.raises(NotImplementedError): - self.browser.find_by_css("#visible").mouse_out() - - def test_links_with_nested_tags_xpath(self): - links = self.browser.find_by_xpath('//a/span[text()="first bar"]/..') - assert len(links) == 1, 'Found more than one link with a span with text "BAR ONE". %s' % [ - item.outer_html for item in links - ] - - def test_finding_all_links_by_non_ascii_text(self): - "should find links by non ascii text" - non_ascii_encodings = { - "pangram_pl": "Jeżu klątw, spłódź Finom część gry hańb!", - "pangram_ja": "天 地 星 空", - "pangram_ru": "В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!", # NOQA RUF001 - "pangram_eo": "Laŭ Ludoviko Zamenhof bongustas freŝa ĉeĥa manĝaĵo kun spicoj.", - } - for key, text in non_ascii_encodings.items(): - link = self.browser.links.find_by_text(text) - assert key == link["id"] - def test_fill_form_missing_values(self): """Missing values should raise an error.""" with pytest.raises(LookupError): From 41e29057177fd1a6a35cdfc78144aad4f0d5cc7d Mon Sep 17 00:00:00 2001 From: Joshua Fehler Date: Sun, 9 Jun 2024 20:39:07 -0400 Subject: [PATCH 2/2] fixup --- tests/test_djangoclient.py | 2 +- tests/test_flaskclient.py | 2 +- tests/test_zopetestbrowser.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_djangoclient.py b/tests/test_djangoclient.py index 4d5f3dbe5..843e68984 100644 --- a/tests/test_djangoclient.py +++ b/tests/test_djangoclient.py @@ -21,7 +21,7 @@ django.setup() -class TestDjangoClientDriver(BaseBrowserTests, LxmlDriverTests): +class TestDjangoClientDriver(LxmlDriverTests, BaseBrowserTests): @pytest.fixture(autouse=True, scope="class") def setup_browser(self, request): request.cls.browser = get_browser("django") diff --git a/tests/test_flaskclient.py b/tests/test_flaskclient.py index e8ad3e97b..c5ece799c 100644 --- a/tests/test_flaskclient.py +++ b/tests/test_flaskclient.py @@ -12,7 +12,7 @@ from .lxml_drivers import LxmlDriverTests -class TestFlaskClientDriver(BaseBrowserTests, LxmlDriverTests): +class TestFlaskClientDriver(LxmlDriverTests, BaseBrowserTests): @pytest.fixture(autouse=True, scope="class") def setup_browser(self, request): request.cls.browser = get_browser("flask", app=app, wait_time=0.1) diff --git a/tests/test_zopetestbrowser.py b/tests/test_zopetestbrowser.py index 9dbee33db..c28759bed 100644 --- a/tests/test_zopetestbrowser.py +++ b/tests/test_zopetestbrowser.py @@ -9,7 +9,7 @@ from .lxml_drivers import LxmlDriverTests -class TestZopeTestBrowserDriver(BaseBrowserTests, LxmlDriverTests): +class TestZopeTestBrowserDriver(LxmlDriverTests, BaseBrowserTests): @pytest.fixture(autouse=True, scope="class") def setup_browser(self, request): request.cls.browser = get_browser("zope.testbrowser", wait_time=0.1)