|
8 | 8 |
|
9 | 9 | from app.models import Job, JobStatus, JobType |
10 | 10 | from app.models.guardrails import GuardrailsRequest |
| 11 | +from app.models.llm.request import InlineValidator, Validator |
11 | 12 | from app.services.guardrails.jobs import ( |
12 | 13 | _build_callback_payload, |
13 | 14 | _coerce_int, |
@@ -301,6 +302,85 @@ def test_execute_job_dedupes_duplicate_validators_and_warns( |
301 | 302 | assert any("duplicate" in w for w in warnings) |
302 | 303 |
|
303 | 304 |
|
| 305 | +def test_execute_job_passes_inline_specs_and_dedupes_them( |
| 306 | + user_api_key: TestAuthContext, |
| 307 | +) -> None: |
| 308 | + pii = {"type": "pii_remover", "on_fail": "fix"} |
| 309 | + req = GuardrailsRequest.model_validate( |
| 310 | + { |
| 311 | + "text": "My email is alice@example.com", |
| 312 | + "config": [ |
| 313 | + {"validator_config_id": str(VALIDATOR_A)}, |
| 314 | + pii, |
| 315 | + {"on_fail": "fix", "type": "pii_remover"}, |
| 316 | + ], |
| 317 | + } |
| 318 | + ) |
| 319 | + |
| 320 | + with _patched_worker_db() as mock_crud, patch( |
| 321 | + "app.services.guardrails.jobs.apply_guardrails" |
| 322 | + ) as mock_apply: |
| 323 | + mock_apply.return_value = GuardrailsOutcome( |
| 324 | + safe_text="ok", |
| 325 | + error=None, |
| 326 | + bypassed=False, |
| 327 | + rephrase_needed=False, |
| 328 | + raw={"data": {}}, |
| 329 | + ) |
| 330 | + execute_job( |
| 331 | + project_id=user_api_key.project_id, |
| 332 | + job_id=str(uuid4()), |
| 333 | + task_id="t", |
| 334 | + task_instance=None, |
| 335 | + request_data=req.model_dump(mode="json"), |
| 336 | + organization_id=user_api_key.organization_id, |
| 337 | + ) |
| 338 | + |
| 339 | + ref, inline = mock_apply.call_args.kwargs["validators"] |
| 340 | + assert isinstance(ref, Validator) and ref.validator_config_id == VALIDATOR_A |
| 341 | + assert isinstance(inline, InlineValidator) |
| 342 | + assert inline.model_dump(mode="json", exclude={"is_enabled"}) == pii |
| 343 | + |
| 344 | + warnings = _update_calls(mock_crud)[-1].meta["callback"]["warnings"] |
| 345 | + assert any("duplicate" in w for w in warnings) |
| 346 | + |
| 347 | + |
| 348 | +def test_execute_job_disabled_entry_does_not_shadow_enabled_duplicate( |
| 349 | + user_api_key: TestAuthContext, |
| 350 | +) -> None: |
| 351 | + req = GuardrailsRequest.model_validate( |
| 352 | + { |
| 353 | + "text": "hi", |
| 354 | + "config": [ |
| 355 | + {"validator_config_id": str(VALIDATOR_A), "is_enabled": False}, |
| 356 | + {"validator_config_id": str(VALIDATOR_A)}, |
| 357 | + ], |
| 358 | + } |
| 359 | + ) |
| 360 | + |
| 361 | + with _patched_worker_db(), patch( |
| 362 | + "app.services.guardrails.jobs.apply_guardrails" |
| 363 | + ) as mock_apply: |
| 364 | + mock_apply.return_value = GuardrailsOutcome( |
| 365 | + safe_text="hi", |
| 366 | + error=None, |
| 367 | + bypassed=False, |
| 368 | + rephrase_needed=False, |
| 369 | + raw={"data": {}}, |
| 370 | + ) |
| 371 | + execute_job( |
| 372 | + project_id=user_api_key.project_id, |
| 373 | + job_id=str(uuid4()), |
| 374 | + task_id="t", |
| 375 | + task_instance=None, |
| 376 | + request_data=req.model_dump(mode="json"), |
| 377 | + organization_id=user_api_key.organization_id, |
| 378 | + ) |
| 379 | + |
| 380 | + (validator,) = mock_apply.call_args.kwargs["validators"] |
| 381 | + assert validator.is_enabled |
| 382 | + |
| 383 | + |
304 | 384 | def test_execute_job_bypassed_adds_warning(user_api_key: TestAuthContext) -> None: |
305 | 385 | req = _make_request() |
306 | 386 |
|
|
0 commit comments