use crate::language::{
KERNEL_LANGUAGE, LanguageVocabulary, identifiers, informative_tokens, surface_tokens,
};
use super::question_rendering_fault::QuestionRenderingFault;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct QuestionRendering {
question: String,
}
impl QuestionRendering {
pub fn lint(asked_as: &str, question: &str) -> Result<Self, Vec<QuestionRenderingFault>> {
let mut faults = Vec::new();
if let Some(language) = LanguageVocabulary::shipped().leans_in(question)
&& language != KERNEL_LANGUAGE
{
faults.push(QuestionRenderingFault::NotEnglish {
read: language.to_string(),
});
}
if informative_tokens(question).next().is_none() {
faults.push(QuestionRenderingFault::Empty);
}
let carried = surface_tokens(question);
let dropped = identifiers(asked_as)
.into_iter()
.filter(|identifier| !carried.contains(identifier))
.collect::<Vec<_>>();
if !dropped.is_empty() {
faults.push(QuestionRenderingFault::DropsIdentifiers(dropped));
}
if faults.is_empty() {
Ok(Self {
question: question.to_string(),
})
} else {
Err(faults)
}
}
pub fn as_str(&self) -> &str {
&self.question
}
}
#[cfg(test)]
mod tests {
use super::*;
const ASKED: &str = "¿Por qué se retrasó el despliegue de v0.7.0 (#469)?";
fn faults(asked_as: &str, question: &str) -> Vec<QuestionRenderingFault> {
QuestionRendering::lint(asked_as, question).expect_err("the rendering should be faulted")
}
#[test]
fn a_faithful_english_rendering_carries() {
let rendering =
QuestionRendering::lint(ASKED, "Why was the v0.7.0 launch (#469) postponed?")
.expect("identifiers kept, English, informative");
assert_eq!(
rendering.as_str(),
"Why was the v0.7.0 launch (#469) postponed?"
);
}
#[test]
fn a_question_that_repeats_the_users_english_is_not_a_fault() {
QuestionRendering::lint(
"Which valve froze during the night shift?",
"Which valve froze during the night shift?",
)
.expect("the user may already have asked in English");
}
#[test]
fn a_rendering_that_drops_an_identifier_says_which() {
let faults = faults(ASKED, "Why was the launch postponed?");
assert_eq!(
faults,
[QuestionRenderingFault::DropsIdentifiers(vec![
"#469".to_string(),
"v0.7.0".to_string()
])]
);
assert_eq!(
faults[0].to_string(),
"drops identifiers the user's words carry: #469, v0.7.0"
);
}
#[test]
fn a_rendering_in_the_users_language_is_faulted() {
let faults = faults(ASKED, "¿Por qué se retrasó el despliegue de v0.7.0 (#469)?");
assert_eq!(
faults,
[QuestionRenderingFault::NotEnglish {
read: "spanish".to_string()
}]
);
}
#[test]
fn a_rendering_with_no_informative_word_is_faulted() {
let faults = faults("¿Qué?", "What?");
assert_eq!(faults, [QuestionRenderingFault::Empty]);
}
#[test]
fn every_fault_is_reported_at_once() {
let faults = faults(ASKED, "¿Por qué?");
assert_eq!(
QuestionRenderingFault::describe(&faults),
"leans to spanish, not to English; carries no informative word; \
drops identifiers the user's words carry: #469, v0.7.0"
);
}
}