mirror of
https://github.com/emilybache/GildedRose-Refactoring-Kata.git
synced 2026-02-08 11:11:24 +00:00
124 lines
4.4 KiB
Python
124 lines
4.4 KiB
Python
import filecmp
|
|
import os
|
|
import pathlib
|
|
from typing import Callable, List, Optional
|
|
|
|
from typing_extensions import override
|
|
|
|
from approval_utilities.utilities.multiline_string_utils import remove_indentation_from
|
|
from approvaltests.core.comparator import Comparator
|
|
from approvaltests.core.namer import Namer
|
|
from approvaltests.core.reporter import Reporter
|
|
from approvaltests.core.writer import Writer
|
|
from approvaltests.internals.logs.approved_file_log import ApprovedFilesLog
|
|
from approvaltests.internals.logs.failed_comparison_log import FailedComparisonLog
|
|
|
|
|
|
def exists(path: str) -> bool:
|
|
return os.path.isfile(path)
|
|
|
|
|
|
class ReporterNotWorkingException(Exception):
|
|
def __init__(self, reporter: Reporter):
|
|
super().__init__(f"Reporter {reporter} failed to work!")
|
|
|
|
|
|
class FileComparator(Comparator):
|
|
@override
|
|
def compare(self, received_path: str, approved_path: str) -> bool:
|
|
if not exists(approved_path) or not exists(received_path):
|
|
return False
|
|
if filecmp.cmp(approved_path, received_path, shallow=False):
|
|
return True
|
|
try:
|
|
approved_raw = pathlib.Path(approved_path).read_text()
|
|
approved_text = approved_raw.replace("\r\n", "\n")
|
|
received_raw = pathlib.Path(received_path).read_text()
|
|
received_text = received_raw.replace("\r\n", "\n")
|
|
return approved_text == received_text
|
|
except BaseException:
|
|
return False
|
|
|
|
|
|
class FileApprover:
|
|
previous_approved: List[str] = []
|
|
allowed_duplicates: List[Callable[[str], bool]] = []
|
|
|
|
@staticmethod
|
|
def verify(
|
|
namer: Namer, writer: Writer, reporter: Reporter, comparator: Comparator
|
|
) -> Optional[str]:
|
|
approved = namer.get_approved_filename()
|
|
received = namer.get_received_filename()
|
|
|
|
if FileApprover.is_this_a_multiple_verify(approved):
|
|
return FileApprover.get_duplicate_verify_error_message(approved)
|
|
FileApprover.previous_approved.append(approved)
|
|
|
|
# The writer has the ability to change the name of the received file
|
|
received = writer.write_received_file(received)
|
|
verified = FileApprover.verify_files(approved, received, reporter, comparator)
|
|
|
|
if not verified:
|
|
return (
|
|
f"Approval Mismatch, received != approved\n"
|
|
f"\tApproved: {approved}\n"
|
|
f"\tReceived: {received} "
|
|
)
|
|
return None
|
|
|
|
@staticmethod
|
|
def get_duplicate_verify_error_message(approved: str) -> str:
|
|
return remove_indentation_from(
|
|
f"""
|
|
We noticed that you called verify more than once in the same test.
|
|
This is the second call to verify:
|
|
approved_file: {approved}
|
|
|
|
By default, ApprovalTests only allows one verify() call per test.
|
|
To find out more, visit:
|
|
https://github.com/approvals/ApprovalTests.Python/blob/main/docs/how_to/multiple_approvals_per_test.md
|
|
|
|
# Possible Fixes
|
|
1. Separate your test into two tests
|
|
2. In your verify call, add `options=NamerFactory.with_parameters("your_paramater")`
|
|
3. In your test, call `approvals.settings().allow_multiple_verify_calls_for_this_method()`
|
|
"""
|
|
)
|
|
|
|
@staticmethod
|
|
def is_this_a_multiple_verify(approved: str) -> bool:
|
|
return (
|
|
approved in FileApprover.previous_approved
|
|
and not FileApprover.is_duplicate_allowed(approved)
|
|
)
|
|
|
|
@staticmethod
|
|
def is_duplicate_allowed(approved: str) -> bool:
|
|
for allowed in FileApprover.allowed_duplicates:
|
|
if allowed(approved):
|
|
return True
|
|
return False
|
|
|
|
@staticmethod
|
|
def verify_files(
|
|
approved_file: str,
|
|
received_file: str,
|
|
reporter: Reporter,
|
|
comparator: Comparator,
|
|
) -> bool:
|
|
ApprovedFilesLog.log(approved_file)
|
|
|
|
if comparator.compare(received_file, approved_file):
|
|
os.remove(received_file)
|
|
return True
|
|
FailedComparisonLog.log(received_file, approved_file)
|
|
worked = reporter.report(received_file, approved_file)
|
|
if not worked:
|
|
raise ReporterNotWorkingException(reporter)
|
|
return False
|
|
|
|
@staticmethod
|
|
def add_allowed_duplicates(is_duplicate_allowed: Callable[[str], bool]) -> None:
|
|
FileApprover.allowed_duplicates.append(is_duplicate_allowed)
|