Merge pull request #668 from The-Compiler/visual-tests

Add javascript tests for position_caret.js.
This commit is contained in:
Florian Bruhin 2015-05-18 21:40:26 +02:00
commit 1a957b6c10
7 changed files with 286 additions and 0 deletions

View 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>

View 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)

View 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 %}

View 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 %}

View 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 %}

View File

@ -0,0 +1,4 @@
{% extends "base.html" %}
{% block content %}
<p>MARKER this should be the paragraph the caret is on.</p>
{% endblock %}

View 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()