use crate::core::RunnerConfig;
#[cfg(test)]
mod tests {
use super::*;
use crate::core::RunnerConfig;
fn config(include: Vec<&str>, exclude: Vec<&str>) -> RunnerConfig {
RunnerConfig {
include_tags: include.into_iter().map(String::from).collect(),
exclude_tags: exclude.into_iter().map(String::from).collect(),
..RunnerConfig::default()
}
}
mod tags_match {
use super::*;
#[test]
fn no_tags_no_filters() {
assert!(tags_match(&[], &config(vec![], vec![])));
}
#[test]
fn matching_include_tag() {
let tags = vec!["smoke".to_string()];
assert!(tags_match(&tags, &config(vec!["smoke"], vec![])));
}
#[test]
fn missing_include_tag() {
let tags = vec!["slow".to_string()];
assert!(!tags_match(&tags, &config(vec!["smoke"], vec![])));
}
#[test]
fn all_include_tags_must_match() {
let tags = vec!["smoke".to_string(), "fast".to_string()];
assert!(tags_match(&tags, &config(vec!["smoke", "fast"], vec![])));
}
#[test]
fn not_all_include_tags_match() {
let tags = vec!["smoke".to_string()];
assert!(!tags_match(&tags, &config(vec!["smoke", "fast"], vec![])));
}
#[test]
fn exclude_tag_rejected() {
let tags = vec!["slow".to_string()];
assert!(!tags_match(&tags, &config(vec![], vec!["slow"])));
}
#[test]
fn exclude_tag_not_present() {
let tags = vec!["fast".to_string()];
assert!(tags_match(&tags, &config(vec![], vec!["slow"])));
}
#[test]
fn include_wins_over_exclude() {
let tags = vec!["slow".to_string()];
assert!(!tags_match(&tags, &config(vec!["smoke"], vec!["slow"])));
}
#[test]
fn exclude_rejected_even_if_include_matches() {
let tags = vec!["smoke".to_string(), "slow".to_string()];
assert!(!tags_match(&tags, &config(vec!["smoke"], vec!["slow"])));
}
#[test]
fn multiple_exclude_tags() {
let tags = vec!["slow".to_string()];
assert!(!tags_match(&tags, &config(vec![], vec!["slow", "flaky"])));
}
#[test]
fn empty_tags_with_include() {
assert!(!tags_match(&[], &config(vec!["smoke"], vec![])));
}
#[test]
fn empty_tags_no_include_no_exclude() {
assert!(tags_match(&[], &config(vec![], vec![])));
}
}
mod name_matches {
use super::*;
#[test]
fn no_filter() {
assert!(name_matches("anything", None));
}
#[test]
fn empty_filter_matches_all() {
assert!(name_matches("anything", Some("")));
}
#[test]
fn exact_match() {
assert!(name_matches("hello", Some("hello")));
}
#[test]
fn case_insensitive() {
assert!(name_matches("Hello World", Some("hello")));
assert!(name_matches("hello world", Some("WORLD")));
}
#[test]
fn substring_match() {
assert!(name_matches("Calculator :: adds", Some("adds")));
}
#[test]
fn no_match() {
assert!(!name_matches("Calculator", Some("Database")));
}
#[test]
fn partial_word_no_match() {
assert!(!name_matches("addition", Some("subtract")));
}
#[test]
fn filter_matches_start() {
assert!(name_matches("testing framework", Some("test")));
}
#[test]
fn filter_matches_end() {
assert!(name_matches("rust testing", Some("testing")));
}
}
}
pub fn tags_match(tags: &[String], config: &RunnerConfig) -> bool {
if !config.include_tags.is_empty() {
for required in &config.include_tags {
if !tags.iter().any(|t| t == required) {
return false;
}
}
}
for excluded in &config.exclude_tags {
if tags.iter().any(|t| t == excluded) {
return false;
}
}
true
}
pub fn name_matches(name: &str, filter: Option<&str>) -> bool {
match filter {
None => true,
Some(f) => {
if f.is_empty() {
return true;
}
name.to_lowercase().contains(&f.to_lowercase())
}
}
}