forked from Crockan/MercuryToolbox
chore(release): prepare public source release
This commit is contained in:
@@ -0,0 +1,247 @@
|
||||
//! Integration tests for the `config` command.
|
||||
|
||||
use std::fs;
|
||||
|
||||
use assert_cmd::Command;
|
||||
use predicates::prelude::*;
|
||||
use serde_json::json;
|
||||
use tempfile::tempdir;
|
||||
|
||||
fn cargo_command() -> Command {
|
||||
Command::cargo_bin("config").expect("binary")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_args_prints_quick_help_card() {
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.assert()
|
||||
.code(2)
|
||||
.stdout(predicate::str::is_empty())
|
||||
.stderr(predicate::str::contains(
|
||||
"error: provide a subcommand: get, set, delete, or ls",
|
||||
))
|
||||
.stderr(predicate::str::contains("config - Mercury Toolbox"))
|
||||
.stderr(predicate::str::contains("Usage:"))
|
||||
.stderr(predicate::str::contains("get [PATH] [POINTER]"))
|
||||
.stderr(predicate::str::contains(
|
||||
"config [OPTIONS] inspect [PATH] [POINTER]",
|
||||
))
|
||||
.stderr(predicate::str::contains(
|
||||
"Type 'config --help' for the full command reference.",
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_reads_toml_pointer_as_json() {
|
||||
let temp = tempdir().expect("tempdir");
|
||||
let path = temp.path().join("sample.toml");
|
||||
fs::write(
|
||||
&path,
|
||||
"[package]\nname = \"toolbox\"\nversion = \"3.0.0\"\n",
|
||||
)
|
||||
.expect("fixture");
|
||||
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.arg("--json")
|
||||
.arg("get")
|
||||
.arg(&path)
|
||||
.arg("/package/version")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains("\"format\":\"toml\""))
|
||||
.stdout(predicate::str::contains("\"pointer\":\"/package/version\""))
|
||||
.stdout(predicate::str::contains("\"value\":\"3.0.0\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_then_get_updates_json_number_value() {
|
||||
let temp = tempdir().expect("tempdir");
|
||||
let path = temp.path().join("config.json");
|
||||
fs::write(&path, "{\"retries\":1}\n").expect("fixture");
|
||||
|
||||
let mut set = cargo_command();
|
||||
set.arg("set")
|
||||
.arg(&path)
|
||||
.arg("/retries")
|
||||
.arg("5")
|
||||
.arg("--json")
|
||||
.arg("--value-type")
|
||||
.arg("number")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains("\"changed\":true"));
|
||||
|
||||
let mut get = cargo_command();
|
||||
get.arg("--json")
|
||||
.arg("get")
|
||||
.arg(&path)
|
||||
.arg("/retries")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains("\"value\":5"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delete_removes_env_key() {
|
||||
let temp = tempdir().expect("tempdir");
|
||||
let path = temp.path().join(".env");
|
||||
fs::write(&path, "KEEP=yes\nDROP=no\n").expect("fixture");
|
||||
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.arg("delete")
|
||||
.arg(&path)
|
||||
.arg("/DROP")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains("op=delete"));
|
||||
|
||||
let content = fs::read_to_string(&path).expect("updated");
|
||||
assert!(content.contains("KEEP=yes"));
|
||||
assert!(!content.contains("DROP=no"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ls_lists_ini_section_entries() {
|
||||
let temp = tempdir().expect("tempdir");
|
||||
let path = temp.path().join("settings.ini");
|
||||
fs::write(&path, "mode=dev\n[server]\nport=8080\nhost=127.0.0.1\n").expect("fixture");
|
||||
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.arg("--json")
|
||||
.arg("ls")
|
||||
.arg(&path)
|
||||
.arg("/server")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains("\"key\":\"host\""))
|
||||
.stdout(predicate::str::contains("\"key\":\"port\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ls_accepts_single_stdin_path_stream() {
|
||||
let temp = tempdir().expect("tempdir");
|
||||
let path = temp.path().join("config.json");
|
||||
fs::write(&path, "{\"mode\":\"dev\",\"nested\":{\"ok\":true}}\n").expect("fixture");
|
||||
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.arg("--json")
|
||||
.arg("ls")
|
||||
.write_stdin(format!("{}\n", path.display()))
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains("\"pointer\":\"/\""))
|
||||
.stdout(predicate::str::contains("\"key\":\"mode\""))
|
||||
.stdout(predicate::str::contains("\"key\":\"nested\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn help_includes_new_subcommands_and_flags() {
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.arg("--help")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains("get [PATH] [POINTER]"))
|
||||
.stdout(predicate::str::contains("set <PATH> <POINTER> <VALUE>"))
|
||||
.stdout(predicate::str::contains("--value-type"))
|
||||
.stdout(predicate::str::contains("--format"))
|
||||
.stdout(predicate::str::contains("config"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ls_on_scalar_pointer_returns_no_results_exit_code() {
|
||||
let temp = tempdir().expect("tempdir");
|
||||
let path = temp.path().join("config.json");
|
||||
fs::write(&path, "{\"mode\":\"dev\"}\n").expect("fixture");
|
||||
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.arg("ls")
|
||||
.arg(&path)
|
||||
.arg("/mode")
|
||||
.assert()
|
||||
.code(1)
|
||||
.stdout(predicate::str::contains("entries=0"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delete_missing_json_key_returns_no_results_and_preserves_file() {
|
||||
let temp = tempdir().expect("tempdir");
|
||||
let path = temp.path().join("config.json");
|
||||
fs::write(&path, "{\"present\":true}\n").expect("fixture");
|
||||
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.arg("--json")
|
||||
.arg("delete")
|
||||
.arg(&path)
|
||||
.arg("/missing")
|
||||
.assert()
|
||||
.code(1)
|
||||
.stdout(predicate::str::contains("\"changed\":false"))
|
||||
.stdout(predicate::str::contains("\"pointer\":\"/missing\""));
|
||||
|
||||
let content = fs::read_to_string(&path).expect("updated");
|
||||
let parsed: serde_json::Value = serde_json::from_str(&content).expect("valid json");
|
||||
assert_eq!(parsed, json!({"present": true}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_creates_nested_json_arrays_and_objects() {
|
||||
let temp = tempdir().expect("tempdir");
|
||||
let path = temp.path().join("config.json");
|
||||
fs::write(&path, "{}\n").expect("fixture");
|
||||
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.arg("--json")
|
||||
.arg("set")
|
||||
.arg(&path)
|
||||
.arg("/pkg/deps/0/name")
|
||||
.arg("serde")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains("\"changed\":true"));
|
||||
|
||||
let content = fs::read_to_string(&path).expect("updated");
|
||||
let parsed: serde_json::Value = serde_json::from_str(&content).expect("valid json");
|
||||
assert_eq!(parsed, json!({"pkg": {"deps": [{"name": "serde"}]}}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn env_set_rejects_nested_pointer_and_non_scalar_json_values() {
|
||||
let temp = tempdir().expect("tempdir");
|
||||
let path = temp.path().join(".env");
|
||||
fs::write(&path, "KEEP=yes\n").expect("fixture");
|
||||
|
||||
let mut nested_pointer = cargo_command();
|
||||
nested_pointer
|
||||
.arg("set")
|
||||
.arg(&path)
|
||||
.arg("/A/B")
|
||||
.arg("x")
|
||||
.assert()
|
||||
.code(3)
|
||||
.stderr(predicate::str::contains(
|
||||
"env write operations only support root keys like /NAME",
|
||||
));
|
||||
|
||||
let mut object_value = cargo_command();
|
||||
object_value
|
||||
.arg("set")
|
||||
.arg(&path)
|
||||
.arg("/OBJ")
|
||||
.arg("{\"nested\":true}")
|
||||
.arg("--value-type")
|
||||
.arg("json")
|
||||
.assert()
|
||||
.code(3)
|
||||
.stderr(predicate::str::contains(
|
||||
"env/ini writes require scalar string|number|bool values",
|
||||
));
|
||||
}
|
||||
Reference in New Issue
Block a user