local describe = require("lua_test.test").describe
local test = require("lua_test.test").test
local expect = require("lua_test.test").expect
describe("Integration - GLOBAL chaintalk via EVENT.fire", function()
local EVENT
local STORE
local REG
local RES
local GLOBAL
local function setup()
package.loaded["pasta.store"] = nil
package.loaded["pasta.shiori.event"] = nil
package.loaded["pasta.shiori.event.register"] = nil
package.loaded["pasta.shiori.res"] = nil
package.loaded["pasta.shiori.act"] = nil
package.loaded["pasta.global"] = nil
STORE = require("pasta.store")
EVENT = require("pasta.shiori.event")
REG = require("pasta.shiori.event.register")
RES = require("pasta.shiori.res")
GLOBAL = require("pasta.global")
STORE.actors = { sakura = { name = "さくら", spot = "sakura" } }
STORE.co_scene = nil
end
test("chaintalk yield splits coroutine into 2 resumes via EVENT.fire", function()
setup()
local resume_count = 0
REG.OnChaintalkTest = function(handler_act)
local function scene_fn(act)
resume_count = resume_count + 1
act:talk("前半メッセージ")
GLOBAL["チェイントーク"](act)
resume_count = resume_count + 1
act:talk("後半メッセージ")
end
local function wrapped_fn(act, ...)
scene_fn(act, ...)
local result = act:build()
if result ~= nil then return result end
end
return coroutine.create(wrapped_fn)
end
local response1 = EVENT.fire({ id = "OnChaintalkTest" })
expect(resume_count):toBe(1)
expect(STORE.co_scene).not_:toBe(nil)
expect(coroutine.status(STORE.co_scene)):toBe("suspended")
REG.OnChaintalkContinue = function(handler_act)
return STORE.co_scene
end
local response2 = EVENT.fire({ id = "OnChaintalkContinue" })
expect(resume_count):toBe(2)
expect(STORE.co_scene):toBe(nil)
end)
test("first resume returns only pre-yield tokens as intermediate output", function()
setup()
REG.OnIntermediateTest = function(handler_act)
local function scene_fn(act)
act:talk("中間出力テスト")
GLOBAL["チェイントーク"](act)
act:talk("最終出力テスト")
end
local function wrapped_fn(act, ...)
scene_fn(act, ...)
local result = act:build()
if result ~= nil then return result end
end
return coroutine.create(wrapped_fn)
end
local response1 = EVENT.fire({ id = "OnIntermediateTest" })
expect(response1).not_:toBe(nil)
expect(type(response1)):toBe("string")
expect(response1:find("200 OK")).not_:toBe(nil)
expect(response1:find("最終出力テスト")):toBe(nil)
end)
test("second resume returns post-yield tokens as final output", function()
setup()
REG.OnFinalTest = function(handler_act)
local function scene_fn(act)
act:talk("前半出力")
GLOBAL["チェイントーク"](act)
act:talk("後半出力")
end
local function wrapped_fn(act, ...)
scene_fn(act, ...)
local result = act:build()
if result ~= nil then return result end
end
return coroutine.create(wrapped_fn)
end
local response1 = EVENT.fire({ id = "OnFinalTest" })
expect(STORE.co_scene).not_:toBe(nil)
expect(response1).not_:toBe(nil)
expect(response1:find("200 OK")).not_:toBe(nil)
REG.OnFinalContinue = function(handler_act)
return STORE.co_scene
end
local response2 = EVENT.fire({ id = "OnFinalContinue" })
expect(response2).not_:toBe(nil)
expect(type(response2)):toBe("string")
expect(response2:find("200 OK")).not_:toBe(nil)
expect(STORE.co_scene):toBe(nil)
end)
test("STORE.co_scene lifecycle: suspended after 1st resume, nil after 2nd", function()
setup()
REG.OnLifecycleTest = function(handler_act)
local function scene_fn(act)
act:talk("ステップ1")
GLOBAL["チェイントーク"](act)
act:talk("ステップ2")
end
local function wrapped_fn(act, ...)
scene_fn(act, ...)
local result = act:build()
if result ~= nil then return result end
end
return coroutine.create(wrapped_fn)
end
expect(STORE.co_scene):toBe(nil)
EVENT.fire({ id = "OnLifecycleTest" })
expect(STORE.co_scene).not_:toBe(nil)
expect(coroutine.status(STORE.co_scene)):toBe("suspended")
REG.OnLifecycleContinue = function(handler_act)
return STORE.co_scene
end
EVENT.fire({ id = "OnLifecycleContinue" })
expect(STORE.co_scene):toBe(nil)
end)
test("GLOBAL.yield also splits coroutine correctly via EVENT.fire", function()
setup()
REG.OnYieldAliasTest = function(handler_act)
local function scene_fn(act)
act:talk("yield前")
GLOBAL["yield"](act)
act:talk("yield後")
end
local function wrapped_fn(act, ...)
scene_fn(act, ...)
local result = act:build()
if result ~= nil then return result end
end
return coroutine.create(wrapped_fn)
end
local response1 = EVENT.fire({ id = "OnYieldAliasTest" })
expect(response1).not_:toBe(nil)
expect(response1:find("200 OK")).not_:toBe(nil)
expect(STORE.co_scene).not_:toBe(nil)
expect(coroutine.status(STORE.co_scene)):toBe("suspended")
REG.OnYieldAliasContinue = function(handler_act)
return STORE.co_scene
end
local response2 = EVENT.fire({ id = "OnYieldAliasContinue" })
expect(response2).not_:toBe(nil)
expect(response2:find("200 OK")).not_:toBe(nil)
expect(STORE.co_scene):toBe(nil)
end)
end)