]> Untitled Git - bdk-cli/commitdiff
test: Add wallets, descriptor, compile & config
authorVihiga Tyonum <withtvpeter@gmail.com>
Fri, 12 Jun 2026 07:05:06 +0000 (08:05 +0100)
committerVihiga Tyonum <withtvpeter@gmail.com>
Mon, 22 Jun 2026 21:49:42 +0000 (22:49 +0100)
- Add integration tests for wallets, descriptor,
compile and config modules

tests/cli.rs
tests/common/mod.rs

index db97d656a74307d4fc607728d859fa009c50739a..955d958e5abc8a415c70c28051cb795797fa76e2 100644 (file)
 
 mod common;
 
+use crate::common::BdkCli;
+use predicates::prelude::*;
+use tempfile::TempDir;
 // --- KEY COMMAND TESTS ---
 mod test_key {
-    use crate::common::BdkCli;
-    use predicates::prelude::*;
+    use super::*;
     use serde_json::Value;
 
     #[test]
     fn test_cli_key_generate() {
-        // compile binary
-        let cli = BdkCli::new("testnet", None);
+        let temp_dir = TempDir::new().unwrap();
+        let cli = BdkCli::new("testnet", Some(temp_dir.path().to_path_buf()));
 
         cli.key_cmd(&["generate"])
             .assert()
@@ -34,7 +36,8 @@ mod test_key {
 
     #[test]
     fn test_cli_key_derive() {
-        let cli = BdkCli::new("testnet", None);
+        let temp_dir = TempDir::new().unwrap();
+        let cli = BdkCli::new("testnet", Some(temp_dir.path().to_path_buf()));
 
         let generate_output = cli
             .key_cmd(&["generate"])
@@ -62,8 +65,8 @@ mod test_key {
 
     #[test]
     fn test_cli_key_restore() {
-        // Generate key
-        let cli = BdkCli::new("testnet", None);
+        let temp_dir = TempDir::new().unwrap();
+        let cli = BdkCli::new("testnet", Some(temp_dir.path().to_path_buf()));
 
         // Execute the command and capture the output
         let generate_cmd = cli
@@ -85,7 +88,8 @@ mod test_key {
             .expect("Fingerprint missing");
 
         // Restore using the mnemonic
-     let output_restore = cli.key_cmd(&["restore", "--mnemonic", mnemonic])
+        let output_restore = cli
+            .key_cmd(&["restore", "--mnemonic", mnemonic])
             .output()
             .expect("Failed to execute restore command");
         assert!(output_restore.status.success(), "Restore command failed");
@@ -113,3 +117,150 @@ mod test_key {
         );
     }
 }
+
+// --- WALLETS COMMAND TESTS ---
+mod test_wallets {
+    use super::*;
+
+    #[test]
+    fn test_list_wallets_empty() {
+        let temp_dir = TempDir::new().unwrap();
+        let cli = BdkCli::new("testnet", Some(temp_dir.path().to_path_buf()));
+
+        let mut cmd = cli.build_base_cmd();
+        cmd.arg("wallets");
+
+        cmd.assert()
+            .failure()
+            .stderr(predicate::str::contains("No wallets configured yet."));
+    }
+}
+
+// --- DESCRIPTOR COMMAND TESTS ---
+mod test_descriptor {
+    use super::*;
+
+    #[test]
+    fn test_generate_new_descriptor() {
+        let temp_dir = TempDir::new().unwrap();
+        let cli = BdkCli::new("testnet", Some(temp_dir.path().to_path_buf()));
+
+        // Run `bdk-cli descriptor --type tr`
+        cli.cmd("descriptor", &["--type", "tr"])
+            .assert()
+            .success()
+            .stdout(predicate::str::contains("\"public_descriptors\":"))
+            .stdout(predicate::str::contains("\"private_descriptors\":"))
+            .stdout(predicate::str::contains("\"mnemonic\":"))
+            .stdout(predicate::str::contains("\"fingerprint\":"));
+    }
+}
+
+// --- COMPILE COMMAND TESTS ---
+#[cfg(feature = "compiler")]
+mod test_compile {
+    use super::*;
+
+    #[test]
+    fn test_compile_valid_policy() {
+        let temp_dir = TempDir::new().unwrap();
+        let cli = BdkCli::new("testnet", Some(temp_dir.path().to_path_buf()));
+
+        let policy = "pk(02e5b88fdb71c696e1a473f309a47535b7190e21a22bd25e7fc8bd055db3bba12f)";
+
+        cli.cmd("compile", &[policy, "--type", "wsh"])
+            .assert()
+            .success()
+            .stdout(predicate::str::contains("\"descriptor\":"))
+            .stdout(predicate::str::contains("wsh("));
+    }
+
+    #[test]
+    fn test_compile_invalid_policy() {
+        let temp_dir = TempDir::new().unwrap();
+        let cli = BdkCli::new("testnet", Some(temp_dir.path().to_path_buf()));
+
+        cli.cmd("compile", &["invalid_policy", "--type", "wsh"])
+            .assert()
+            .failure()
+            .stderr(predicate::str::contains("Invalid policy"));
+    }
+}
+
+// --- CONFIG COMMAND TESTS ---
+#[cfg(feature = "rpc")]
+mod test_config {
+    use super::*;
+    use serde_json::Value;
+
+    #[test]
+    fn test_save_and_read_wallet_config() {
+        let temp_dir = TempDir::new().unwrap();
+        let cli = BdkCli::new("regtest", Some(temp_dir.path().to_path_buf()));
+
+        let desc = cli
+            .cmd("descriptor", &["--type", "tr"])
+            .output()
+            .expect("Command to generate descriptors failed");
+
+        let desc_values: Value =
+            serde_json::from_slice(&desc.stdout).expect("Invalid JSON from output descriptor");
+
+        let pub_desc = &desc_values["public_descriptors"];
+
+        let ext_desc = pub_desc["external"].as_str().unwrap();
+        let int_desc = pub_desc["internal"].as_str().unwrap();
+        let wallet_name = "test_config_wallet";
+        let client_type = "rpc";
+        let db = "sqlite";
+        let url = "http://localhost:18443";
+
+        let mut cmd_init = cli.build_base_cmd();
+        cmd_init
+            .arg("wallet")
+            .arg("--wallet")
+            .arg(wallet_name)
+            .arg("config")
+            .arg("--ext-descriptor")
+            .arg(ext_desc)
+            .arg("--int-descriptor")
+            .arg(int_desc)
+            .arg("--client-type")
+            .arg(client_type)
+            .arg("--database-type")
+            .arg(db)
+            .arg("--url")
+            .arg(url);
+
+        cmd_init.assert().success();
+
+        // verify saved config
+        let mut cmd = cli.build_base_cmd();
+        cmd.arg("wallets");
+
+        let output = cmd.output().expect("Failed to execute wallets command");
+
+        assert!(
+            output.status.success(),
+            "The wallets command failed to execute"
+        );
+
+        let json_output: Value =
+            serde_json::from_slice(&output.stdout).expect("CLI did not output valid JSON");
+
+        let config = &json_output[wallet_name];
+
+        assert!(
+            !config.is_null(),
+            "The wallet {wallet_name} was not found in the root JSON object"
+        );
+
+        assert_eq!(config["wallet"].as_str().unwrap(), wallet_name);
+        assert_eq!(config["network"].as_str().unwrap(), "regtest");
+        assert_eq!(config["database_type"].as_str().unwrap(), db);
+        assert_eq!(config["client_type"].as_str().unwrap(), client_type);
+        assert_eq!(config["server_url"].as_str().unwrap(), url);
+        assert_eq!(config["ext_descriptor"].as_str().unwrap(), ext_desc);
+        assert_eq!(config["int_descriptor"].as_str().unwrap(), int_desc);
+    }
+}
index e957584faedc7385ae8b4188b1054d883597be13..4dbd261f2505c7b17f094f82206c82ba46b12f90 100644 (file)
@@ -37,7 +37,7 @@ impl BdkCli {
     }
 
     /// Creates the base assert_cmd::Command with the global flags pre-loaded
-    fn build_base_cmd(&self) -> Command {
+    pub fn build_base_cmd(&self) -> Command {
         let mut cmd = Command::cargo_bin("bdk-cli").expect("bdk-cli binary must compile");
 
         cmd.arg("--network").arg(&self.network);
@@ -53,15 +53,24 @@ impl BdkCli {
         cmd
     }
 
+    /// Returns a pre-configured Command builder for any top-level subcommand
+    pub fn cmd(&self, subcommand: &str, args: &[&str]) -> Command {
+        let mut cmd = self.build_base_cmd();
+        cmd.arg(subcommand);
+        cmd.args(args);
+        cmd
+    }
+
     /// Returns a pre-configured Command builder for `key` operations
     pub fn key_cmd(&self, args: &[&str]) -> Command {
         let mut cmd = self.build_base_cmd();
         cmd.arg("key");
-        cmd.args(args); 
+        cmd.args(args);
         cmd
     }
 
     /// Returns a pre-configured Command builder for `wallet` operations
+    #[allow(unused)]
     pub fn wallet_cmd(&self, args: &[&str]) -> Command {
         let mut cmd = self.build_base_cmd();
         cmd.arg("wallet");