a73x

tests/trust_test.rs

Ref:   Size: 6.1 KiB

mod common;

use common::TestRepo;

// ===========================================================================
// T006: Integration tests for `collab key add`
// ===========================================================================

#[test]
fn test_key_add_valid_key() {
    let repo = TestRepo::new("Alice", "alice@example.com");

    // Add own key via --self
    let out = repo.run_ok(&["key", "add", "--self"]);
    assert!(
        out.contains("Trusted key added:"),
        "should confirm key added, got: {}",
        out
    );
}

#[test]
fn test_key_add_with_label() {
    let repo = TestRepo::new("Alice", "alice@example.com");

    let out = repo.run_ok(&["key", "add", "--self", "--label", "Alice (main laptop)"]);
    assert!(out.contains("Trusted key added:"));
    assert!(out.contains("Alice (main laptop)"));

    // Verify it shows up in list
    let out = repo.run_ok(&["key", "list"]);
    assert!(out.contains("Alice (main laptop)"));
}

#[test]
fn test_key_add_duplicate_prints_message() {
    let repo = TestRepo::new("Alice", "alice@example.com");

    repo.run_ok(&["key", "add", "--self"]);
    let out = repo.run_ok(&["key", "add", "--self"]);
    assert!(
        out.contains("already trusted"),
        "should say already trusted, got: {}",
        out
    );
}

#[test]
fn test_key_add_invalid_key_returns_error() {
    let repo = TestRepo::new("Alice", "alice@example.com");

    let err = repo.run_err(&["key", "add", "not-a-valid-key!!!"]);
    assert!(
        err.contains("invalid") || err.contains("base64"),
        "should mention invalid key, got: {}",
        err
    );
}

#[test]
fn test_key_add_self_and_pubkey_errors() {
    let repo = TestRepo::new("Alice", "alice@example.com");

    let err = repo.run_err(&["key", "add", "--self", "somepubkey"]);
    assert!(
        err.contains("cannot specify both"),
        "should error on --self with pubkey, got: {}",
        err
    );
}

#[test]
fn test_key_add_explicit_pubkey() {
    let repo = TestRepo::new("Alice", "alice@example.com");

    // Get our own public key to use as a valid key
    let out = repo.run_ok(&["key", "add", "--self", "--label", "Me"]);
    assert!(out.contains("Trusted key added:"));

    // List should show the key
    let out = repo.run_ok(&["key", "list"]);
    assert!(out.contains("Me"));
}

// ===========================================================================
// T016: Integration tests for `collab key list`
// ===========================================================================

#[test]
fn test_key_list_no_keys() {
    let repo = TestRepo::new("Alice", "alice@example.com");

    let out = repo.run_ok(&["key", "list"]);
    assert!(
        out.contains("No trusted keys configured"),
        "should say no keys, got: {}",
        out
    );
}

#[test]
fn test_key_list_shows_keys_and_labels() {
    let repo = TestRepo::new("Alice", "alice@example.com");

    repo.run_ok(&["key", "add", "--self", "--label", "Alice"]);

    let out = repo.run_ok(&["key", "list"]);
    assert!(out.contains("Alice"), "should show label, got: {}", out);
    // Should contain a base64 key string (44 chars for ed25519)
    assert!(
        out.lines().any(|l| l.len() >= 44),
        "should contain a key string, got: {}",
        out
    );
}

// ===========================================================================
// T017: Integration tests for `collab key remove`
// ===========================================================================

#[test]
fn test_key_remove_existing() {
    let repo = TestRepo::new("Alice", "alice@example.com");

    // Add a key, extract the pubkey from the list
    repo.run_ok(&["key", "add", "--self", "--label", "Alice"]);

    let list = repo.run_ok(&["key", "list"]);
    let pubkey = list.lines().next().unwrap().split_whitespace().next().unwrap();

    let out = repo.run_ok(&["key", "remove", pubkey]);
    assert!(
        out.contains("Removed trusted key:"),
        "should confirm removal, got: {}",
        out
    );
    assert!(out.contains("Alice"), "should show label of removed key");

    // List should now be empty
    let out = repo.run_ok(&["key", "list"]);
    assert!(out.contains("No trusted keys configured"));
}

#[test]
fn test_key_remove_nonexistent_errors() {
    let repo = TestRepo::new("Alice", "alice@example.com");

    // Add a key first so the file exists
    repo.run_ok(&["key", "add", "--self"]);

    let err = repo.run_err(&["key", "remove", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY="]);
    assert!(
        err.contains("not in the trusted keys list"),
        "should say not found, got: {}",
        err
    );
}

// ===========================================================================
// T021: Edge case tests
// ===========================================================================

#[test]
fn test_key_add_then_remove_then_readd() {
    let repo = TestRepo::new("Alice", "alice@example.com");

    repo.run_ok(&["key", "add", "--self", "--label", "Original"]);

    let list = repo.run_ok(&["key", "list"]);
    let pubkey = list.lines().next().unwrap().split_whitespace().next().unwrap().to_string();

    // Remove
    repo.run_ok(&["key", "remove", &pubkey]);

    // Re-add with a different label
    let out = repo.run_ok(&["key", "add", &pubkey, "--label", "Re-added"]);
    assert!(out.contains("Trusted key added:"));

    let list = repo.run_ok(&["key", "list"]);
    assert!(list.contains("Re-added"));
}

#[test]
fn test_key_list_with_corrupted_file() {
    let repo = TestRepo::new("Alice", "alice@example.com");

    // Add a valid key first
    repo.run_ok(&["key", "add", "--self", "--label", "Good key"]);

    // Manually corrupt the file by adding a bad line
    let git_dir = repo.dir.path().join(".git/collab/trusted-keys");
    let content = std::fs::read_to_string(&git_dir).unwrap();
    std::fs::write(
        &git_dir,
        format!("{}garbage_not_a_valid_key BadEntry\n", content),
    )
    .unwrap();

    // List should still work, showing valid keys and skipping the bad one
    let out = repo.run_ok(&["key", "list"]);
    assert!(out.contains("Good key"), "valid key should still appear");
    // The bad line should be skipped (warning goes to stderr)
}