133 lines
4.6 KiB
Python
133 lines
4.6 KiB
Python
from datetime import datetime, time
|
|
from decimal import Decimal
|
|
from zoneinfo import ZoneInfo
|
|
|
|
import pytest
|
|
from django.utils import timezone
|
|
|
|
from apps.jobs.models import Application, Feedback, ScoreRun
|
|
from apps.jobs.services.scoring import score_and_save
|
|
from apps.notifications.models import ReminderOutbox
|
|
from apps.notifications.services import (
|
|
create_closing_reminders,
|
|
create_follow_up_reminders,
|
|
create_top_match_reminders,
|
|
)
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_closing_reminder_is_idempotent_and_skips_hidden(profile, job):
|
|
zone = ZoneInfo(profile.timezone)
|
|
now = timezone.now().astimezone(zone)
|
|
job.valid_through = datetime(
|
|
year=now.year,
|
|
month=now.month,
|
|
day=now.day,
|
|
hour=20,
|
|
tzinfo=zone,
|
|
)
|
|
job.save(update_fields=["valid_through"])
|
|
|
|
Feedback.objects.create(
|
|
user=profile.user,
|
|
profile=profile,
|
|
job=job,
|
|
action=Feedback.Action.HIDE,
|
|
)
|
|
assert create_closing_reminders(profile, now=now) == []
|
|
|
|
Feedback.objects.filter(user=profile.user, profile=profile, job=job).delete()
|
|
first = create_closing_reminders(profile, now=now)[0]
|
|
second = create_closing_reminders(profile, now=now)[0]
|
|
assert first.pk == second.pk
|
|
assert first.status == ReminderOutbox.Status.PENDING
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_follow_up_reminder_respects_configured_weekdays(profile, job):
|
|
zone = ZoneInfo(profile.timezone)
|
|
now = timezone.now().astimezone(zone)
|
|
follow_date = now.date()
|
|
Application.objects.create(
|
|
user=profile.user,
|
|
job=job,
|
|
follow_up_date=follow_date,
|
|
status=Application.Status.APPLIED,
|
|
notes="",
|
|
)
|
|
profile.follow_up_weekdays = [(follow_date.weekday() + 1) % 7]
|
|
profile.save(update_fields=["follow_up_weekdays"])
|
|
assert create_follow_up_reminders(profile, now=now) == []
|
|
|
|
profile.follow_up_weekdays = [follow_date.weekday()]
|
|
profile.save(update_fields=["follow_up_weekdays"])
|
|
reminders = create_follow_up_reminders(profile, now=now)
|
|
assert len(reminders) == 1
|
|
assert reminders[0].reminder_type == ReminderOutbox.ReminderType.FOLLOW_UP
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_top_match_reminder_requires_threshold_and_profile_setting(profile, job):
|
|
profile.top_match_reminders_enabled = True
|
|
profile.top_match_threshold = 90
|
|
profile.save(update_fields=["top_match_reminders_enabled", "top_match_threshold"])
|
|
score = score_and_save(job, profile)
|
|
score.recommendation = ScoreRun.Recommendation.STRONG
|
|
score.score = 85
|
|
score.confidence = Decimal("0.9")
|
|
score.save(update_fields=["recommendation", "score", "confidence"])
|
|
|
|
assert create_top_match_reminders(profile) == []
|
|
|
|
score.score = 95
|
|
score.confidence = Decimal("0.90")
|
|
score.save(update_fields=["score", "confidence"])
|
|
score.confidence = Decimal("0.84")
|
|
score.save(update_fields=["confidence"])
|
|
assert create_top_match_reminders(profile) == []
|
|
|
|
score.confidence = Decimal("0.86")
|
|
score.save(update_fields=["confidence"])
|
|
reminders = create_top_match_reminders(profile)
|
|
assert len(reminders) == 1
|
|
assert reminders[0].reminder_type == ReminderOutbox.ReminderType.TOP_MATCH
|
|
|
|
profile.top_match_reminders_enabled = False
|
|
profile.save(update_fields=["top_match_reminders_enabled"])
|
|
assert create_top_match_reminders(profile) == []
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_reminder_obeys_quiet_hours_and_empty_recipient(profile, job):
|
|
zone = ZoneInfo(profile.timezone)
|
|
now = timezone.now().astimezone(zone).replace(hour=6, minute=30, second=0, microsecond=0)
|
|
job.valid_through = datetime(
|
|
year=now.year,
|
|
month=now.month,
|
|
day=now.day,
|
|
hour=18,
|
|
tzinfo=zone,
|
|
)
|
|
job.save(update_fields=["valid_through"])
|
|
|
|
profile.user.email = ""
|
|
profile.user.save(update_fields=["email"])
|
|
assert create_closing_reminders(profile, now=now)[0].status == ReminderOutbox.Status.SKIPPED
|
|
|
|
profile.user.email = "reminder@example.invalid"
|
|
profile.user.save(update_fields=["email"])
|
|
reminder = create_closing_reminders(profile, now=now)[0]
|
|
assert reminder.status == ReminderOutbox.Status.PENDING
|
|
assert reminder.scheduled_for.timetz().replace(tzinfo=None) == time(7, 0)
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_reminder_service_handles_dst_dates(profile, job):
|
|
zone = ZoneInfo(profile.timezone)
|
|
now = datetime(2026, 10, 25, 1, 30, tzinfo=zone)
|
|
job.valid_through = now.replace(hour=20)
|
|
job.save(update_fields=["valid_through"])
|
|
reminder = create_closing_reminders(profile, now=now)[0]
|
|
assert reminder.scheduled_for.tzinfo is not None
|
|
assert reminder.scheduled_for.tzinfo.key == "Europe/Brussels"
|