migrate session handling to aioweb_tls/refactoring of helpers
This commit is contained in:
1 parent
3a8a12ac6e
commit
1441e7179c
10 files changed
+244
-295
No files matched your search
@@ -0,0 +1,48 @@
|
||||
"""unit test: convert_product_to_mongo flattens a Product to its Mongo document
|
||||
|
||||
run from the repo root:
|
||||
uv run pytest tests/test_convert_product_to_mongo.py
|
||||
|
||||
pure and offline — no Mongo. Also pins the fact that prices are already floats
|
||||
by the time they reach the flattener (pydantic coerces numeric strings on the
|
||||
Product), which is why convert_product_to_mongo no longer coerces them itself.
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from monitor_utils.database import convert_product_to_mongo
|
||||
from monitor_utils.models import PricingInfo, Product
|
||||
|
||||
|
||||
def _product(**pricing) -> Product:
|
||||
return Product(
|
||||
product_id="p1",
|
||||
title="Widget",
|
||||
url="http://x/p1",
|
||||
pricing=PricingInfo(**pricing),
|
||||
)
|
||||
|
||||
|
||||
def test_numeric_string_prices_arrive_as_floats():
|
||||
"""a numeric-string price is a float in the doc (pydantic coerced it on init)"""
|
||||
|
||||
doc = convert_product_to_mongo(_product(original_price="200", current_price=150.0))
|
||||
assert doc["originalPrice"] == 200.0
|
||||
assert isinstance(doc["originalPrice"], float)
|
||||
assert doc["currentPrice"] == 150.0
|
||||
assert isinstance(doc["currentPrice"], float)
|
||||
|
||||
|
||||
def test_lastupdated_is_stamped():
|
||||
"""every document gets a UTC lastUpdated timestamp"""
|
||||
|
||||
doc = convert_product_to_mongo(_product(original_price=200.0, current_price=150.0))
|
||||
assert isinstance(doc["lastUpdated"], datetime)
|
||||
|
||||
|
||||
def test_core_fields_map_through():
|
||||
"""title and url pass straight through to the document"""
|
||||
|
||||
doc = convert_product_to_mongo(_product(original_price=200.0, current_price=150.0))
|
||||
assert doc["title"] == "Widget"
|
||||
assert doc["url"] == "http://x/p1"
|
||||
@@ -1,11 +1,12 @@
|
||||
"""unit test: execute_pagination honours a caller-supplied shared semaphore
|
||||
|
||||
run from the repo root:
|
||||
uv run python tests/test_pagination_semaphore.py
|
||||
uv run pytest tests/test_pagination_semaphore.py
|
||||
|
||||
offline — no network. A fake page func records peak concurrency so we can
|
||||
assert the fan-out limit actually holds, both for the shared-semaphore path
|
||||
(one instance capping many categories at once) and the default per-call path.
|
||||
(one instance capping many categories at once) and a single call bounding one
|
||||
category with its own semaphore.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
@@ -62,9 +63,10 @@ def test_shared_semaphore_caps_total_concurrency_across_categories():
|
||||
assert state["peak"] <= limit, f"peak {state['peak']} exceeded shared limit {limit}"
|
||||
|
||||
|
||||
def test_default_falls_back_to_max_concurrent_tasks():
|
||||
"""Without a semaphore, max_concurrent_tasks still bounds a single call."""
|
||||
def test_single_call_respects_its_semaphore():
|
||||
"""A single call bounds its own fan-out to the supplied semaphore limit."""
|
||||
|
||||
limit = 2
|
||||
state = {"live": 0, "peak": 0}
|
||||
func = _make_tracking_func(state)
|
||||
|
||||
@@ -75,13 +77,8 @@ def test_default_falls_back_to_max_concurrent_tasks():
|
||||
products_per_page=30,
|
||||
func=func,
|
||||
session=None,
|
||||
max_concurrent_tasks=2,
|
||||
semaphore=asyncio.Semaphore(limit),
|
||||
)
|
||||
|
||||
asyncio.run(run())
|
||||
assert state["peak"] <= 2, f"peak {state['peak']} exceeded max_concurrent_tasks 2"
|
||||
|
||||
|
||||
test_shared_semaphore_caps_total_concurrency_across_categories()
|
||||
test_default_falls_back_to_max_concurrent_tasks()
|
||||
print("pagination semaphore test passed")
|
||||
assert state["peak"] <= limit, f"peak {state['peak']} over limit {limit}"
|
||||
@@ -1,7 +1,7 @@
|
||||
"""unit test: resolve_price_before_drop detects a drop from the prior stored price
|
||||
|
||||
run from the repo root:
|
||||
uv run python tests/test_price_before_drop.py
|
||||
uv run pytest tests/test_price_before_drop.py
|
||||
|
||||
pure and offline — no Mongo, no product construction; just the drop rule
|
||||
add_products_to_database relies on
|
||||
@@ -23,8 +23,3 @@ def test_non_drops_return_none():
|
||||
assert resolve_price_before_drop(150.0, 150.0) is None # unchanged
|
||||
assert resolve_price_before_drop(150.0, 200.0) is None # price rose
|
||||
assert resolve_price_before_drop(200.0, None) is None # missing new price
|
||||
|
||||
|
||||
test_drop_returns_previous_price()
|
||||
test_non_drops_return_none()
|
||||
print("price before drop test passed")
|
||||
Reference in new issue
Block a user