Skip to content

Commit 9abfb62

Browse files
committed
[DISCO-3613] Merino - add locale string parsing for curated rec client
1 parent 365edb4 commit 9abfb62

File tree

1 file changed

+93
-0
lines changed
  • components/merino/src/curated_recommendations

1 file changed

+93
-0
lines changed

components/merino/src/curated_recommendations/models.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,46 @@ pub enum CuratedRecommendationLocale {
4343
#[serde(rename = "de-CH")]
4444
DeCh,
4545
}
46+
47+
impl CuratedRecommendationLocale {
48+
/// Returns all supported locale strings (e.g. `"en-US"`, `"fr-FR"`).
49+
///
50+
/// These strings are the canonical serialized values of the enum variants.
51+
pub fn all_locales() -> Vec<String> {
52+
vec![
53+
CuratedRecommendationLocale::Fr,
54+
CuratedRecommendationLocale::FrFr,
55+
CuratedRecommendationLocale::Es,
56+
CuratedRecommendationLocale::EsEs,
57+
CuratedRecommendationLocale::It,
58+
CuratedRecommendationLocale::ItIt,
59+
CuratedRecommendationLocale::En,
60+
CuratedRecommendationLocale::EnCa,
61+
CuratedRecommendationLocale::EnGb,
62+
CuratedRecommendationLocale::EnUs,
63+
CuratedRecommendationLocale::De,
64+
CuratedRecommendationLocale::DeDe,
65+
CuratedRecommendationLocale::DeAt,
66+
CuratedRecommendationLocale::DeCh,
67+
]
68+
.into_iter()
69+
.map(|l| {
70+
serde_json::to_string(&l)
71+
.unwrap()
72+
.trim_matches('"')
73+
.to_string()
74+
})
75+
.collect()
76+
}
77+
78+
/// Parses a locale string (e.g. `"en-US"`) into a `CuratedRecommendationLocale` enum variant.
79+
///
80+
/// Returns `None` if the string does not match a known variant.
81+
pub fn from_locale_string(locale: String) -> Option<CuratedRecommendationLocale> {
82+
serde_json::from_str(&format!("\"{}\"", locale)).ok()
83+
}
84+
}
85+
4686
// Configuration settings for a Section
4787
#[derive(Debug, Serialize, Deserialize, PartialEq, uniffi::Record)]
4888
pub struct SectionSettings {
@@ -259,3 +299,56 @@ pub struct Tile {
259299
#[serde(rename = "hasExcerpt")]
260300
pub has_excerpt: bool,
261301
}
302+
303+
#[cfg(test)]
304+
mod tests {
305+
use super::*;
306+
307+
#[test]
308+
fn test_from_locale_string_valid_cases() {
309+
assert_eq!(
310+
CuratedRecommendationLocale::from_locale_string("en-US".into()),
311+
Some(CuratedRecommendationLocale::EnUs)
312+
);
313+
assert_eq!(
314+
CuratedRecommendationLocale::from_locale_string("fr".into()),
315+
Some(CuratedRecommendationLocale::Fr)
316+
);
317+
}
318+
319+
#[test]
320+
fn test_from_locale_string_invalid_cases() {
321+
assert_eq!(
322+
CuratedRecommendationLocale::from_locale_string("en_US".into()),
323+
None
324+
);
325+
assert_eq!(
326+
CuratedRecommendationLocale::from_locale_string("zz-ZZ".into()),
327+
None
328+
);
329+
}
330+
331+
#[test]
332+
fn test_all_locales_contains_expected_values() {
333+
let locales = CuratedRecommendationLocale::all_locales();
334+
assert!(locales.contains(&"en-US".to_string()));
335+
assert!(locales.contains(&"de-CH".to_string()));
336+
assert!(locales.contains(&"fr".to_string()));
337+
}
338+
339+
#[test]
340+
fn test_all_locales_round_trip() {
341+
for locale_str in CuratedRecommendationLocale::all_locales() {
342+
let parsed = CuratedRecommendationLocale::from_locale_string(locale_str.clone());
343+
assert!(parsed.is_some(), "Failed to parse locale: {}", locale_str);
344+
345+
let reserialized = serde_json::to_string(&parsed.unwrap()).unwrap();
346+
let clean = reserialized.trim_matches('"');
347+
assert_eq!(
348+
clean, locale_str,
349+
"Round-trip mismatch: {} => {}",
350+
locale_str, clean
351+
);
352+
}
353+
}
354+
}

0 commit comments

Comments
 (0)