diff --git a/src/kleinanzeigen_bot/__init__.py b/src/kleinanzeigen_bot/__init__.py index faf3268..61c94e6 100644 --- a/src/kleinanzeigen_bot/__init__.py +++ b/src/kleinanzeigen_bot/__init__.py @@ -961,10 +961,7 @@ class KleinanzeigenBot(WebScrapingMixin): await self.web_click(By.XPATH, '//*[contains(@class, "SubSection")]//button[contains(@class, "SelectionButton")]') await self.web_click(By.XPATH, '//*[contains(@class, "CarrierSelectionModal")]//button[contains(., "Andere Versandmethoden")]') await self.web_click(By.XPATH, '//*[contains(@id, "INDIVIDUAL") and contains(@data-testid, "Individueller Versand")]') - - if ad_cfg.shipping_costs: - await self.web_input(By.CSS_SELECTOR, '.IndividualShippingInput input[type="text"]', - str.replace(str(ad_cfg.shipping_costs), ".", ",")) + await self.web_input(By.CSS_SELECTOR, '.IndividualShippingInput input[type="text"]', str.replace(str(ad_cfg.shipping_costs), ".", ",")) await self.web_click(By.XPATH, '//dialog//button[contains(., "Fertig")]') except TimeoutError as ex: LOG.debug(ex, exc_info = True) diff --git a/src/kleinanzeigen_bot/model/ad_model.py b/src/kleinanzeigen_bot/model/ad_model.py index af8bf1a..102bb75 100644 --- a/src/kleinanzeigen_bot/model/ad_model.py +++ b/src/kleinanzeigen_bot/model/ad_model.py @@ -93,9 +93,9 @@ class AdPartial(ContextualModel): @field_validator("shipping_costs", mode = "before") @classmethod def _parse_shipping_costs(cls, v:float | int | str) -> Any: - if v: - return round(parse_decimal(v), 2) - return None + if v is None or (isinstance(v, str) and not v.strip()): + return None + return round(parse_decimal(v), 2) @field_validator("description") @classmethod diff --git a/tests/unit/test_ad_model.py b/tests/unit/test_ad_model.py index 018d27b..f75046b 100644 --- a/tests/unit/test_ad_model.py +++ b/tests/unit/test_ad_model.py @@ -1,6 +1,8 @@ # SPDX-FileCopyrightText: © Sebastian Thomschke and contributors # SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-ArtifactOfProjectHomePage: https://github.com/Second-Hand-Friends/kleinanzeigen-bot/ +import math + from kleinanzeigen_bot.model.ad_model import AdPartial @@ -37,3 +39,24 @@ def test_update_content_hash() -> None: "special_attributes": {}, "contact": {}, }).update_content_hash().content_hash != minimal_ad_cfg_hash + + +def test_shipping_costs() -> None: + minimal_ad_cfg = { + "id": "123456789", + "title": "Test Ad Title", + "category": "160", + "description": "Test Description", + } + + def is_close(a:float | None, b:float) -> bool: + return a is not None and math.isclose(a, b, rel_tol = 1e-09, abs_tol = 1e-09) + + assert AdPartial.model_validate(minimal_ad_cfg | {"shipping_costs": 0}).shipping_costs == 0 + assert is_close(AdPartial.model_validate(minimal_ad_cfg | {"shipping_costs": 0.00}).shipping_costs, 0) + assert is_close(AdPartial.model_validate(minimal_ad_cfg | {"shipping_costs": 0.10}).shipping_costs, 0.10) + assert is_close(AdPartial.model_validate(minimal_ad_cfg | {"shipping_costs": 1.00}).shipping_costs, 1) + assert AdPartial.model_validate(minimal_ad_cfg | {"shipping_costs": ""}).shipping_costs is None + assert AdPartial.model_validate(minimal_ad_cfg | {"shipping_costs": " "}).shipping_costs is None + assert AdPartial.model_validate(minimal_ad_cfg | {"shipping_costs": None}).shipping_costs is None + assert AdPartial.model_validate(minimal_ad_cfg).shipping_costs is None