pasta_dsl 0.2.1

Pasta DSL - Independent DSL parser and AST definitions
Documentation
//! ActorScope code_blocks パーサーテスト
//!
//! タスク1.3: code_blockを含むactor_scopeが正しくパースされることを検証

use pasta_dsl::parser::{FileItem, parse_str};

/// code_blockを含むactor_scopeが正しくパースされることを検証
#[test]
fn test_actor_scope_with_code_block() {
    let source = r#"%さくら
 @通常:\s[0]
```lua
function ACTOR.時刻(act)
    return "朝"
end
```
"#;

    let ast = parse_str(source, "test.pasta").expect("パース成功すべし");

    // ActorScopeが1つあることを確認
    let actors: Vec<_> = ast
        .items
        .iter()
        .filter_map(|item| {
            if let FileItem::ActorScope(actor) = item {
                Some(actor)
            } else {
                None
            }
        })
        .collect();

    assert_eq!(actors.len(), 1, "アクターは1つであるべし");
    let actor = actors[0];

    assert_eq!(actor.name, "さくら");
    assert_eq!(actor.words.len(), 1, "単語定義は1つ");
    assert_eq!(actor.words[0].name(), "通常");

    // code_blocksが正しく格納されることを検証
    assert_eq!(actor.code_blocks.len(), 1, "code_blockは1つであるべし");

    let code_block = &actor.code_blocks[0];
    assert_eq!(
        code_block.language,
        Some("lua".to_string()),
        "言語はluaであるべし"
    );
    assert!(
        code_block.content.contains("function ACTOR.時刻"),
        "コード内容が正しいこと"
    );
}

/// 複数のcode_blocksが順序通りに格納されることを検証
#[test]
fn test_actor_scope_with_multiple_code_blocks() {
    let source = r#"%さくら
 @通常:\s[0]
```lua
function ACTOR.時刻(act)
    return "朝"
end
```
```lua
function ACTOR.天気(act)
    return "晴れ"
end
```
"#;

    let ast = parse_str(source, "test.pasta").expect("パース成功すべし");

    let actors: Vec<_> = ast
        .items
        .iter()
        .filter_map(|item| {
            if let FileItem::ActorScope(actor) = item {
                Some(actor)
            } else {
                None
            }
        })
        .collect();

    assert_eq!(actors.len(), 1);
    let actor = actors[0];

    assert_eq!(
        actor.code_blocks.len(),
        2,
        "code_blockは2つであるべし(順序通り)"
    );
    assert!(actor.code_blocks[0].content.contains("時刻"));
    assert!(actor.code_blocks[1].content.contains("天気"));
}

/// code_blocksがないactor_scopeも正しくパースされることを検証(後方互換性)
#[test]
fn test_actor_scope_without_code_block() {
    let source = r#"%さくら
 @通常:\s[0]
 @照れ:\s[1]
"#;

    let ast = parse_str(source, "test.pasta").expect("パース成功すべし");

    let actors: Vec<_> = ast
        .items
        .iter()
        .filter_map(|item| {
            if let FileItem::ActorScope(actor) = item {
                Some(actor)
            } else {
                None
            }
        })
        .collect();

    assert_eq!(actors.len(), 1);
    let actor = actors[0];

    assert_eq!(actor.name, "さくら");
    assert_eq!(actor.words.len(), 2);
    assert_eq!(
        actor.code_blocks.len(),
        0,
        "code_blocksは空であるべし(後方互換)"
    );
}