from datetime import timedelta import pytest from django.core.exceptions import ValidationError from django.db import IntegrityError from django.utils import timezone from apps.sources.models import Source, SourceRun @pytest.mark.django_db def test_source_validation_and_scheduling(source): now = timezone.now() source.schedule_after_success(now=now) source.refresh_from_db() assert source.failure_count == 0 assert source.next_run_at == now + timedelta(minutes=source.crawl_interval_minutes) source.schedule_after_failure(now=now, backoff_minutes=30) source.refresh_from_db() assert source.failure_count == 1 assert source.next_run_at == now + timedelta(minutes=30) source.base_url = "https://other.example.org/jobs" with pytest.raises(ValidationError): source.full_clean() source.base_url = "https://jobs.example.org/jobs" source.policy = Source.Policy.DENY source.status = Source.Status.ACTIVE with pytest.raises(ValidationError): source.full_clean() @pytest.mark.django_db def test_source_run_finish_updates_metrics(source): run = SourceRun.objects.create(source=source) run.finish(SourceRun.Status.SUCCESS, http_status=200, extracted_count=3) run.refresh_from_db() assert run.status == SourceRun.Status.SUCCESS assert run.finished_at is not None assert run.http_status == 200 assert run.extracted_count == 3 @pytest.mark.django_db(transaction=True) def test_shared_ats_domain_accepts_distinct_public_feeds_but_not_duplicate_urls(): Source.objects.create( name="Lever A", source_type=Source.Type.ATS, base_url="https://api.lever.co/v0/postings/a?mode=json", domain="api.lever.co", ) Source.objects.create( name="Lever B", source_type=Source.Type.ATS, base_url="https://api.lever.co/v0/postings/b?mode=json", domain="api.lever.co", ) with pytest.raises(IntegrityError): Source.objects.create( name="Lever A dubbel", source_type=Source.Type.ATS, base_url="https://api.lever.co/v0/postings/a?mode=json", domain="api.lever.co", )