This commit is contained in:
@@ -18,7 +18,9 @@ from apps.jobs.services.feedback import record_feedback
|
||||
|
||||
@pytest.mark.integration
|
||||
@pytest.mark.django_db
|
||||
def test_applied_feedback_creates_sanitized_application_snapshot_and_timeline(job, profile, source, user):
|
||||
def test_applied_feedback_creates_sanitized_application_snapshot_and_timeline(
|
||||
job, profile, source, user
|
||||
):
|
||||
JobSourceAlias.objects.create(
|
||||
job=job,
|
||||
source=source,
|
||||
@@ -43,14 +45,20 @@ def test_applied_feedback_creates_sanitized_application_snapshot_and_timeline(jo
|
||||
assert snapshot["sources"][0]["is_canonical"] is True
|
||||
assert snapshot["scores"] is None
|
||||
|
||||
event_types = set(ApplicationTimelineEvent.objects.filter(application=application).values_list("event_type", flat=True))
|
||||
event_types = set(
|
||||
ApplicationTimelineEvent.objects.filter(application=application).values_list(
|
||||
"event_type", flat=True
|
||||
)
|
||||
)
|
||||
assert ApplicationTimelineEvent.EventType.CREATED in event_types
|
||||
assert ApplicationTimelineEvent.EventType.SNAPSHOT_CAPTURED in event_types
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
@pytest.mark.django_db
|
||||
def test_application_update_creates_timeline_events_for_status_notes_and_contact(client, job, profile, source, user):
|
||||
def test_application_update_creates_timeline_events_for_status_notes_and_contact(
|
||||
client, job, profile, source, user
|
||||
):
|
||||
record_feedback(user=user, job=job, action="applied")
|
||||
application = Application.objects.get(user=user, job=job)
|
||||
|
||||
@@ -71,7 +79,11 @@ def test_application_update_creates_timeline_events_for_status_notes_and_contact
|
||||
assert application.contact_name == "Sofie Van Hecke"
|
||||
assert application.contact_email == "recruiter@example.invalid"
|
||||
|
||||
event_types = set(ApplicationTimelineEvent.objects.filter(application=application).values_list("event_type", flat=True))
|
||||
event_types = set(
|
||||
ApplicationTimelineEvent.objects.filter(application=application).values_list(
|
||||
"event_type", flat=True
|
||||
)
|
||||
)
|
||||
assert ApplicationTimelineEvent.EventType.STATUS_CHANGED in event_types
|
||||
assert ApplicationTimelineEvent.EventType.NOTES_UPDATED in event_types
|
||||
assert ApplicationTimelineEvent.EventType.CONTACT_UPDATED in event_types
|
||||
@@ -136,7 +148,10 @@ def test_application_export_generates_sanitized_zip_payload(client, job, source,
|
||||
assert application_payload["snapshot"]["sources"][0]["url"] == job.canonical_url
|
||||
|
||||
csv_rows = list(csv.DictReader(io.StringIO(archive.read("timeline.csv").decode("utf-8"))))
|
||||
assert {row["type"] for row in csv_rows} >= {ApplicationTimelineEvent.EventType.CREATED, ApplicationTimelineEvent.EventType.SNAPSHOT_CAPTURED}
|
||||
assert {row["type"] for row in csv_rows} >= {
|
||||
ApplicationTimelineEvent.EventType.CREATED,
|
||||
ApplicationTimelineEvent.EventType.SNAPSHOT_CAPTURED,
|
||||
}
|
||||
|
||||
html = archive.read("application_print.html").decode("utf-8")
|
||||
assert "<html" in html.lower()
|
||||
@@ -170,12 +185,18 @@ def test_application_export_and_delete_are_scoped_and_idempotent(client, job, us
|
||||
)
|
||||
|
||||
client.force_login(user)
|
||||
assert client.get(
|
||||
reverse("jobs:application-export", kwargs={"pk": other_application.pk})
|
||||
).status_code == 404
|
||||
assert client.post(
|
||||
reverse("jobs:application-delete", kwargs={"pk": other_application.pk})
|
||||
).status_code == 404
|
||||
assert (
|
||||
client.get(
|
||||
reverse("jobs:application-export", kwargs={"pk": other_application.pk})
|
||||
).status_code
|
||||
== 404
|
||||
)
|
||||
assert (
|
||||
client.post(
|
||||
reverse("jobs:application-delete", kwargs={"pk": other_application.pk})
|
||||
).status_code
|
||||
== 404
|
||||
)
|
||||
|
||||
delete_response = client.post(
|
||||
reverse("jobs:application-delete", kwargs={"pk": owner_application.pk}),
|
||||
|
||||
@@ -2,13 +2,14 @@ from __future__ import annotations
|
||||
|
||||
from io import StringIO
|
||||
|
||||
import pytest
|
||||
from django.core.management import call_command
|
||||
from django.core.management.base import CommandError
|
||||
import pytest
|
||||
|
||||
from apps.jobs.models import ScoreRun
|
||||
from apps.jobs.services.scoring import score_and_save
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_import_geodata_validate_only_and_import_command(tmp_path):
|
||||
csv_path = tmp_path / "geodata.csv"
|
||||
@@ -58,18 +59,18 @@ def test_import_geodata_rejects_half_license_metadata(tmp_path):
|
||||
"postal_code,municipality,region,latitude,longitude\n9000,Gent,Vlaams-Brabant,51.05,3.73\n"
|
||||
)
|
||||
out = StringIO()
|
||||
with pytest.raises(CommandError):
|
||||
call_command(
|
||||
"import_geodata",
|
||||
str(csv_path),
|
||||
"--source-name",
|
||||
with pytest.raises(CommandError):
|
||||
call_command(
|
||||
"import_geodata",
|
||||
str(csv_path),
|
||||
"--source-name",
|
||||
"local-test",
|
||||
"--dataset-version",
|
||||
"2026-01-01",
|
||||
"--license-name",
|
||||
"Test Dataset",
|
||||
stdout=out,
|
||||
)
|
||||
"--license-name",
|
||||
"Test Dataset",
|
||||
stdout=out,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
|
||||
@@ -34,6 +34,7 @@ def test_pipeline_is_idempotent_and_scores(source, profile):
|
||||
assert ScoreRun.objects.filter(profile=profile).count() == 2
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_pipeline_resolves_recruiter_alias_to_direct_employer():
|
||||
source = Source.objects.create(
|
||||
name="SmartRecruiters",
|
||||
@@ -76,14 +77,32 @@ def test_pipeline_resolves_recruiter_alias_to_direct_employer():
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "JobPosting",
|
||||
"identifier": {"@type": "PropertyValue", "name": "Example Public IT", "value": "VR-DEMO-SEC-001"},
|
||||
"identifier": {
|
||||
"@type": "PropertyValue",
|
||||
"name": "Example Public IT",
|
||||
"value": "VR-DEMO-SEC-001"
|
||||
},
|
||||
"title": "Security Engineer",
|
||||
"description": "<p>Beveiliging, monitoring en hybride support.</p>",
|
||||
"datePosted": "2026-07-20",
|
||||
"validThrough": "2026-08-31T23:59:00+02:00",
|
||||
"employmentType": ["FULL_TIME"],
|
||||
"hiringOrganization": {"@type": "Organization", "name": "Example Public IT", "sameAs": "https://www.example.org"},
|
||||
"jobLocation": {"@type": "Place", "address": {"@type": "PostalAddress", "streetAddress": "Voorbeeldstraat 1", "addressLocality": "Antwerpen", "addressRegion": "Antwerpen", "postalCode": "2000", "addressCountry": "BE"}},
|
||||
"hiringOrganization": {
|
||||
"@type": "Organization",
|
||||
"name": "Example Public IT",
|
||||
"sameAs": "https://www.example.org"
|
||||
},
|
||||
"jobLocation": {
|
||||
"@type": "Place",
|
||||
"address": {
|
||||
"@type": "PostalAddress",
|
||||
"streetAddress": "Voorbeeldstraat 1",
|
||||
"addressLocality": "Antwerpen",
|
||||
"addressRegion": "Antwerpen",
|
||||
"postalCode": "2000",
|
||||
"addressCountry": "BE"
|
||||
}
|
||||
},
|
||||
"jobLocationType": "HYBRID",
|
||||
"url": "/example/security-engineer"
|
||||
}
|
||||
@@ -114,7 +133,4 @@ def test_pipeline_resolves_recruiter_alias_to_direct_employer():
|
||||
assert payload is not None
|
||||
assert payload["reason"] == "resolved_direct_match"
|
||||
assert payload["resolved_direct"] is True
|
||||
assert (
|
||||
payload["canonical_url"]
|
||||
== "https://jobs.example.org/vacatures/security-engineer"
|
||||
)
|
||||
assert payload["canonical_url"] == "https://jobs.example.org/vacatures/security-engineer"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from datetime import datetime, time
|
||||
from zoneinfo import ZoneInfo
|
||||
from decimal import Decimal
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import pytest
|
||||
from django.utils import timezone
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
from datetime import timedelta
|
||||
|
||||
from django.utils import timezone
|
||||
|
||||
import pytest
|
||||
from django.utils import timezone
|
||||
|
||||
from apps.sources.models import RawDocument, Source, SourceRun
|
||||
from apps.sources.services.health import collect_source_health
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
from django.core.cache import cache
|
||||
from django.test import override_settings
|
||||
from django.urls import reverse
|
||||
|
||||
import pytest
|
||||
|
||||
from apps.sources.services.fetcher import FetchedDocument
|
||||
from apps.sources.services.manual_import import ManualImportError
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ from django.utils import timezone
|
||||
from apps.jobs.models import Feedback, ScoreRun
|
||||
from apps.jobs.tasks import rescore_active_jobs, update_job_lifecycle
|
||||
from apps.notifications.tasks import build_due_digests
|
||||
from apps.sources.models import RawDocument, Source, SourcePolicyReview, SourceLease, SourceRun
|
||||
from apps.sources.services.fetcher import RateLimitedError, FetchedDocument
|
||||
from apps.sources.models import RawDocument, Source, SourceLease, SourcePolicyReview, SourceRun
|
||||
from apps.sources.services.fetcher import FetchedDocument, RateLimitedError
|
||||
from apps.sources.tasks import cleanup_raw_documents, fetch_source, schedule_due_sources
|
||||
|
||||
|
||||
@@ -181,7 +181,17 @@ def test_sources_candidate_bulk_actions_and_evidence_view(client, user):
|
||||
domain="jobs.example.org",
|
||||
status=Source.Status.CANDIDATE,
|
||||
policy=Source.Policy.REVIEW,
|
||||
metadata={"discovery": [{"url": "https://jobs.example.org/careers", "discovered_from": "html", "reason": "career-link", "confidence": 0.9, "label": "Werken bij"}]},
|
||||
metadata={
|
||||
"discovery": [
|
||||
{
|
||||
"url": "https://jobs.example.org/careers",
|
||||
"discovered_from": "html",
|
||||
"reason": "career-link",
|
||||
"confidence": 0.9,
|
||||
"label": "Werken bij",
|
||||
}
|
||||
]
|
||||
},
|
||||
)
|
||||
|
||||
other = Source.objects.create(
|
||||
|
||||
Reference in New Issue
Block a user