line-webhook / test_webhook.py
Therdpoom's picture
Upload 10 files
82eac1b verified
Raw
History Blame Contribute Delete
3.67 kB
"""
Unit Tests β€” Webhook Server
"""
import hashlib
import hmac
import base64
import pytest
from fastapi.testclient import TestClient
from unittest.mock import AsyncMock, patch
# ─── Signature Helper ──────────────────────────────────────────────────────────
def make_signature(body: bytes, secret: str) -> str:
h = hmac.new(secret.encode(), body, hashlib.sha256).digest()
return base64.b64encode(h).decode()
# ─── Fixture: mock settings ───────────────────────────────────────────────────
@pytest.fixture(autouse=True)
def mock_settings(monkeypatch):
monkeypatch.setenv("LINE_CHANNEL_SECRET", "test_secret")
monkeypatch.setenv("LINE_CHANNEL_ACCESS_TOKEN", "test_token")
monkeypatch.setenv("HF_API_TOKEN", "hf_test")
monkeypatch.setenv("DATABASE_URL", "postgresql://u:p@localhost/test")
monkeypatch.setenv("REDIS_URL", "redis://localhost:6379")
# ─── Tests ────────────────────────────────────────────────────────────────────
class TestSignatureVerification:
def test_valid_signature(self):
from app.main import verify_line_signature
body = b'{"test": "data"}'
sig = make_signature(body, "test_secret")
assert verify_line_signature(body, sig) is True
def test_invalid_signature(self):
from app.main import verify_line_signature
body = b'{"test": "data"}'
assert verify_line_signature(body, "wrong_sig") is False
def test_empty_signature(self):
from app.main import verify_line_signature
assert verify_line_signature(b"body", "") is False
class TestPayloadParsing:
def test_parse_text_message(self):
from app.models import LineWebhookPayload
raw = """{
"destination": "U123",
"events": [{
"type": "message",
"timestamp": 1700000000000,
"replyToken": "token123",
"source": {"type": "user", "userId": "Uabc"},
"message": {"id": "m1", "type": "text", "text": "ΰΈͺΰΈ§ΰΈ±ΰΈͺΰΈ”ΰΈ΅ΰΈ„ΰΈ£ΰΈ±ΰΈš"}
}]
}"""
payload = LineWebhookPayload.model_validate_json(raw)
assert len(payload.events) == 1
assert payload.events[0].message.text == "ΰΈͺΰΈ§ΰΈ±ΰΈͺΰΈ”ΰΈ΅ΰΈ„ΰΈ£ΰΈ±ΰΈš"
def test_skip_non_text_event(self):
from app.models import LineWebhookPayload
raw = """{
"destination": "U123",
"events": [{
"type": "follow",
"timestamp": 1700000000000,
"source": {"type": "user", "userId": "Uabc"}
}]
}"""
payload = LineWebhookPayload.model_validate_json(raw)
assert payload.events[0].type == "follow"
assert payload.events[0].message is None
class TestSentimentResult:
def test_label_mapping_positive(self):
from app.models import SentimentResult
r = SentimentResult(
label="positive",
score=0.91,
raw_scores={"positive": 0.91, "neutral": 0.07, "negative": 0.02},
)
assert r.label == "positive"
assert r.score == 0.91
def test_fallback_is_neutral(self):
from app.sentiment import _fallback_result
r = _fallback_result()
assert r.label == "neutral"
assert r.score == 0.0