Files
factorio-scenario-ExpCluster/exp_roles/test/module/holders.lua
T
bbassieandClaude Fable 5 08fe6b688e Type the test environments for autocomplete
Building on the class annotations from the smoke test changes:

- The suite is generic over its environment: Framework.suite is
  @generic T : Stubs with the extension returning T, and Suite<T> passes T to
  every test function. A test file declares
  `local Suite = ... --- @type Suite<ExpRoles.TestEnv>` and env autocompletes
  from there.
- The stubs declare their recorded fields, add_player returns Stubs.Player,
  and the server is one.
- ExpRoles.TestEnv : Stubs declares the extension fields, so env.R returns
  ExpRoles.Role and env.Roles is the module.

The typing immediately paid for itself by flagging real drift in the tests,
now fixed: _script_data is package private so the env exposes script_data()
instead, the join event carries its name and tick, the assignment record type
admits is_deleted, admin_state is a file local rather than an undeclared
field, and the event assertions which indexed [1] without a nil check compare
the whole event list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-01 06:09:40 +00:00

69 lines
2.9 KiB
Lua

--- Tests for listing and printing to the players who hold a role
local Suite = ... --- @type Suite<ExpRoles.TestEnv> The suite this file adds its tests to, see test/lua/framework.lua
local test, check, eq = Suite.test, Suite.check, Suite.eq
--- alice and dave are moderators with dave offline, zed has never joined
local function setup(env)
local players = {
alice = env.add_player("alice"),
bob = env.add_player("bob"),
dave = env.add_player("dave", false),
}
env.initialise{
env.assignment("alice", { "Moderator" }),
env.assignment("bob", { "Regular" }),
env.assignment("dave", { "Moderator" }),
env.assignment("zed", { "Moderator" }),
}
env.Roles.set_emit_events(true)
return players
end
test(".get_player_names() includes players not on this map", function(env)
setup(env)
eq(Suite.sorted(env.R("Moderator"):get_player_names()), { "alice", "dave", "zed" },
"every player given the role is listed")
end)
test(".get_player_names() counts a player in both lists once", function(env)
local players = setup(env)
env.R("Regular"):assign(players.alice, { silent = true, local_only = true })
env.Roles.receive_assignment_updates{ env.assignment("alice", { "Moderator", "Regular" }) }
local sd = env.script_data()
check(sd.local_players.alice ~= nil and sd.synced_players.alice ~= nil, "the role is held in both lists")
eq(Suite.sorted(env.R("Regular"):get_player_names()), { "alice", "bob" }, "the player is counted once")
end)
test(".get_players() is limited to this map and can be filtered", function(env)
setup(env)
local moderator = env.R("Moderator")
eq(Suite.sorted(Suite.names(moderator:get_players())), { "alice", "dave" }, "players are limited to this map")
eq(Suite.names(moderator:get_players(true)), { "alice" }, "filtered to connected players")
eq(Suite.names(moderator:get_players(false)), { "dave" }, "filtered to offline players")
end)
test(".print() reaches online holders", function(env)
setup(env)
env.reset_log()
eq(env.R("Moderator"):print("hello"), 1, "print returns the number of players reached")
eq(env.printed, { { "hello", to = "alice" } }, "only online holders receive the message")
eq(env.R("Jail"):print("hello"), 0, "a role with no online holders reaches nobody")
end)
test(".print() over get_higher_roles() can repeat", function(env)
local players = setup(env)
env.R("Regular"):assign(players.alice, { silent = true, local_only = true })
env.reset_log()
for _, role in ipairs(env.Roles.get_higher_roles(env.R("Regular"))) do
role:print("hello")
end
local got = {}
for _, entry in ipairs(env.printed) do got[#got + 1] = entry.to end
-- alice holds two of the roles, so like the legacy system the message can repeat
eq(Suite.sorted(got), { "alice", "alice", "bob" }, "the online holders of each role are reached")
end)
return Suite.run()