Skip to main content

whitaker_common/i18n/
testing.rs

1//! Test doubles and utilities for localization tests.
2//!
3//! This module provides test doubles such as [`FailingLookup`] and
4//! [`RecordingEmitter`] for exercising error paths and verifying diagnostic
5//! output during localization tests.
6
7use std::borrow::Cow;
8use std::cell::RefCell;
9
10pub use super::helpers::{MessageResolution, safe_resolve_message_set};
11use super::{Arguments, AttrKey, BundleLookup, I18nError, MessageKey};
12
13/// Test double that always returns `MissingMessage` errors for message lookups.
14///
15/// Shared across localization tests to exercise error-handling paths when Fluent
16/// bundles do not contain the requested messages.
17#[derive(Clone, Debug, Eq, PartialEq)]
18pub struct FailingLookup {
19    message_key: Cow<'static, str>,
20    locale: Cow<'static, str>,
21}
22
23impl FailingLookup {
24    /// Construct a failing lookup for `message_key` using the default test locale.
25    #[must_use]
26    pub fn new(message_key: impl Into<Cow<'static, str>>) -> Self {
27        Self::with_locale(message_key, Cow::Borrowed("test"))
28    }
29
30    /// Construct a failing lookup for `message_key` and `locale`.
31    #[must_use]
32    pub fn with_locale(
33        message_key: impl Into<Cow<'static, str>>,
34        locale: impl Into<Cow<'static, str>>,
35    ) -> Self {
36        Self {
37            message_key: message_key.into(),
38            locale: locale.into(),
39        }
40    }
41}
42
43impl BundleLookup for FailingLookup {
44    fn message(&self, _key: MessageKey<'_>, _args: &Arguments<'_>) -> Result<String, I18nError> {
45        Err(I18nError::MissingMessage {
46            key: self.message_key.clone().into_owned(),
47            locale: self.locale.clone().into_owned(),
48        })
49    }
50
51    fn attribute(
52        &self,
53        _key: MessageKey<'_>,
54        _attribute: AttrKey<'_>,
55        _args: &Arguments<'_>,
56    ) -> Result<String, I18nError> {
57        Err(I18nError::MissingMessage {
58            key: self.message_key.clone().into_owned(),
59            locale: self.locale.clone().into_owned(),
60        })
61    }
62}
63
64/// Test emitter recording delayed bug invocations for assertions.
65#[derive(Debug, Default)]
66pub struct RecordingEmitter {
67    messages: RefCell<Vec<String>>,
68}
69
70impl RecordingEmitter {
71    /// Access the recorded messages emitted during localization failures.
72    #[must_use]
73    pub fn recorded_messages(&self) -> Vec<String> {
74        self.messages.borrow().clone()
75    }
76
77    /// Record a delayed bug message for later assertions.
78    pub fn record(&self, message: String) {
79        self.messages.borrow_mut().push(message);
80    }
81}