aboutsummaryrefslogtreecommitdiff
path: root/mingling_core/tests
diff options
context:
space:
mode:
Diffstat (limited to 'mingling_core/tests')
-rw-r--r--mingling_core/tests/test-all/Cargo.lock465
-rw-r--r--mingling_core/tests/test-all/Cargo.toml20
-rw-r--r--mingling_core/tests/test-all/tests/integration.rs235
-rw-r--r--mingling_core/tests/test-basic/Cargo.lock76
-rw-r--r--mingling_core/tests/test-basic/Cargo.toml10
-rw-r--r--mingling_core/tests/test-basic/tests/integration.rs93
-rw-r--r--mingling_core/tests/test-comp/Cargo.lock86
-rw-r--r--mingling_core/tests/test-comp/Cargo.toml10
-rw-r--r--mingling_core/tests/test-comp/tests/integration.rs123
-rw-r--r--mingling_core/tests/test-dispatch-tree/Cargo.lock76
-rw-r--r--mingling_core/tests/test-dispatch-tree/Cargo.toml10
-rw-r--r--mingling_core/tests/test-dispatch-tree/tests/integration.rs93
-rw-r--r--mingling_core/tests/test-general-renderer/Cargo.lock287
-rw-r--r--mingling_core/tests/test-general-renderer/Cargo.toml11
-rw-r--r--mingling_core/tests/test-general-renderer/tests/integration.rs77
-rw-r--r--mingling_core/tests/test-repl/Cargo.lock76
-rw-r--r--mingling_core/tests/test-repl/Cargo.toml10
-rw-r--r--mingling_core/tests/test-repl/tests/integration.rs63
18 files changed, 1821 insertions, 0 deletions
diff --git a/mingling_core/tests/test-all/Cargo.lock b/mingling_core/tests/test-all/Cargo.lock
new file mode 100644
index 0000000..9fe2a28
--- /dev/null
+++ b/mingling_core/tests/test-all/Cargo.lock
@@ -0,0 +1,465 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "bitflags"
+version = "2.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "bytes"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
+
+[[package]]
+name = "equivalent"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+
+[[package]]
+name = "errno"
+version = "0.3.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
+
+[[package]]
+name = "indexmap"
+version = "2.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
+
+[[package]]
+name = "just_fmt"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5454cda0d57db59778608d7a47bff5b16c6705598265869fb052b657f66cf05e"
+
+[[package]]
+name = "just_template"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db3edb658c34b10b69c4b3b58f7ba989cd09c82c0621dee1eef51843c2327225"
+dependencies = [
+ "just_fmt",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.186"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
+
+[[package]]
+name = "lock_api"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "memchr"
+version = "2.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
+
+[[package]]
+name = "mingling"
+version = "0.2.0"
+dependencies = [
+ "mingling_core",
+ "mingling_macros",
+ "serde",
+ "size",
+]
+
+[[package]]
+name = "mingling_core"
+version = "0.2.0"
+dependencies = [
+ "just_fmt",
+ "just_template",
+ "ron",
+ "serde",
+ "serde_json",
+ "serde_yaml",
+ "toml",
+]
+
+[[package]]
+name = "mingling_macros"
+version = "0.2.0"
+dependencies = [
+ "just_fmt",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "mio"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda"
+dependencies = [
+ "libc",
+ "wasi",
+ "windows-sys",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.21.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
+
+[[package]]
+name = "parking_lot"
+version = "0.12.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-link",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.5.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "ron"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4147b952f3f819eca0e99527022f7d6a8d05f111aeb0a62960c74eb283bec8fc"
+dependencies = [
+ "bitflags",
+ "once_cell",
+ "serde",
+ "serde_derive",
+ "typeid",
+ "unicode-ident",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "serde"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
+dependencies = [
+ "serde_core",
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_core"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.150"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
+dependencies = [
+ "itoa",
+ "memchr",
+ "serde",
+ "serde_core",
+ "zmij",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "serde_yaml"
+version = "0.9.34+deprecated"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
+dependencies = [
+ "indexmap",
+ "itoa",
+ "ryu",
+ "serde",
+ "unsafe-libyaml",
+]
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
+dependencies = [
+ "errno",
+ "libc",
+]
+
+[[package]]
+name = "size"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b6709c7b6754dca1311b3c73e79fcce40dd414c782c66d88e8823030093b02b"
+
+[[package]]
+name = "smallvec"
+version = "1.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
+
+[[package]]
+name = "socket2"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "test-all"
+version = "0.1.0"
+dependencies = [
+ "mingling",
+ "serde",
+ "tokio",
+]
+
+[[package]]
+name = "tokio"
+version = "1.52.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe"
+dependencies = [
+ "bytes",
+ "libc",
+ "mio",
+ "parking_lot",
+ "pin-project-lite",
+ "signal-hook-registry",
+ "socket2",
+ "tokio-macros",
+ "windows-sys",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "toml"
+version = "1.1.2+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee"
+dependencies = [
+ "indexmap",
+ "serde_core",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_parser",
+ "toml_writer",
+ "winnow",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "1.1.1+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "toml_parser"
+version = "1.1.2+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
+dependencies = [
+ "winnow",
+]
+
+[[package]]
+name = "toml_writer"
+version = "1.1.1+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db"
+
+[[package]]
+name = "typeid"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "unsafe-libyaml"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
+
+[[package]]
+name = "wasi"
+version = "0.11.1+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
+
+[[package]]
+name = "windows-link"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
+
+[[package]]
+name = "windows-sys"
+version = "0.61.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "winnow"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1"
+
+[[package]]
+name = "zmij"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
diff --git a/mingling_core/tests/test-all/Cargo.toml b/mingling_core/tests/test-all/Cargo.toml
new file mode 100644
index 0000000..9eea2de
--- /dev/null
+++ b/mingling_core/tests/test-all/Cargo.toml
@@ -0,0 +1,20 @@
+[package]
+name = "test-all"
+version = "0.1.0"
+edition = "2024"
+publish = false
+
+[workspace]
+
+[dependencies]
+mingling = { path = "../../../mingling", features = [
+ "general_renderer_full",
+ "comp",
+ "builds",
+ "repl",
+ "dispatch_tree",
+ "parser",
+ "extra_macros",
+] }
+tokio = { version = "1", features = ["full"] }
+serde = { version = "1", features = ["derive"] }
diff --git a/mingling_core/tests/test-all/tests/integration.rs b/mingling_core/tests/test-all/tests/integration.rs
new file mode 100644
index 0000000..f910729
--- /dev/null
+++ b/mingling_core/tests/test-all/tests/integration.rs
@@ -0,0 +1,235 @@
+use mingling::Flag;
+use mingling::GeneralRenderer;
+use mingling::GeneralRendererSetting;
+use mingling::Groupped;
+use mingling::NextProcess;
+use mingling::Node;
+use mingling::Program;
+use mingling::ProgramCollect;
+use mingling::RenderResult;
+use mingling::StringVec;
+use mingling::comp::{ShellContext, ShellFlag, Suggest};
+use mingling::core_res::ResREPL;
+use mingling::hook::ProgramHook;
+use serde::Serialize;
+use std::sync::atomic::{AtomicBool, Ordering};
+
+// MockCollect for is_completing tests
+
+#[derive(Debug, Clone, PartialEq)]
+struct MockCollect;
+
+impl Groupped<MockCollect> for MockCollect {
+ fn member_id() -> MockCollect {
+ MockCollect
+ }
+}
+
+impl ProgramCollect for MockCollect {
+ type Enum = MockCollect;
+ type ErrorDispatcherNotFound = MockCollect;
+ type ErrorRendererNotFound = MockCollect;
+ type ResultEmpty = MockCollect;
+
+ fn build_renderer_not_found(_member_id: MockCollect) -> mingling::AnyOutput<MockCollect> {
+ unimplemented!()
+ }
+ fn build_dispatcher_not_found(_args: Vec<String>) -> mingling::AnyOutput<MockCollect> {
+ unimplemented!()
+ }
+ fn build_empty_result() -> mingling::AnyOutput<MockCollect> {
+ unimplemented!()
+ }
+ fn render(_any: mingling::AnyOutput<MockCollect>, _r: &mut RenderResult) {
+ unimplemented!()
+ }
+ fn render_help(_any: mingling::AnyOutput<MockCollect>, _r: &mut RenderResult) {
+ unimplemented!()
+ }
+ fn do_chain(_any: mingling::AnyOutput<MockCollect>) -> mingling::ChainProcess<MockCollect> {
+ unimplemented!()
+ }
+ fn do_comp(_any: &mingling::AnyOutput<MockCollect>, _ctx: &ShellContext) -> Suggest {
+ unimplemented!()
+ }
+ fn has_renderer(_any: &mingling::AnyOutput<MockCollect>) -> bool {
+ unimplemented!()
+ }
+ fn has_chain(_any: &mingling::AnyOutput<MockCollect>) -> bool {
+ unimplemented!()
+ }
+
+ fn dispatch_args_trie(
+ _raw: &[String],
+ ) -> Result<mingling::AnyOutput<MockCollect>, mingling::error::ProgramInternalExecuteError>
+ {
+ unimplemented!()
+ }
+
+ fn get_nodes() -> Vec<(
+ String,
+ &'static (dyn mingling::Dispatcher<MockCollect> + Send + Sync),
+ )> {
+ unimplemented!()
+ }
+
+ fn general_render(
+ _any: mingling::AnyOutput<MockCollect>,
+ _setting: &GeneralRendererSetting,
+ ) -> Result<RenderResult, mingling::error::GeneralRendererSerializeError> {
+ unimplemented!()
+ }
+}
+
+// ShellContext
+
+#[test]
+fn test_shell_context_from_args() {
+ let ctx = ShellContext::try_from(vec![
+ "-f".to_string(),
+ "app greet".to_string(),
+ "-F".to_string(),
+ "zsh".to_string(),
+ ])
+ .unwrap();
+ assert!(matches!(ctx.shell_flag, ShellFlag::Zsh));
+ assert_eq!(ctx.all_words, vec!["app", "greet"]);
+}
+
+// Suggest
+
+#[test]
+fn test_suggest_creation() {
+ let s: Suggest = vec!["--help".to_string()].into();
+ assert!(matches!(s, Suggest::Suggest(_)));
+}
+
+// ResREPL
+
+#[test]
+fn test_res_repl_default() {
+ let res = ResREPL::default();
+ assert!(!res.exit);
+}
+
+// Node
+
+#[test]
+fn test_node_creation() {
+ let node = Node::from("a.b.c");
+ assert_eq!(node.to_string(), "a.b.c");
+}
+
+#[test]
+fn test_node_kebab() {
+ let node = Node::from("HelloWorld.FooBar");
+ assert_eq!(node.to_string(), "hello-world.foo-bar");
+}
+
+// Flag
+
+#[test]
+fn test_flag_conversion() {
+ let flag = Flag::from(["-h", "--help"]);
+ assert_eq!(flag.as_ref(), &["-h", "--help"]);
+}
+
+#[test]
+fn test_flag_empty() {
+ let flag = Flag::from(());
+ assert!(flag.is_empty());
+}
+
+// RenderResult
+
+#[test]
+fn test_render_result_default() {
+ let r = RenderResult::default();
+ assert!(r.is_empty());
+ assert_eq!(r.exit_code, 0);
+}
+
+#[test]
+fn test_render_result_print() {
+ let mut r = RenderResult::default();
+ r.print("hello");
+ assert_eq!(&*r, "hello");
+}
+
+// GeneralRenderer
+
+#[derive(Debug, Clone, PartialEq, Serialize)]
+struct TestData {
+ name: String,
+ value: i32,
+}
+
+#[test]
+fn test_general_renderer_disable() {
+ let data = TestData {
+ name: "test".into(),
+ value: 42,
+ };
+ let mut r = RenderResult::default();
+ let result = GeneralRenderer::render(&data, &GeneralRendererSetting::Disable, &mut r);
+ assert!(result.is_ok());
+ assert!(r.is_empty());
+}
+
+#[test]
+fn test_general_renderer_json() {
+ let data = TestData {
+ name: "test".into(),
+ value: 42,
+ };
+ let mut r = RenderResult::default();
+ let result = GeneralRenderer::render(&data, &GeneralRendererSetting::Json, &mut r);
+ assert!(result.is_ok());
+ assert!(!r.is_empty());
+}
+
+// is_completing
+
+#[test]
+fn test_is_completing() {
+ let program: Program<MockCollect> = Program::new_with_args(["app", "__comp"]);
+ assert!(program.is_completing());
+}
+
+#[test]
+fn test_is_not_completing() {
+ let program: Program<MockCollect> = Program::new_with_args(["app", "greet"]);
+ assert!(!program.is_completing());
+}
+
+// Hooks
+
+#[test]
+fn test_hook_setup() {
+ static CALLED: AtomicBool = AtomicBool::new(false);
+
+ let hook = ProgramHook::<MockCollect>::empty().on_begin(|| {
+ CALLED.store(true, Ordering::SeqCst);
+ });
+
+ assert!(hook.begin.is_some());
+ (hook.begin.unwrap())();
+ assert!(CALLED.load(Ordering::SeqCst));
+}
+
+// NextProcess
+
+#[test]
+fn test_next_process_display() {
+ assert_eq!(format!("{}", NextProcess::Chain), "Chain");
+ assert_eq!(format!("{}", NextProcess::Renderer), "Renderer");
+}
+
+// StringVec
+
+#[test]
+fn test_string_vec_from_array() {
+ let sv = StringVec::from(["a", "b", "c"]);
+ let v: Vec<String> = sv.into();
+ assert_eq!(v, vec!["a", "b", "c"]);
+}
diff --git a/mingling_core/tests/test-basic/Cargo.lock b/mingling_core/tests/test-basic/Cargo.lock
new file mode 100644
index 0000000..a5d9ab9
--- /dev/null
+++ b/mingling_core/tests/test-basic/Cargo.lock
@@ -0,0 +1,76 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "just_fmt"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5454cda0d57db59778608d7a47bff5b16c6705598265869fb052b657f66cf05e"
+
+[[package]]
+name = "mingling"
+version = "0.2.0"
+dependencies = [
+ "mingling_core",
+ "mingling_macros",
+]
+
+[[package]]
+name = "mingling_core"
+version = "0.2.0"
+dependencies = [
+ "just_fmt",
+]
+
+[[package]]
+name = "mingling_macros"
+version = "0.2.0"
+dependencies = [
+ "just_fmt",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "test-basic"
+version = "0.1.0"
+dependencies = [
+ "mingling",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
diff --git a/mingling_core/tests/test-basic/Cargo.toml b/mingling_core/tests/test-basic/Cargo.toml
new file mode 100644
index 0000000..7b326c1
--- /dev/null
+++ b/mingling_core/tests/test-basic/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "test-basic"
+version = "0.1.0"
+edition = "2024"
+publish = false
+
+[workspace]
+
+[dependencies]
+mingling = { path = "../../../mingling" }
diff --git a/mingling_core/tests/test-basic/tests/integration.rs b/mingling_core/tests/test-basic/tests/integration.rs
new file mode 100644
index 0000000..7cd7b8c
--- /dev/null
+++ b/mingling_core/tests/test-basic/tests/integration.rs
@@ -0,0 +1,93 @@
+use mingling::Flag;
+use mingling::NextProcess;
+use mingling::Node;
+use mingling::RenderResult;
+use mingling::StringVec;
+
+#[test]
+fn test_node_from_str() {
+ let node = Node::from("a.b.c");
+ assert_eq!(node.to_string(), "a.b.c");
+}
+
+#[test]
+fn test_node_kebab_case() {
+ let node = Node::from("HelloWorld.FooBar");
+ assert_eq!(node.to_string(), "hello-world.foo-bar");
+}
+
+#[test]
+fn test_node_join() {
+ let node = Node::from("base").join("sub");
+ assert_eq!(node.to_string(), "base.sub");
+}
+
+#[test]
+fn test_node_eq() {
+ let a = Node::from("x.y");
+ let b = Node::from("x.y");
+ let c = Node::from("x.z");
+ assert_eq!(a, b);
+ assert_ne!(a, c);
+}
+
+#[test]
+fn test_flag_from_static_str() {
+ let flag = Flag::from("-h");
+ assert_eq!(flag.as_ref(), &["-h"]);
+}
+
+#[test]
+fn test_flag_from_array() {
+ let flag = Flag::from(["-h", "--help"]);
+ assert_eq!(flag.as_ref(), &["-h", "--help"]);
+}
+
+#[test]
+fn test_flag_empty() {
+ let flag = Flag::from(());
+ assert!(flag.is_empty());
+}
+
+#[test]
+fn test_render_result_default() {
+ let r = RenderResult::default();
+ assert!(r.is_empty());
+ assert_eq!(r.exit_code, 0);
+}
+
+#[test]
+fn test_render_result_print() {
+ let mut r = RenderResult::default();
+ r.print("hello");
+ assert_eq!(&*r, "hello");
+}
+
+#[test]
+fn test_render_result_clear() {
+ let mut r = RenderResult::default();
+ r.print("data");
+ assert!(!r.is_empty());
+ r.clear();
+ assert!(r.is_empty());
+}
+
+#[test]
+fn test_next_process_display() {
+ assert_eq!(format!("{}", NextProcess::Chain), "Chain");
+ assert_eq!(format!("{}", NextProcess::Renderer), "Renderer");
+}
+
+#[test]
+fn test_string_vec_from_array() {
+ let sv = StringVec::from(["a", "b", "c"]);
+ let v: Vec<String> = sv.into();
+ assert_eq!(v, vec!["a", "b", "c"]);
+}
+
+#[test]
+fn test_string_vec_from_vec() {
+ let original = vec!["x".to_string(), "y".to_string()];
+ let sv = StringVec::from(original.clone());
+ assert_eq!(*sv, original);
+}
diff --git a/mingling_core/tests/test-comp/Cargo.lock b/mingling_core/tests/test-comp/Cargo.lock
new file mode 100644
index 0000000..ad384fe
--- /dev/null
+++ b/mingling_core/tests/test-comp/Cargo.lock
@@ -0,0 +1,86 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "just_fmt"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5454cda0d57db59778608d7a47bff5b16c6705598265869fb052b657f66cf05e"
+
+[[package]]
+name = "just_template"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db3edb658c34b10b69c4b3b58f7ba989cd09c82c0621dee1eef51843c2327225"
+dependencies = [
+ "just_fmt",
+]
+
+[[package]]
+name = "mingling"
+version = "0.2.0"
+dependencies = [
+ "mingling_core",
+ "mingling_macros",
+]
+
+[[package]]
+name = "mingling_core"
+version = "0.2.0"
+dependencies = [
+ "just_fmt",
+ "just_template",
+]
+
+[[package]]
+name = "mingling_macros"
+version = "0.2.0"
+dependencies = [
+ "just_fmt",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "test-comp"
+version = "0.1.0"
+dependencies = [
+ "mingling",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
diff --git a/mingling_core/tests/test-comp/Cargo.toml b/mingling_core/tests/test-comp/Cargo.toml
new file mode 100644
index 0000000..9ceca3e
--- /dev/null
+++ b/mingling_core/tests/test-comp/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "test-comp"
+version = "0.1.0"
+edition = "2024"
+publish = false
+
+[workspace]
+
+[dependencies]
+mingling = { path = "../../../mingling", features = ["comp", "builds"] }
diff --git a/mingling_core/tests/test-comp/tests/integration.rs b/mingling_core/tests/test-comp/tests/integration.rs
new file mode 100644
index 0000000..4e6455e
--- /dev/null
+++ b/mingling_core/tests/test-comp/tests/integration.rs
@@ -0,0 +1,123 @@
+use mingling::Groupped;
+use mingling::Program;
+use mingling::ProgramCollect;
+use mingling::RenderResult;
+use mingling::comp::{ShellContext, ShellFlag, Suggest, SuggestItem};
+
+/// Minimal mock collector that satisfies `C: ProgramCollect<Enum = C>`
+/// by setting `Enum = Self`.
+#[derive(Debug, Clone, PartialEq)]
+struct MockCollect;
+
+impl Groupped<MockCollect> for MockCollect {
+ fn member_id() -> MockCollect {
+ MockCollect
+ }
+}
+
+impl ProgramCollect for MockCollect {
+ type Enum = MockCollect;
+ type ErrorDispatcherNotFound = MockCollect;
+ type ErrorRendererNotFound = MockCollect;
+ type ResultEmpty = MockCollect;
+
+ fn build_renderer_not_found(_member_id: MockCollect) -> mingling::AnyOutput<MockCollect> {
+ unimplemented!()
+ }
+ fn build_dispatcher_not_found(_args: Vec<String>) -> mingling::AnyOutput<MockCollect> {
+ unimplemented!()
+ }
+ fn build_empty_result() -> mingling::AnyOutput<MockCollect> {
+ unimplemented!()
+ }
+ fn render(_any: mingling::AnyOutput<MockCollect>, _r: &mut RenderResult) {
+ unimplemented!()
+ }
+ fn render_help(_any: mingling::AnyOutput<MockCollect>, _r: &mut RenderResult) {
+ unimplemented!()
+ }
+ fn do_chain(_any: mingling::AnyOutput<MockCollect>) -> mingling::ChainProcess<MockCollect> {
+ unimplemented!()
+ }
+ fn do_comp(_any: &mingling::AnyOutput<MockCollect>, _ctx: &ShellContext) -> Suggest {
+ unimplemented!()
+ }
+ fn has_renderer(_any: &mingling::AnyOutput<MockCollect>) -> bool {
+ unimplemented!()
+ }
+ fn has_chain(_any: &mingling::AnyOutput<MockCollect>) -> bool {
+ unimplemented!()
+ }
+}
+
+#[test]
+fn test_shell_context_parsing_full() {
+ let args = vec![
+ "-f".to_string(),
+ "myapp hello ^world".to_string(),
+ "-C".to_string(),
+ "14".to_string(),
+ "-w".to_string(),
+ "hello".to_string(),
+ "-p".to_string(),
+ "myapp".to_string(),
+ "-c".to_string(),
+ "myapp".to_string(),
+ "-i".to_string(),
+ "1".to_string(),
+ "-F".to_string(),
+ "bash".to_string(),
+ ];
+ let ctx = ShellContext::try_from(args).unwrap();
+ assert_eq!(ctx.command_line, "myapp hello -world");
+ assert_eq!(ctx.cursor_position, 14);
+ assert_eq!(ctx.current_word, "hello");
+ assert_eq!(ctx.previous_word, "myapp");
+ assert_eq!(ctx.command_name, "myapp");
+ assert_eq!(ctx.word_index, 1);
+ assert!(matches!(ctx.shell_flag, ShellFlag::Bash));
+}
+
+#[test]
+fn test_shell_context_parsing_empty() {
+ let ctx = ShellContext::try_from(vec![]).unwrap();
+ assert!(ctx.all_words.is_empty());
+ assert!(matches!(ctx.shell_flag, ShellFlag::Other(_)));
+}
+
+#[test]
+fn test_suggest_from_vec() {
+ let s: Suggest = vec!["--help".to_string(), "--version".to_string()].into();
+ match &s {
+ Suggest::Suggest(items) => {
+ assert_eq!(items.len(), 2);
+ }
+ _ => panic!("expected Suggest::Suggest"),
+ }
+}
+
+#[test]
+fn test_suggest_item_new() {
+ let item = SuggestItem::new("hello".to_string());
+ assert_eq!(item.suggest(), "hello");
+ assert!(item.description().is_none());
+}
+
+#[test]
+fn test_suggest_item_with_description() {
+ let item = SuggestItem::new_with_desc("hello".to_string(), "a greeting".to_string());
+ assert_eq!(item.suggest(), "hello");
+ assert_eq!(item.description(), Some(&"a greeting".to_string()));
+}
+
+#[test]
+fn test_program_is_completing() {
+ let program: Program<MockCollect> = Program::new_with_args(["myapp", "__comp", "hello", ""]);
+ assert!(program.is_completing());
+}
+
+#[test]
+fn test_program_is_not_completing() {
+ let program: Program<MockCollect> = Program::new_with_args(["myapp", "hello"]);
+ assert!(!program.is_completing());
+}
diff --git a/mingling_core/tests/test-dispatch-tree/Cargo.lock b/mingling_core/tests/test-dispatch-tree/Cargo.lock
new file mode 100644
index 0000000..be5b922
--- /dev/null
+++ b/mingling_core/tests/test-dispatch-tree/Cargo.lock
@@ -0,0 +1,76 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "just_fmt"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5454cda0d57db59778608d7a47bff5b16c6705598265869fb052b657f66cf05e"
+
+[[package]]
+name = "mingling"
+version = "0.2.0"
+dependencies = [
+ "mingling_core",
+ "mingling_macros",
+]
+
+[[package]]
+name = "mingling_core"
+version = "0.2.0"
+dependencies = [
+ "just_fmt",
+]
+
+[[package]]
+name = "mingling_macros"
+version = "0.2.0"
+dependencies = [
+ "just_fmt",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "test-dispatch-tree"
+version = "0.1.0"
+dependencies = [
+ "mingling",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
diff --git a/mingling_core/tests/test-dispatch-tree/Cargo.toml b/mingling_core/tests/test-dispatch-tree/Cargo.toml
new file mode 100644
index 0000000..bb94292
--- /dev/null
+++ b/mingling_core/tests/test-dispatch-tree/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "test-dispatch-tree"
+version = "0.1.0"
+edition = "2024"
+publish = false
+
+[workspace]
+
+[dependencies]
+mingling = { path = "../../../mingling", features = ["dispatch_tree"] }
diff --git a/mingling_core/tests/test-dispatch-tree/tests/integration.rs b/mingling_core/tests/test-dispatch-tree/tests/integration.rs
new file mode 100644
index 0000000..7cd7b8c
--- /dev/null
+++ b/mingling_core/tests/test-dispatch-tree/tests/integration.rs
@@ -0,0 +1,93 @@
+use mingling::Flag;
+use mingling::NextProcess;
+use mingling::Node;
+use mingling::RenderResult;
+use mingling::StringVec;
+
+#[test]
+fn test_node_from_str() {
+ let node = Node::from("a.b.c");
+ assert_eq!(node.to_string(), "a.b.c");
+}
+
+#[test]
+fn test_node_kebab_case() {
+ let node = Node::from("HelloWorld.FooBar");
+ assert_eq!(node.to_string(), "hello-world.foo-bar");
+}
+
+#[test]
+fn test_node_join() {
+ let node = Node::from("base").join("sub");
+ assert_eq!(node.to_string(), "base.sub");
+}
+
+#[test]
+fn test_node_eq() {
+ let a = Node::from("x.y");
+ let b = Node::from("x.y");
+ let c = Node::from("x.z");
+ assert_eq!(a, b);
+ assert_ne!(a, c);
+}
+
+#[test]
+fn test_flag_from_static_str() {
+ let flag = Flag::from("-h");
+ assert_eq!(flag.as_ref(), &["-h"]);
+}
+
+#[test]
+fn test_flag_from_array() {
+ let flag = Flag::from(["-h", "--help"]);
+ assert_eq!(flag.as_ref(), &["-h", "--help"]);
+}
+
+#[test]
+fn test_flag_empty() {
+ let flag = Flag::from(());
+ assert!(flag.is_empty());
+}
+
+#[test]
+fn test_render_result_default() {
+ let r = RenderResult::default();
+ assert!(r.is_empty());
+ assert_eq!(r.exit_code, 0);
+}
+
+#[test]
+fn test_render_result_print() {
+ let mut r = RenderResult::default();
+ r.print("hello");
+ assert_eq!(&*r, "hello");
+}
+
+#[test]
+fn test_render_result_clear() {
+ let mut r = RenderResult::default();
+ r.print("data");
+ assert!(!r.is_empty());
+ r.clear();
+ assert!(r.is_empty());
+}
+
+#[test]
+fn test_next_process_display() {
+ assert_eq!(format!("{}", NextProcess::Chain), "Chain");
+ assert_eq!(format!("{}", NextProcess::Renderer), "Renderer");
+}
+
+#[test]
+fn test_string_vec_from_array() {
+ let sv = StringVec::from(["a", "b", "c"]);
+ let v: Vec<String> = sv.into();
+ assert_eq!(v, vec!["a", "b", "c"]);
+}
+
+#[test]
+fn test_string_vec_from_vec() {
+ let original = vec!["x".to_string(), "y".to_string()];
+ let sv = StringVec::from(original.clone());
+ assert_eq!(*sv, original);
+}
diff --git a/mingling_core/tests/test-general-renderer/Cargo.lock b/mingling_core/tests/test-general-renderer/Cargo.lock
new file mode 100644
index 0000000..7c4b628
--- /dev/null
+++ b/mingling_core/tests/test-general-renderer/Cargo.lock
@@ -0,0 +1,287 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "bitflags"
+version = "2.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+
+[[package]]
+name = "hashbrown"
+version = "0.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
+
+[[package]]
+name = "indexmap"
+version = "2.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
+
+[[package]]
+name = "just_fmt"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5454cda0d57db59778608d7a47bff5b16c6705598265869fb052b657f66cf05e"
+
+[[package]]
+name = "memchr"
+version = "2.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
+
+[[package]]
+name = "mingling"
+version = "0.2.0"
+dependencies = [
+ "mingling_core",
+ "mingling_macros",
+ "serde",
+ "size",
+]
+
+[[package]]
+name = "mingling_core"
+version = "0.2.0"
+dependencies = [
+ "just_fmt",
+ "ron",
+ "serde",
+ "serde_json",
+ "serde_yaml",
+ "toml",
+]
+
+[[package]]
+name = "mingling_macros"
+version = "0.2.0"
+dependencies = [
+ "just_fmt",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.21.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "ron"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4147b952f3f819eca0e99527022f7d6a8d05f111aeb0a62960c74eb283bec8fc"
+dependencies = [
+ "bitflags",
+ "once_cell",
+ "serde",
+ "serde_derive",
+ "typeid",
+ "unicode-ident",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
+
+[[package]]
+name = "serde"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
+dependencies = [
+ "serde_core",
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_core"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.150"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
+dependencies = [
+ "itoa",
+ "memchr",
+ "serde",
+ "serde_core",
+ "zmij",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "serde_yaml"
+version = "0.9.34+deprecated"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
+dependencies = [
+ "indexmap",
+ "itoa",
+ "ryu",
+ "serde",
+ "unsafe-libyaml",
+]
+
+[[package]]
+name = "size"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b6709c7b6754dca1311b3c73e79fcce40dd414c782c66d88e8823030093b02b"
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "test-general-renderer"
+version = "0.1.0"
+dependencies = [
+ "mingling",
+ "serde",
+]
+
+[[package]]
+name = "toml"
+version = "1.1.2+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee"
+dependencies = [
+ "indexmap",
+ "serde_core",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_parser",
+ "toml_writer",
+ "winnow",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "1.1.1+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "toml_parser"
+version = "1.1.2+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
+dependencies = [
+ "winnow",
+]
+
+[[package]]
+name = "toml_writer"
+version = "1.1.1+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db"
+
+[[package]]
+name = "typeid"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "unsafe-libyaml"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
+
+[[package]]
+name = "winnow"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1"
+
+[[package]]
+name = "zmij"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
diff --git a/mingling_core/tests/test-general-renderer/Cargo.toml b/mingling_core/tests/test-general-renderer/Cargo.toml
new file mode 100644
index 0000000..3d038aa
--- /dev/null
+++ b/mingling_core/tests/test-general-renderer/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "test-general-renderer"
+version = "0.1.0"
+edition = "2024"
+publish = false
+
+[workspace]
+
+[dependencies]
+mingling = { path = "../../../mingling", features = ["general_renderer_full", "parser"] }
+serde = { version = "1", features = ["derive"] }
diff --git a/mingling_core/tests/test-general-renderer/tests/integration.rs b/mingling_core/tests/test-general-renderer/tests/integration.rs
new file mode 100644
index 0000000..0fcc38d
--- /dev/null
+++ b/mingling_core/tests/test-general-renderer/tests/integration.rs
@@ -0,0 +1,77 @@
+use mingling::GeneralRenderer;
+use mingling::GeneralRendererSetting;
+use mingling::RenderResult;
+use serde::Serialize;
+
+#[derive(Debug, Clone, PartialEq, Serialize)]
+struct TestData {
+ name: String,
+ value: i32,
+}
+
+fn test_data() -> TestData {
+ TestData {
+ name: "test".into(),
+ value: 42,
+ }
+}
+
+#[test]
+fn test_render_disable() {
+ let mut r = RenderResult::default();
+ let result = GeneralRenderer::render(&test_data(), &GeneralRendererSetting::Disable, &mut r);
+ assert!(result.is_ok());
+ assert!(r.is_empty());
+}
+
+#[test]
+fn test_render_json() {
+ let mut r = RenderResult::default();
+ let result = GeneralRenderer::render(&test_data(), &GeneralRendererSetting::Json, &mut r);
+ assert!(result.is_ok());
+ assert!(!r.is_empty());
+ let output: String = r.into();
+ assert!(output.contains("\"name\""));
+ assert!(output.contains("\"test\""));
+ assert!(output.contains("\"value\""));
+ assert!(output.contains("42"));
+}
+
+#[test]
+fn test_render_yaml() {
+ let mut r = RenderResult::default();
+ let result = GeneralRenderer::render(&test_data(), &GeneralRendererSetting::Yaml, &mut r);
+ assert!(result.is_ok());
+ assert!(!r.is_empty());
+ let output: String = r.into();
+ assert!(output.contains("name:"));
+ assert!(output.contains("test"));
+ assert!(output.contains("value:"));
+ assert!(output.contains("42"));
+}
+
+#[test]
+fn test_render_toml() {
+ let mut r = RenderResult::default();
+ let result = GeneralRenderer::render(&test_data(), &GeneralRendererSetting::Toml, &mut r);
+ assert!(result.is_ok());
+ assert!(!r.is_empty());
+ let output: String = r.into();
+ assert!(output.contains("name = "));
+ assert!(output.contains("test"));
+ assert!(output.contains("value = "));
+ assert!(output.contains("42"));
+}
+
+#[test]
+fn test_render_ron() {
+ let mut r = RenderResult::default();
+ let result = GeneralRenderer::render(&test_data(), &GeneralRendererSetting::Ron, &mut r);
+ assert!(result.is_ok());
+ assert!(!r.is_empty());
+ let output: String = r.into();
+ assert!(output.contains("name:"));
+ assert!(output.contains("\"test\""));
+ assert!(output.contains("value:"));
+ assert!(output.contains("42"));
+}
diff --git a/mingling_core/tests/test-repl/Cargo.lock b/mingling_core/tests/test-repl/Cargo.lock
new file mode 100644
index 0000000..0950248
--- /dev/null
+++ b/mingling_core/tests/test-repl/Cargo.lock
@@ -0,0 +1,76 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "just_fmt"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5454cda0d57db59778608d7a47bff5b16c6705598265869fb052b657f66cf05e"
+
+[[package]]
+name = "mingling"
+version = "0.2.0"
+dependencies = [
+ "mingling_core",
+ "mingling_macros",
+]
+
+[[package]]
+name = "mingling_core"
+version = "0.2.0"
+dependencies = [
+ "just_fmt",
+]
+
+[[package]]
+name = "mingling_macros"
+version = "0.2.0"
+dependencies = [
+ "just_fmt",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "test-repl"
+version = "0.1.0"
+dependencies = [
+ "mingling",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
diff --git a/mingling_core/tests/test-repl/Cargo.toml b/mingling_core/tests/test-repl/Cargo.toml
new file mode 100644
index 0000000..c4c83ce
--- /dev/null
+++ b/mingling_core/tests/test-repl/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "test-repl"
+version = "0.1.0"
+edition = "2024"
+publish = false
+
+[workspace]
+
+[dependencies]
+mingling = { path = "../../../mingling", features = ["repl", "extra_macros"] }
diff --git a/mingling_core/tests/test-repl/tests/integration.rs b/mingling_core/tests/test-repl/tests/integration.rs
new file mode 100644
index 0000000..1792525
--- /dev/null
+++ b/mingling_core/tests/test-repl/tests/integration.rs
@@ -0,0 +1,63 @@
+use mingling::Flag;
+use mingling::Node;
+use mingling::RenderResult;
+use mingling::core_res::ResREPL;
+
+// ResREPL tests
+
+#[test]
+fn test_res_repl_default_exit_false() {
+ let res = ResREPL::default();
+ assert!(!res.exit);
+}
+
+#[test]
+fn test_res_repl_exit_true() {
+ let mut res = ResREPL::default();
+ res.exit = true;
+ assert!(res.exit);
+}
+
+// Node tests
+
+#[test]
+fn test_node_from_str() {
+ let node = Node::from("a.b.c");
+ assert_eq!(node.to_string(), "a.b.c");
+}
+
+#[test]
+fn test_node_kebab_case() {
+ let node = Node::from("HelloWorld.FooBar");
+ assert_eq!(node.to_string(), "hello-world.foo-bar");
+}
+
+// Flag tests
+
+#[test]
+fn test_flag_from_static_str() {
+ let flag = Flag::from("-h");
+ assert_eq!(flag.as_ref(), &["-h"]);
+}
+
+#[test]
+fn test_flag_empty() {
+ let flag = Flag::from(());
+ assert!(flag.is_empty());
+}
+
+// RenderResult tests
+
+#[test]
+fn test_render_result_default() {
+ let r = RenderResult::default();
+ assert!(r.is_empty());
+ assert_eq!(r.exit_code, 0);
+}
+
+#[test]
+fn test_render_result_print() {
+ let mut r = RenderResult::default();
+ r.print("hello");
+ assert_eq!(&*r, "hello");
+}