rubot/tests/weather.rs
reverse b312ff0338
Friendlier weather output
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 18:14:51 +00:00

83 lines
2.7 KiB
Rust

use std::collections::BTreeMap;
use std::path::PathBuf;
use rustbot::bot::module::{Action, Command, Module};
use rustbot::bot::modules::weather::{format_weather, parse_db, to_json, Weather};
fn cmd<'a>(sender: &'a str, name: &'a str, args: &'a [&'a str]) -> Command<'a> {
Command { sender, reply_to: "#chan", name, args, prefix: ">", network: "test" }
}
fn reply(actions: &[Action]) -> &str {
match actions {
[Action::Reply(s)] => s,
_ => panic!("expected exactly one Reply"),
}
}
fn temp(name: &str) -> PathBuf {
let p = std::env::temp_dir().join(format!("rubot-test-{name}.json"));
let _ = std::fs::remove_file(&p);
p
}
#[test]
fn json_round_trip_handles_special_chars() {
let mut m = BTreeMap::new();
m.insert("alice".to_string(), "73700".to_string());
m.insert("bob".to_string(), "Saint-Étienne, FR".to_string());
m.insert("carol".to_string(), "a\"b\\c\nd".to_string());
let back = parse_db(&to_json(&m));
assert_eq!(m, back);
}
#[test]
fn parse_db_tolerates_junk() {
assert!(parse_db("").is_empty());
assert!(parse_db("not json").is_empty());
assert_eq!(parse_db("{}").len(), 0);
assert_eq!(parse_db("{\"a\":\"b\"}").get("a").map(String::as_str), Some("b"));
}
#[test]
fn add_saves_and_persists_case_insensitively() {
let path = temp("weather-add");
let mut w = Weather::with_path(path.clone());
let r = reply(&w.on_command(&cmd("Alice", "add", &["73700"]))).to_string();
assert!(r.contains("73700"), "reply: {r:?}");
let w2 = Weather::with_path(path.clone());
assert_eq!(w2.location_of("alice"), Some("73700"));
assert_eq!(w2.location_of("ALICE"), Some("73700"));
let _ = std::fs::remove_file(&path);
}
#[test]
fn add_without_arg_shows_usage() {
let mut w = Weather::with_path(temp("weather-usage"));
let r = reply(&w.on_command(&cmd("alice", "add", &[]))).to_string();
assert!(r.contains("usage"), "reply: {r:?}");
}
#[test]
fn w_without_saved_location_hints_to_add() {
let mut w = Weather::with_path(temp("weather-hint"));
let r = reply(&w.on_command(&cmd("nobody", "w", &[]))).to_string();
assert!(r.contains("add"), "reply: {r:?}");
}
#[test]
fn format_weather_builds_friendly_line() {
let out = format_weather("73700|☀️ |Sunny|+23°C|+18°C|↘8km/h|45%", "73700");
assert!(out.contains("☀️"), "{out}");
assert!(out.contains("73700: Sunny"), "{out}");
assert!(out.contains("23°C") && !out.contains("+23"), "{out}");
assert!(out.contains("feels like 18°C"), "{out}");
assert!(out.contains("45%"), "{out}");
}
#[test]
fn format_weather_friendly_not_found() {
let out = format_weather("location not found: upstream error", "zzz");
assert!(out.contains("couldn't find 'zzz'"), "{out}");
}