config-easy 0.2.1

A small interactive settings menu for command-line Rust applications
Documentation
use super::*;
use rusqlite::params;

fn connection() -> rusqlite::Connection {
    rusqlite::Connection::open_in_memory().unwrap()
}

fn create_settings(conn: &rusqlite::Connection) {
    conn.execute(
        "CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT NOT NULL)",
        [],
    )
    .unwrap();
}

fn insert_setting(conn: &rusqlite::Connection, key: &str, value: &str) {
    conn.execute(
        "INSERT INTO settings (key, value) VALUES (?1, ?2)",
        params![key, value],
    )
    .unwrap();
}

#[test]
fn loads_default_table_ordered_by_key() {
    let conn = connection();
    create_settings(&conn);
    insert_setting(&conn, "log_level", "info");
    insert_setting(&conn, "graph_client_id", "abc123");

    let store = RusqliteStore::new(&conn);
    let rows = store
        .load_settings(&SettingsQuery {
            table: "settings",
            key_column: "key",
            value_column: "value",
            order_by: "key",
        })
        .unwrap();

    assert_eq!(rows[0].key, "graph_client_id");
    assert_eq!(rows[1].key, "log_level");
}

#[test]
fn updates_default_table() {
    let conn = connection();
    create_settings(&conn);
    insert_setting(&conn, "log_level", "info");

    let store = RusqliteStore::new(&conn);
    store
        .update_setting(
            &SettingsQuery {
                table: "settings",
                key_column: "key",
                value_column: "value",
                order_by: "key",
            },
            "log_level",
            "debug",
        )
        .unwrap();

    let value: String = conn
        .query_row(
            "SELECT value FROM settings WHERE key = 'log_level'",
            [],
            |row| row.get(0),
        )
        .unwrap();
    assert_eq!(value, "debug");
}

#[test]
fn supports_custom_table_columns_and_ordering() {
    let conn = connection();
    conn.execute(
        "CREATE TABLE app_config (name TEXT PRIMARY KEY, setting TEXT NOT NULL, display_order INTEGER NOT NULL)",
        [],
    )
    .unwrap();
    conn.execute(
        "INSERT INTO app_config (name, setting, display_order) VALUES ('second', '2', 2), ('first', '1', 1)",
        [],
    )
    .unwrap();

    let store = RusqliteStore::new(&conn);
    let rows = store
        .load_settings(&SettingsQuery {
            table: "app_config",
            key_column: "name",
            value_column: "setting",
            order_by: "display_order",
        })
        .unwrap();

    assert_eq!(rows[0].key, "first");
    assert_eq!(rows[1].key, "second");
}

#[test]
fn builder_accepts_action_that_captures_connection() {
    let conn = connection();
    create_settings(&conn);
    insert_setting(&conn, "log_level", "info");

    let _menu = builder(&conn).action("r", "reset", || {
        conn.execute(
            "UPDATE settings SET value = 'debug' WHERE key = 'log_level'",
            [],
        )?;
        Ok(())
    });
}