This commit is contained in:
@@ -3,6 +3,7 @@ from pathlib import Path
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import pytest
|
||||
from cryptography.fernet import Fernet
|
||||
from django.core import mail
|
||||
from django.test import override_settings
|
||||
|
||||
@@ -10,8 +11,10 @@ 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.models import EmailMessageRecord, MailboxConnection, RawDocument
|
||||
from apps.sources.services.email_import import ingest_email, message_identity
|
||||
from apps.sources.services.imap_import import poll_imap_mailbox
|
||||
from apps.sources.services.mailbox_connections import encrypt_mailbox_password
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -27,6 +30,132 @@ def test_email_import_is_idempotent(profile):
|
||||
assert len(first.links) == 2
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_vdab_alert_has_provider_provenance_and_replays_idempotently(profile):
|
||||
raw = Path("fixtures/emails/vdab_job_alert.eml").read_bytes()
|
||||
|
||||
first = ingest_email(raw)
|
||||
second = ingest_email(raw)
|
||||
|
||||
assert second.pk == first.pk
|
||||
assert first.processed is True
|
||||
assert first.raw_document.metadata["alert_provider"] == "vdab"
|
||||
assert len(first.links) == 2
|
||||
assert all("vdab.be/vindeenjob/vacatures/" in link for link in first.links)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@pytest.mark.parametrize(
|
||||
("platform", "fixture", "expected_domain"),
|
||||
(
|
||||
(MailboxConnection.Platform.LINKEDIN, "linkedin_job_alert.eml", "linkedin.com"),
|
||||
(MailboxConnection.Platform.ICTJOB, "ictjob_job_alert.eml", "ictjob.be"),
|
||||
(MailboxConnection.Platform.JOBAT, "jobat_job_alert.eml", "jobat.be"),
|
||||
(MailboxConnection.Platform.STEPSTONE, "stepstone_job_alert.eml", "stepstone.be"),
|
||||
(MailboxConnection.Platform.CAREERJET, "careerjet_job_alert.eml", "careerjet.be"),
|
||||
(MailboxConnection.Platform.RANDSTAD, "randstad_job_alert.eml", "randstad.be"),
|
||||
(
|
||||
MailboxConnection.Platform.ROBERTHALF,
|
||||
"roberthalf_job_alert.eml",
|
||||
"roberthalf.com",
|
||||
),
|
||||
),
|
||||
)
|
||||
def test_jobboard_mail_import_keeps_platform_provenance_and_rejects_external_links(
|
||||
profile, platform, fixture, expected_domain
|
||||
):
|
||||
raw = (Path("fixtures/emails") / fixture).read_bytes()
|
||||
|
||||
record = ingest_email(raw, platform=platform)
|
||||
|
||||
assert record.processed is True
|
||||
assert len(record.links) == 1
|
||||
assert expected_domain in record.links[0]
|
||||
assert "outside.example.invalid" not in record.links[0]
|
||||
assert record.raw_document.metadata["alert_provider"] == platform
|
||||
assert record.raw_document.source.name == f"{platform.label} vacaturemailbox"
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_imap_poll_is_bounded_and_one_bad_message_does_not_abort(profile):
|
||||
valid = Path("fixtures/emails/vdab_job_alert.eml").read_bytes()
|
||||
oversized = b"x" * (len(valid) + 1)
|
||||
|
||||
class FakeImapClient:
|
||||
def __init__(self, host, port, timeout=None):
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.timeout = timeout
|
||||
self.logged_out = False
|
||||
|
||||
def login(self, user, password):
|
||||
return "OK", []
|
||||
|
||||
def select(self, mailbox, readonly=True):
|
||||
assert readonly is True
|
||||
return "OK", []
|
||||
|
||||
def uid(self, command, *args):
|
||||
if command == "search":
|
||||
return "OK", [b"1 2 3"]
|
||||
uid = args[0]
|
||||
if uid == b"1":
|
||||
return "OK", [(b"RFC822", valid)]
|
||||
if uid == b"2":
|
||||
return "OK", [(b"RFC822", oversized)]
|
||||
return "NO", []
|
||||
|
||||
def logout(self):
|
||||
self.logged_out = True
|
||||
|
||||
clients = []
|
||||
|
||||
def factory(host, port, timeout=None):
|
||||
client = FakeImapClient(host, port, timeout=timeout)
|
||||
clients.append(client)
|
||||
return client
|
||||
|
||||
key = Fernet.generate_key().decode("ascii")
|
||||
with override_settings(
|
||||
MAILBOX_CREDENTIAL_KEYS=[key],
|
||||
IMAP_MAX_MESSAGES_PER_POLL=3,
|
||||
IMAP_MAX_MESSAGE_BYTES=len(valid),
|
||||
):
|
||||
connection = MailboxConnection.objects.create(
|
||||
user=profile.user,
|
||||
platform=MailboxConnection.Platform.VDAB,
|
||||
provider=MailboxConnection.Provider.CUSTOM,
|
||||
custom_host="imap.example.invalid",
|
||||
username="radar@example.invalid",
|
||||
encrypted_password=encrypt_mailbox_password("test-only"),
|
||||
)
|
||||
first = poll_imap_mailbox(
|
||||
connection, client_factory=factory, host_validator=lambda url: url
|
||||
)
|
||||
second = poll_imap_mailbox(
|
||||
connection, client_factory=factory, host_validator=lambda url: url
|
||||
)
|
||||
|
||||
assert first == {
|
||||
"status": "ok",
|
||||
"imported": 1,
|
||||
"duplicates": 0,
|
||||
"skipped_oversized": 1,
|
||||
"failed": 1,
|
||||
}
|
||||
assert second == {
|
||||
"status": "ok",
|
||||
"imported": 0,
|
||||
"duplicates": 1,
|
||||
"skipped_oversized": 1,
|
||||
"failed": 1,
|
||||
}
|
||||
assert all(client.logged_out for client in clients)
|
||||
record = EmailMessageRecord.objects.get(mailbox_connection=connection)
|
||||
assert record.raw_document.metadata["alert_provider"] == "vdab"
|
||||
assert record.raw_document.metadata["mailbox_connection_id"] == connection.pk
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_digest_payload_outbox_deduplication_and_send(profile, job):
|
||||
score = score_and_save(job, profile)
|
||||
|
||||
Reference in New Issue
Block a user