2015-11-02 23:49:44 +01:00
|
|
|
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
|
|
|
|
2016-01-04 07:12:39 +01:00
|
|
|
# Copyright 2015-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
|
2015-11-02 23:49:44 +01:00
|
|
|
#
|
|
|
|
# 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/>.
|
|
|
|
|
|
|
|
"""Steps for bdd-like tests."""
|
|
|
|
|
2015-11-02 23:39:35 +01:00
|
|
|
import re
|
2016-06-06 23:09:19 +02:00
|
|
|
import sys
|
2015-11-21 14:23:44 +01:00
|
|
|
import time
|
2015-11-23 14:37:40 +01:00
|
|
|
import json
|
2015-11-24 18:22:43 +01:00
|
|
|
import os.path
|
2015-11-01 22:10:48 +01:00
|
|
|
import logging
|
2015-11-23 20:00:25 +01:00
|
|
|
import collections
|
2016-01-12 11:24:31 +01:00
|
|
|
import textwrap
|
2015-10-11 13:53:59 +02:00
|
|
|
|
2015-11-27 11:50:23 +01:00
|
|
|
import pytest
|
2015-11-02 20:32:15 +01:00
|
|
|
import pytest_bdd as bdd
|
2015-10-11 13:53:59 +02:00
|
|
|
|
2016-06-06 23:09:19 +02:00
|
|
|
from qutebrowser.utils import log
|
2015-12-01 22:47:10 +01:00
|
|
|
from helpers import utils
|
2015-11-02 23:39:35 +01:00
|
|
|
|
2015-10-11 13:53:59 +02:00
|
|
|
|
2016-06-06 23:09:19 +02:00
|
|
|
@pytest.hookimpl(hookwrapper=True)
|
|
|
|
def pytest_runtest_makereport(item, call):
|
|
|
|
"""Add a BDD section to the test output."""
|
|
|
|
outcome = yield
|
|
|
|
if call.when not in ['call', 'teardown']:
|
|
|
|
return
|
|
|
|
report = outcome.get_result()
|
|
|
|
|
|
|
|
if report.passed:
|
|
|
|
return
|
|
|
|
|
2016-06-06 23:37:26 +02:00
|
|
|
if (not hasattr(report.longrepr, 'addsection') or
|
|
|
|
not hasattr(report, 'scenario')):
|
2016-06-06 23:09:19 +02:00
|
|
|
# In some conditions (on OS X and Windows it seems), report.longrepr is
|
|
|
|
# actually a tuple. This is handled similarily in pytest-qt too.
|
2016-06-06 23:37:26 +02:00
|
|
|
#
|
|
|
|
# Since this hook is invoked for any test, we also need to skip it for
|
|
|
|
# non-BDD ones.
|
2016-06-06 23:09:19 +02:00
|
|
|
return
|
|
|
|
|
|
|
|
if sys.stdout.isatty() and item.config.getoption('--color') != 'no':
|
|
|
|
colors = {
|
|
|
|
'failed': log.COLOR_ESCAPES['red'],
|
|
|
|
'passed': log.COLOR_ESCAPES['green'],
|
|
|
|
'keyword': log.COLOR_ESCAPES['cyan'],
|
|
|
|
'reset': log.RESET_ESCAPE,
|
|
|
|
}
|
|
|
|
else:
|
|
|
|
colors = {
|
|
|
|
'failed': '',
|
|
|
|
'passed': '',
|
|
|
|
'keyword': '',
|
|
|
|
'reset': '',
|
|
|
|
}
|
|
|
|
|
|
|
|
output = []
|
|
|
|
output.append("{kw_color}Feature:{reset} {name}".format(
|
|
|
|
kw_color=colors['keyword'],
|
|
|
|
name=report.scenario['feature']['name'],
|
|
|
|
reset=colors['reset'],
|
|
|
|
))
|
2016-06-07 08:23:35 +02:00
|
|
|
output.append(
|
|
|
|
" {kw_color}Scenario:{reset} {name} ({filename}:{line})".format(
|
2016-06-06 23:09:19 +02:00
|
|
|
kw_color=colors['keyword'],
|
2016-06-07 08:23:35 +02:00
|
|
|
name=report.scenario['name'],
|
|
|
|
filename=report.scenario['feature']['rel_filename'],
|
|
|
|
line=report.scenario['line_number'],
|
|
|
|
reset=colors['reset'])
|
|
|
|
)
|
|
|
|
for step in report.scenario['steps']:
|
|
|
|
output.append(
|
|
|
|
" {kw_color}{keyword}{reset} {color}{name}{reset} "
|
|
|
|
"({duration:.2f}s)".format(
|
|
|
|
kw_color=colors['keyword'],
|
|
|
|
color=colors['failed'] if step['failed'] else colors['passed'],
|
|
|
|
keyword=step['keyword'],
|
|
|
|
name=step['name'],
|
|
|
|
duration=step['duration'],
|
|
|
|
reset=colors['reset'])
|
|
|
|
)
|
2016-06-06 23:09:19 +02:00
|
|
|
|
|
|
|
report.longrepr.addsection("BDD scenario", '\n'.join(output))
|
|
|
|
|
|
|
|
|
2015-11-26 14:25:33 +01:00
|
|
|
## Given
|
|
|
|
|
|
|
|
|
2015-10-11 13:53:59 +02:00
|
|
|
@bdd.given(bdd.parsers.parse("I set {sect} -> {opt} to {value}"))
|
2015-11-26 14:25:33 +01:00
|
|
|
def set_setting_given(quteproc, httpbin, sect, opt, value):
|
|
|
|
"""Set a qutebrowser setting.
|
|
|
|
|
|
|
|
This is available as "Given:" step so it can be used as "Background:".
|
|
|
|
"""
|
2015-11-24 19:19:03 +01:00
|
|
|
value = value.replace('(port)', str(httpbin.port))
|
2015-10-11 13:53:59 +02:00
|
|
|
quteproc.set_setting(sect, opt, value)
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.given(bdd.parsers.parse("I open {path}"))
|
2015-11-03 07:00:46 +01:00
|
|
|
def open_path_given(quteproc, path):
|
2015-11-26 14:25:33 +01:00
|
|
|
"""Open a URL.
|
|
|
|
|
|
|
|
This is available as "Given:" step so it can be used as "Background:".
|
|
|
|
|
|
|
|
It always opens a new tab, unlike "When I open ..."
|
|
|
|
"""
|
2015-10-13 07:14:32 +02:00
|
|
|
quteproc.open_path(path, new_tab=True)
|
2015-10-11 13:53:59 +02:00
|
|
|
|
|
|
|
|
2015-11-26 14:25:33 +01:00
|
|
|
@bdd.given(bdd.parsers.parse("I run {command}"))
|
|
|
|
def run_command_given(quteproc, command):
|
|
|
|
"""Run a qutebrowser command.
|
|
|
|
|
|
|
|
This is available as "Given:" step so it can be used as "Background:".
|
|
|
|
"""
|
|
|
|
quteproc.send_cmd(command)
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.given("I have a fresh instance")
|
|
|
|
def fresh_instance(quteproc):
|
|
|
|
"""Restart qutebrowser instance for tests needing a fresh state."""
|
|
|
|
quteproc.terminate()
|
|
|
|
quteproc.start()
|
|
|
|
|
|
|
|
|
|
|
|
## When
|
|
|
|
|
|
|
|
|
2015-10-11 13:53:59 +02:00
|
|
|
@bdd.when(bdd.parsers.parse("I open {path}"))
|
2015-11-26 14:25:33 +01:00
|
|
|
def open_path(quteproc, path):
|
|
|
|
"""Open a URL.
|
|
|
|
|
2016-01-07 08:20:48 +01:00
|
|
|
If used like "When I open ... in a new tab", the URL is opened in a new
|
|
|
|
tab. With "... in a new window", it's opened in a new window.
|
2015-11-26 14:25:33 +01:00
|
|
|
"""
|
2016-01-14 22:26:42 +01:00
|
|
|
new_tab = False
|
|
|
|
new_window = False
|
2016-05-29 16:14:33 +02:00
|
|
|
wait = True
|
2016-01-14 22:26:42 +01:00
|
|
|
|
2015-11-23 19:42:01 +01:00
|
|
|
new_tab_suffix = ' in a new tab'
|
2016-01-07 08:20:48 +01:00
|
|
|
new_window_suffix = ' in a new window'
|
2016-01-14 22:26:42 +01:00
|
|
|
do_not_wait_suffix = ' without waiting'
|
|
|
|
|
2015-11-23 19:42:01 +01:00
|
|
|
if path.endswith(new_tab_suffix):
|
|
|
|
path = path[:-len(new_tab_suffix)]
|
|
|
|
new_tab = True
|
2016-01-07 08:20:48 +01:00
|
|
|
elif path.endswith(new_window_suffix):
|
|
|
|
path = path[:-len(new_window_suffix)]
|
|
|
|
new_window = True
|
2016-01-14 22:26:42 +01:00
|
|
|
|
|
|
|
if path.endswith(do_not_wait_suffix):
|
|
|
|
path = path[:-len(do_not_wait_suffix)]
|
2016-05-29 16:14:33 +02:00
|
|
|
wait = False
|
2015-11-23 19:42:01 +01:00
|
|
|
|
2016-05-29 16:14:33 +02:00
|
|
|
quteproc.open_path(path, new_tab=new_tab, new_window=new_window, wait=wait)
|
2015-10-11 13:53:59 +02:00
|
|
|
|
|
|
|
|
2015-11-09 07:37:04 +01:00
|
|
|
@bdd.when(bdd.parsers.parse("I set {sect} -> {opt} to {value}"))
|
2015-11-26 14:25:33 +01:00
|
|
|
def set_setting(quteproc, httpbin, sect, opt, value):
|
|
|
|
"""Set a qutebrowser setting."""
|
2015-11-24 19:19:03 +01:00
|
|
|
value = value.replace('(port)', str(httpbin.port))
|
2015-11-09 07:37:04 +01:00
|
|
|
quteproc.set_setting(sect, opt, value)
|
|
|
|
|
|
|
|
|
2015-10-11 13:53:59 +02:00
|
|
|
@bdd.when(bdd.parsers.parse("I run {command}"))
|
2016-07-11 20:47:37 +02:00
|
|
|
def run_command(quteproc, httpbin, tmpdir, command):
|
2015-11-26 14:25:33 +01:00
|
|
|
"""Run a qutebrowser command.
|
|
|
|
|
|
|
|
The suffix "with count ..." can be used to pass a count to the command.
|
|
|
|
"""
|
2015-11-15 20:48:07 +01:00
|
|
|
if 'with count' in command:
|
|
|
|
command, count = command.split(' with count ')
|
|
|
|
count = int(count)
|
|
|
|
else:
|
|
|
|
count = None
|
2016-06-06 16:10:01 +02:00
|
|
|
|
|
|
|
invalid_tag = ' (invalid command)'
|
|
|
|
if command.endswith(invalid_tag):
|
|
|
|
command = command[:-len(invalid_tag)]
|
|
|
|
invalid = True
|
|
|
|
else:
|
|
|
|
invalid = False
|
|
|
|
|
2015-11-09 07:37:04 +01:00
|
|
|
command = command.replace('(port)', str(httpbin.port))
|
2016-05-25 02:25:34 +02:00
|
|
|
command = command.replace('(testdata)', utils.abs_datapath())
|
2016-07-11 20:47:37 +02:00
|
|
|
command = command.replace('(tmpdir)', str(tmpdir))
|
2016-03-28 23:48:37 +02:00
|
|
|
|
2016-06-06 16:10:01 +02:00
|
|
|
quteproc.send_cmd(command, count=count, invalid=invalid)
|
2015-10-11 13:53:59 +02:00
|
|
|
|
|
|
|
|
2015-10-27 06:59:57 +01:00
|
|
|
@bdd.when(bdd.parsers.parse("I reload"))
|
2015-10-27 08:07:16 +01:00
|
|
|
def reload(qtbot, httpbin, quteproc, command):
|
2015-11-26 14:25:33 +01:00
|
|
|
"""Reload and wait until a new request is received."""
|
2016-01-08 09:49:06 +01:00
|
|
|
with qtbot.waitSignal(httpbin.new_request):
|
2015-10-27 06:59:57 +01:00
|
|
|
quteproc.send_cmd(':reload')
|
|
|
|
|
|
|
|
|
2015-11-05 07:02:02 +01:00
|
|
|
@bdd.when(bdd.parsers.parse("I wait until {path} is loaded"))
|
|
|
|
def wait_until_loaded(quteproc, path):
|
2015-11-26 14:25:33 +01:00
|
|
|
"""Wait until the given path is loaded (as per qutebrowser log)."""
|
2015-11-05 07:02:02 +01:00
|
|
|
quteproc.wait_for_load_finished(path)
|
|
|
|
|
|
|
|
|
2015-11-05 08:02:55 +01:00
|
|
|
@bdd.when(bdd.parsers.re(r'I wait for (?P<is_regex>regex )?"'
|
2016-01-06 08:22:30 +01:00
|
|
|
r'(?P<pattern>[^"]+)" in the log(?P<do_skip> or skip '
|
|
|
|
r'the test)?'))
|
|
|
|
def wait_in_log(quteproc, is_regex, pattern, do_skip):
|
2015-11-26 14:25:33 +01:00
|
|
|
"""Wait for a given pattern in the qutebrowser log.
|
|
|
|
|
|
|
|
If used like "When I wait for regex ... in the log" the argument is treated
|
|
|
|
as regex. Otherwise, it's treated as a pattern (* can be used as wildcard).
|
|
|
|
"""
|
2015-11-05 08:02:55 +01:00
|
|
|
if is_regex:
|
|
|
|
pattern = re.compile(pattern)
|
2016-01-06 08:22:30 +01:00
|
|
|
|
2016-01-13 21:44:30 +01:00
|
|
|
line = quteproc.wait_for(message=pattern, do_skip=bool(do_skip))
|
|
|
|
line.expected = True
|
2015-11-05 08:02:55 +01:00
|
|
|
|
|
|
|
|
2015-11-09 07:37:23 +01:00
|
|
|
@bdd.when(bdd.parsers.re(r'I wait for the (?P<category>error|message|warning) '
|
|
|
|
r'"(?P<message>.*)"'))
|
|
|
|
def wait_for_message(quteproc, httpbin, category, message):
|
2015-11-26 14:25:33 +01:00
|
|
|
"""Wait for a given statusbar message/error/warning."""
|
2016-04-20 07:16:56 +02:00
|
|
|
quteproc.log_summary('Waiting for {} "{}"'.format(category, message))
|
2015-11-26 14:25:33 +01:00
|
|
|
expect_message(quteproc, httpbin, category, message)
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.when(bdd.parsers.parse("I wait {delay}s"))
|
|
|
|
def wait_time(quteproc, delay):
|
|
|
|
"""Sleep for the given delay."""
|
|
|
|
time.sleep(float(delay))
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.when(bdd.parsers.re('I press the keys? "(?P<keys>[^"]*)"'))
|
|
|
|
def press_keys(quteproc, keys):
|
|
|
|
"""Send the given fake keys to qutebrowser."""
|
|
|
|
quteproc.press_keys(keys)
|
|
|
|
|
|
|
|
|
2015-11-26 21:22:50 +01:00
|
|
|
@bdd.when("selection is supported")
|
|
|
|
def selection_supported(qapp):
|
|
|
|
"""Skip the test if selection isn't supported."""
|
|
|
|
if not qapp.clipboard().supportsSelection():
|
|
|
|
pytest.skip("OS doesn't support primary selection!")
|
|
|
|
|
|
|
|
|
2016-05-08 21:18:30 +02:00
|
|
|
@bdd.when("selection is not supported")
|
|
|
|
def selection_not_supported(qapp):
|
|
|
|
"""Skip the test if selection is supported."""
|
|
|
|
if qapp.clipboard().supportsSelection():
|
|
|
|
pytest.skip("OS supports primary selection!")
|
|
|
|
|
|
|
|
|
2015-11-26 21:22:50 +01:00
|
|
|
@bdd.when(bdd.parsers.re(r'I put "(?P<content>.*)" into the '
|
|
|
|
r'(?P<what>primary selection|clipboard)'))
|
2016-02-03 20:27:11 +01:00
|
|
|
def fill_clipboard(quteproc, httpbin, what, content):
|
2015-11-26 21:22:50 +01:00
|
|
|
content = content.replace('(port)', str(httpbin.port))
|
2016-02-02 06:37:49 +01:00
|
|
|
content = content.replace(r'\n', '\n')
|
2016-02-03 20:27:11 +01:00
|
|
|
quteproc.send_cmd(':debug-set-fake-clipboard "{}"'.format(content))
|
2016-02-03 07:44:41 +01:00
|
|
|
|
2015-11-26 21:22:50 +01:00
|
|
|
|
2016-01-12 09:59:03 +01:00
|
|
|
@bdd.when(bdd.parsers.re(r'I put the following lines into the '
|
|
|
|
r'(?P<what>primary selection|clipboard):\n'
|
|
|
|
r'(?P<content>.+)$', flags=re.DOTALL))
|
2016-02-03 20:27:11 +01:00
|
|
|
def fill_clipboard_multiline(quteproc, httpbin, what, content):
|
|
|
|
fill_clipboard(quteproc, httpbin, what, textwrap.dedent(content))
|
2016-01-12 09:59:03 +01:00
|
|
|
|
|
|
|
|
2015-11-26 14:25:33 +01:00
|
|
|
## Then
|
2015-11-09 07:37:23 +01:00
|
|
|
|
|
|
|
|
2015-10-11 13:53:59 +02:00
|
|
|
@bdd.then(bdd.parsers.parse("{path} should be loaded"))
|
2016-01-06 22:57:49 +01:00
|
|
|
def path_should_be_loaded(quteproc, path):
|
|
|
|
"""Make sure the given path was loaded according to the log.
|
|
|
|
|
|
|
|
This is usally the better check compared to "should be requested" as the
|
|
|
|
page could be loaded from local cache.
|
|
|
|
"""
|
2016-02-18 07:34:35 +01:00
|
|
|
quteproc.wait_for_load_finished(path)
|
2016-01-06 22:57:49 +01:00
|
|
|
|
|
|
|
|
|
|
|
@bdd.then(bdd.parsers.parse("{path} should be requested"))
|
|
|
|
def path_should_be_requested(httpbin, path):
|
2015-11-26 14:25:33 +01:00
|
|
|
"""Make sure the given path was loaded from the webserver."""
|
2015-11-17 06:41:58 +01:00
|
|
|
httpbin.wait_for(verb='GET', path='/' + path)
|
2015-10-11 13:53:59 +02:00
|
|
|
|
|
|
|
|
|
|
|
@bdd.then(bdd.parsers.parse("The requests should be:\n{pages}"))
|
2015-11-26 14:25:33 +01:00
|
|
|
def list_of_requests(httpbin, pages):
|
|
|
|
"""Make sure the given requests were done from the webserver."""
|
2015-11-16 23:14:24 +01:00
|
|
|
expected_requests = [httpbin.ExpectedRequest('GET', '/' + path.strip())
|
2015-11-09 07:38:34 +01:00
|
|
|
for path in pages.split('\n')]
|
|
|
|
actual_requests = httpbin.get_requests()
|
|
|
|
assert actual_requests == expected_requests
|
2015-10-22 06:44:05 +02:00
|
|
|
|
|
|
|
|
2015-11-23 20:00:25 +01:00
|
|
|
@bdd.then(bdd.parsers.parse("The unordered requests should be:\n{pages}"))
|
2015-11-26 14:25:33 +01:00
|
|
|
def list_of_requests_unordered(httpbin, pages):
|
|
|
|
"""Make sure the given requests were done (in no particular order)."""
|
2015-11-23 20:00:25 +01:00
|
|
|
expected_requests = [httpbin.ExpectedRequest('GET', '/' + path.strip())
|
|
|
|
for path in pages.split('\n')]
|
|
|
|
actual_requests = httpbin.get_requests()
|
|
|
|
# Requests are not hashable, we need to convert to ExpectedRequests
|
2015-11-26 14:25:33 +01:00
|
|
|
actual_requests = [httpbin.ExpectedRequest.from_request(req)
|
|
|
|
for req in actual_requests]
|
2015-11-23 20:00:25 +01:00
|
|
|
assert (collections.Counter(actual_requests) ==
|
|
|
|
collections.Counter(expected_requests))
|
|
|
|
|
|
|
|
|
2015-11-03 22:40:19 +01:00
|
|
|
@bdd.then(bdd.parsers.re(r'the (?P<category>error|message|warning) '
|
2015-11-26 17:50:39 +01:00
|
|
|
r'"(?P<message>.*)" should be shown'))
|
2015-11-26 14:25:33 +01:00
|
|
|
def expect_message(quteproc, httpbin, category, message):
|
|
|
|
"""Expect the given message in the qutebrowser log."""
|
2015-11-02 07:43:37 +01:00
|
|
|
category_to_loglevel = {
|
|
|
|
'message': logging.INFO,
|
|
|
|
'error': logging.ERROR,
|
2015-11-03 22:40:19 +01:00
|
|
|
'warning': logging.WARNING,
|
2015-11-02 07:43:37 +01:00
|
|
|
}
|
|
|
|
message = message.replace('(port)', str(httpbin.port))
|
|
|
|
quteproc.mark_expected(category='message',
|
|
|
|
loglevel=category_to_loglevel[category],
|
2015-11-01 22:10:48 +01:00
|
|
|
message=message)
|
2015-11-02 23:39:35 +01:00
|
|
|
|
|
|
|
|
2015-11-26 14:25:33 +01:00
|
|
|
@bdd.then(bdd.parsers.re(r'(?P<is_regex>regex )?"(?P<pattern>[^"]+)" should '
|
|
|
|
r'be logged'))
|
2016-04-20 16:58:14 +02:00
|
|
|
def should_be_logged(quteproc, httpbin, is_regex, pattern):
|
2015-11-26 14:25:33 +01:00
|
|
|
"""Expect the given pattern on regex in the log."""
|
|
|
|
if is_regex:
|
|
|
|
pattern = re.compile(pattern)
|
2016-04-20 16:58:14 +02:00
|
|
|
else:
|
|
|
|
pattern = pattern.replace('(port)', str(httpbin.port))
|
2016-01-13 21:44:30 +01:00
|
|
|
line = quteproc.wait_for(message=pattern)
|
|
|
|
line.expected = True
|
2015-11-25 17:19:16 +01:00
|
|
|
|
|
|
|
|
2015-11-13 23:27:33 +01:00
|
|
|
@bdd.then(bdd.parsers.parse('"{pattern}" should not be logged'))
|
|
|
|
def ensure_not_logged(quteproc, pattern):
|
2015-11-26 14:25:33 +01:00
|
|
|
"""Make sure the given pattern was *not* logged."""
|
2015-11-13 23:27:33 +01:00
|
|
|
quteproc.ensure_not_logged(message=pattern)
|
|
|
|
|
|
|
|
|
2015-11-20 07:03:51 +01:00
|
|
|
@bdd.then(bdd.parsers.parse('the javascript message "{message}" should be '
|
|
|
|
'logged'))
|
|
|
|
def javascript_message_logged(quteproc, message):
|
2015-11-26 14:25:33 +01:00
|
|
|
"""Make sure the given message was logged via javascript."""
|
2016-01-14 18:50:36 +01:00
|
|
|
quteproc.wait_for_js(message)
|
2015-11-20 07:03:51 +01:00
|
|
|
|
|
|
|
|
2015-11-25 17:20:05 +01:00
|
|
|
@bdd.then(bdd.parsers.parse('the javascript message "{message}" should not be '
|
|
|
|
'logged'))
|
|
|
|
def javascript_message_not_logged(quteproc, message):
|
2015-11-26 14:25:33 +01:00
|
|
|
"""Make sure the given message was *not* logged via javascript."""
|
2015-11-25 17:20:05 +01:00
|
|
|
quteproc.ensure_not_logged(category='js',
|
|
|
|
function='javaScriptConsoleMessage',
|
|
|
|
message='[*] {}'.format(message))
|
|
|
|
|
|
|
|
|
2015-11-26 14:25:33 +01:00
|
|
|
@bdd.then(bdd.parsers.parse("The session should look like:\n{expected}"))
|
|
|
|
def compare_session(quteproc, expected):
|
|
|
|
"""Compare the current sessions against the given template.
|
|
|
|
|
|
|
|
partial_compare is used, which means only the keys/values listed will be
|
|
|
|
compared.
|
|
|
|
"""
|
2016-04-21 00:14:52 +02:00
|
|
|
quteproc.compare_session(expected)
|
2015-11-25 17:19:49 +01:00
|
|
|
|
|
|
|
|
2015-11-09 07:37:52 +01:00
|
|
|
@bdd.then("no crash should happen")
|
|
|
|
def no_crash():
|
|
|
|
"""Don't do anything.
|
|
|
|
|
2016-04-08 07:35:53 +02:00
|
|
|
This is actually a NOP as a crash is already checked in the log.
|
|
|
|
"""
|
2016-05-20 16:03:52 +02:00
|
|
|
time.sleep(0.5)
|
2015-11-23 14:37:40 +01:00
|
|
|
|
|
|
|
|
|
|
|
@bdd.then(bdd.parsers.parse("the header {header} should be set to {value}"))
|
|
|
|
def check_header(quteproc, header, value):
|
|
|
|
"""Check if a given header is set correctly.
|
|
|
|
|
|
|
|
This assumes we're on the httpbin header page.
|
|
|
|
"""
|
|
|
|
content = quteproc.get_content()
|
|
|
|
data = json.loads(content)
|
|
|
|
print(data)
|
|
|
|
assert data['headers'][header] == value
|
2015-11-24 18:22:43 +01:00
|
|
|
|
|
|
|
|
|
|
|
@bdd.then(bdd.parsers.parse("the page source should look like {filename}"))
|
|
|
|
def check_contents(quteproc, filename):
|
|
|
|
"""Check the current page's content.
|
|
|
|
|
2016-05-29 18:20:00 +02:00
|
|
|
The filename is interpreted relative to tests/end2end/data.
|
2015-11-24 18:22:43 +01:00
|
|
|
"""
|
|
|
|
content = quteproc.get_content(plain=False)
|
2016-03-29 19:52:46 +02:00
|
|
|
path = os.path.join(utils.abs_datapath(),
|
2016-03-28 23:48:37 +02:00
|
|
|
os.path.join(*filename.split('/')))
|
2015-11-24 18:22:43 +01:00
|
|
|
with open(path, 'r', encoding='utf-8') as f:
|
2016-01-18 08:07:32 +01:00
|
|
|
file_content = f.read()
|
|
|
|
assert content == file_content
|
2015-11-26 01:33:56 +01:00
|
|
|
|
|
|
|
|
2016-01-06 07:15:06 +01:00
|
|
|
@bdd.then(bdd.parsers.parse('the page should contain the plaintext "{text}"'))
|
2016-01-06 07:55:42 +01:00
|
|
|
def check_contents_plain(quteproc, text):
|
|
|
|
"""Check the current page's content based on a substring."""
|
2016-01-06 07:15:06 +01:00
|
|
|
content = quteproc.get_content().strip()
|
2016-01-06 07:42:33 +01:00
|
|
|
assert text in content
|
2016-01-06 07:15:06 +01:00
|
|
|
|
|
|
|
|
2016-05-12 13:45:48 +02:00
|
|
|
@bdd.then(bdd.parsers.parse('the page should not contain the plaintext '
|
|
|
|
'"{text}"'))
|
2016-05-12 13:47:20 +02:00
|
|
|
def check_not_contents_plain(quteproc, text):
|
2016-05-12 13:45:48 +02:00
|
|
|
"""Check the current page's content based on a substring."""
|
|
|
|
content = quteproc.get_content().strip()
|
|
|
|
assert text not in content
|
|
|
|
|
|
|
|
|
2016-01-14 22:27:00 +01:00
|
|
|
@bdd.then(bdd.parsers.parse('the json on the page should be:\n{text}'))
|
|
|
|
def check_contents_json(quteproc, text):
|
|
|
|
"""Check the current page's content as json."""
|
|
|
|
content = quteproc.get_content().strip()
|
|
|
|
expected = json.loads(text)
|
|
|
|
actual = json.loads(content)
|
|
|
|
assert actual == expected
|
|
|
|
|
|
|
|
|
2015-11-26 01:33:56 +01:00
|
|
|
@bdd.then(bdd.parsers.parse("the following tabs should be open:\n{tabs}"))
|
|
|
|
def check_open_tabs(quteproc, tabs):
|
2015-11-26 14:25:33 +01:00
|
|
|
"""Check the list of open tabs in the session.
|
|
|
|
|
|
|
|
This is a lightweight alternative for "The session should look like: ...".
|
|
|
|
|
|
|
|
It expects a list of URLs, with an optional "(active)" suffix.
|
|
|
|
"""
|
2015-11-26 01:33:56 +01:00
|
|
|
session = quteproc.get_session()
|
|
|
|
active_suffix = ' (active)'
|
|
|
|
tabs = tabs.splitlines()
|
|
|
|
assert len(session['windows']) == 1
|
|
|
|
assert len(session['windows'][0]['tabs']) == len(tabs)
|
|
|
|
|
|
|
|
for i, line in enumerate(tabs):
|
|
|
|
line = line.strip()
|
2016-01-09 00:14:57 +01:00
|
|
|
assert line.startswith('- ')
|
2015-11-26 01:33:56 +01:00
|
|
|
line = line[2:] # remove "- " prefix
|
|
|
|
if line.endswith(active_suffix):
|
|
|
|
path = line[:-len(active_suffix)]
|
|
|
|
active = True
|
|
|
|
else:
|
|
|
|
path = line
|
|
|
|
active = False
|
|
|
|
|
|
|
|
session_tab = session['windows'][0]['tabs'][i]
|
|
|
|
assert session_tab['history'][-1]['url'] == quteproc.path_to_url(path)
|
|
|
|
if active:
|
|
|
|
assert session_tab['active']
|
|
|
|
else:
|
|
|
|
assert 'active' not in session_tab
|
2015-11-26 21:22:50 +01:00
|
|
|
|
|
|
|
|
|
|
|
@bdd.then(bdd.parsers.re(r'the (?P<what>primary selection|clipboard) should '
|
|
|
|
r'contain "(?P<content>.*)"'))
|
2016-02-03 20:27:11 +01:00
|
|
|
def clipboard_contains(quteproc, httpbin, what, content):
|
2015-11-26 21:22:50 +01:00
|
|
|
expected = content.replace('(port)', str(httpbin.port))
|
2015-11-26 22:32:01 +01:00
|
|
|
expected = expected.replace('\\n', '\n')
|
2016-02-03 21:28:05 +01:00
|
|
|
quteproc.wait_for(message='Setting fake {}: {}'.format(
|
2016-02-03 20:52:45 +01:00
|
|
|
what, json.dumps(expected)))
|
2015-12-17 22:17:38 +01:00
|
|
|
|
2015-11-26 21:22:50 +01:00
|
|
|
|
2015-12-17 22:17:38 +01:00
|
|
|
@bdd.then(bdd.parsers.parse('the clipboard should contain:\n{content}'))
|
2016-05-08 21:59:25 +02:00
|
|
|
def clipboard_contains_multiline(quteproc, httpbin, content):
|
2016-05-08 22:09:19 +02:00
|
|
|
expected = textwrap.dedent(content).replace('(port)', str(httpbin.port))
|
2016-02-03 20:52:45 +01:00
|
|
|
quteproc.wait_for(message='Setting fake clipboard: {}'.format(
|
|
|
|
json.dumps(expected)))
|
2016-01-17 20:59:39 +01:00
|
|
|
|
|
|
|
|
|
|
|
@bdd.then("qutebrowser should quit")
|
|
|
|
def should_quit(qtbot, quteproc):
|
2016-01-20 06:54:00 +01:00
|
|
|
quteproc.wait_for_quit()
|