Merge pull request #668 from The-Compiler/visual-tests
Add javascript tests for position_caret.js.
This commit is contained in:
commit
1a957b6c10
23
tests/javascript/base.html
Normal file
23
tests/javascript/base.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
vim: ft=html fileencoding=utf-8 sts=4 sw=4 et:
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>qutebrowser javascript test</title>
|
||||
<style type="text/css">
|
||||
{% block style %}
|
||||
body {
|
||||
font-size: 50px;
|
||||
line-height: 70px;
|
||||
}
|
||||
{% endblock %}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
</html>
|
141
tests/javascript/conftest.py
Normal file
141
tests/javascript/conftest.py
Normal file
@ -0,0 +1,141 @@
|
||||
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
||||
|
||||
# Copyright 2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
|
||||
#
|
||||
# This file is part of qutebrowser.
|
||||
#
|
||||
# qutebrowser is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# qutebrowser is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""pylint conftest file for javascript test."""
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
import jinja2
|
||||
from PyQt5.QtWebKit import QWebSettings
|
||||
from PyQt5.QtWebKitWidgets import QWebView, QWebPage
|
||||
|
||||
import qutebrowser
|
||||
|
||||
|
||||
class TestWebPage(QWebPage):
|
||||
|
||||
"""QWebPage subclass which overrides some test methods.
|
||||
|
||||
Attributes:
|
||||
_logger: The logger used for alerts.
|
||||
"""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self._logger = logging.getLogger('js-tests')
|
||||
|
||||
def javaScriptAlert(self, _frame, msg):
|
||||
"""Log javascript alerts."""
|
||||
self._logger.info("js alert: {}".format(msg))
|
||||
|
||||
def javaScriptConfirm(self, _frame, msg):
|
||||
"""Fail tests on js confirm() as that should never happen."""
|
||||
pytest.fail("js confirm: {}".format(msg))
|
||||
|
||||
def javaScriptPrompt(self, _frame, msg, _default):
|
||||
"""Fail tests on js prompt() as that should never happen."""
|
||||
pytest.fail("js prompt: {}".format(msg))
|
||||
|
||||
def javaScriptConsoleMessage(self, msg, line, source):
|
||||
"""Fail tests on js console messages as they're used for errors."""
|
||||
pytest.fail("js console ({}:{}): {}".format(source, line, msg))
|
||||
|
||||
|
||||
class JSTester:
|
||||
|
||||
"""Object returned by js_tester which provides test data and a webview.
|
||||
|
||||
Attributes:
|
||||
webview: The webview which is used.
|
||||
_qtbot: The QtBot fixture from pytest-qt.
|
||||
_jinja_env: The jinja2 environment used to get templates.
|
||||
"""
|
||||
|
||||
def __init__(self, webview, qtbot):
|
||||
self.webview = webview
|
||||
self.webview.setPage(TestWebPage(self.webview))
|
||||
self._qtbot = qtbot
|
||||
loader = jinja2.FileSystemLoader(os.path.dirname(__file__))
|
||||
self._jinja_env = jinja2.Environment(loader=loader, autoescape=True)
|
||||
|
||||
def scroll_anchor(self, name):
|
||||
"""Scroll the main frame to the given anchor."""
|
||||
page = self.webview.page()
|
||||
with self._qtbot.waitSignal(page.scrollRequested):
|
||||
page.mainFrame().scrollToAnchor(name)
|
||||
|
||||
def load(self, path, **kwargs):
|
||||
"""Load and display the given test data.
|
||||
|
||||
Args:
|
||||
path: The path to the test file, relative to the javascript/
|
||||
folder.
|
||||
**kwargs: Passed to jinja's template.render().
|
||||
"""
|
||||
template = self._jinja_env.get_template(path)
|
||||
with self._qtbot.waitSignal(self.webview.loadFinished):
|
||||
self.webview.setHtml(template.render(**kwargs))
|
||||
|
||||
def run_file(self, filename):
|
||||
"""Run a javascript file.
|
||||
|
||||
Args:
|
||||
filename: The javascript filename, relative to
|
||||
qutebrowser/javascript.
|
||||
|
||||
Return:
|
||||
The javascript return value.
|
||||
"""
|
||||
base_path = os.path.join(os.path.dirname(qutebrowser.__file__),
|
||||
'javascript')
|
||||
full_path = os.path.join(base_path, filename)
|
||||
with open(full_path, 'r', encoding='utf-8') as f:
|
||||
source = f.read()
|
||||
return self.run(source)
|
||||
|
||||
def run(self, source):
|
||||
"""Run the given javascript source.
|
||||
|
||||
Args:
|
||||
source: The source to run as a string.
|
||||
|
||||
Return:
|
||||
The javascript return value.
|
||||
"""
|
||||
assert self.webview.settings().testAttribute(
|
||||
QWebSettings.JavascriptEnabled)
|
||||
return self.webview.page().mainFrame().evaluateJavaScript(source)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def js_tester(qtbot):
|
||||
"""Fixture to test javascript snippets.
|
||||
|
||||
Provides a QWebView with a 640x480px size and a JSTester instance.
|
||||
|
||||
Args:
|
||||
qtbot: pytestqt.plugin.QtBot fixture.
|
||||
"""
|
||||
webview = QWebView()
|
||||
qtbot.add_widget(webview)
|
||||
webview.resize(640, 480)
|
||||
return JSTester(webview, qtbot)
|
5
tests/javascript/position_caret/invisible.html
Normal file
5
tests/javascript/position_caret/invisible.html
Normal file
@ -0,0 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<p style="{{style}}">This line is hidden.</p>
|
||||
<p>MARKER this should be the paragraph the caret is on.</p>
|
||||
{% endblock %}
|
8
tests/javascript/position_caret/scrolled_down.html
Normal file
8
tests/javascript/position_caret/scrolled_down.html
Normal file
@ -0,0 +1,8 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales ligula in libero. </p>
|
||||
|
||||
<a id="anchor" /><p>MARKER this should be the paragraph the caret is on.</p>
|
||||
|
||||
<p>Some more text</p>
|
||||
{% endblock %}
|
9
tests/javascript/position_caret/scrolled_down_img.html
Normal file
9
tests/javascript/position_caret/scrolled_down_img.html
Normal file
@ -0,0 +1,9 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales ligula in libero. </p>
|
||||
|
||||
<a id="anchor" /><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wUMEQsSoCNVVgAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAFklEQVQoz2P8z0AaYGIY1TCqYdhqAABALgEfsZDCTQAAAABJRU5ErkJggg==" />
|
||||
|
||||
<p>MARKER this should be the paragraph the caret is on.</p>
|
||||
<p>Some more text</p>
|
||||
{% endblock %}
|
4
tests/javascript/position_caret/simple.html
Normal file
4
tests/javascript/position_caret/simple.html
Normal file
@ -0,0 +1,4 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<p>MARKER this should be the paragraph the caret is on.</p>
|
||||
{% endblock %}
|
96
tests/javascript/position_caret/test_position_caret.py
Normal file
96
tests/javascript/position_caret/test_position_caret.py
Normal file
@ -0,0 +1,96 @@
|
||||
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
||||
|
||||
# Copyright 2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
|
||||
#
|
||||
# This file is part of qutebrowser.
|
||||
#
|
||||
# qutebrowser is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# qutebrowser is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Tests for position_caret.js."""
|
||||
|
||||
import pytest
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWebKit import QWebSettings
|
||||
from PyQt5.QtWebKitWidgets import QWebPage
|
||||
|
||||
|
||||
@pytest.yield_fixture(autouse=True)
|
||||
def enable_caret_browsing():
|
||||
"""Fixture to enable caret browsing globally."""
|
||||
settings = QWebSettings.globalSettings()
|
||||
old_value = settings.testAttribute(QWebSettings.CaretBrowsingEnabled)
|
||||
settings.setAttribute(QWebSettings.CaretBrowsingEnabled, True)
|
||||
yield
|
||||
settings.setAttribute(QWebSettings.CaretBrowsingEnabled, old_value)
|
||||
|
||||
|
||||
class CaretTester:
|
||||
|
||||
"""Helper class (for the caret_tester fixture) for asserts.
|
||||
|
||||
Attributes:
|
||||
js: The js_tester fixture.
|
||||
"""
|
||||
|
||||
def __init__(self, js_tester):
|
||||
self.js = js_tester
|
||||
|
||||
def check(self):
|
||||
"""Check whether the caret is before the MARKER text."""
|
||||
self.js.run_file('position_caret.js')
|
||||
self.js.webview.triggerPageAction(QWebPage.SelectNextWord)
|
||||
assert self.js.webview.selectedText() == "MARKER"
|
||||
|
||||
def check_scrolled(self):
|
||||
"""Check if the page is scrolled down."""
|
||||
frame = self.js.webview.page().mainFrame()
|
||||
minimum = frame.scrollBarMinimum(Qt.Vertical)
|
||||
value = frame.scrollBarValue(Qt.Vertical)
|
||||
assert value > minimum
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def caret_tester(js_tester):
|
||||
"""Helper fixture to test caret browsing positions."""
|
||||
return CaretTester(js_tester)
|
||||
|
||||
|
||||
def test_simple(caret_tester):
|
||||
"""Test with a simple (one-line) HTML text."""
|
||||
caret_tester.js.load('position_caret/simple.html')
|
||||
caret_tester.check()
|
||||
|
||||
|
||||
def test_scrolled_down(caret_tester):
|
||||
"""Test with multiple text blocks with the viewport scrolled down."""
|
||||
caret_tester.js.load('position_caret/scrolled_down.html')
|
||||
caret_tester.js.scroll_anchor('anchor')
|
||||
caret_tester.check_scrolled()
|
||||
caret_tester.check()
|
||||
|
||||
|
||||
@pytest.mark.parametrize('style', ['visibility: hidden', 'display: none'])
|
||||
def test_invisible(caret_tester, style):
|
||||
"""Test with hidden text elements."""
|
||||
caret_tester.js.load('position_caret/invisible.html', style=style)
|
||||
caret_tester.check()
|
||||
|
||||
|
||||
def test_scrolled_down_img(caret_tester):
|
||||
"""Test with an image at the top with the viewport scrolled down."""
|
||||
caret_tester.js.load('position_caret/scrolled_down_img.html')
|
||||
caret_tester.js.scroll_anchor('anchor')
|
||||
caret_tester.check_scrolled()
|
||||
caret_tester.check()
|
Loading…
Reference in New Issue
Block a user