typeduck-codex-web 0.4.0

A standalone browser interface and Codex runtime
Documentation
use std::fs;

use pretty_assertions::assert_eq;
use tempfile::TempDir;

use super::DaemonConfig;

#[test]
fn loads_ordered_accounts_and_tunnel() {
    let temp = TempDir::new().expect("temp dir");
    let first = temp.path().join("first");
    let second = temp.path().join("second");
    let identity = temp.path().join("id_ed25519");
    let config = temp.path().join("daemon.toml");
    fs::write(
        &config,
        format!(
            r#"
port = 36915
mcp_oauth_callback_url = "http://127.0.0.1:36915/oauth/callback"

[[accounts]]
name = "primary"
label = "Primary"
codex_home = {first:?}
proxy = "http://proxy.example:8080"

[[accounts]]
name = "backup"
codex_home = {second:?}
use_ssh_tunnel = true

[ssh_tunnel]
destination = "codex@example.com"
identity_file = {identity:?}
ssh_port = 2222
local_port = 1080
"#
        ),
    )
    .expect("write config");

    let loaded = DaemonConfig::load(Some(&config)).expect("load config");

    assert_eq!(loaded.port, Some(36915));
    assert_eq!(
        loaded.mcp_oauth_callback_url.as_deref(),
        Some("http://127.0.0.1:36915/oauth/callback")
    );
    assert_eq!(loaded.accounts.len(), 2);
    assert_eq!(loaded.accounts[0].name, "primary");
    assert_eq!(loaded.accounts[1].label, "backup");
    assert!(loaded.accounts[1].use_ssh_tunnel);
    assert_eq!(loaded.ssh_tunnel.expect("tunnel").local_port, Some(1080));
}

#[test]
fn rejects_invalid_persistent_callback_url() {
    let temp = TempDir::new().expect("temp dir");
    let config = temp.path().join("daemon.toml");
    fs::write(
        &config,
        r#"mcp_oauth_callback_url = "https://example.com/not-the-callback""#,
    )
    .expect("write config");

    let error = DaemonConfig::load(Some(&config)).expect_err("invalid callback URL");

    assert!(error.to_string().contains("must end at /oauth/callback"));
}

#[test]
fn rejects_duplicate_accounts_and_unsupported_proxies() {
    let temp = TempDir::new().expect("temp dir");
    let home = temp.path().join("home");
    let config = temp.path().join("daemon.toml");
    fs::write(
        &config,
        format!(
            r#"
[[accounts]]
name = "same"
codex_home = {home:?}
proxy = "ftp://proxy.example"

[[accounts]]
name = "same"
codex_home = {home:?}
"#
        ),
    )
    .expect("write config");

    let error = DaemonConfig::load(Some(&config)).expect_err("invalid config");

    assert!(error.to_string().contains("proxy URL scheme"));
}