use pasta_dsl::ParseError;
use pasta_dsl::parser::*;
fn get_global_scene_scopes(file: &PastaFile) -> Vec<&GlobalSceneScope> {
file.items
.iter()
.filter_map(|item| {
if let FileItem::GlobalSceneScope(scene) = item {
Some(scene)
} else {
None
}
})
.collect()
}
fn get_file_attrs(file: &PastaFile) -> Vec<&Attr> {
file.items
.iter()
.filter_map(|item| {
if let FileItem::FileAttr(attr) = item {
Some(attr)
} else {
None
}
})
.collect()
}
#[test]
fn test_parse_empty_file() {
let result = parse_str("", "test.pasta");
assert!(result.is_ok());
let file = result.unwrap();
assert!(get_global_scene_scopes(&file).is_empty());
}
#[test]
fn test_parse_simple_global_scene() {
let source = "*挨拶\n Alice:こんにちは\n";
let result = parse_str(source, "test.pasta");
assert!(result.is_ok());
let file = result.unwrap();
let scenes = get_global_scene_scopes(&file);
assert_eq!(scenes.len(), 1);
assert_eq!(scenes[0].name, "挨拶");
assert!(!scenes[0].is_continuation);
}
#[test]
fn test_parse_continuation_scene() {
let source = "*挨拶\n Alice:こんにちは\n*\n Bob:やあ\n";
let result = parse_str(source, "test.pasta");
assert!(result.is_ok());
let file = result.unwrap();
let scenes = get_global_scene_scopes(&file);
assert_eq!(scenes.len(), 2);
assert_eq!(scenes[0].name, "挨拶");
assert!(!scenes[0].is_continuation);
assert_eq!(scenes[1].name, "挨拶");
assert!(scenes[1].is_continuation);
}
#[test]
fn test_parse_unnamed_scene_at_start_error() {
let source = "*\n Alice:こんにちは\n";
let result = parse_str(source, "test.pasta");
assert!(result.is_err());
if let Err(ParseError::SyntaxError { message, .. }) = result {
assert!(message.contains("Unnamed global scene at start of file"));
}
}
#[test]
fn test_parse_file_scope() {
let source = "&author:テスト\n*挨拶\n Alice:こんにちは\n";
let result = parse_str(source, "test.pasta");
assert!(result.is_ok());
let file = result.unwrap();
let attrs = get_file_attrs(&file);
assert_eq!(attrs.len(), 1);
assert_eq!(attrs[0].key, "author");
}
#[test]
fn test_parse_continue_action_line() {
let source = "*挨拶\n Alice:こんにちは\n :続きの台詞\n";
let result = parse_str(source, "test.pasta");
assert!(result.is_ok());
let file = result.unwrap();
let scenes = get_global_scene_scopes(&file);
assert_eq!(scenes.len(), 1);
let local_scene = &scenes[0].local_scenes[0];
assert!(local_scene.items.len() >= 2);
assert!(matches!(
local_scene.items[0],
LocalSceneItem::ActionLine(_)
));
assert!(matches!(
local_scene.items[1],
LocalSceneItem::ContinueAction(_)
));
}
#[test]
fn test_parse_code_block() {
let source = "*挨拶\n Alice:こんにちは\n```rune\nlet x = 1;\n```\n";
let result = parse_str(source, "test.pasta");
assert!(result.is_ok());
let file = result.unwrap();
assert_eq!(get_global_scene_scopes(&file).len(), 1);
}
#[test]
fn test_parse_scene_actors_single() {
let source = "*挨拶\n %さくら\n さくら:こんにちは\n";
let result = parse_str(source, "test.pasta");
assert!(result.is_ok());
let file = result.unwrap();
let scenes = get_global_scene_scopes(&file);
assert_eq!(scenes.len(), 1);
assert_eq!(scenes[0].actors.len(), 1);
assert_eq!(scenes[0].actors[0].name, "さくら");
assert_eq!(scenes[0].actors[0].number, 0);
}
#[test]
fn test_parse_scene_actors_with_explicit_number() {
let source = "*挨拶\n %さくら、うにゅう=2\n さくら:こんにちは\n";
let result = parse_str(source, "test.pasta");
assert!(result.is_ok());
let file = result.unwrap();
let scenes = get_global_scene_scopes(&file);
assert_eq!(scenes.len(), 1);
assert_eq!(scenes[0].actors.len(), 2);
assert_eq!(scenes[0].actors[0].name, "さくら");
assert_eq!(scenes[0].actors[0].number, 0);
assert_eq!(scenes[0].actors[1].name, "うにゅう");
assert_eq!(scenes[0].actors[1].number, 2);
}
#[test]
fn test_parse_scene_actors_csharp_enum_numbering() {
let source = "*挨拶\n %さくら、うにゅう=2、まりか\n さくら:こんにちは\n";
let result = parse_str(source, "test.pasta");
assert!(result.is_ok());
let file = result.unwrap();
let scenes = get_global_scene_scopes(&file);
assert_eq!(scenes.len(), 1);
assert_eq!(scenes[0].actors.len(), 3);
assert_eq!(scenes[0].actors[0].name, "さくら");
assert_eq!(scenes[0].actors[0].number, 0);
assert_eq!(scenes[0].actors[1].name, "うにゅう");
assert_eq!(scenes[0].actors[1].number, 2);
assert_eq!(scenes[0].actors[2].name, "まりか");
assert_eq!(scenes[0].actors[2].number, 3);
}
#[test]
fn test_parse_scene_actors_fullwidth_number() {
let source = "*挨拶\n %さくら=10\n さくら:こんにちは\n";
let result = parse_str(source, "test.pasta");
assert!(result.is_ok());
let file = result.unwrap();
let scenes = get_global_scene_scopes(&file);
assert_eq!(scenes.len(), 1);
assert_eq!(scenes[0].actors.len(), 1);
assert_eq!(scenes[0].actors[0].name, "さくら");
assert_eq!(scenes[0].actors[0].number, 10);
}
#[test]
fn test_parse_scene_actors_u32_max_explicit_number_no_panic() {
let source = "*挨拶\n %さくら=4294967295\n さくら:こんにちは\n";
let result = parse_str(source, "test.pasta");
assert!(result.is_ok());
let file = result.unwrap();
let scenes = get_global_scene_scopes(&file);
assert_eq!(scenes.len(), 1);
assert_eq!(scenes[0].actors.len(), 1);
assert_eq!(scenes[0].actors[0].number, u32::MAX);
}
#[test]
fn test_parse_scene_actors_u32_max_then_implicit_no_panic() {
let source = "*挨拶\n %さくら=4294967295、うにゅう\n さくら:こんにちは\n";
let result = parse_str(source, "test.pasta");
assert!(result.is_ok());
let file = result.unwrap();
let scenes = get_global_scene_scopes(&file);
assert_eq!(scenes.len(), 1);
assert_eq!(scenes[0].actors.len(), 2);
assert_eq!(scenes[0].actors[0].number, u32::MAX);
assert_eq!(scenes[0].actors[1].number, u32::MAX);
}
#[test]
fn test_parse_scene_actors_multiple_lines() {
let source = "*挨拶\n %さくら\n %うにゅう=5\n %まりか\n さくら:こんにちは\n";
let result = parse_str(source, "test.pasta");
assert!(result.is_ok());
let file = result.unwrap();
let scenes = get_global_scene_scopes(&file);
assert_eq!(scenes.len(), 1);
assert_eq!(scenes[0].actors.len(), 3);
assert_eq!(scenes[0].actors[0].name, "さくら");
assert_eq!(scenes[0].actors[0].number, 0);
assert_eq!(scenes[0].actors[1].name, "うにゅう");
assert_eq!(scenes[0].actors[1].number, 5);
assert_eq!(scenes[0].actors[2].name, "まりか");
assert_eq!(scenes[0].actors[2].number, 6);
}
#[test]
fn test_parse_scene_actors_complex_numbering() {
let source =
"*挨拶\n %さくら、うにゅう=2、まりか、ゆかり=10、あかね\n さくら:こんにちは\n";
let result = parse_str(source, "test.pasta");
assert!(result.is_ok());
let file = result.unwrap();
let scenes = get_global_scene_scopes(&file);
assert_eq!(scenes.len(), 1);
assert_eq!(scenes[0].actors.len(), 5);
assert_eq!(scenes[0].actors[0].name, "さくら");
assert_eq!(scenes[0].actors[0].number, 0);
assert_eq!(scenes[0].actors[1].name, "うにゅう");
assert_eq!(scenes[0].actors[1].number, 2);
assert_eq!(scenes[0].actors[2].name, "まりか");
assert_eq!(scenes[0].actors[2].number, 3);
assert_eq!(scenes[0].actors[3].name, "ゆかり");
assert_eq!(scenes[0].actors[3].number, 10);
assert_eq!(scenes[0].actors[4].name, "あかね");
assert_eq!(scenes[0].actors[4].number, 11);
}
#[test]
fn test_parse_scene_actors_span_valid() {
let source = "*挨拶\n %さくら\n さくら:こんにちは\n";
let result = parse_str(source, "test.pasta");
assert!(result.is_ok());
let file = result.unwrap();
let scenes = get_global_scene_scopes(&file);
assert_eq!(scenes.len(), 1);
assert_eq!(scenes[0].actors.len(), 1);
assert!(scenes[0].actors[0].span.is_valid());
}