145 lines
4.4 KiB
Python
145 lines
4.4 KiB
Python
from __future__ import annotations
|
|
|
|
import io
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from sticker_downloader.progress import ConsoleProgress, NullProgress
|
|
from sticker_downloader.results import (
|
|
FileOutcome,
|
|
FileStatus,
|
|
PackResult,
|
|
RunTotals,
|
|
format_size,
|
|
)
|
|
|
|
|
|
def outcome(name: str, status: FileStatus, size: int = 0) -> FileOutcome:
|
|
return FileOutcome(Path("downloads/Pack") / name, status, size=size)
|
|
|
|
|
|
def reporter(**kwargs) -> tuple[ConsoleProgress, io.StringIO]:
|
|
stream = io.StringIO()
|
|
return ConsoleProgress(stream, use_ansi=False, **kwargs), stream
|
|
|
|
|
|
def test_pack_lifecycle_is_reported():
|
|
progress, stream = reporter()
|
|
progress.pack_started("Pack", "Pack", 2, 3)
|
|
progress.file_finished(outcome("001.webp", FileStatus.DOWNLOADED, 1024))
|
|
result = PackResult(
|
|
reference="Pack",
|
|
name="Pack",
|
|
directory=Path("downloads/Pack"),
|
|
total_stickers=2,
|
|
outcomes=[outcome("001.webp", FileStatus.DOWNLOADED, 1024)],
|
|
)
|
|
progress.pack_finished(result)
|
|
|
|
text = stream.getvalue()
|
|
assert "Pack: 2 stickers, 3 files" in text
|
|
assert "1 downloaded" in text
|
|
assert "downloads/Pack" in text
|
|
|
|
|
|
def test_quiet_files_are_not_listed_without_verbose():
|
|
progress, stream = reporter()
|
|
progress.file_finished(outcome("001.webp", FileStatus.DOWNLOADED, 10))
|
|
assert stream.getvalue() == ""
|
|
|
|
|
|
def test_verbose_lists_each_file_with_its_size():
|
|
progress, stream = reporter(verbose=True)
|
|
progress.file_finished(outcome("001.webp", FileStatus.DOWNLOADED, 2048))
|
|
assert "downloaded: 001.webp (2.0 KiB)" in stream.getvalue()
|
|
|
|
|
|
def test_failures_are_always_reported():
|
|
progress, stream = reporter()
|
|
progress.file_finished(
|
|
FileOutcome(Path("001.webp"), FileStatus.FAILED, error="HTTP 404")
|
|
)
|
|
assert "error: 001.webp: HTTP 404" in stream.getvalue()
|
|
|
|
|
|
def test_pack_error_is_reported_instead_of_a_summary():
|
|
progress, stream = reporter()
|
|
progress.pack_finished(PackResult(reference="Nope", error="sticker pack not found"))
|
|
assert "error: Nope: sticker pack not found" in stream.getvalue()
|
|
|
|
|
|
def test_run_summary_lists_failing_packs():
|
|
progress, stream = reporter()
|
|
good = PackResult(
|
|
reference="A",
|
|
name="A",
|
|
outcomes=[outcome("001.webp", FileStatus.DOWNLOADED, 1024)],
|
|
)
|
|
bad = PackResult(reference="B", name="B", error="sticker pack not found")
|
|
progress.run_finished([good, bad])
|
|
|
|
text = stream.getvalue()
|
|
assert "Done: 1/2 packs" in text
|
|
assert "files downloaded : 1 (1.0 KiB)" in text
|
|
assert "packs failed : 1" in text
|
|
assert "- B: sticker pack not found" in text
|
|
|
|
|
|
def test_empty_run_says_so():
|
|
progress, stream = reporter()
|
|
progress.run_finished([])
|
|
assert "Nothing to do." in stream.getvalue()
|
|
|
|
|
|
def test_live_line_is_redrawn_on_a_terminal():
|
|
stream = io.StringIO()
|
|
progress = ConsoleProgress(stream, use_ansi=True)
|
|
progress.pack_started("Pack", "Pack", 1, 2)
|
|
progress.file_finished(outcome("001.webp", FileStatus.DOWNLOADED, 1))
|
|
progress.file_finished(outcome("002.webp", FileStatus.DOWNLOADED, 1))
|
|
assert "\r 1/2 files" in stream.getvalue()
|
|
assert "\r 2/2 files" in stream.getvalue()
|
|
|
|
|
|
def test_null_progress_accepts_every_call():
|
|
progress = NullProgress()
|
|
progress.info("x")
|
|
progress.warn("x")
|
|
progress.error("x")
|
|
progress.pack_started("a", "b", 1, 1)
|
|
progress.file_finished(outcome("001.webp", FileStatus.DOWNLOADED))
|
|
progress.pack_finished(PackResult(reference="a"))
|
|
progress.run_finished([])
|
|
|
|
|
|
def test_run_totals_aggregate_every_status():
|
|
results = [
|
|
PackResult(
|
|
reference="A",
|
|
outcomes=[
|
|
outcome("001.webp", FileStatus.DOWNLOADED, 100),
|
|
outcome("002.webp", FileStatus.SKIPPED_EXISTING),
|
|
outcome("003.webp", FileStatus.FAILED),
|
|
],
|
|
),
|
|
PackResult(reference="B", outcomes=[outcome("001.webp", FileStatus.PLANNED)]),
|
|
]
|
|
totals = RunTotals.from_results(results)
|
|
assert (totals.packs, totals.packs_ok, totals.packs_failed) == (2, 1, 1)
|
|
assert (totals.downloaded, totals.skipped, totals.planned, totals.failed) == (
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
)
|
|
assert totals.bytes_written == 100
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("num_bytes", "expected"),
|
|
[(0, "0 B"), (512, "512 B"), (2048, "2.0 KiB"), (5 * 1024**2, "5.0 MiB")],
|
|
)
|
|
def test_format_size(num_bytes: int, expected: str):
|
|
assert format_size(num_bytes) == expected
|