From 2ae4408ced2e813d269dde4f848951d563fff837 Mon Sep 17 00:00:00 2001 From: Devyn Cairns Date: Mon, 25 Mar 2024 19:20:35 -0700 Subject: [PATCH] Add example tests (nu-plugin-test-support) for plugins in repo (#12281) # Description Uses the new `nu-plugin-test-support` crate to test the examples of commands provided by plugins in the repo. Also fixed some of the examples to pass. # User-Facing Changes - Examples that are more guaranteed to work # Tests + Formatting - :green_circle: `toolkit fmt` - :green_circle: `toolkit clippy` - :green_circle: `toolkit test` - :green_circle: `toolkit test stdlib` --- Cargo.lock | 4 ++++ crates/nu-plugin-test-support/src/plugin_test.rs | 13 +++++++++++++ crates/nu_plugin_custom_values/Cargo.toml | 3 +++ crates/nu_plugin_custom_values/src/generate.rs | 8 ++++++++ crates/nu_plugin_custom_values/src/generate2.rs | 8 ++++++++ .../src/second_custom_value.rs | 14 +++++++++++++- crates/nu_plugin_custom_values/src/update.rs | 12 ++++++++++-- crates/nu_plugin_example/Cargo.toml | 4 ++++ .../src/commands/collect_external.rs | 6 ++++++ crates/nu_plugin_example/src/commands/for_each.rs | 6 ++++++ crates/nu_plugin_example/src/commands/generate.rs | 9 +++++++++ crates/nu_plugin_example/src/commands/one.rs | 6 ++++++ crates/nu_plugin_example/src/commands/seq.rs | 6 ++++++ crates/nu_plugin_example/src/commands/sum.rs | 8 +++++++- crates/nu_plugin_formats/Cargo.toml | 3 +++ crates/nu_plugin_formats/src/from/eml.rs | 9 +++++++++ crates/nu_plugin_formats/src/from/ics.rs | 12 ++++++++++-- crates/nu_plugin_formats/src/from/ini.rs | 7 +++++++ crates/nu_plugin_formats/src/from/vcf.rs | 7 +++++++ 19 files changed, 139 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3d106123ab..93bd02d3fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3214,6 +3214,7 @@ name = "nu_plugin_custom_values" version = "0.1.0" dependencies = [ "nu-plugin", + "nu-plugin-test-support", "nu-protocol", "serde", "typetag", @@ -3223,7 +3224,9 @@ dependencies = [ name = "nu_plugin_example" version = "0.91.1" dependencies = [ + "nu-cmd-lang", "nu-plugin", + "nu-plugin-test-support", "nu-protocol", ] @@ -3235,6 +3238,7 @@ dependencies = [ "ical", "indexmap", "nu-plugin", + "nu-plugin-test-support", "nu-protocol", "rust-ini", ] diff --git a/crates/nu-plugin-test-support/src/plugin_test.rs b/crates/nu-plugin-test-support/src/plugin_test.rs index f0a53c8bd5..9ce67a083c 100644 --- a/crates/nu-plugin-test-support/src/plugin_test.rs +++ b/crates/nu-plugin-test-support/src/plugin_test.rs @@ -61,6 +61,19 @@ impl PluginTest { &mut self.engine_state } + /// Make additional command declarations available for use by tests. + /// + /// This can be used to pull in commands from `nu-cmd-lang` for example, as required. + pub fn add_decl( + &mut self, + decl: Box, + ) -> Result<&mut Self, ShellError> { + let mut working_set = StateWorkingSet::new(&self.engine_state); + working_set.add_decl(decl); + self.engine_state.merge_delta(working_set.render())?; + Ok(self) + } + /// Evaluate some Nushell source code with the plugin commands in scope with the given input to /// the pipeline. /// diff --git a/crates/nu_plugin_custom_values/Cargo.toml b/crates/nu_plugin_custom_values/Cargo.toml index 548e84c5ff..3b0041c08f 100644 --- a/crates/nu_plugin_custom_values/Cargo.toml +++ b/crates/nu_plugin_custom_values/Cargo.toml @@ -14,3 +14,6 @@ nu-plugin = { path = "../nu-plugin", version = "0.91.1" } nu-protocol = { path = "../nu-protocol", version = "0.91.1", features = ["plugin"] } serde = { workspace = true, default-features = false } typetag = "0.2" + +[dev-dependencies] +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.91.1" } diff --git a/crates/nu_plugin_custom_values/src/generate.rs b/crates/nu_plugin_custom_values/src/generate.rs index 814551ec51..d62a05ecc3 100644 --- a/crates/nu_plugin_custom_values/src/generate.rs +++ b/crates/nu_plugin_custom_values/src/generate.rs @@ -29,3 +29,11 @@ impl SimplePluginCommand for Generate { Ok(CoolCustomValue::new("abc").into_value(call.head)) } } + +#[test] +fn test_examples() -> Result<(), nu_protocol::ShellError> { + use nu_plugin_test_support::PluginTest; + + PluginTest::new("custom_values", crate::CustomValuePlugin.into())? + .test_command_examples(&Generate) +} diff --git a/crates/nu_plugin_custom_values/src/generate2.rs b/crates/nu_plugin_custom_values/src/generate2.rs index 951de152bc..dbc1f88291 100644 --- a/crates/nu_plugin_custom_values/src/generate2.rs +++ b/crates/nu_plugin_custom_values/src/generate2.rs @@ -54,3 +54,11 @@ impl SimplePluginCommand for Generate2 { } } } + +#[test] +fn test_examples() -> Result<(), nu_protocol::ShellError> { + use nu_plugin_test_support::PluginTest; + + PluginTest::new("custom_values", crate::CustomValuePlugin.into())? + .test_command_examples(&Generate2) +} diff --git a/crates/nu_plugin_custom_values/src/second_custom_value.rs b/crates/nu_plugin_custom_values/src/second_custom_value.rs index 3c9fc39f34..a9c3bb7488 100644 --- a/crates/nu_plugin_custom_values/src/second_custom_value.rs +++ b/crates/nu_plugin_custom_values/src/second_custom_value.rs @@ -1,7 +1,9 @@ +use std::cmp::Ordering; + use nu_protocol::{CustomValue, ShellError, Span, Value}; use serde::{Deserialize, Serialize}; -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub struct SecondCustomValue { pub(crate) something: String, } @@ -59,6 +61,16 @@ impl CustomValue for SecondCustomValue { )) } + fn partial_cmp(&self, other: &Value) -> Option { + if let Value::CustomValue { val, .. } = other { + val.as_any() + .downcast_ref() + .and_then(|other: &SecondCustomValue| PartialOrd::partial_cmp(self, other)) + } else { + None + } + } + fn as_any(&self) -> &dyn std::any::Any { self } diff --git a/crates/nu_plugin_custom_values/src/update.rs b/crates/nu_plugin_custom_values/src/update.rs index 7344a97d87..bcdb4d6649 100644 --- a/crates/nu_plugin_custom_values/src/update.rs +++ b/crates/nu_plugin_custom_values/src/update.rs @@ -23,9 +23,9 @@ impl SimplePluginCommand for Update { result: Some(CoolCustomValue::new("abcxyz").into_value(Span::test_data())), }, PluginExample { - example: "custom-value generate | custom-value update".into(), + example: "custom-value generate2 | custom-value update".into(), description: "Update a SecondCustomValue".into(), - result: Some(CoolCustomValue::new("xyzabc").into_value(Span::test_data())), + result: Some(SecondCustomValue::new("xyzabc").into_value(Span::test_data())), }, ]) } @@ -56,3 +56,11 @@ impl SimplePluginCommand for Update { .into()) } } + +#[test] +fn test_examples() -> Result<(), nu_protocol::ShellError> { + use nu_plugin_test_support::PluginTest; + + PluginTest::new("custom_values", crate::CustomValuePlugin.into())? + .test_command_examples(&Update) +} diff --git a/crates/nu_plugin_example/Cargo.toml b/crates/nu_plugin_example/Cargo.toml index 8a93244acb..bc6e463452 100644 --- a/crates/nu_plugin_example/Cargo.toml +++ b/crates/nu_plugin_example/Cargo.toml @@ -17,3 +17,7 @@ bench = false [dependencies] nu-plugin = { path = "../nu-plugin", version = "0.91.1" } nu-protocol = { path = "../nu-protocol", version = "0.91.1", features = ["plugin"] } + +[dev-dependencies] +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.91.1" } +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.91.1" } diff --git a/crates/nu_plugin_example/src/commands/collect_external.rs b/crates/nu_plugin_example/src/commands/collect_external.rs index b1fd7b4b1f..8ab70bdd9e 100644 --- a/crates/nu_plugin_example/src/commands/collect_external.rs +++ b/crates/nu_plugin_example/src/commands/collect_external.rs @@ -51,3 +51,9 @@ impl PluginCommand for CollectExternal { }) } } + +#[test] +fn test_examples() -> Result<(), nu_protocol::ShellError> { + use nu_plugin_test_support::PluginTest; + PluginTest::new("example", Example.into())?.test_command_examples(&CollectExternal) +} diff --git a/crates/nu_plugin_example/src/commands/for_each.rs b/crates/nu_plugin_example/src/commands/for_each.rs index 6e289613b9..3395ab02ce 100644 --- a/crates/nu_plugin_example/src/commands/for_each.rs +++ b/crates/nu_plugin_example/src/commands/for_each.rs @@ -45,3 +45,9 @@ impl PluginCommand for ForEach { Ok(PipelineData::Empty) } } + +#[test] +fn test_examples() -> Result<(), nu_protocol::ShellError> { + use nu_plugin_test_support::PluginTest; + PluginTest::new("example", Example.into())?.test_command_examples(&ForEach) +} diff --git a/crates/nu_plugin_example/src/commands/generate.rs b/crates/nu_plugin_example/src/commands/generate.rs index 5b7495dda2..011311ce9a 100644 --- a/crates/nu_plugin_example/src/commands/generate.rs +++ b/crates/nu_plugin_example/src/commands/generate.rs @@ -76,3 +76,12 @@ impl PluginCommand for Generate { .into_pipeline_data(None)) } } + +#[test] +fn test_examples() -> Result<(), nu_protocol::ShellError> { + use nu_cmd_lang::If; + use nu_plugin_test_support::PluginTest; + PluginTest::new("example", Example.into())? + .add_decl(Box::new(If))? + .test_command_examples(&Generate) +} diff --git a/crates/nu_plugin_example/src/commands/one.rs b/crates/nu_plugin_example/src/commands/one.rs index 27a35914db..dcf5951f67 100644 --- a/crates/nu_plugin_example/src/commands/one.rs +++ b/crates/nu_plugin_example/src/commands/one.rs @@ -41,3 +41,9 @@ impl SimplePluginCommand for One { Ok(Value::nothing(call.head)) } } + +#[test] +fn test_examples() -> Result<(), nu_protocol::ShellError> { + use nu_plugin_test_support::PluginTest; + PluginTest::new("example", Example.into())?.test_command_examples(&One) +} diff --git a/crates/nu_plugin_example/src/commands/seq.rs b/crates/nu_plugin_example/src/commands/seq.rs index 1b90ef7ba0..db48a35ebc 100644 --- a/crates/nu_plugin_example/src/commands/seq.rs +++ b/crates/nu_plugin_example/src/commands/seq.rs @@ -46,3 +46,9 @@ impl PluginCommand for Seq { Ok(PipelineData::ListStream(list_stream, None)) } } + +#[test] +fn test_examples() -> Result<(), nu_protocol::ShellError> { + use nu_plugin_test_support::PluginTest; + PluginTest::new("example", Example.into())?.test_command_examples(&Seq) +} diff --git a/crates/nu_plugin_example/src/commands/sum.rs b/crates/nu_plugin_example/src/commands/sum.rs index dafce1edfc..8a6b0601f0 100644 --- a/crates/nu_plugin_example/src/commands/sum.rs +++ b/crates/nu_plugin_example/src/commands/sum.rs @@ -20,7 +20,7 @@ impl PluginCommand for Sum { (Type::List(Type::Float.into()), Type::Float), ]) .plugin_examples(vec![PluginExample { - example: "seq 1 5 | example sum".into(), + example: "example seq 1 5 | example sum".into(), description: "sum values from 1 to 5".into(), result: Some(Value::test_int(15)), }]) @@ -88,3 +88,9 @@ impl IntOrFloat { } } } + +#[test] +fn test_examples() -> Result<(), nu_protocol::ShellError> { + use nu_plugin_test_support::PluginTest; + PluginTest::new("example", Example.into())?.test_command_examples(&Sum) +} diff --git a/crates/nu_plugin_formats/Cargo.toml b/crates/nu_plugin_formats/Cargo.toml index bdb9c9642f..82b0423b32 100644 --- a/crates/nu_plugin_formats/Cargo.toml +++ b/crates/nu_plugin_formats/Cargo.toml @@ -16,3 +16,6 @@ indexmap = { workspace = true } eml-parser = "0.1" ical = "0.10" rust-ini = "0.20.0" + +[dev-dependencies] +nu-plugin-test-support = { path = "../nu-plugin-test-support", version = "0.91.1" } diff --git a/crates/nu_plugin_formats/src/from/eml.rs b/crates/nu_plugin_formats/src/from/eml.rs index 427be71ecc..fe4c51e463 100644 --- a/crates/nu_plugin_formats/src/from/eml.rs +++ b/crates/nu_plugin_formats/src/from/eml.rs @@ -53,6 +53,7 @@ pub fn examples() -> Vec { example: "'From: test@email.com Subject: Welcome To: someone@somewhere.com + Test' | from eml" .into(), result: Some(Value::test_record(record! { @@ -73,6 +74,7 @@ Test' | from eml" example: "'From: test@email.com Subject: Welcome To: someone@somewhere.com + Test' | from eml -b 1" .into(), result: Some(Value::test_record(record! { @@ -164,3 +166,10 @@ fn from_eml(input: &Value, body_preview: usize, head: Span) -> Result Result<(), nu_protocol::ShellError> { + use nu_plugin_test_support::PluginTest; + + PluginTest::new("formats", crate::FromCmds.into())?.test_command_examples(&FromEml) +} diff --git a/crates/nu_plugin_formats/src/from/ics.rs b/crates/nu_plugin_formats/src/from/ics.rs index d0b77daaf3..2447f6eb52 100644 --- a/crates/nu_plugin_formats/src/from/ics.rs +++ b/crates/nu_plugin_formats/src/from/ics.rs @@ -75,8 +75,9 @@ impl SimplePluginCommand for FromIcs { pub fn examples() -> Vec { vec![PluginExample { - example: "'BEGIN:VCALENDAR - END:VCALENDAR' | from ics" + example: " +'BEGIN:VCALENDAR +END:VCALENDAR' | from ics" .into(), description: "Converts ics formatted string to table".into(), result: Some(Value::test_list(vec![Value::test_record(record! { @@ -263,3 +264,10 @@ fn params_to_value(params: Vec<(String, Vec)>, span: Span) -> Value { Value::record(row.into_iter().collect(), span) } + +#[test] +fn test_examples() -> Result<(), nu_protocol::ShellError> { + use nu_plugin_test_support::PluginTest; + + PluginTest::new("formats", crate::FromCmds.into())?.test_command_examples(&FromIcs) +} diff --git a/crates/nu_plugin_formats/src/from/ini.rs b/crates/nu_plugin_formats/src/from/ini.rs index 1f7957bb9a..ae0ef46a9c 100644 --- a/crates/nu_plugin_formats/src/from/ini.rs +++ b/crates/nu_plugin_formats/src/from/ini.rs @@ -89,3 +89,10 @@ b=2' | from ini" })), }] } + +#[test] +fn test_examples() -> Result<(), nu_protocol::ShellError> { + use nu_plugin_test_support::PluginTest; + + PluginTest::new("formats", crate::FromCmds.into())?.test_command_examples(&FromIni) +} diff --git a/crates/nu_plugin_formats/src/from/vcf.rs b/crates/nu_plugin_formats/src/from/vcf.rs index 41851878fc..47973f8ec0 100644 --- a/crates/nu_plugin_formats/src/from/vcf.rs +++ b/crates/nu_plugin_formats/src/from/vcf.rs @@ -153,3 +153,10 @@ fn params_to_value(params: Vec<(String, Vec)>, span: Span) -> Value { Value::record(row.into_iter().collect(), span) } + +#[test] +fn test_examples() -> Result<(), nu_protocol::ShellError> { + use nu_plugin_test_support::PluginTest; + + PluginTest::new("formats", crate::FromCmds.into())?.test_command_examples(&FromVcf) +}