fix(tests): replace datetime.utcnow() with utcnow_iso() in test files

Also fixes test_supplier_webhooks.py fromisoformat() comparisons:
expires (naive, from DB) now compared against datetime.now(UTC).replace(tzinfo=None)
to avoid mixing naive/aware datetimes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Deeman
2026-02-24 10:24:16 +01:00
parent 5644a1ebf8
commit a05c230ce3
5 changed files with 30 additions and 24 deletions

View File

@@ -9,6 +9,8 @@ import importlib
import json
import sqlite3
from datetime import date, datetime
from padelnomics.core import utcnow_iso
from pathlib import Path
import pytest
@@ -70,7 +72,7 @@ async def _create_published_scenario(slug="test-scenario", city="TestCity", coun
async def _create_article(slug="test-article", url_path="/test-article",
status="published", published_at=None):
"""Insert an article row, return its id."""
pub = published_at or datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
pub = published_at or utcnow_iso()
return await execute(
"""INSERT INTO articles
(url_path, slug, title, meta_description, country, region,
@@ -936,8 +938,7 @@ class TestRouteRegistration:
@pytest.fixture
async def admin_client(app, db):
"""Test client with admin user (has admin role)."""
from datetime import datetime
now = datetime.utcnow().isoformat()
now = utcnow_iso()
async with db.execute(
"INSERT INTO users (email, name, created_at) VALUES (?, ?, ?)",
("admin@test.com", "Admin", now),

View File

@@ -3,7 +3,7 @@ Tests for the credit system (credits.py).
Pure SQL operations against real in-memory SQLite — no mocking needed.
"""
from datetime import datetime
from padelnomics.core import utcnow_iso
import pytest
from padelnomics.credits import (
@@ -24,7 +24,7 @@ from padelnomics.credits import (
@pytest.fixture
async def supplier(db):
"""Supplier with credit_balance=100, monthly_credits=30, tier=growth."""
now = datetime.utcnow().isoformat()
now = utcnow_iso()
async with db.execute(
"""INSERT INTO suppliers
(name, slug, country_code, region, category, tier,
@@ -41,7 +41,7 @@ async def supplier(db):
@pytest.fixture
async def lead(db):
"""Lead request with heat_score=warm, credit_cost=20."""
now = datetime.utcnow().isoformat()
now = utcnow_iso()
async with db.execute(
"""INSERT INTO lead_requests
(lead_type, heat_score, credit_cost, status, created_at)
@@ -154,7 +154,7 @@ class TestAlreadyUnlocked:
assert await already_unlocked(supplier["id"], lead["id"]) is False
async def test_returns_true_after_unlock(self, db, supplier, lead):
now = datetime.utcnow().isoformat()
now = utcnow_iso()
await db.execute(
"""INSERT INTO lead_forwards (lead_id, supplier_id, credit_cost, created_at)
VALUES (?, ?, 20, ?)""",
@@ -210,7 +210,7 @@ class TestUnlockLead:
async def test_raises_insufficient_credits(self, db, lead):
"""Supplier with only 5 credits tries to unlock a 20-credit lead."""
now = datetime.utcnow().isoformat()
now = utcnow_iso()
async with db.execute(
"""INSERT INTO suppliers
(name, slug, country_code, region, category, tier,
@@ -247,7 +247,7 @@ class TestMonthlyRefill:
async def test_noop_when_no_monthly_credits(self, db):
"""Supplier with monthly_credits=0 gets no refill."""
now = datetime.utcnow().isoformat()
now = utcnow_iso()
async with db.execute(
"""INSERT INTO suppliers
(name, slug, country_code, region, category, tier,

View File

@@ -7,7 +7,8 @@ Integration tests exercise full request/response flows via Quart test client.
"""
import sqlite3
from datetime import datetime
from padelnomics.core import utcnow_iso
from pathlib import Path
from unittest.mock import AsyncMock, patch
@@ -30,7 +31,7 @@ def mock_csrf_validation():
@pytest.fixture
async def admin_client(app, db):
"""Test client with an admin-role user session (module-level, follows test_content.py)."""
now = datetime.utcnow().isoformat()
now = utcnow_iso()
async with db.execute(
"INSERT INTO users (email, name, created_at) VALUES (?, ?, ?)",
("flags_admin@test.com", "Flags Admin", now),

View File

@@ -1,6 +1,8 @@
"""Tests for the SEO metrics module: queries, sync functions, admin routes."""
from datetime import datetime, timedelta
from datetime import UTC, datetime, timedelta
from padelnomics.core import utcnow_iso
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
@@ -21,11 +23,11 @@ from padelnomics import core
# ── Fixtures ──────────────────────────────────────────────────
def _today():
return datetime.utcnow().strftime("%Y-%m-%d")
return datetime.now(UTC).strftime("%Y-%m-%d")
def _days_ago(n: int) -> str:
return (datetime.utcnow() - timedelta(days=n)).strftime("%Y-%m-%d")
return (datetime.now(UTC) - timedelta(days=n)).strftime("%Y-%m-%d")
@pytest.fixture
@@ -72,7 +74,7 @@ async def seo_data(db):
@pytest.fixture
async def articles_data(db, seo_data):
"""Create articles that match the SEO data URLs."""
now = datetime.utcnow().isoformat()
now = utcnow_iso()
pub = _days_ago(10)
for title, url, tpl, lang in [
@@ -91,7 +93,7 @@ async def articles_data(db, seo_data):
@pytest.fixture
async def admin_client(app, db):
"""Authenticated admin client."""
now = datetime.utcnow().isoformat()
now = utcnow_iso()
async with db.execute(
"INSERT INTO users (email, name, created_at) VALUES (?, ?, ?)",
("admin@test.com", "Admin", now),
@@ -258,7 +260,7 @@ class TestSyncStatus:
"""Tests for get_sync_status()."""
async def test_returns_last_sync_per_source(self, db):
now = datetime.utcnow().isoformat()
now = utcnow_iso()
await db.execute(
"""INSERT INTO seo_sync_log (source, status, rows_synced, started_at, completed_at, duration_ms)
VALUES ('gsc', 'success', 100, ?, ?, 500)""",
@@ -286,7 +288,7 @@ class TestCleanupOldMetrics:
"""Tests for cleanup_old_metrics()."""
async def test_deletes_old_data(self, db):
old_date = (datetime.utcnow() - timedelta(days=400)).strftime("%Y-%m-%d")
old_date = (datetime.now(UTC) - timedelta(days=400)).strftime("%Y-%m-%d")
recent_date = _today()
await db.execute(

View File

@@ -5,7 +5,9 @@ POST real webhook payloads to /billing/webhook/paddle and verify DB state.
Uses the existing client, db, sign_payload from conftest.
"""
import json
from datetime import datetime
from datetime import UTC, datetime
from padelnomics.core import utcnow_iso
from unittest.mock import AsyncMock, patch
import pytest
@@ -21,7 +23,7 @@ SIG_HEADER = "Paddle-Signature"
@pytest.fixture
async def supplier(db):
"""Supplier with tier=free, credit_balance=0."""
now = datetime.utcnow().isoformat()
now = utcnow_iso()
async with db.execute(
"""INSERT INTO suppliers
(name, slug, country_code, region, category, tier,
@@ -38,7 +40,7 @@ async def supplier(db):
@pytest.fixture
async def paddle_products(db):
"""Insert paddle_products rows for all keys the handlers need."""
now = datetime.utcnow().isoformat()
now = utcnow_iso()
products = [
("credits_25", "pri_credits25", "Credit Pack 25", 999, "one_time"),
("credits_100", "pri_credits100", "Credit Pack 100", 3290, "one_time"),
@@ -175,7 +177,7 @@ class TestStickyBoostPurchase:
assert boosts[0][1] == "active"
# expires_at should be ~7 days from now
expires = datetime.fromisoformat(boosts[0][2])
assert abs((expires - datetime.utcnow()).days - 7) <= 1
assert abs((expires - datetime.now(UTC).replace(tzinfo=None)).days - 7) <= 1
# Verify sticky_until set on supplier
sup = await db.execute_fetchall(
@@ -202,7 +204,7 @@ class TestStickyBoostPurchase:
assert len(boosts) == 1
assert boosts[0][0] == "sticky_month"
expires = datetime.fromisoformat(boosts[0][1])
assert abs((expires - datetime.utcnow()).days - 30) <= 1
assert abs((expires - datetime.now(UTC).replace(tzinfo=None)).days - 30) <= 1
async def test_sticky_boost_sets_country(self, client, db, supplier, paddle_products):
payload = make_transaction_payload(
@@ -387,7 +389,7 @@ class TestBusinessPlanPurchase:
self, client, db, supplier, paddle_products, test_user,
):
# Need a scenario for the export
now = datetime.utcnow().isoformat()
now = utcnow_iso()
async with db.execute(
"""INSERT INTO scenarios (user_id, name, state_json, created_at)
VALUES (?, 'Test Scenario', '{}', ?)""",