parlov-elicit 0.5.0

Elicitation engine: strategy selection and probe plan generation for parlov.
Documentation
//! Shared test helpers for strategy unit tests.
//!
//! All helpers construct `ScanContext` values covering the common variants
//! across existence strategy tests. File-specific targets and probe IDs are
//! expressed as struct-update-syntax from these bases.

use http::{HeaderMap, HeaderValue};

use crate::context::{KnownDuplicate, ScanContext, StateField};
use crate::types::RiskLevel;

/// Base context: `RiskLevel::Safe`, no auth, no optional fields.
pub(crate) fn minimal_ctx() -> ScanContext {
    ScanContext {
        target: "https://api.example.com/users/{id}".to_owned(),
        baseline_id: "1001".to_owned(),
        probe_id: "9999".to_owned(),
        headers: HeaderMap::new(),
        max_risk: RiskLevel::Safe,
        known_duplicate: None,
        state_field: None,
        alt_credential: None,
        body_template: None,
    }
}

/// `minimal_ctx` elevated to `RiskLevel::MethodDestructive`.
pub(crate) fn ctx_method_destructive() -> ScanContext {
    ScanContext {
        max_risk: RiskLevel::MethodDestructive,
        ..minimal_ctx()
    }
}

/// `minimal_ctx` elevated to `RiskLevel::OperationDestructive`.
pub(crate) fn ctx_operation_destructive() -> ScanContext {
    ScanContext {
        max_risk: RiskLevel::OperationDestructive,
        ..minimal_ctx()
    }
}

/// `minimal_ctx` with `Authorization: Bearer token123` header added.
pub(crate) fn ctx_with_auth() -> ScanContext {
    let mut headers = HeaderMap::new();
    headers.insert(
        http::header::AUTHORIZATION,
        HeaderValue::from_static("Bearer token123"),
    );
    ScanContext {
        headers,
        ..minimal_ctx()
    }
}

/// `minimal_ctx` with a known-duplicate `email` field.
pub(crate) fn ctx_with_duplicate() -> ScanContext {
    ScanContext {
        known_duplicate: Some(KnownDuplicate {
            field: "email".to_owned(),
            value: "alice@example.com".to_owned(),
        }),
        ..minimal_ctx()
    }
}

/// `ctx_method_destructive` with an invalid `status` state field.
pub(crate) fn ctx_with_state_field() -> ScanContext {
    ScanContext {
        state_field: Some(StateField {
            field: "status".to_owned(),
            value: "invalid_state".to_owned(),
        }),
        ..ctx_method_destructive()
    }
}

/// Full scope-manipulation context: auth header + under-scoped `alt_credential`.
pub(crate) fn ctx_with_alt_credential() -> ScanContext {
    let mut headers = HeaderMap::new();
    headers.insert(
        http::header::AUTHORIZATION,
        HeaderValue::from_static("Bearer token123"),
    );
    let mut alt = HeaderMap::new();
    alt.insert(
        http::header::AUTHORIZATION,
        HeaderValue::from_static("Bearer under-scoped-token"),
    );
    ScanContext {
        headers,
        alt_credential: Some(alt),
        ..minimal_ctx()
    }
}