Add more tests
This commit is contained in:
parent
9ba8b2876c
commit
a00891f622
@ -399,7 +399,7 @@ class ComicVineTalker:
|
||||
"filter": flt,
|
||||
}
|
||||
|
||||
cv_response = self.get_cv_content(self.api_base_url + "/issues", params)
|
||||
cv_response = self.get_cv_content(self.api_base_url + "/issues/", params)
|
||||
|
||||
current_result_count = cv_response["number_of_page_results"]
|
||||
total_result_count = cv_response["number_of_total_results"]
|
||||
@ -429,7 +429,7 @@ class ComicVineTalker:
|
||||
|
||||
f_record = None
|
||||
for record in issues_list_results:
|
||||
if IssueString(issue_number).as_string() is None:
|
||||
if not IssueString(issue_number).as_string():
|
||||
issue_number = "1"
|
||||
if (
|
||||
IssueString(record["issue_number"]).as_string().casefold()
|
||||
|
@ -90,17 +90,9 @@ class MetadataFormatter(string.Formatter):
|
||||
field_name = field_name.casefold()
|
||||
# this is some markup, find the object and do the formatting
|
||||
|
||||
# handle arg indexing when empty field_names are given.
|
||||
if field_name == "":
|
||||
if auto_arg_index is False:
|
||||
raise ValueError("cannot switch from manual field specification to automatic field numbering")
|
||||
field_name = str(auto_arg_index)
|
||||
auto_arg_index += 1
|
||||
elif field_name.isdigit():
|
||||
if auto_arg_index:
|
||||
raise ValueError("cannot switch from manual field specification to automatic field numbering")
|
||||
# disable auto arg incrementing, if it gets used later on, then an exception will be raised
|
||||
auto_arg_index = False
|
||||
# handle arg indexing when digit field_names are given.
|
||||
if field_name.isdigit():
|
||||
raise ValueError("cannot use a number as a field name")
|
||||
|
||||
# given the field_name, find the object it references
|
||||
# and the argument it came from
|
||||
@ -111,8 +103,8 @@ class MetadataFormatter(string.Formatter):
|
||||
obj = self.convert_field(obj, conversion) # type: ignore
|
||||
|
||||
# expand the format spec, if needed
|
||||
format_spec, auto_arg_index = self._vformat(
|
||||
cast(str, format_spec), args, kwargs, used_args, recursion_depth - 1, auto_arg_index=auto_arg_index
|
||||
format_spec, _ = self._vformat(
|
||||
cast(str, format_spec), args, kwargs, used_args, recursion_depth - 1, auto_arg_index=False
|
||||
)
|
||||
|
||||
# format the object and append to the result
|
||||
@ -128,7 +120,7 @@ class MetadataFormatter(string.Formatter):
|
||||
fmt_obj = str(sanitize_filename(fmt_obj, platform=self.platform))
|
||||
result.append(fmt_obj)
|
||||
|
||||
return "".join(result), auto_arg_index
|
||||
return "".join(result), False
|
||||
|
||||
|
||||
class FileRenamer:
|
||||
|
@ -19,7 +19,7 @@ import itertools
|
||||
import logging
|
||||
from collections import deque
|
||||
|
||||
from PyQt5 import QtCore, QtWidgets, uic
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets, uic
|
||||
from PyQt5.QtCore import pyqtSignal
|
||||
|
||||
from comicapi import utils
|
||||
@ -452,15 +452,16 @@ class VolumeSelectionWindow(QtWidgets.QDialog):
|
||||
self.twList.selectRow(0)
|
||||
self.twList.resizeColumnsToContents()
|
||||
|
||||
if not self.cv_search_results:
|
||||
QtCore.QCoreApplication.processEvents()
|
||||
QtWidgets.QMessageBox.information(self, "Search Result", "No matches found!")
|
||||
QtCore.QTimer.singleShot(200, self.close_me)
|
||||
def showEvent(self, event: QtGui.QShowEvent):
|
||||
if not self.cv_search_results:
|
||||
QtCore.QCoreApplication.processEvents()
|
||||
QtWidgets.QMessageBox.information(self, "Search Result", "No matches found!")
|
||||
QtCore.QTimer.singleShot(200, self.close_me)
|
||||
|
||||
if self.immediate_autoselect and self.cv_search_results:
|
||||
# defer the immediate autoselect so this dialog has time to pop up
|
||||
QtCore.QCoreApplication.processEvents()
|
||||
QtCore.QTimer.singleShot(10, self.do_immediate_autoselect)
|
||||
elif self.immediate_autoselect:
|
||||
# defer the immediate autoselect so this dialog has time to pop up
|
||||
QtCore.QCoreApplication.processEvents()
|
||||
QtCore.QTimer.singleShot(10, self.do_immediate_autoselect)
|
||||
|
||||
def do_immediate_autoselect(self) -> None:
|
||||
self.immediate_autoselect = False
|
||||
|
@ -5,6 +5,14 @@ from typing import Any
|
||||
import comicapi.genericmetadata
|
||||
import comictaggerlib.comicvinetalker
|
||||
|
||||
|
||||
def filter_field_list(cv_result, kwargs):
|
||||
if "field_list" in kwargs["params"]:
|
||||
for key in list(cv_result.keys()):
|
||||
if key not in kwargs["params"]["field_list"]:
|
||||
del cv_result[key]
|
||||
|
||||
|
||||
cv_issue_result: dict[str, Any] = {
|
||||
"error": "OK",
|
||||
"limit": 1,
|
||||
@ -99,6 +107,15 @@ cv_volume_result: dict[str, Any] = {
|
||||
},
|
||||
"version": "1.0",
|
||||
}
|
||||
cv_not_found = {
|
||||
"error": "Object Not Found",
|
||||
"limit": 0,
|
||||
"offset": 0,
|
||||
"number_of_page_results": 0,
|
||||
"number_of_total_results": 0,
|
||||
"status_code": 101,
|
||||
"results": [],
|
||||
}
|
||||
date = comictaggerlib.comicvinetalker.ComicVineTalker().parse_date_str(cv_issue_result["results"]["cover_date"])
|
||||
|
||||
cv_md = comicapi.genericmetadata.GenericMetadata(
|
||||
|
@ -11,6 +11,16 @@ format is
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import pathlib
|
||||
from contextlib import nullcontext as does_not_raise
|
||||
|
||||
import pytest
|
||||
|
||||
datadir = pathlib.Path(__file__).parent / "data"
|
||||
cbz_path = datadir / "Cory Doctorow's Futuristic Tales of the Here and Now #001 - Anda's Game (2007).cbz"
|
||||
|
||||
fnames = [
|
||||
(
|
||||
"batman 3 title (DC).cbz",
|
||||
@ -731,89 +741,125 @@ rnames = [
|
||||
False,
|
||||
"universal",
|
||||
"Cory Doctorow's Futuristic Tales of the Here and Now #001 - Anda's Game (2007).cbz",
|
||||
does_not_raise(),
|
||||
),
|
||||
(
|
||||
"{series} #{issue} - {title} ({year})({price})", # price should be none, test no space between ')('
|
||||
False,
|
||||
"universal",
|
||||
"Cory Doctorow's Futuristic Tales of the Here and Now #001 - Anda's Game (2007).cbz",
|
||||
does_not_raise(),
|
||||
),
|
||||
(
|
||||
"{series} #{issue} - {title} ({year}) ({price})", # price should be none, test double space ') ('
|
||||
False,
|
||||
"universal",
|
||||
"Cory Doctorow's Futuristic Tales of the Here and Now #001 - Anda's Game (2007).cbz",
|
||||
does_not_raise(),
|
||||
),
|
||||
(
|
||||
"{series} #{issue} - {title} ({year})",
|
||||
False,
|
||||
"universal",
|
||||
"Cory Doctorow's Futuristic Tales of the Here and Now #001 - Anda's Game (2007).cbz",
|
||||
does_not_raise(),
|
||||
),
|
||||
(
|
||||
"{series}: {title} #{issue} ({year})", # on windows the ':' is replaced
|
||||
False,
|
||||
"universal",
|
||||
"Cory Doctorow's Futuristic Tales of the Here and Now - Anda's Game #001 (2007).cbz",
|
||||
does_not_raise(),
|
||||
),
|
||||
(
|
||||
"{series}: {title} #{issue} ({year})", # on linux the ':' is preserved
|
||||
False,
|
||||
"Linux",
|
||||
"Cory Doctorow's Futuristic Tales of the Here and Now: Anda's Game #001 (2007).cbz",
|
||||
does_not_raise(),
|
||||
),
|
||||
(
|
||||
"{publisher}/ {series} #{issue} - {title} ({year})", # leading whitespace is removed when moving
|
||||
True,
|
||||
"universal",
|
||||
"IDW Publishing/Cory Doctorow's Futuristic Tales of the Here and Now #001 - Anda's Game (2007).cbz",
|
||||
does_not_raise(),
|
||||
),
|
||||
(
|
||||
"{publisher}/ {series} #{issue} - {title} ({year})", # leading whitespace is removed when only renaming
|
||||
False,
|
||||
"universal",
|
||||
"Cory Doctorow's Futuristic Tales of the Here and Now #001 - Anda's Game (2007).cbz",
|
||||
does_not_raise(),
|
||||
),
|
||||
(
|
||||
r"{publisher}\ {series} #{issue} - {title} ({year})", # backslashes separate directories
|
||||
False,
|
||||
"universal",
|
||||
"Cory Doctorow's Futuristic Tales of the Here and Now #001 - Anda's Game (2007).cbz",
|
||||
does_not_raise(),
|
||||
),
|
||||
(
|
||||
"{series} # {issue} - {title} ({year})", # double spaces are reduced to one
|
||||
False,
|
||||
"universal",
|
||||
"Cory Doctorow's Futuristic Tales of the Here and Now # 001 - Anda's Game (2007).cbz",
|
||||
does_not_raise(),
|
||||
),
|
||||
(
|
||||
"{series} # {issue} - {locations} ({year})",
|
||||
False,
|
||||
"universal",
|
||||
"Cory Doctorow's Futuristic Tales of the Here and Now # 001 - lonely cottage (2007).cbz",
|
||||
does_not_raise(),
|
||||
),
|
||||
(
|
||||
"{series} #{issue} - {title} - {WriteR}, {EDITOR} ({year})", # fields are case in-sensitive
|
||||
False,
|
||||
"universal",
|
||||
"Cory Doctorow's Futuristic Tales of the Here and Now #001 - Anda's Game - Dara Naraghi, Ted Adams (2007).cbz",
|
||||
does_not_raise(),
|
||||
),
|
||||
(
|
||||
"{series} v{price} #{issue} ({year})", # Remove previous text if value is ""
|
||||
False,
|
||||
"universal",
|
||||
"Cory Doctorow's Futuristic Tales of the Here and Now #001 (2007).cbz",
|
||||
does_not_raise(),
|
||||
),
|
||||
(
|
||||
"{series} {price} #{issue} ({year})", # Ensure that a single space remains
|
||||
False,
|
||||
"universal",
|
||||
"Cory Doctorow's Futuristic Tales of the Here and Now #001 (2007).cbz",
|
||||
does_not_raise(),
|
||||
),
|
||||
(
|
||||
"{series} - {title}{price} #{issue} ({year})", # Ensure removal before None values only impacts literal text
|
||||
False,
|
||||
"universal",
|
||||
"Cory Doctorow's Futuristic Tales of the Here and Now - Anda's Game #001 (2007).cbz",
|
||||
does_not_raise(),
|
||||
),
|
||||
(
|
||||
"{series} - {title} {test} #{issue} ({year})", # Test non-existent key
|
||||
False,
|
||||
"universal",
|
||||
"Cory Doctorow's Futuristic Tales of the Here and Now - Anda's Game {test} #001 (2007).cbz",
|
||||
does_not_raise(),
|
||||
),
|
||||
(
|
||||
"{series} - {title} {1} #{issue} ({year})", # Test numeric key
|
||||
False,
|
||||
"universal",
|
||||
"Cory Doctorow's Futuristic Tales of the Here and Now - Anda's Game {test} #001 (2007).cbz",
|
||||
pytest.raises(ValueError),
|
||||
),
|
||||
]
|
||||
|
||||
rfnames = [
|
||||
(None, lambda x: x.path.parent.absolute()),
|
||||
("", lambda x: pathlib.Path(os.getcwd())),
|
||||
("test", lambda x: (pathlib.Path(os.getcwd()) / "test")),
|
||||
(pathlib.Path(os.getcwd()) / "test", lambda x: pathlib.Path(os.getcwd()) / "test"),
|
||||
]
|
||||
|
@ -1,16 +1,12 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pathlib
|
||||
import shutil
|
||||
|
||||
import pytest
|
||||
|
||||
import comicapi.comicarchive
|
||||
import comicapi.genericmetadata
|
||||
import testing
|
||||
|
||||
datadir = pathlib.Path(testing.__file__).parent / "data"
|
||||
cbz_path = datadir / "Cory Doctorow's Futuristic Tales of the Here and Now #001 - Anda's Game (2007).cbz"
|
||||
from testing.filenames import cbz_path, datadir
|
||||
|
||||
|
||||
@pytest.mark.xfail(not comicapi.comicarchive.rar_support, reason="rar support")
|
||||
@ -28,25 +24,14 @@ def test_getPageNameList():
|
||||
]
|
||||
|
||||
|
||||
def test_set_default_page_list(tmp_path):
|
||||
md = comicapi.genericmetadata.GenericMetadata()
|
||||
md.overlay(comicapi.genericmetadata.md_test)
|
||||
md.pages = []
|
||||
md.set_default_page_list(len(comicapi.genericmetadata.md_test.pages))
|
||||
|
||||
assert isinstance(md.pages[0]["Image"], int)
|
||||
|
||||
|
||||
def test_page_type_read():
|
||||
c = comicapi.comicarchive.ComicArchive(cbz_path)
|
||||
md = c.read_cix()
|
||||
def test_page_type_read(cbz):
|
||||
md = cbz.read_cix()
|
||||
|
||||
assert isinstance(md.pages[0]["Type"], str)
|
||||
|
||||
|
||||
def test_metadata_read():
|
||||
c = comicapi.comicarchive.ComicArchive(cbz_path)
|
||||
md = c.read_cix()
|
||||
def test_metadata_read(cbz):
|
||||
md = cbz.read_cix()
|
||||
assert md == comicapi.genericmetadata.md_test
|
||||
|
||||
|
||||
@ -101,10 +86,9 @@ archivers = [
|
||||
|
||||
|
||||
@pytest.mark.parametrize("archiver", archivers)
|
||||
def test_copy_to_archive(archiver, tmp_path):
|
||||
comic_path = tmp_path / cbz_path.with_suffix("").name
|
||||
def test_copy_to_archive(archiver, tmp_path, cbz):
|
||||
comic_path = tmp_path / cbz.path.with_suffix("").name
|
||||
|
||||
cbz = comicapi.comicarchive.ComicArchive(cbz_path)
|
||||
archive = archiver(comic_path)
|
||||
|
||||
assert archive.copy_from_archive(cbz.archiver)
|
||||
|
@ -2,6 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
import comicapi.genericmetadata
|
||||
import comictaggerlib.comicvinetalker
|
||||
import testing.comicvine
|
||||
from testing.comicdata import select_details
|
||||
@ -16,12 +17,60 @@ def test_fetch_volume_data(comicvine_api, settings, mock_now, comic_cache):
|
||||
assert volume == comic_cache.get_volume_info(23437, ct.source_name)
|
||||
|
||||
|
||||
def test_fetch_issues_by_volume(comicvine_api, settings, comic_cache):
|
||||
ct = comictaggerlib.comicvinetalker.ComicVineTalker()
|
||||
issues = ct.fetch_issues_by_volume(23437)
|
||||
cache_issues = comic_cache.get_volume_issues_info(23437, ct.source_name)
|
||||
|
||||
issues[0]["image"] = {"super_url": issues[0]["image"]["super_url"], "thumb_url": issues[0]["image"]["thumb_url"]}
|
||||
del issues[0]["volume"]
|
||||
assert issues == cache_issues
|
||||
|
||||
|
||||
def test_fetch_issue_data_by_issue_id(comicvine_api, settings, mock_now, mock_version):
|
||||
ct = comictaggerlib.comicvinetalker.ComicVineTalker()
|
||||
md = ct.fetch_issue_data_by_issue_id(311811, settings)
|
||||
assert md == testing.comicvine.cv_md
|
||||
|
||||
|
||||
def test_fetch_issues_by_volume_issue_num_and_year(comicvine_api):
|
||||
ct = comictaggerlib.comicvinetalker.ComicVineTalker()
|
||||
cv = ct.fetch_issues_by_volume_issue_num_and_year([23437], "3", None)
|
||||
cv_expected = testing.comicvine.cv_issue_result["results"].copy()
|
||||
testing.comicvine.filter_field_list(
|
||||
cv_expected,
|
||||
{"params": {"field_list": "id,volume,issue_number,name,image,cover_date,site_detail_url,description"}},
|
||||
)
|
||||
assert cv[0] == cv_expected
|
||||
|
||||
|
||||
cv_issue = [
|
||||
(23437, "3", testing.comicvine.cv_md),
|
||||
(23437, "", comicapi.genericmetadata.GenericMetadata()),
|
||||
(23437, "0", comicapi.genericmetadata.GenericMetadata()),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("volume_id, issue_number, result_md", cv_issue)
|
||||
def test_fetch_issue_data(comicvine_api, settings, mock_now, mock_version, volume_id, issue_number, result_md):
|
||||
ct = comictaggerlib.comicvinetalker.ComicVineTalker()
|
||||
md = ct.fetch_issue_data(volume_id, issue_number, settings)
|
||||
assert md == result_md
|
||||
|
||||
|
||||
# @pytest.mark.parametrize("volume_id, issue_number, result_md", cv_issue)
|
||||
def test_fetch_issue_select_details(comicvine_api, settings, mock_now, mock_version):
|
||||
ct = comictaggerlib.comicvinetalker.ComicVineTalker()
|
||||
md = ct.fetch_issue_select_details(311811)
|
||||
res = {
|
||||
"cover_date": testing.comicvine.cv_issue_result["results"]["cover_date"],
|
||||
"site_detail_url": testing.comicvine.cv_issue_result["results"]["site_detail_url"],
|
||||
"image_url": testing.comicvine.cv_issue_result["results"]["image"]["super_url"],
|
||||
"thumb_image_url": testing.comicvine.cv_issue_result["results"]["image"]["thumb_url"],
|
||||
}
|
||||
assert md == res
|
||||
|
||||
|
||||
@pytest.mark.parametrize("details", select_details)
|
||||
def test_issue_select_details(comic_cache, details):
|
||||
ct = comictaggerlib.comicvinetalker.ComicVineTalker()
|
||||
|
@ -8,15 +8,21 @@ from typing import Any, Generator
|
||||
import pytest
|
||||
import requests
|
||||
|
||||
import comicapi.comicarchive
|
||||
import comicapi.genericmetadata
|
||||
import comictaggerlib.comiccacher
|
||||
import comictaggerlib.comicvinetalker
|
||||
import comictaggerlib.settings
|
||||
from comicapi import utils
|
||||
from testing import comicvine
|
||||
from testing import comicvine, filenames
|
||||
from testing.comicdata import all_seed_imprints, seed_imprints
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def cbz():
|
||||
yield comicapi.comicarchive.ComicArchive(filenames.cbz_path)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def no_requests(monkeypatch) -> None:
|
||||
"""Remove requests.sessions.Session.request for all tests."""
|
||||
@ -35,7 +41,18 @@ def comicvine_api(monkeypatch) -> unittest.mock.Mock:
|
||||
return comicvine.MockResponse(comicvine.cv_volume_result)
|
||||
if args[0].startswith("https://comicvine.gamespot.com/api/issue/4000-311811"):
|
||||
return comicvine.MockResponse(comicvine.cv_issue_result)
|
||||
return comicvine.MockResponse({})
|
||||
if (
|
||||
args[0].startswith("https://comicvine.gamespot.com/api/issues/")
|
||||
and "params" in kwargs
|
||||
and "filter" in kwargs["params"]
|
||||
and "23437" in kwargs["params"]["filter"]
|
||||
):
|
||||
cv_list = comicvine.cv_issue_result.copy()
|
||||
cv_list["results"] = cv_list["results"].copy()
|
||||
comicvine.filter_field_list(cv_list["results"], kwargs)
|
||||
cv_list["results"] = [cv_list["results"]]
|
||||
return comicvine.MockResponse(cv_list)
|
||||
return comicvine.MockResponse(comicvine.cv_not_found)
|
||||
|
||||
m_get = unittest.mock.Mock(side_effect=mock_get)
|
||||
|
||||
|
@ -6,6 +6,15 @@ import comicapi.genericmetadata
|
||||
from testing.comicdata import credits, metadata
|
||||
|
||||
|
||||
def test_set_default_page_list(tmp_path):
|
||||
md = comicapi.genericmetadata.GenericMetadata()
|
||||
md.overlay(comicapi.genericmetadata.md_test)
|
||||
md.pages = []
|
||||
md.set_default_page_list(len(comicapi.genericmetadata.md_test.pages))
|
||||
|
||||
assert isinstance(md.pages[0]["Image"], int)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("replaced, expected", metadata)
|
||||
def test_metadata_overlay(md: comicapi.genericmetadata.GenericMetadata, replaced, expected):
|
||||
md.overlay(replaced)
|
||||
|
@ -5,13 +5,19 @@ import pathlib
|
||||
import pytest
|
||||
|
||||
from comicapi.genericmetadata import md_test
|
||||
from comictaggerlib.filerenamer import FileRenamer
|
||||
from testing.filenames import rnames
|
||||
from comictaggerlib import filerenamer
|
||||
from testing.filenames import rfnames, rnames
|
||||
|
||||
|
||||
@pytest.mark.parametrize("template, move, platform, expected", rnames)
|
||||
def test_rename(template, platform, move, expected):
|
||||
fr = FileRenamer(md_test, platform=platform)
|
||||
@pytest.mark.parametrize("template, move, platform, expected, exception", rnames)
|
||||
def test_rename(template, platform, move, expected, exception):
|
||||
fr = filerenamer.FileRenamer(md_test, platform=platform)
|
||||
fr.move = move
|
||||
fr.set_template(template)
|
||||
assert str(pathlib.PureWindowsPath(fr.determine_name(".cbz"))) == str(pathlib.PureWindowsPath(expected))
|
||||
with exception:
|
||||
assert str(pathlib.PureWindowsPath(fr.determine_name(".cbz"))) == str(pathlib.PureWindowsPath(expected))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("inp, result", rfnames)
|
||||
def test_get_rename_dir(inp, result, cbz):
|
||||
assert result(cbz) == filerenamer.get_rename_dir(cbz, inp)
|
||||
|
Loading…
Reference in New Issue
Block a user