1
|
# SPDX-License-Identifier: CC0-1.0
|
2
|
|
3
|
"""
|
4
|
Haketilo unit tests - routing HTTP requests through background script
|
5
|
"""
|
6
|
|
7
|
# This file is part of Haketilo
|
8
|
#
|
9
|
# Copyright (C) 2022 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 CC0 1.0 Universal License as published by
|
13
|
# the Creative Commons Corporation.
|
14
|
#
|
15
|
# This program is distributed in the hope that it will be useful,
|
16
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
17
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
18
|
# CC0 1.0 Universal License for more details.
|
19
|
|
20
|
import pytest
|
21
|
import json
|
22
|
from selenium.webdriver.support.ui import WebDriverWait
|
23
|
|
24
|
from ..script_loader import load_script
|
25
|
from ..world_wide_library import some_data
|
26
|
|
27
|
urls = {
|
28
|
'resource': 'https://anotherdoma.in/resource/blocked/by/CORS.json',
|
29
|
'nonexistent': 'https://nxdoma.in/resource.json',
|
30
|
'invalid': 'w3csucks://invalid.url/'
|
31
|
}
|
32
|
|
33
|
content_script = '''\
|
34
|
const urls = %s;
|
35
|
|
36
|
function fetch_data(url) {
|
37
|
return {
|
38
|
url,
|
39
|
to_get: ["ok", "status"],
|
40
|
to_call: ["text", "json"]
|
41
|
};
|
42
|
}
|
43
|
|
44
|
async function fetch_resources() {
|
45
|
const results = {};
|
46
|
const promises = [];
|
47
|
for (const [name, url] of Object.entries(urls)) {
|
48
|
const sending = browser.runtime.sendMessage(["CORS_bypass",
|
49
|
fetch_data(url)]);
|
50
|
promises.push(sending.then(response => results[name] = response));
|
51
|
}
|
52
|
|
53
|
await Promise.all(promises);
|
54
|
|
55
|
window.wrappedJSObject.haketilo_fetch_results = results;
|
56
|
}
|
57
|
|
58
|
fetch_resources();
|
59
|
'''
|
60
|
|
61
|
content_script = content_script % json.dumps(urls);
|
62
|
|
63
|
@pytest.mark.ext_data({
|
64
|
'content_script': content_script,
|
65
|
'background_script':
|
66
|
lambda: load_script('background/CORS_bypass_server.js') + '; start();'
|
67
|
})
|
68
|
@pytest.mark.usefixtures('webextension')
|
69
|
def test_CORS_bypass_server(driver, execute_in_page):
|
70
|
"""
|
71
|
Test if CORS bypassing works and if errors get properly forwarded.
|
72
|
"""
|
73
|
driver.get('https://gotmyowndoma.in/')
|
74
|
|
75
|
# First, verify that requests without CORS bypass measures fail.
|
76
|
results = execute_in_page(
|
77
|
'''
|
78
|
const result = {};
|
79
|
let promises = [];
|
80
|
for (const [name, url] of Object.entries(arguments[0])) {
|
81
|
const [ok_cb, err_cb] =
|
82
|
["ok", "err"].map(status => () => result[name] = status);
|
83
|
promises.push(fetch(url).then(ok_cb, err_cb));
|
84
|
}
|
85
|
// Make the promises non-failing.
|
86
|
promises = promises.map(p => new Promise(cb => p.then(cb, cb)));
|
87
|
returnval(Promise.all(promises).then(() => result));
|
88
|
''',
|
89
|
{**urls, 'sameorigin': './nonexistent_resource'})
|
90
|
|
91
|
assert results == dict([*[(k, 'err') for k in urls.keys()],
|
92
|
('sameorigin', 'ok')])
|
93
|
|
94
|
done = lambda d: d.execute_script('return window.haketilo_fetch_results;')
|
95
|
results = WebDriverWait(driver, 10).until(done)
|
96
|
|
97
|
assert set(results['invalid'].keys()) == {'error'}
|
98
|
|
99
|
assert set(results['nonexistent'].keys()) == \
|
100
|
{'ok', 'status', 'text', 'error_json'}
|
101
|
assert results['nonexistent']['ok'] == False
|
102
|
assert results['nonexistent']['status'] == 404
|
103
|
assert results['nonexistent']['text'] == 'Handler for this URL not found.'
|
104
|
|
105
|
assert set(results['resource'].keys()) == {'ok', 'status', 'text', 'json'}
|
106
|
assert results['resource']['ok'] == True
|
107
|
assert results['resource']['status'] == 200
|
108
|
assert results['resource']['text'] == some_data
|
109
|
assert results['resource']['json'] == json.loads(some_data)
|