use pixelsrc::alias::{expand_aliases, extract_aliases};
use pixelsrc::models::TtpObject;
use pixelsrc::parser::parse_stream;
use std::collections::HashMap;
use std::io::Cursor;
#[test]
fn test_alias_basic() {
let input = include_str!("../../../examples/demos/cli/format/alias_sprite.jsonl");
let reader = Cursor::new(input);
let result = parse_stream(reader);
let sprite = result
.objects
.iter()
.find_map(|o| match o {
TtpObject::Sprite(s) if s.name == "robot_head" => Some(s),
_ => None,
})
.expect("Sprite 'robot_head' should exist");
let (aliases, transformed) = extract_aliases(&sprite.grid);
assert!(!aliases.is_empty(), "Should extract aliases");
assert_eq!(transformed.len(), sprite.grid.len(), "Transformed grid should have same row count");
for row in &transformed {
let tokens: Vec<&str> = row.split('{').filter(|s| !s.is_empty()).collect();
for token in tokens {
assert!(token.len() <= 2, "Aliased tokens should be short (found: {{{})", token);
}
}
}
#[test]
fn test_alias_underscore_preserved() {
let grid = vec!["{_}{x}{y}".to_string(), "{x}{_}{x}".to_string(), "{y}{x}{_}".to_string()];
let (aliases, transformed) = extract_aliases(&grid);
assert_eq!(aliases.get(&'_'), Some(&"_".to_string()), "{{_}} should always map to '_'");
assert!(
transformed.iter().any(|row| row.contains("{_}")),
"Transformed grid should preserve {{_}} tokens"
);
}
#[test]
fn test_alias_frequency_order() {
let grid = vec![
"{x}{x}{x}{y}{y}{z}".to_string(),
"{x}{x}{x}{y}{y}{z}".to_string(),
"{x}{x}{x}{y}{y}{z}".to_string(),
];
let (aliases, _transformed) = extract_aliases(&grid);
assert_eq!(aliases.get(&'a'), Some(&"x".to_string()), "Most frequent token should get 'a'");
assert_eq!(aliases.get(&'b'), Some(&"y".to_string()), "Second most frequent should get 'b'");
assert_eq!(aliases.get(&'c'), Some(&"z".to_string()), "Third most frequent should get 'c'");
}
#[test]
fn test_alias_roundtrip() {
let original = vec![
"{transparent}{skin}{skin}{transparent}".to_string(),
"{transparent}{hair}{hair}{transparent}".to_string(),
"{skin}{eye}{eye}{skin}".to_string(),
"{skin}{skin}{skin}{skin}".to_string(),
];
let (aliases, transformed) = extract_aliases(&original);
let expanded = expand_aliases(&transformed, &aliases);
assert_eq!(original, expanded, "Roundtrip should preserve original grid");
}
#[test]
fn test_alias_expand() {
let aliases: HashMap<char, String> = [
('a', "skin".to_string()),
('b', "hair".to_string()),
('c', "eye".to_string()),
('_', "_".to_string()),
]
.into_iter()
.collect();
let grid = vec!["{_}{b}{b}{_}".to_string(), "{a}{c}{c}{a}".to_string()];
let expanded = expand_aliases(&grid, &aliases);
assert_eq!(expanded[0], "{_}{hair}{hair}{_}");
assert_eq!(expanded[1], "{skin}{eye}{eye}{skin}");
}
#[test]
fn test_alias_json_output() {
let grid = vec!["{_}{red}{green}".to_string(), "{blue}{red}{_}".to_string()];
let (aliases, transformed) = extract_aliases(&grid);
let mut alias_map: HashMap<String, String> = HashMap::new();
for (alias_char, full_name) in &aliases {
let key = format!("{{{}}}", alias_char);
let value = format!("{{{}}}", full_name);
alias_map.insert(key, value);
}
assert!(alias_map.contains_key("{_}"), "Should have {{_}} in map");
assert_eq!(transformed.len(), 2, "Should have 2 rows");
}
#[test]
fn test_alias_verbose_tokens() {
let input = include_str!("../../../examples/demos/cli/format/alias_sprite.jsonl");
let reader = Cursor::new(input);
let result = parse_stream(reader);
let sprite = result
.objects
.iter()
.find_map(|o| match o {
TtpObject::Sprite(s) if s.name == "robot_head" => Some(s),
_ => None,
})
.expect("Sprite 'robot_head' should exist");
let original_len: usize = sprite.grid.iter().map(|r| r.len()).sum();
let (_aliases, transformed) = extract_aliases(&sprite.grid);
let transformed_len: usize = transformed.iter().map(|r| r.len()).sum();
assert!(
transformed_len < original_len,
"Aliased grid should be shorter ({} < {})",
transformed_len,
original_len
);
}