Project

General

Profile

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

haketilo / test / unit / conftest.py @ c699b640

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
from pathlib import Path
30
from selenium.webdriver.support.ui import WebDriverWait
31
from selenium.webdriver.support import expected_conditions as EC
32

    
33
from ..profiles           import firefox_safe_mode
34
from ..server             import do_an_internet
35
from ..script_loader      import load_script
36
from ..extension_crafting import make_extension
37

    
38
@pytest.fixture(scope="package")
39
def proxy():
40
    httpd = do_an_internet()
41
    yield httpd
42
    httpd.shutdown()
43

    
44
@pytest.fixture(scope="package")
45
def driver(proxy):
46
    with firefox_safe_mode() as driver:
47
        yield driver
48
        driver.quit()
49

    
50
@pytest.fixture()
51
def webextension(driver, request):
52
    ext_data = request.node.get_closest_marker('ext_data')
53
    if ext_data is None:
54
        raise Exception('"webextension" fixture requires "ext_data" marker to be set')
55

    
56
    ext_path = make_extension(Path(driver.firefox_profile.path),
57
                              **ext_data.args[0])
58
    driver.get('https://gotmyowndoma.in/')
59
    addon_id = driver.install_addon(str(ext_path), temporary=True)
60
    WebDriverWait(driver, 10).until(
61
        EC.title_contains("Extension's options page for testing")
62
    )
63
    yield
64
    driver.uninstall_addon(addon_id)
65
    ext_path.unlink()
66

    
67
script_injecting_script = '''\
68
/*
69
 * Selenium by default executes scripts in some weird one-time context. We want
70
 * separately-loaded scripts to be able to access global variables defined
71
 * before, including those declared with `const` or `let`. To achieve that, we
72
 * run our scripts by injecting them into the page inside a <script> tag. We use
73
 * custom properties of the `window` object to communicate with injected code.
74
 */
75

    
76
const script_elem = document.createElement('script');
77
script_elem.textContent = arguments[0];
78

    
79
delete window.haketilo_selenium_return_value;
80
delete window.haketilo_selenium_exception;
81
window.returnval = (val => window.haketilo_selenium_return_value = val);
82
window.arguments = arguments[1];
83

    
84
document.body.append(script_elem);
85

    
86
/*
87
 * To ease debugging, we want this script to signal all exceptions from the
88
 * injectee.
89
 */
90
try {
91
    if (window.haketilo_selenium_exception !== false)
92
        throw 'Error in injected script! Check your geckodriver.log!';
93
} finally {
94
    script_elem.remove();
95
}
96

    
97
return window.haketilo_selenium_return_value;
98
'''
99

    
100
def _execute_in_page_context(driver, script, args):
101
    script = script + '\n;\nwindow.haketilo_selenium_exception = false;'
102
    driver.loaded_scripts.append(script)
103
    try:
104
        return driver.execute_script(script_injecting_script, script, args)
105
    except Exception as e:
106
        import sys
107

    
108
        print("Scripts loaded since driver's last get() method call:",
109
              file=sys.stderr)
110

    
111
        for script in driver.loaded_scripts:
112
            lines = enumerate(script.split('\n'), 1)
113
            for err_info in [('===',), *lines]:
114
                print(*err_info, file=sys.stderr)
115

    
116
        raise e from None
117

    
118
@pytest.fixture(scope="package")
119
def execute_in_page(driver):
120
    def do_execute(script, *args, **kwargs):
121
        if 'page' in kwargs:
122
            driver.get(kwargs['page'])
123

    
124
        return _execute_in_page_context(driver, script, args)
125

    
126
    yield do_execute
127

    
128
@pytest.fixture(scope="package")
129
def load_into_page(driver):
130
    def do_load(path, import_dirs, *args, **kwargs):
131
        if 'page' in kwargs:
132
            driver.get(kwargs['page'])
133

    
134
        _execute_in_page_context(driver, load_script(path, import_dirs), args)
135

    
136
    yield do_load
(2-2/6)