summaryrefslogtreecommitdiff
path: root/src/bindings.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bindings.rs')
-rw-r--r--src/bindings.rs131
1 files changed, 102 insertions, 29 deletions
diff --git a/src/bindings.rs b/src/bindings.rs
index 40ef0b4..9d80394 100644
--- a/src/bindings.rs
+++ b/src/bindings.rs
@@ -5,12 +5,13 @@ use super::StepKind;
use crate::{Result, SubplotError};
use serde::Deserialize;
+use serde_aux::prelude::*;
use std::fs::File;
use std::io::Read;
use std::path::Path;
-use regex::{escape, Regex};
+use regex::{escape, Regex, RegexBuilder};
/// A binding of a scenario step to its implementation.
///
@@ -33,11 +34,15 @@ impl Binding {
pattern: &str,
function: &str,
cleanup: Option<&str>,
+ case_sensitive: bool,
) -> Result<Binding> {
+ let regex = RegexBuilder::new(&format!("^{}$", pattern))
+ .case_insensitive(!case_sensitive)
+ .build()?;
Ok(Binding {
kind,
pattern: pattern.to_owned(),
- regex: Regex::new(&format!("^{}$", pattern))?,
+ regex,
function: function.to_string(),
cleanup: cleanup.map(String::from),
})
@@ -149,7 +154,7 @@ mod test_binding {
#[test]
fn creates_new_without_cleanup() {
- let b = Binding::new(StepKind::Given, "I am Tomjon", "set_name", None).unwrap();
+ let b = Binding::new(StepKind::Given, "I am Tomjon", "set_name", None, false).unwrap();
assert_eq!(b.kind(), StepKind::Given);
assert!(b.regex().is_match("I am Tomjon"));
assert!(!b.regex().is_match("I am Tomjon of Lancre"));
@@ -165,6 +170,7 @@ mod test_binding {
"I am Tomjon",
"set_name",
Some("unset_name"),
+ false,
)
.unwrap();
assert_eq!(b.kind(), StepKind::Given);
@@ -177,36 +183,57 @@ mod test_binding {
#[test]
fn equal() {
- let a = Binding::new(StepKind::Given, "I am Tomjon", "set_name", Some("unset")).unwrap();
- let b = Binding::new(StepKind::Given, "I am Tomjon", "set_name", Some("unset")).unwrap();
+ let a = Binding::new(
+ StepKind::Given,
+ "I am Tomjon",
+ "set_name",
+ Some("unset"),
+ false,
+ )
+ .unwrap();
+ let b = Binding::new(
+ StepKind::Given,
+ "I am Tomjon",
+ "set_name",
+ Some("unset"),
+ false,
+ )
+ .unwrap();
assert_eq!(a, b);
}
#[test]
fn not_equal() {
- let a = Binding::new(StepKind::Given, "I am Tomjon", "set_name", None).unwrap();
- let b = Binding::new(StepKind::Given, "I am Tomjon of Lancre", "set_name", None).unwrap();
+ let a = Binding::new(StepKind::Given, "I am Tomjon", "set_name", None, false).unwrap();
+ let b = Binding::new(
+ StepKind::Given,
+ "I am Tomjon of Lancre",
+ "set_name",
+ None,
+ false,
+ )
+ .unwrap();
assert_ne!(a, b);
}
#[test]
fn does_not_match_with_wrong_kind() {
let step = ScenarioStep::new(StepKind::Given, "given", "yo");
- let b = Binding::new(StepKind::When, "yo", "do_yo", None).unwrap();
+ let b = Binding::new(StepKind::When, "yo", "do_yo", None, false).unwrap();
assert!(b.match_with_step(&step).is_none());
}
#[test]
fn does_not_match_with_wrong_text() {
let step = ScenarioStep::new(StepKind::Given, "given", "foo");
- let b = Binding::new(StepKind::Given, "bar", "yo", None).unwrap();
+ let b = Binding::new(StepKind::Given, "bar", "yo", None, false).unwrap();
assert!(b.match_with_step(&step).is_none());
}
#[test]
fn match_with_fixed_pattern() {
let step = ScenarioStep::new(StepKind::Given, "given", "foo");
- let b = Binding::new(StepKind::Given, "foo", "do_foo", None).unwrap();
+ let b = Binding::new(StepKind::Given, "foo", "do_foo", None, false).unwrap();
let m = b.match_with_step(&step).unwrap();
assert_eq!(m.kind(), StepKind::Given);
let mut parts = m.parts();
@@ -223,6 +250,7 @@ mod test_binding {
r"I am (?P<who>\S+), I am",
"set_name",
None,
+ false,
)
.unwrap();
let m = b.match_with_step(&step).unwrap();
@@ -233,6 +261,15 @@ mod test_binding {
assert_eq!(parts.next().unwrap(), &PartialStep::uncaptured(", I am"));
assert_eq!(parts.next(), None);
}
+
+ #[test]
+ fn case_sensitive_mismatch() {
+ let step = ScenarioStep::new(StepKind::Given, "given", "I am Tomjon");
+ let b = Binding::new(StepKind::Given, r"i am tomjon", "set_name", None, false).unwrap();
+ assert!(b.match_with_step(&step).is_some());
+ let b = Binding::new(StepKind::Given, r"i am tomjon", "set_name", None, true).unwrap();
+ assert!(b.match_with_step(&step).is_none());
+ }
}
/// Set of all known bindings.
@@ -255,6 +292,15 @@ struct ParsedBinding {
function: String,
cleanup: Option<String>,
regex: Option<bool>,
+ #[serde(default)]
+ case_sensitive: bool,
+}
+
+#[derive(Debug, Deserialize)]
+#[serde(transparent)]
+struct ParsedBindingWrapper {
+ #[serde(deserialize_with = "deserialize_struct_case_insensitive")]
+ binding: ParsedBinding,
}
impl Bindings {
@@ -280,9 +326,9 @@ impl Bindings {
/// Add bindings from a YAML string
pub fn add_from_yaml(&mut self, yaml: &str) -> Result<()> {
- let bindings: Vec<ParsedBinding> = serde_yaml::from_str(yaml)?;
- for b in bindings {
- self.add(from_hashmap(&b)?);
+ let bindings: Vec<ParsedBindingWrapper> = serde_yaml::from_str(yaml)?;
+ for wrapper in bindings {
+ self.add(from_hashmap(&wrapper.binding)?);
}
Ok(())
}
@@ -372,6 +418,7 @@ fn from_hashmap(parsed: &ParsedBinding) -> Result<Binding> {
None => None,
Some(ref s) => Some(s),
},
+ parsed.case_sensitive,
)?)
}
@@ -392,8 +439,14 @@ mod test_bindings {
#[test]
fn adds_binding() {
- let binding =
- Binding::new(StepKind::Given, r"I am (?P<name>\S+)", "set_name", None).unwrap();
+ let binding = Binding::new(
+ StepKind::Given,
+ r"I am (?P<name>\S+)",
+ "set_name",
+ None,
+ false,
+ )
+ .unwrap();
let mut bindings = Bindings::new();
bindings.add(binding.clone());
assert_eq!(bindings.bindings(), &[binding]);
@@ -402,12 +455,15 @@ mod test_bindings {
#[test]
fn adds_from_yaml() {
let yaml = "
-- given: I am Tomjon
+- GIVEN: I am Tomjon
function: set_name
- when: I declare myself king
- function: declare_king
-- then: there is applause
+ Function: declare_king
+- tHEn: there is applause
function: check_for_applause
+- given: you are alice
+ function: other_name
+ case_sensitive: true
";
let mut bindings = Bindings::new();
bindings.add_from_yaml(&yaml).unwrap();
@@ -415,15 +471,17 @@ mod test_bindings {
assert!(bindings.has(StepKind::Given, "I am Tomjon"));
assert!(bindings.has(StepKind::When, "I declare myself king"));
assert!(bindings.has(StepKind::Then, "there is applause"));
- assert_eq!(bindings.len(), 3);
+ assert!(bindings.has(StepKind::Given, "you are alice"));
+ assert!(!bindings.has(StepKind::Given, "you are Alice"));
+ assert_eq!(bindings.len(), 4);
}
#[test]
fn add_from_yaml_notices_multiple_keywords() {
let yaml = "
-- given: I am Tomjon
- when: I am indeed Tomjon
- function: set_name
+- Given: I am Tomjon
+ wheN: I am indeed Tomjon
+ FUNCTION: set_name
";
match Bindings::new().add_from_yaml(&yaml) {
Ok(_) => unreachable!(),
@@ -435,7 +493,7 @@ mod test_bindings {
#[test]
fn does_not_find_match_for_unmatching_kind() {
let step = ScenarioStep::new(StepKind::Given, "given", "I am Tomjon");
- let binding = Binding::new(StepKind::When, r"I am Tomjon", "set_foo", None).unwrap();
+ let binding = Binding::new(StepKind::When, r"I am Tomjon", "set_foo", None, false).unwrap();
let mut bindings = Bindings::new();
bindings.add(binding);
assert!(match bindings.find(&step) {
@@ -447,8 +505,14 @@ mod test_bindings {
#[test]
fn does_not_find_match_for_unmatching_pattern() {
let step = ScenarioStep::new(StepKind::Given, "given", "I am Tomjon");
- let binding =
- Binding::new(StepKind::Given, r"I am Tomjon of Lancre", "set_foo", None).unwrap();
+ let binding = Binding::new(
+ StepKind::Given,
+ r"I am Tomjon of Lancre",
+ "set_foo",
+ None,
+ false,
+ )
+ .unwrap();
let mut bindings = Bindings::new();
bindings.add(binding);
assert!(match bindings.find(&step) {
@@ -461,13 +525,15 @@ mod test_bindings {
fn two_matching_bindings() {
let step = ScenarioStep::new(StepKind::Given, "given", "I am Tomjon");
let mut bindings = Bindings::default();
- bindings.add(Binding::new(StepKind::Given, r"I am Tomjon", "set_foo", None).unwrap());
+ bindings
+ .add(Binding::new(StepKind::Given, r"I am Tomjon", "set_foo", None, false).unwrap());
bindings.add(
Binding::new(
StepKind::Given,
&super::regex_from_simple_pattern(r"I am {name}", false).unwrap(),
"set_foo",
None,
+ false,
)
.unwrap(),
);
@@ -480,7 +546,8 @@ mod test_bindings {
#[test]
fn finds_match_for_fixed_string_pattern() {
let step = ScenarioStep::new(StepKind::Given, "given", "I am Tomjon");
- let binding = Binding::new(StepKind::Given, r"I am Tomjon", "set_name", None).unwrap();
+ let binding =
+ Binding::new(StepKind::Given, r"I am Tomjon", "set_name", None, false).unwrap();
let mut bindings = Bindings::new();
bindings.add(binding);
let m = bindings.find(&step).unwrap();
@@ -497,8 +564,14 @@ mod test_bindings {
#[test]
fn finds_match_for_regexp_pattern() {
let step = ScenarioStep::new(StepKind::Given, "given", "I am Tomjon");
- let binding =
- Binding::new(StepKind::Given, r"I am (?P<name>\S+)", "set_name", None).unwrap();
+ let binding = Binding::new(
+ StepKind::Given,
+ r"I am (?P<name>\S+)",
+ "set_name",
+ None,
+ false,
+ )
+ .unwrap();
let mut bindings = Bindings::new();
bindings.add(binding);
let m = bindings.find(&step).unwrap();