@@ -0,0 +1,72 @@
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import pytest
|
||||
from django.core import mail
|
||||
from django.test import override_settings
|
||||
|
||||
from apps.jobs.models import Feedback, ScoreRun
|
||||
from apps.jobs.services.scoring import score_and_save
|
||||
from apps.notifications.models import DigestOutbox
|
||||
from apps.notifications.services import build_digest_payload, create_daily_outbox, send_digest
|
||||
from apps.sources.models import EmailMessageRecord, RawDocument
|
||||
from apps.sources.services.email_import import ingest_email, message_identity
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_email_import_is_idempotent(profile):
|
||||
raw = Path("fixtures/emails/sample_alert.eml").read_bytes()
|
||||
identity = message_identity(raw)
|
||||
first = ingest_email(raw)
|
||||
second = ingest_email(raw)
|
||||
assert first.pk == second.pk
|
||||
assert first.message_id == identity
|
||||
assert EmailMessageRecord.objects.count() == 1
|
||||
assert RawDocument.objects.filter(kind=RawDocument.Kind.EMAIL).count() == 1
|
||||
assert len(first.links) == 2
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_digest_payload_outbox_deduplication_and_send(profile, job):
|
||||
score = score_and_save(job, profile)
|
||||
score.recommendation = ScoreRun.Recommendation.STRONG
|
||||
score.score = 92
|
||||
score.save(update_fields=["recommendation", "score"])
|
||||
|
||||
local_tz = ZoneInfo(profile.timezone)
|
||||
due = datetime(2026, 7, 20, 7, 35, tzinfo=local_tz)
|
||||
payload = build_digest_payload(profile, local_date=due.date())
|
||||
assert payload["strong_count"] == 1
|
||||
assert payload["scores"][0]["title"] == job.original_title
|
||||
|
||||
with override_settings(DIGEST_RECIPIENT="digest@example.invalid"):
|
||||
first = create_daily_outbox(profile, now=due)
|
||||
second = create_daily_outbox(profile, now=due)
|
||||
assert first is not None
|
||||
assert second.pk == first.pk
|
||||
assert first.status == DigestOutbox.Status.PENDING
|
||||
|
||||
send_digest(first)
|
||||
first.refresh_from_db()
|
||||
assert first.status == DigestOutbox.Status.SENT
|
||||
assert first.sent_at is not None
|
||||
assert len(mail.outbox) == 1
|
||||
assert "Infrastructure Engineer" in mail.outbox[0].body
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_digest_skips_outside_window_and_hidden_jobs(profile, job):
|
||||
score_and_save(job, profile)
|
||||
Feedback.objects.create(
|
||||
user=profile.user,
|
||||
profile=profile,
|
||||
job=job,
|
||||
action=Feedback.Action.HIDE,
|
||||
)
|
||||
payload = build_digest_payload(profile)
|
||||
assert payload["scores"] == []
|
||||
|
||||
local_tz = ZoneInfo(profile.timezone)
|
||||
too_early = datetime(2026, 7, 20, 6, 0, tzinfo=local_tz)
|
||||
assert create_daily_outbox(profile, now=too_early) is None
|
||||
Reference in New Issue
Block a user