mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-26 02:48:38 -04:00
114 lines
4.4 KiB
Python
114 lines
4.4 KiB
Python
import asyncio
|
|
import json
|
|
import pathlib
|
|
from itertools import zip_longest
|
|
from typing import List, Dict
|
|
from uuid import uuid4
|
|
|
|
import pytest
|
|
from mock import mock
|
|
|
|
from modules.zim.downloader import KiwixCatalogDownloader, KiwixZimDownloader
|
|
from modules.zim.models import Zim
|
|
from wrolpi.common import DownloadFileInfo
|
|
from wrolpi.downloader import DownloadManager
|
|
from wrolpi.vars import PROJECT_DIR
|
|
|
|
|
|
@pytest.fixture
|
|
def kiwix_download_manager(test_download_manager) -> DownloadManager:
|
|
kiwix_downloader = KiwixCatalogDownloader()
|
|
kiwix_zim_downloader = KiwixZimDownloader()
|
|
|
|
test_download_manager.register_downloader(kiwix_downloader)
|
|
test_download_manager.register_downloader(kiwix_zim_downloader)
|
|
|
|
yield test_download_manager
|
|
|
|
|
|
@pytest.fixture
|
|
def kiwix_download_zim(test_directory, kiwix_download_manager, test_zim_bytes, mock_downloader_download_file):
|
|
async def do_download(download_info: DownloadFileInfo = None, expected_url: str = None,
|
|
download_file_side_effect=None, hrefs: List[str] = None):
|
|
with mock.patch('modules.zim.downloader.fetch_hrefs') as mock_fetch_hrefs:
|
|
# Fake the download, but make sure it is called correctly. Also creates a Zim file at the output_path.
|
|
# These are the links in the parent directory of the url.
|
|
mock_fetch_hrefs.return_value = hrefs or ['?C=N;O=D', '?C=M;O=A', '?C=S;O=A', '?C=D;O=A', '/zim/',
|
|
'wikipedia_es_all_maxi_2023-05.zim',
|
|
'wikipedia_es_all_maxi_2023-06.zim',
|
|
'wikipedia_es_all_nopic_2023-05.zim',
|
|
'wikipedia_es_all_nopic_2023-06.zim']
|
|
mock_downloader_download_file(test_zim_bytes)
|
|
|
|
await kiwix_download_manager.wait_for_all_downloads()
|
|
# Async download are hard to test, sleep to let tasks finish.
|
|
await asyncio.sleep(0.1)
|
|
await kiwix_download_manager.wait_for_all_downloads()
|
|
|
|
return do_download
|
|
|
|
|
|
@pytest.fixture()
|
|
def test_zim_bytes():
|
|
"""Read the byte contents of the test Zim (test/zim.zim)."""
|
|
path = PROJECT_DIR / 'test/zim.zim'
|
|
return path.read_bytes()
|
|
|
|
|
|
@pytest.fixture
|
|
def zim_path_factory(test_zim_bytes, test_directory):
|
|
"""Copy the test Zim into the test directory."""
|
|
|
|
def _(name: str = None) -> pathlib.Path:
|
|
name = name if name else f'{uuid4()}.zim'
|
|
path = test_directory / name
|
|
path.write_bytes(test_zim_bytes)
|
|
return path
|
|
|
|
return _
|
|
|
|
|
|
@pytest.fixture
|
|
def test_zim(test_session, zim_path_factory) -> Zim:
|
|
zim = Zim.from_paths(test_session, zim_path_factory())
|
|
return zim
|
|
|
|
|
|
@pytest.fixture
|
|
def zim_factory(test_session, zim_path_factory, test_directory):
|
|
def _(name: str) -> Zim:
|
|
zim = Zim.from_paths(test_session, zim_path_factory(name))
|
|
return zim
|
|
|
|
return _
|
|
|
|
|
|
@pytest.fixture
|
|
def assert_zim_search(async_client, test_directory):
|
|
from http import HTTPStatus
|
|
|
|
async def _(search_str: str, zim_id: int, expected: Dict, tag_names: List[str] = [],
|
|
expected_status_code: int = HTTPStatus.OK):
|
|
content = dict(search_str=search_str, tag_names=tag_names)
|
|
assert isinstance(zim_id, int), 'This fixture only supports Zim ids of type integer'
|
|
request, response = await async_client.post(f'api/zim/search/{zim_id}', content=json.dumps(content))
|
|
assert response.status_code == expected_status_code
|
|
|
|
result = response.json['zim']
|
|
|
|
if path := expected.get('path'):
|
|
assert result['path'] == str(path.relative_to(test_directory))
|
|
|
|
if estimate := expected.get('estimate'):
|
|
assert result['estimate'] == estimate
|
|
|
|
for response_entry, expected_entry in zip_longest(result['search'], expected['search']):
|
|
if response_entry and not expected_entry:
|
|
raise AssertionError(f'Response contained more entries than expected: {response_entry}')
|
|
elif not response_entry and expected_entry:
|
|
raise AssertionError(f'Response did not contain the expected entry: {expected_entry}')
|
|
assert response_entry['path'] == expected_entry['path']
|
|
assert response_entry['headline'] == expected_entry['headline']
|
|
assert response_entry['rank'] == expected_entry['rank']
|
|
|
|
return _
|