chore: fix ruff lint (webhooks v2) + Windows-safe test teardown
This commit is contained in:
+4
-1
@@ -42,7 +42,10 @@ def client():
|
||||
|
||||
yield TestClient(app)
|
||||
|
||||
os.unlink(db_path)
|
||||
try:
|
||||
os.unlink(db_path)
|
||||
except PermissionError:
|
||||
pass # Windows: file may still be open in another thread
|
||||
|
||||
|
||||
# ── Core ──
|
||||
|
||||
+21
-30
@@ -1,12 +1,7 @@
|
||||
"""FlowDeck — v6.4.0 Webhooks v2 tests (HMAC, retries, +20 events)."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import hashlib
|
||||
import hmac
|
||||
import json
|
||||
import time
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
@@ -17,15 +12,11 @@ from app.services.webhook_outbound import (
|
||||
RETRY_DELAYS,
|
||||
_deliver_once,
|
||||
_event_matches,
|
||||
deliver_to_sub,
|
||||
fire_event,
|
||||
init_webhook_tables,
|
||||
retry_due_deliveries,
|
||||
sign_payload,
|
||||
verify_signature,
|
||||
)
|
||||
|
||||
|
||||
# ── Fixtures ────────────────────────────────────────────────────────────────
|
||||
|
||||
@pytest.fixture
|
||||
@@ -53,7 +44,7 @@ def test_sign_payload_returns_sha256_hex():
|
||||
secret = "my_secret"
|
||||
body = b'{"event": "page.created", "data": {}}'
|
||||
signature = sign_payload(secret, body)
|
||||
|
||||
|
||||
assert signature.startswith("sha256=")
|
||||
hex_part = signature[7:] # Remove 'sha256=' prefix
|
||||
assert len(hex_part) == 64 # SHA-256 hex is 64 chars
|
||||
@@ -63,10 +54,10 @@ def test_sign_payload_consistency():
|
||||
"""Test that the same input produces the same signature."""
|
||||
secret = "my_secret"
|
||||
body = b'{"event": "page.created"}'
|
||||
|
||||
|
||||
sig1 = sign_payload(secret, body)
|
||||
sig2 = sign_payload(secret, body)
|
||||
|
||||
|
||||
assert sig1 == sig2
|
||||
|
||||
|
||||
@@ -75,7 +66,7 @@ def test_verify_signature_valid():
|
||||
secret = "my_secret"
|
||||
body = b'{"event": "page.created", "data": {}}'
|
||||
signature = sign_payload(secret, body)
|
||||
|
||||
|
||||
assert verify_signature(secret, body, signature) is True
|
||||
|
||||
|
||||
@@ -85,7 +76,7 @@ def test_verify_signature_invalid_secret():
|
||||
wrong_secret = "wrong_secret"
|
||||
body = b'{"event": "page.created"}'
|
||||
signature = sign_payload(secret, body)
|
||||
|
||||
|
||||
assert verify_signature(wrong_secret, body, signature) is False
|
||||
|
||||
|
||||
@@ -94,7 +85,7 @@ def test_verify_signature_invalid_signature():
|
||||
secret = "my_secret"
|
||||
body = b'{"event": "page.created"}'
|
||||
signature = "sha256=invalid_hex_value"
|
||||
|
||||
|
||||
assert verify_signature(secret, body, signature) is False
|
||||
|
||||
|
||||
@@ -102,7 +93,7 @@ def test_verify_signature_empty_secret():
|
||||
"""Test that verify_signature returns False for empty secret."""
|
||||
body = b'{"event": "page.created"}'
|
||||
signature = "sha256=somehash"
|
||||
|
||||
|
||||
assert verify_signature("", body, signature) is False
|
||||
|
||||
|
||||
@@ -110,7 +101,7 @@ def test_verify_signature_empty_signature():
|
||||
"""Test that verify_signature returns False for empty signature."""
|
||||
secret = "my_secret"
|
||||
body = b'{"event": "page.created"}'
|
||||
|
||||
|
||||
assert verify_signature(secret, body, "") is False
|
||||
|
||||
|
||||
@@ -220,14 +211,14 @@ async def test_deliver_once_success():
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 200
|
||||
mock_client.post.return_value = mock_response
|
||||
|
||||
|
||||
url = "https://example.com/webhook"
|
||||
event = "page.created"
|
||||
payload = {"page_id": 123}
|
||||
secret = "test_secret"
|
||||
|
||||
|
||||
code, error = await _deliver_once(mock_client, url, event, payload, secret)
|
||||
|
||||
|
||||
assert code == 200
|
||||
assert error == ""
|
||||
mock_client.post.assert_called_once()
|
||||
@@ -243,14 +234,14 @@ async def test_deliver_once_http_error():
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 500
|
||||
mock_client.post.return_value = mock_response
|
||||
|
||||
|
||||
url = "https://example.com/webhook"
|
||||
event = "page.created"
|
||||
payload = {}
|
||||
secret = "test_secret"
|
||||
|
||||
|
||||
code, error = await _deliver_once(mock_client, url, event, payload, secret)
|
||||
|
||||
|
||||
assert code == 500
|
||||
assert "HTTP 500" in error
|
||||
|
||||
@@ -260,14 +251,14 @@ async def test_deliver_once_timeout():
|
||||
"""Test _deliver_once handles timeout errors."""
|
||||
mock_client = AsyncMock()
|
||||
mock_client.post.side_effect = httpx.TimeoutException("Timeout after 30s")
|
||||
|
||||
|
||||
url = "https://example.com/webhook"
|
||||
event = "page.created"
|
||||
payload = {}
|
||||
secret = "test_secret"
|
||||
|
||||
|
||||
code, error = await _deliver_once(mock_client, url, event, payload, secret)
|
||||
|
||||
|
||||
assert code is None
|
||||
assert "Timeout" in error
|
||||
|
||||
@@ -277,14 +268,14 @@ async def test_deliver_once_request_error():
|
||||
"""Test _deliver_once handles request errors."""
|
||||
mock_client = AsyncMock()
|
||||
mock_client.post.side_effect = httpx.RequestError("Connection refused")
|
||||
|
||||
|
||||
url = "https://example.com/webhook"
|
||||
event = "page.created"
|
||||
payload = {}
|
||||
secret = "test_secret"
|
||||
|
||||
|
||||
code, error = await _deliver_once(mock_client, url, event, payload, secret)
|
||||
|
||||
|
||||
assert code is None
|
||||
assert "Request error" in error
|
||||
|
||||
|
||||
Reference in New Issue
Block a user