Project

General

Profile

Download (3.41 KB) Statistics
| Branch: | Tag: | Revision:

haketilo / test / unit / conftest.py @ 5c583de8

1
# SPDX-License-Identifier: GPL-3.0-or-later
2

    
3
"""
4
Common fixtures for Haketilo unit tests
5
"""
6

    
7
# This file is part of Haketilo.
8
#
9
# Copyright (C) 2021 Wojtek Kosior <koszko@koszko.org>
10
#
11
# This program is free software: you can redistribute it and/or modify
12
# it under the terms of the GNU General Public License as published by
13
# the Free Software Foundation, either version 3 of the License, or
14
# (at your option) any later version.
15
#
16
# This program is distributed in the hope that it will be useful,
17
# but WITHOUT ANY WARRANTY; without even the implied warranty of
18
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
# GNU General Public License for more details.
20
#
21
# You should have received a copy of the GNU General Public License
22
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
23
#
24
# I, Wojtek Kosior, thereby promise not to sue for violation of this file's
25
# license. Although I request that you do not make use this code in a
26
# proprietary program, I am not going to enforce this in court.
27

    
28
import pytest
29

    
30
from ..profiles      import firefox_safe_mode
31
from ..server        import do_an_internet
32
from ..script_loader import load_script
33

    
34
@pytest.fixture(scope="package")
35
def proxy():
36
    httpd = do_an_internet()
37
    yield httpd
38
    httpd.shutdown()
39

    
40
@pytest.fixture(scope="package")
41
def driver(proxy):
42
    with firefox_safe_mode() as driver:
43
        yield driver
44
        driver.quit()
45

    
46
script_injecting_script = '''\
47
/*
48
 * Selenium by default executes scripts in some weird one-time context. We want
49
 * separately-loaded scripts to be able to access global variables defined
50
 * before, including those declared with `const` or `let`. To achieve that, we
51
 * run our scripts by injecting them into the page inside a <script> tag. We use
52
 * custom properties of the `window` object to communicate with injected code.
53
 */
54

    
55
const script_elem = document.createElement('script');
56
script_elem.textContent = arguments[0];
57

    
58
delete window.haketilo_selenium_return_value;
59
delete window.haketilo_selenium_exception;
60
window.returnval = (val => window.haketilo_selenium_return_value = val);
61
window.arguments = arguments[1];
62

    
63
document.body.append(script_elem);
64

    
65
/*
66
 * To ease debugging, we want this script to forward signal all exceptions from
67
 * the injectee.
68
 */
69
try {
70
    if (window.haketilo_selenium_exception !== false)
71
        throw 'Error in injected script! Check your geckodriver.log!';
72
} finally {
73
    script_elem.remove();
74
}
75

    
76
return window.haketilo_selenium_return_value;
77
'''
78

    
79
def _execute_in_page_context(driver, script, args):
80
    script = script + '\n;\nwindow.haketilo_selenium_exception = false;'
81
    try:
82
        return driver.execute_script(script_injecting_script, script, args)
83
    except Exception as e:
84
        import sys
85
        lines = enumerate(script.split('\n'), 1)
86
        for err_info in [('Failing script\n',), *lines]:
87
            print(*err_info, file=sys.stderr)
88

    
89
        raise e from None
90

    
91
@pytest.fixture(scope="package")
92
def execute_in_page(driver):
93
    def do_execute(script, *args, **kwargs):
94
        if 'page' in kwargs:
95
            driver.get(kwargs['page'])
96

    
97
        return _execute_in_page_context(driver, script, args)
98

    
99
    yield do_execute
100

    
101
@pytest.fixture(scope="package")
102
def load_into_page(driver):
103
    def do_load(path, import_dirs, *args, **kwargs):
104
        if 'page' in kwargs:
105
            driver.get(kwargs['page'])
106

    
107
        _execute_in_page_context(driver, load_script(path, import_dirs), args)
108

    
109
    yield do_load
(2-2/5)