1 |
b75a5717
|
Wojtek Kosior
|
# SPDX-License-Identifier: CC0-1.0
|
2 |
|
|
|
3 |
|
|
"""
|
4 |
42fe4405
|
Wojtek Kosior
|
Haketilo unit tests - repository querying
|
5 |
b75a5717
|
Wojtek Kosior
|
"""
|
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 |
|
|
from selenium.webdriver.support.ui import WebDriverWait
|
22 |
|
|
|
23 |
|
|
from ..extension_crafting import ExtraHTML
|
24 |
|
|
from ..script_loader import load_script
|
25 |
|
|
from .utils import *
|
26 |
|
|
|
27 |
|
|
repo_urls = [f'https://hydril.la/{s}' for s in ('', '1/', '2/', '3/', '4/')]
|
28 |
|
|
|
29 |
|
|
queried_url = 'https://example_a.com/something'
|
30 |
|
|
|
31 |
|
|
def setup_view(execute_in_page, repo_urls):
|
32 |
|
|
mock_cacher(execute_in_page)
|
33 |
|
|
|
34 |
|
|
execute_in_page(load_script('html/repo_query.js'))
|
35 |
|
|
execute_in_page(
|
36 |
|
|
'''
|
37 |
|
|
const repo_proms = arguments[0].map(url => haketilodb.set_repo(url));
|
38 |
|
|
|
39 |
|
|
const cb_calls = [];
|
40 |
|
|
const view = new RepoQueryView(0,
|
41 |
|
|
() => cb_calls.push("show"),
|
42 |
|
|
() => cb_calls.push("hide"));
|
43 |
|
|
document.body.append(view.main_div);
|
44 |
|
|
const shw = slice => [cb_calls.slice(slice || 0), view.shown];
|
45 |
|
|
|
46 |
|
|
returnval(Promise.all(repo_proms));
|
47 |
|
|
''',
|
48 |
|
|
repo_urls)
|
49 |
|
|
|
50 |
|
|
repo_query_ext_data = {
|
51 |
|
|
'background_script': broker_js,
|
52 |
|
|
'extra_html': ExtraHTML('html/repo_query.html', {}),
|
53 |
|
|
'navigate_to': 'html/repo_query.html'
|
54 |
|
|
}
|
55 |
|
|
|
56 |
|
|
@pytest.mark.ext_data(repo_query_ext_data)
|
57 |
|
|
@pytest.mark.usefixtures('webextension')
|
58 |
|
|
def test_repo_query_normal_usage(driver, execute_in_page):
|
59 |
|
|
"""
|
60 |
|
|
Test of using the repo query view to browse results from repository and to
|
61 |
|
|
start installation.
|
62 |
|
|
"""
|
63 |
|
|
setup_view(execute_in_page, repo_urls)
|
64 |
|
|
|
65 |
|
|
assert execute_in_page('returnval(shw());') == [[], False]
|
66 |
|
|
|
67 |
|
|
execute_in_page('view.show(arguments[0]);', queried_url)
|
68 |
|
|
|
69 |
|
|
assert execute_in_page('returnval(shw());') == [['show'], True]
|
70 |
|
|
|
71 |
|
|
def get_repo_entries(driver):
|
72 |
|
|
return execute_in_page(
|
73 |
|
|
f'returnval((view.repo_entries || []).map({nodes_props_code}));'
|
74 |
|
|
)
|
75 |
|
|
|
76 |
|
|
repo_entries = WebDriverWait(driver, 10).until(get_repo_entries)
|
77 |
|
|
|
78 |
|
|
assert len(repo_urls) == len(repo_entries)
|
79 |
|
|
|
80 |
|
|
for url, entry in reversed(list(zip(repo_urls, repo_entries))):
|
81 |
|
|
assert url in entry['main_li'].text
|
82 |
|
|
|
83 |
|
|
but_ids = ('show_results_but', 'hide_results_but')
|
84 |
|
|
for but_idx in (0, 1, 0):
|
85 |
|
|
assert bool(but_idx) == entry['list_container'].is_displayed()
|
86 |
|
|
|
87 |
|
|
assert not entry[but_ids[1 - but_idx]].is_displayed()
|
88 |
|
|
|
89 |
|
|
entry[but_ids[but_idx]].click()
|
90 |
|
|
|
91 |
|
|
def get_mapping_entries(driver):
|
92 |
|
|
return execute_in_page(
|
93 |
|
|
f'''{{
|
94 |
|
|
const result_entries = (view.repo_entries[0].result_entries || []);
|
95 |
|
|
returnval(result_entries.map({nodes_props_code}));
|
96 |
|
|
}}''')
|
97 |
|
|
|
98 |
|
|
mapping_entries = WebDriverWait(driver, 10).until(get_mapping_entries)
|
99 |
|
|
|
100 |
|
|
assert len(mapping_entries) == 3
|
101 |
|
|
|
102 |
57ce414c
|
Wojtek Kosior
|
expected_names = ['MAPPING-ABCD', 'MAPPING-ABCD-DEFG-GHIJ', 'MAPPING-A']
|
103 |
b75a5717
|
Wojtek Kosior
|
|
104 |
|
|
for name, entry in zip(expected_names, mapping_entries):
|
105 |
|
|
assert entry['mapping_name'].text == name
|
106 |
|
|
assert entry['mapping_id'].text == f'{name.lower()}-2022.5.11'
|
107 |
|
|
|
108 |
|
|
containers = execute_in_page(
|
109 |
|
|
'''{
|
110 |
|
|
const reductor = (acc, k) => Object.assign(acc, {[k]: view[k]});
|
111 |
|
|
returnval(container_ids.reduce(reductor, {}));
|
112 |
|
|
}''')
|
113 |
|
|
|
114 |
|
|
for id, container in containers.items():
|
115 |
|
|
assert (id == 'repos_list_container') == container.is_displayed()
|
116 |
|
|
|
117 |
|
|
entry['install_but'].click()
|
118 |
|
|
|
119 |
|
|
for id, container in containers.items():
|
120 |
|
|
assert (id == 'install_view_container') == container.is_displayed()
|
121 |
|
|
|
122 |
|
|
execute_in_page('returnval(view.install_view.cancel_but);').click()
|
123 |
|
|
|
124 |
|
|
for id, container in containers.items():
|
125 |
|
|
assert (id == 'repos_list_container') == container.is_displayed()
|
126 |
|
|
|
127 |
|
|
assert execute_in_page('returnval(shw());') == [['show'], True]
|
128 |
|
|
execute_in_page('returnval(view.cancel_but);').click()
|
129 |
|
|
assert execute_in_page('returnval(shw());') == [['show', 'hide'], False]
|
130 |
|
|
|
131 |
|
|
@pytest.mark.ext_data(repo_query_ext_data)
|
132 |
|
|
@pytest.mark.usefixtures('webextension')
|
133 |
|
|
@pytest.mark.parametrize('message', [
|
134 |
|
|
'browsing_for',
|
135 |
|
|
'no_repos',
|
136 |
|
|
'failure_to_communicate',
|
137 |
|
|
'HTTP_code',
|
138 |
|
|
'invalid_JSON',
|
139 |
|
|
'newer_API_version',
|
140 |
72553a2d
|
Wojtek Kosior
|
'invalid_response_format',
|
141 |
b75a5717
|
Wojtek Kosior
|
'querying_repo',
|
142 |
|
|
'no_results'
|
143 |
|
|
])
|
144 |
|
|
def test_repo_query_messages(driver, execute_in_page, message):
|
145 |
|
|
"""
|
146 |
|
|
Test of loading and error messages shown in parts of the repo query view.
|
147 |
|
|
"""
|
148 |
|
|
def has_msg(message, elem=None):
|
149 |
|
|
def has_msg_and_is_visible(dummy_driver):
|
150 |
|
|
if elem:
|
151 |
|
|
return elem.is_displayed() and message in elem.text
|
152 |
|
|
else:
|
153 |
|
|
return message in driver.page_source
|
154 |
|
|
return has_msg_and_is_visible
|
155 |
|
|
|
156 |
|
|
def show_and_wait_for_repo_entry():
|
157 |
|
|
execute_in_page('view.show(arguments[0]);', queried_url)
|
158 |
|
|
done = lambda d: execute_in_page('returnval(!!view.repo_entries);')
|
159 |
|
|
WebDriverWait(driver, 10).until(done)
|
160 |
|
|
execute_in_page(
|
161 |
|
|
'''
|
162 |
|
|
if (view.repo_entries.length > 0)
|
163 |
|
|
view.repo_entries[0].show_results_but.click();
|
164 |
|
|
''')
|
165 |
|
|
|
166 |
|
|
if message == 'browsing_for':
|
167 |
|
|
setup_view(execute_in_page, [])
|
168 |
|
|
show_and_wait_for_repo_entry()
|
169 |
|
|
|
170 |
|
|
elem = execute_in_page('returnval(view.url_span.parentNode);')
|
171 |
42fe4405
|
Wojtek Kosior
|
assert has_msg(f'Browsing custom resources for: {queried_url}', elem)(0)
|
172 |
b75a5717
|
Wojtek Kosior
|
elif message == 'no_repos':
|
173 |
|
|
setup_view(execute_in_page, [])
|
174 |
|
|
show_and_wait_for_repo_entry()
|
175 |
|
|
|
176 |
|
|
elem = execute_in_page('returnval(view.repos_list);')
|
177 |
|
|
done = has_msg('You have no repositories configured :(', elem)
|
178 |
|
|
WebDriverWait(driver, 10).until(done)
|
179 |
|
|
elif message == 'failure_to_communicate':
|
180 |
|
|
setup_view(execute_in_page, repo_urls)
|
181 |
|
|
execute_in_page(
|
182 |
|
|
'browser.tabs.sendMessage = () => Promise.resolve({error: "sth"});'
|
183 |
|
|
)
|
184 |
|
|
show_and_wait_for_repo_entry()
|
185 |
|
|
|
186 |
72553a2d
|
Wojtek Kosior
|
elem = execute_in_page('returnval(view.repo_entries[0].info_div);')
|
187 |
b75a5717
|
Wojtek Kosior
|
done = has_msg('Failure to communicate with repository :(', elem)
|
188 |
|
|
WebDriverWait(driver, 10).until(done)
|
189 |
|
|
elif message == 'HTTP_code':
|
190 |
|
|
setup_view(execute_in_page, repo_urls)
|
191 |
|
|
execute_in_page(
|
192 |
|
|
'''
|
193 |
|
|
const response = {ok: false, status: 405};
|
194 |
|
|
browser.tabs.sendMessage = () => Promise.resolve(response);
|
195 |
|
|
''')
|
196 |
|
|
show_and_wait_for_repo_entry()
|
197 |
|
|
|
198 |
72553a2d
|
Wojtek Kosior
|
elem = execute_in_page('returnval(view.repo_entries[0].info_div);')
|
199 |
b75a5717
|
Wojtek Kosior
|
done = has_msg('Repository sent HTTP code 405 :(', elem)
|
200 |
|
|
WebDriverWait(driver, 10).until(done)
|
201 |
|
|
elif message == 'invalid_JSON':
|
202 |
|
|
setup_view(execute_in_page, repo_urls)
|
203 |
|
|
execute_in_page(
|
204 |
|
|
'''
|
205 |
|
|
const response = {ok: true, status: 200, error_json: "sth"};
|
206 |
|
|
browser.tabs.sendMessage = () => Promise.resolve(response);
|
207 |
|
|
''')
|
208 |
|
|
show_and_wait_for_repo_entry()
|
209 |
|
|
|
210 |
72553a2d
|
Wojtek Kosior
|
elem = execute_in_page('returnval(view.repo_entries[0].info_div);')
|
211 |
b75a5717
|
Wojtek Kosior
|
done = has_msg("Repository's response is not valid JSON :(", elem)
|
212 |
|
|
WebDriverWait(driver, 10).until(done)
|
213 |
|
|
elif message == 'newer_API_version':
|
214 |
|
|
setup_view(execute_in_page, repo_urls)
|
215 |
|
|
execute_in_page(
|
216 |
|
|
'''
|
217 |
|
|
const response = {
|
218 |
|
|
ok: true,
|
219 |
|
|
status: 200,
|
220 |
57ce414c
|
Wojtek Kosior
|
json: {$schema: "https://hydrilla.koszko.org/schemas/api_query_result-255.2.1.schema.json"}
|
221 |
b75a5717
|
Wojtek Kosior
|
};
|
222 |
|
|
browser.tabs.sendMessage = () => Promise.resolve(response);
|
223 |
|
|
''')
|
224 |
|
|
show_and_wait_for_repo_entry()
|
225 |
|
|
|
226 |
72553a2d
|
Wojtek Kosior
|
elem = execute_in_page('returnval(view.repo_entries[0].info_div);')
|
227 |
|
|
msg = 'Results were served using unsupported Hydrilla API version. You might need to update Haketilo.'
|
228 |
b75a5717
|
Wojtek Kosior
|
WebDriverWait(driver, 10).until(has_msg(msg, elem))
|
229 |
72553a2d
|
Wojtek Kosior
|
elif message == 'invalid_response_format':
|
230 |
b75a5717
|
Wojtek Kosior
|
setup_view(execute_in_page, repo_urls)
|
231 |
|
|
execute_in_page(
|
232 |
|
|
'''
|
233 |
|
|
const response = {
|
234 |
|
|
ok: true,
|
235 |
|
|
status: 200,
|
236 |
72553a2d
|
Wojtek Kosior
|
/* $schema is not a string as it should be. */
|
237 |
|
|
json: {$schema: null}
|
238 |
b75a5717
|
Wojtek Kosior
|
};
|
239 |
|
|
browser.tabs.sendMessage = () => Promise.resolve(response);
|
240 |
|
|
''')
|
241 |
|
|
show_and_wait_for_repo_entry()
|
242 |
|
|
|
243 |
72553a2d
|
Wojtek Kosior
|
elem = execute_in_page('returnval(view.repo_entries[0].info_div);')
|
244 |
|
|
msg = 'Results were served using a nonconforming response format.'
|
245 |
b75a5717
|
Wojtek Kosior
|
WebDriverWait(driver, 10).until(has_msg(msg, elem))
|
246 |
|
|
elif message == 'querying_repo':
|
247 |
|
|
setup_view(execute_in_page, repo_urls)
|
248 |
|
|
execute_in_page(
|
249 |
|
|
'browser.tabs.sendMessage = () => new Promise(() => {});'
|
250 |
|
|
)
|
251 |
|
|
show_and_wait_for_repo_entry()
|
252 |
|
|
|
253 |
72553a2d
|
Wojtek Kosior
|
elem = execute_in_page('returnval(view.repo_entries[0].info_div);')
|
254 |
b75a5717
|
Wojtek Kosior
|
assert has_msg('Querying repository...', elem)(0)
|
255 |
|
|
elif message == 'no_results':
|
256 |
|
|
setup_view(execute_in_page, repo_urls)
|
257 |
|
|
execute_in_page(
|
258 |
|
|
'''
|
259 |
|
|
const response = {
|
260 |
|
|
ok: true,
|
261 |
|
|
status: 200,
|
262 |
|
|
json: {
|
263 |
72553a2d
|
Wojtek Kosior
|
$schema: "https://hydrilla.koszko.org/schemas/api_query_result-1.schema.json",
|
264 |
b75a5717
|
Wojtek Kosior
|
mappings: []
|
265 |
|
|
}
|
266 |
|
|
};
|
267 |
|
|
browser.tabs.sendMessage = () => Promise.resolve(response);
|
268 |
|
|
''')
|
269 |
|
|
show_and_wait_for_repo_entry()
|
270 |
|
|
|
271 |
72553a2d
|
Wojtek Kosior
|
elem = execute_in_page('returnval(view.repo_entries[0].info_div);')
|
272 |
b75a5717
|
Wojtek Kosior
|
WebDriverWait(driver, 10).until(has_msg('No results :(', elem))
|
273 |
|
|
else:
|
274 |
|
|
raise Exception('made a typo in test function params?')
|