use crate::common;
use common::e2e_helpers::{create_runtime_with_finalize, transpile};
use std::path::PathBuf;
#[test]
fn test_scene_collection_basic() {
let lua = create_runtime_with_finalize().unwrap();
let pasta_source = include_str!("../fixtures/sample.pasta");
let lua_code = transpile(pasta_source);
lua.load(&lua_code).exec().unwrap();
lua.load("require('pasta').finalize_scene()")
.exec()
.unwrap();
let result: (String, String) = lua
.load(
r#"
local SEARCH = require "@pasta_search"
return SEARCH:search_scene("メイン", nil)
"#,
)
.eval()
.unwrap();
assert!(
result.0.starts_with("メイン"),
"Global name should start with 'メイン', got: {}",
result.0
);
assert_eq!(result.1, "__start__", "Local name should be '__start__'");
}
#[test]
fn test_scene_collection_multiple_global_scenes() {
let lua = create_runtime_with_finalize().unwrap();
let pasta_source = include_str!("../fixtures/sample.pasta");
let lua_code = transpile(pasta_source);
lua.load(&lua_code).exec().unwrap();
lua.load("require('pasta').finalize_scene()")
.exec()
.unwrap();
let result: (String, String) = lua
.load(
r#"
local SEARCH = require "@pasta_search"
return SEARCH:search_scene("会話分岐", nil)
"#,
)
.eval()
.unwrap();
assert!(
result.0.contains("会話分岐"),
"Should find scene with name containing '会話分岐', got: {}",
result.0
);
}
#[test]
fn test_scene_collection_local_scenes() {
let lua = create_runtime_with_finalize().unwrap();
let pasta_source = include_str!("../fixtures/sample.pasta");
let lua_code = transpile(pasta_source);
lua.load(&lua_code).exec().unwrap();
lua.load("require('pasta').finalize_scene()")
.exec()
.unwrap();
let search_exists: bool = lua
.load(
r#"
local ok, SEARCH = pcall(require, "@pasta_search")
return ok and SEARCH ~= nil
"#,
)
.eval()
.unwrap();
assert!(search_exists, "@pasta_search module should be available");
}
#[test]
fn test_scene_collection_local_scene_search() {
let lua = create_runtime_with_finalize().unwrap();
let pasta_source = include_str!("../fixtures/sample.pasta");
let lua_code = transpile(pasta_source);
lua.load(&lua_code).exec().unwrap();
lua.load("require('pasta').finalize_scene()")
.exec()
.unwrap();
let result: (String, String) = lua
.load(
r#"
local SEARCH = require "@pasta_search"
local SCENE = require "pasta.scene"
local gn = SCENE.get_global_table("メイン1").__global_name__
return SEARCH:search_scene("グローバル単語呼び出し", gn)
"#,
)
.eval()
.unwrap();
assert!(
result.0.contains("メイン"),
"Global name should contain 'メイン', got: {}",
result.0
);
assert!(
result.1.contains("グローバル単語呼び出し"),
"Local name should contain 'グローバル単語呼び出し', got: {}",
result.1
);
}
#[test]
fn test_scene_collection_local_scene_prefix_search() {
let lua = create_runtime_with_finalize().unwrap();
let pasta_source = include_str!("../fixtures/sample.pasta");
let lua_code = transpile(pasta_source);
lua.load(&lua_code).exec().unwrap();
lua.load("require('pasta').finalize_scene()")
.exec()
.unwrap();
let result: (String, String) = lua
.load(
r#"
local SEARCH = require "@pasta_search"
local SCENE = require "pasta.scene"
local gn = SCENE.get_global_table("メイン1").__global_name__
return SEARCH:search_scene("会話分岐", gn)
"#,
)
.eval()
.unwrap();
assert!(
result.0.contains("メイン"),
"Global name should contain 'メイン', got: {}",
result.0
);
assert!(
result.1.contains("会話分岐"),
"Local name should contain '会話分岐', got: {}",
result.1
);
}
#[test]
fn test_word_collection_global() {
let lua = create_runtime_with_finalize().unwrap();
let pasta_source = include_str!("../fixtures/sample.pasta");
let lua_code = transpile(pasta_source);
lua.load(&lua_code).exec().unwrap();
lua.load("require('pasta').finalize_scene()")
.exec()
.unwrap();
let result: mlua::Value = lua
.load(
r#"
local SEARCH = require "@pasta_search"
return SEARCH:search_word("挨拶", nil)
"#,
)
.eval()
.unwrap();
assert!(result.is_string(), "Word search should return a string");
let word = result.as_string().map(|s| s.to_string_lossy()).unwrap();
assert!(
word == "こんにちは" || word == "やあ" || word == "ハロー",
"Word should be one of the registered values, got: {}",
word
);
}
#[test]
fn test_word_collection_local() {
let lua = create_runtime_with_finalize().unwrap();
let pasta_source = include_str!("../fixtures/sample.pasta");
let lua_code = transpile(pasta_source);
lua.load(&lua_code).exec().unwrap();
lua.load("require('pasta').finalize_scene()")
.exec()
.unwrap();
let search_available: bool = lua
.load(
r#"
local ok = pcall(require, "@pasta_search")
return ok
"#,
)
.eval()
.unwrap();
assert!(
search_available,
"@pasta_search should be available after finalize_scene"
);
}
#[test]
fn test_word_builder_pattern() {
let lua = create_runtime_with_finalize().unwrap();
let result: bool = lua
.load(
r#"
local PASTA = require("pasta")
-- Create global word using builder pattern
PASTA.create_word("テスト"):entry("値1", "値2", "値3")
-- Call finalize_scene
PASTA.finalize_scene()
-- Verify word is searchable
local SEARCH = require "@pasta_search"
local word = SEARCH:search_word("テスト", nil)
return word == "値1" or word == "値2" or word == "値3"
"#,
)
.eval()
.unwrap();
assert!(result, "Builder pattern should register word correctly");
}
#[test]
fn test_empty_registry_finalize() {
let lua = create_runtime_with_finalize().unwrap();
let result: bool = lua
.load(
r#"
local PASTA = require("pasta")
return PASTA.finalize_scene()
"#,
)
.eval()
.unwrap();
assert!(
result,
"finalize_scene should return true even with empty registry"
);
let search_available: bool = lua
.load(
r#"
local ok = pcall(require, "@pasta_search")
return ok
"#,
)
.eval()
.unwrap();
assert!(
search_available,
"@pasta_search should be available even with empty registry"
);
}
#[test]
fn test_scene_not_found() {
let lua = create_runtime_with_finalize().unwrap();
let pasta_source = include_str!("../fixtures/sample.pasta");
let lua_code = transpile(pasta_source);
lua.load(&lua_code).exec().unwrap();
lua.load("require('pasta').finalize_scene()")
.exec()
.unwrap();
let result: bool = lua
.load(
r#"
local SEARCH = require "@pasta_search"
local global_name = SEARCH:search_scene("存在しないシーン", nil)
return global_name == nil
"#,
)
.eval()
.unwrap();
assert!(result, "Non-existent scene search should return nil");
}
#[test]
fn test_word_not_found() {
let lua = create_runtime_with_finalize().unwrap();
lua.load("require('pasta').finalize_scene()")
.exec()
.unwrap();
let result: bool = lua
.load(
r#"
local SEARCH = require "@pasta_search"
local word = SEARCH:search_word("存在しない単語", nil)
return word == nil
"#,
)
.eval()
.unwrap();
assert!(result, "Non-existent word search should return nil");
}
#[test]
fn test_multiple_finalize_calls() {
let lua = create_runtime_with_finalize().unwrap();
lua.load(
r#"
local PASTA = require("pasta")
PASTA.create_word("単語A"):entry("値A1", "値A2")
PASTA.finalize_scene()
"#,
)
.exec()
.unwrap();
let word_a_found: bool = lua
.load(
r#"
local SEARCH = require "@pasta_search"
local word = SEARCH:search_word("単語A", nil)
return word ~= nil
"#,
)
.eval()
.unwrap();
assert!(word_a_found, "単語A should be found after first finalize");
lua.load(
r#"
local PASTA = require("pasta")
PASTA.create_word("単語B"):entry("値B1", "値B2")
PASTA.finalize_scene()
"#,
)
.exec()
.unwrap();
let both_found: bool = lua
.load(
r#"
local SEARCH = require "@pasta_search"
local a = SEARCH:search_word("単語A", nil)
local b = SEARCH:search_word("単語B", nil)
return a ~= nil and b ~= nil
"#,
)
.eval()
.unwrap();
assert!(
both_found,
"Both words should be found after second finalize"
);
}
#[test]
fn test_search_unavailable_before_finalize() {
use mlua::{Lua, StdLib};
let lua = unsafe { Lua::unsafe_new_with(StdLib::ALL_SAFE, mlua::LuaOptions::default()) };
let scripts_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("pasta_scripts")
.to_string_lossy()
.replace('\\', "/");
lua.load(format!(
r#"
package.path = "{scripts_dir}/?.lua;{scripts_dir}/?/init.lua;" .. package.path
"#
))
.exec()
.unwrap();
let result: bool = lua
.load(
r#"
local ok = pcall(require, "@pasta_search")
return ok
"#,
)
.eval()
.unwrap();
assert!(
!result,
"@pasta_search should NOT be available before finalize_scene"
);
}
#[test]
fn test_full_e2e_flow() {
let lua = create_runtime_with_finalize().unwrap();
let pasta_source = include_str!("../fixtures/sample.pasta");
let lua_code = transpile(pasta_source);
lua.load(&lua_code).exec().unwrap();
lua.load("require('pasta').finalize_scene()")
.exec()
.unwrap();
let all_ok: bool = lua
.load(
r#"
local SEARCH = require "@pasta_search"
-- Check scenes
local main_ok = SEARCH:search_scene("メイン", nil) ~= nil
local talk_ok = SEARCH:search_scene("会話分岐", nil) ~= nil
-- Check words
local greet_ok = SEARCH:search_word("挨拶", nil) ~= nil
return main_ok and talk_ok and greet_ok
"#,
)
.eval()
.unwrap();
assert!(all_ok, "All scenes and words should be searchable");
}