printwell-pdf 0.1.2

PDF manipulation features (forms, signing) for Printwell
Documentation
//! Tests for PDF signing functionality

use crate::signing::*;

#[cfg(test)]
mod signature_level_tests {
    use super::*;

    #[test]
    fn test_default_is_pades_b() {
        let level = SignatureLevel::default();
        assert_eq!(level, SignatureLevel::PadesB);
    }

    #[test]
    fn test_signature_level_as_str() {
        assert_eq!(SignatureLevel::PadesB.as_str(), "B");
        assert_eq!(SignatureLevel::PadesT.as_str(), "T");
        assert_eq!(SignatureLevel::PadesLT.as_str(), "LT");
        assert_eq!(SignatureLevel::PadesLTA.as_str(), "LTA");
    }

    #[test]
    fn test_signature_level_copy() {
        let level = SignatureLevel::PadesLTA;
        let copy = level;
        assert_eq!(level, copy);
    }

    #[test]
    fn test_signature_level_clone() {
        let level = SignatureLevel::PadesT;
        let cloned = level;
        assert_eq!(level, cloned);
    }
}

#[cfg(test)]
mod signing_options_tests {
    use super::*;

    #[test]
    fn test_default_signing_options() {
        let opts = SigningOptions::default();

        assert!(opts.reason.is_none());
        assert!(opts.location.is_none());
        assert!(opts.contact_info.is_none());
        assert_eq!(opts.signature_level, SignatureLevel::PadesB);
        assert!(opts.timestamp_url.is_none());
    }

    #[test]
    fn test_signing_options_builder() {
        let opts = SigningOptions::builder()
            .reason("Approval".to_string())
            .location("New York".to_string())
            .contact_info("john@example.com".to_string())
            .signature_level(SignatureLevel::PadesT)
            .timestamp_url("https://timestamp.example.com".to_string())
            .build();

        assert_eq!(opts.reason, Some("Approval".to_string()));
        assert_eq!(opts.location, Some("New York".to_string()));
        assert_eq!(opts.contact_info, Some("john@example.com".to_string()));
        assert_eq!(opts.signature_level, SignatureLevel::PadesT);
        assert_eq!(
            opts.timestamp_url,
            Some("https://timestamp.example.com".to_string())
        );
    }
}

#[cfg(test)]
mod signature_appearance_tests {
    use super::*;

    #[test]
    fn test_signature_appearance_builder() {
        let appearance = SignatureAppearance::builder()
            .page(1u32)
            .x(100.0)
            .y(700.0)
            .width(200.0)
            .height(50.0)
            .build();

        assert_eq!(appearance.page, 1);
        assert!((appearance.x - 100.0).abs() < 0.001);
        assert!((appearance.y - 700.0).abs() < 0.001);
        assert!((appearance.width - 200.0).abs() < 0.001);
        assert!((appearance.height - 50.0).abs() < 0.001);
    }

    #[test]
    fn test_signature_appearance_defaults() {
        let appearance = SignatureAppearance::builder()
            .page(1u32)
            .x(0.0)
            .y(0.0)
            .width(100.0)
            .height(40.0)
            .build();

        assert!(appearance.show_name);
        assert!(appearance.show_date);
        assert!(appearance.show_reason);
        assert!(appearance.background_image.is_none());
    }

    #[test]
    fn test_signature_appearance_with_options() {
        let appearance = SignatureAppearance::builder()
            .page(1u32)
            .x(0.0)
            .y(0.0)
            .width(100.0)
            .height(40.0)
            .show_name(false)
            .show_date(false)
            .show_reason(true)
            .build();

        assert!(!appearance.show_name);
        assert!(!appearance.show_date);
        assert!(appearance.show_reason);
    }

    #[test]
    fn test_signature_appearance_with_background() {
        // Mock PNG image data
        let image_data = vec![0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A];

        let appearance = SignatureAppearance::builder()
            .page(1u32)
            .x(0.0)
            .y(0.0)
            .width(100.0)
            .height(40.0)
            .background_image(Some(image_data))
            .build();

        assert!(appearance.background_image.is_some());
        assert_eq!(appearance.background_image.unwrap().len(), 8);
    }
}

#[cfg(test)]
mod signature_verification_tests {
    use super::*;

    #[test]
    fn test_signature_verification_from_info_valid() {
        let info = printwell_sys::SignatureInfo {
            signer_name: "John Doe".to_string(),
            signing_time: "2024-01-15T10:30:00Z".to_string(),
            reason: "Approval".to_string(),
            location: "Office".to_string(),
            is_valid: true,
            covers_whole_document: true,
        };

        let verification: SignatureVerification = info.into();

        assert_eq!(verification.signer_name, "John Doe");
        assert_eq!(
            verification.signing_time,
            Some("2024-01-15T10:30:00Z".to_string())
        );
        assert_eq!(verification.reason, Some("Approval".to_string()));
        assert_eq!(verification.location, Some("Office".to_string()));
        assert!(verification.status.document.is_valid);
        assert!(verification.status.document.covers_whole_document);
    }

    #[test]
    fn test_signature_verification_from_info_empty_strings() {
        let info = printwell_sys::SignatureInfo {
            signer_name: String::new(),
            signing_time: String::new(),
            reason: String::new(),
            location: String::new(),
            is_valid: false,
            covers_whole_document: false,
        };

        let verification: SignatureVerification = info.into();

        assert!(verification.signer_name.is_empty());
        assert!(verification.signing_time.is_none());
        assert!(verification.reason.is_none());
        assert!(verification.location.is_none());
        assert!(!verification.status.document.is_valid);
        assert!(!verification.status.document.covers_whole_document);
    }

    #[test]
    fn test_signature_verification_partial_info() {
        let info = printwell_sys::SignatureInfo {
            signer_name: "Jane Smith".to_string(),
            signing_time: "2024-06-01".to_string(),
            reason: String::new(),
            location: String::new(),
            is_valid: true,
            covers_whole_document: true,
        };

        let verification: SignatureVerification = info.into();

        assert_eq!(verification.signer_name, "Jane Smith");
        assert!(verification.signing_time.is_some());
        assert!(verification.reason.is_none());
        assert!(verification.location.is_none());
    }
}

#[cfg(test)]
mod signed_pdf_tests {
    use super::*;

    // Note: We can't fully test SignedPdf without FFI, but we can test the struct
    #[test]
    fn test_signed_pdf_struct() {
        // This test verifies the SignedPdf struct exists and has expected methods
        // Actual signing requires FFI which would need integration tests

        // We test the API exists by checking the method signatures compile
        fn _check_api(pdf: SignedPdf) {
            let _bytes: &[u8] = pdf.as_bytes();
            let _owned: Vec<u8> = pdf.into_bytes();
        }
    }
}