mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2026-09-21 17:04:00 +00:00
Manual changes following smoke test
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
--- Tests for the assignment methods of module/control.lua
|
||||
local Suite = ... --- @type Suite The suite this file adds its tests to, see env.lua
|
||||
local test, check, eq, empty = Suite.test, Suite.check, Suite.eq, Suite.empty
|
||||
|
||||
--- alice is a moderator and bob a regular, with changes sent to the controller
|
||||
local function setup(env)
|
||||
local players = {
|
||||
alice = env.add_player("alice"),
|
||||
bob = env.add_player("bob"),
|
||||
}
|
||||
env.initialise{
|
||||
env.assignment("alice", { "Moderator" }),
|
||||
env.assignment("bob", { "Regular" }),
|
||||
}
|
||||
env.Roles.set_emit_events(true)
|
||||
env.reset_log()
|
||||
return players
|
||||
end
|
||||
|
||||
test(".assign() applies locally and is sent to the controller", function(env)
|
||||
local players = setup(env)
|
||||
local moderator = env.R("Moderator")
|
||||
moderator:assign(players.bob, { by_player_name = "alice" })
|
||||
eq(env.sent, {
|
||||
{ channel = "exp_roles:assignment_update", data = { name = "bob", assign = { moderator.id } } },
|
||||
}, "the assignment is sent to the controller")
|
||||
check(moderator:has_player(players.bob), "the role applies before confirmation")
|
||||
eq(env.events, {
|
||||
{
|
||||
name = env.Roles.events.on_player_roles_changed,
|
||||
tick = 1,
|
||||
player_index = players.bob.index,
|
||||
by_player_index = players.alice.index,
|
||||
assigned = { moderator.id },
|
||||
unassigned = {},
|
||||
},
|
||||
}, "the event carries the change")
|
||||
eq(env.printed, {
|
||||
{ "exp-roles.game-message-assign", "bob", "Moderator", "alice" },
|
||||
}, "the change is announced")
|
||||
eq(env.sounds, { "bob:utility/achievement_unlocked" }, "the assign sound plays")
|
||||
|
||||
local sd = env.Roles._script_data()
|
||||
eq(sd.local_players.bob, { moderator.id }, "the role is held locally")
|
||||
eq(sd.pending.bob, { moderator.id }, "the role is pending")
|
||||
|
||||
env.reset_log()
|
||||
moderator:assign(players.bob)
|
||||
empty(env.sent, "assigning a held role sends nothing")
|
||||
empty(env.events, "assigning a held role raises nothing")
|
||||
end)
|
||||
|
||||
test(".assign() defaults the by player to game.player", function(env)
|
||||
local players = setup(env)
|
||||
game.player = players.alice
|
||||
env.R("Jail"):assign(players.bob, { silent = true })
|
||||
eq(env.events[1].by_player_index, players.alice.index, "the acting player is game.player")
|
||||
end)
|
||||
|
||||
test("receive_assignment_updates() releases the local hold once confirmed", function(env)
|
||||
local players = setup(env)
|
||||
env.R("Moderator"):assign(players.bob)
|
||||
env.reset_log()
|
||||
env.Roles.receive_assignment_updates{ env.assignment("bob", { "Regular", "Moderator" }) }
|
||||
empty(env.events, "a confirmation raises no events")
|
||||
empty(env.printed, "a confirmation announces nothing")
|
||||
|
||||
local sd = env.Roles._script_data()
|
||||
check(sd.local_players.bob == nil and sd.pending.bob == nil, "the role is no longer held locally")
|
||||
check(env.R("Moderator"):has_player(players.bob), "the role is still held after confirmation")
|
||||
end)
|
||||
|
||||
test(".unassign() removes a synced role", function(env)
|
||||
local players = setup(env)
|
||||
local regular = env.R("Regular")
|
||||
regular:unassign(players.bob, { by_player_name = "alice", silent = true })
|
||||
eq(env.sent, {
|
||||
{ channel = "exp_roles:assignment_update", data = { name = "bob", unassign = { regular.id } } },
|
||||
}, "the unassignment is sent to the controller")
|
||||
check(not regular:has_player(players.bob), "the role is removed locally")
|
||||
eq(env.events, {
|
||||
{
|
||||
name = env.Roles.events.on_player_roles_changed,
|
||||
tick = 1,
|
||||
player_index = players.bob.index,
|
||||
by_player_index = players.alice.index,
|
||||
assigned = {},
|
||||
unassigned = { regular.id },
|
||||
},
|
||||
}, "the event carries the change")
|
||||
empty(env.printed, "silent suppresses the announcement")
|
||||
eq(env.sounds, { "bob:utility/game_lost" }, "the unassign sound plays")
|
||||
end)
|
||||
|
||||
test("reject_assignment() rolls the assignment back", function(env)
|
||||
local players = setup(env)
|
||||
local jail = env.R("Jail")
|
||||
jail:assign(players.alice)
|
||||
check(jail:has_player(players.alice), "the role applies before rejection")
|
||||
|
||||
env.reset_log()
|
||||
env.Roles.reject_assignment{ name = "alice", role_ids = { jail.id } }
|
||||
check(not jail:has_player(players.alice), "the rejected role is rolled back")
|
||||
empty(env.sent, "the rollback is not sent to the controller")
|
||||
eq(env.events, {
|
||||
{
|
||||
name = env.Roles.events.on_player_roles_changed,
|
||||
tick = 1,
|
||||
player_index = players.alice.index,
|
||||
by_player_index = 0,
|
||||
assigned = {},
|
||||
unassigned = { jail.id },
|
||||
},
|
||||
}, "the rollback raises the event")
|
||||
|
||||
local sd = env.Roles._script_data()
|
||||
check(sd.local_players.alice == nil and sd.pending.alice == nil, "the rollback clears the local state")
|
||||
end)
|
||||
|
||||
test(".assign() with local_only never reaches the controller", function(env)
|
||||
local players = setup(env)
|
||||
local regular = env.R("Regular")
|
||||
regular:assign(players.alice, { silent = true, local_only = true })
|
||||
empty(env.sent, "the assignment is not sent")
|
||||
check(regular:has_player(players.alice), "the role applies")
|
||||
|
||||
local sd = env.Roles._script_data()
|
||||
check(sd.pending.alice == nil, "the role is not pending")
|
||||
eq(sd.local_players.alice, { regular.id }, "the role is held locally")
|
||||
|
||||
env.Roles.receive_assignment_updates{ env.assignment("alice", { "Moderator" }) }
|
||||
check(regular:has_player(players.alice), "the role survives controller updates")
|
||||
|
||||
env.reset_log()
|
||||
regular:unassign(players.alice, { local_only = true })
|
||||
check(not regular:has_player(players.alice), "the role is removed")
|
||||
empty(env.sent, "the removal is not sent")
|
||||
end)
|
||||
|
||||
test(".assign() of a higher priority role suppresses the rest", function(env)
|
||||
local players = setup(env)
|
||||
local jail = env.R("Jail")
|
||||
jail:assign(players.alice, { by_player_name = "<server>", silent = true })
|
||||
eq(Suite.names(env.Roles.get_player_roles(players.alice)), { "Jail" }, "only the jail role applies")
|
||||
check(env.R("Moderator"):has_player(players.alice), "a suppressed role is still held")
|
||||
check(not env.Roles.player_has_permission(players.alice, "exp_scenario.command.kill"), "permissions are lost")
|
||||
check(not env.Roles.player_has_permission(players.alice, "exp_scenario.gui.readme"), "the default role is lost")
|
||||
check(not env.Roles.player_outranks(players.alice, players.bob), "a jailed player no longer outranks")
|
||||
eq(env.events[1].assigned, { jail.id }, "the event lists the jail role")
|
||||
empty(env.events[1].unassigned, "the suppressed roles are not listed as unassigned")
|
||||
|
||||
env.reset_log()
|
||||
jail:unassign(players.alice, { by_player_name = "<server>", silent = true })
|
||||
eq(Suite.sorted(Suite.names(env.Roles.get_player_roles(players.alice))), { "Moderator", "Player" },
|
||||
"unjail restores the roles")
|
||||
empty(env.events[1].assigned, "the restored roles are not listed as assigned")
|
||||
eq(env.events[1].unassigned, { jail.id }, "the unjail event lists the jail role")
|
||||
end)
|
||||
|
||||
test(".assign() ignores the server", function(env)
|
||||
setup(env)
|
||||
env.R("Moderator"):assign(env.server)
|
||||
empty(env.sent, "assigning to the server sends nothing")
|
||||
empty(env.events, "assigning to the server raises nothing")
|
||||
end)
|
||||
|
||||
return Suite.run()
|
||||
@@ -0,0 +1,83 @@
|
||||
--[[-- Test environment for module/control.lua
|
||||
The module specific extension between the shared stubs and the test files: it
|
||||
extends each environment with a fresh copy of the roles module and the
|
||||
fixtures below, and hands each test file a suite built around that.
|
||||
|
||||
Run as a chunk by test/lua/runner.js, receiving the shared folder. The suite
|
||||
returned here becomes `...` in each test file.
|
||||
]]
|
||||
|
||||
local shared_root = ... --- @type string
|
||||
local source = assert(debug.getinfo(1, "S")).source:gsub("\\", "/")
|
||||
local plugin_root = assert(source:match("^@(.*)/test/module/env%.lua$"))
|
||||
|
||||
local Framework = assert(loadfile(shared_root .. "/framework.lua"))() --- @type Framework
|
||||
|
||||
--- Standard fixture: permission names sent once and referenced by zero based index
|
||||
local permission_names = {
|
||||
"core.admin", -- 0
|
||||
"exp_scenario.command.kill", -- 1
|
||||
"exp_scenario.command.jail", -- 2
|
||||
"exp_scenario.player.admin", -- 3
|
||||
"exp_scenario.gui.readme", -- 4
|
||||
"exp_scenario.command.assign_role", -- 5
|
||||
}
|
||||
|
||||
local function meta(order, extra)
|
||||
local m = { id = 0, order = order }
|
||||
for k, v in pairs(extra or {}) do m[k] = v end
|
||||
return m
|
||||
end
|
||||
|
||||
--- Standard fixture: the roles as the controller would send them on initialise
|
||||
local function role_records()
|
||||
return {
|
||||
{ id = 0, name = "Cluster Admin", permissions = { 0 }, meta = meta(1, { short_hand = "SYS" }) },
|
||||
{ id = 5, name = "Moderator", permissions = { 1, 2, 3, 5 }, meta = meta(2, { color = { r = 0, g = 170, b = 0 } }) },
|
||||
{ id = 6, name = "Regular", permissions = { 1 }, meta = meta(3) },
|
||||
{ id = 7, name = "Jail", permissions = {}, meta = meta(4, { priority = 1, block_auto_assign = true }) },
|
||||
{ id = 1, name = "Player", permissions = { 4 }, meta = meta(5), is_default = true },
|
||||
{ id = 9, name = "Gone", permissions = {}, meta = meta(6), is_deleted = true },
|
||||
}
|
||||
end
|
||||
|
||||
--- Fixture role ids by name, avoiding a search of the roles on every lookup
|
||||
local role_ids = {}
|
||||
for _, record in ipairs(role_records()) do
|
||||
role_ids[record.name] = record.id
|
||||
end
|
||||
|
||||
return Framework.suite(function(env)
|
||||
env.Roles = assert(loadfile(plugin_root .. "/module/control.lua"))() --- @type ExpRoles
|
||||
env.Roles.on_server_startup()
|
||||
|
||||
--- Get a fixture role by name, failing the test when it does not exist
|
||||
--- Roles added by a test are found by a search instead
|
||||
function env.R(name)
|
||||
local role_id = role_ids[name]
|
||||
if role_id then
|
||||
return (assert(env.Roles.get_role(role_id), "No role with id " .. role_id))
|
||||
end
|
||||
return (assert(env.Roles.get_role_by_name(name), "No role named " .. name))
|
||||
end
|
||||
|
||||
--- An assignment record as the controller would send it, roles by name
|
||||
function env.assignment(player_name, role_names)
|
||||
local ids = {}
|
||||
for index, role_name in ipairs(role_names) do
|
||||
ids[index] = assert(role_ids[role_name], "No fixture role named " .. role_name)
|
||||
end
|
||||
return { name = player_name, role_ids = ids }
|
||||
end
|
||||
|
||||
--- Load the standard fixture and the given assignments
|
||||
function env.initialise(assignments)
|
||||
env.Roles.initialise{
|
||||
permission_names = permission_names,
|
||||
roles = role_records(),
|
||||
assignments = assignments or {},
|
||||
}
|
||||
end
|
||||
|
||||
return env
|
||||
end)
|
||||
@@ -0,0 +1,68 @@
|
||||
--- Tests for listing and printing to the players who hold a role
|
||||
local Suite = ... --- @type Suite 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.Roles._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()
|
||||
@@ -0,0 +1,71 @@
|
||||
--- Tests for the role lookup functions of module/control.lua
|
||||
local Suite = ... --- @type Suite The suite this file adds its tests to, see test/lua/framework.lua
|
||||
local test, check, eq = Suite.test, Suite.check, Suite.eq
|
||||
|
||||
test("get_role() returns the role with the given clusterio id", function(env)
|
||||
env.initialise{}
|
||||
check(env.Roles.get_role(env.R("Regular").id) == env.R("Regular"), "the role is found by id")
|
||||
eq(env.Roles.get_role(9), nil, "deleted roles are not known")
|
||||
end)
|
||||
|
||||
test("get_role_by_name() searches the roles", function(env)
|
||||
env.initialise{}
|
||||
check(env.Roles.get_role_by_name("Moderator") == env.R("Moderator"), "the role is found by name")
|
||||
eq(env.Roles.get_role_by_name("Gone"), nil, "deleted roles are not known")
|
||||
end)
|
||||
|
||||
test("get_roles() returns every role", function(env)
|
||||
env.initialise{}
|
||||
eq(Suite.sorted(Suite.names(env.Roles.get_roles())),
|
||||
{ "Cluster Admin", "Jail", "Moderator", "Player", "Regular" },
|
||||
"every role is returned with deleted roles skipped")
|
||||
end)
|
||||
|
||||
test("get_ordered_roles() returns the most privileged first", function(env)
|
||||
env.initialise{}
|
||||
eq(Suite.names(env.Roles.get_ordered_roles()), { "Cluster Admin", "Moderator", "Regular", "Jail", "Player" },
|
||||
"roles follow their order")
|
||||
end)
|
||||
|
||||
test("sort_roles() orders most privileged first and breaks ties on the id", function(env)
|
||||
env.initialise{}
|
||||
local sorted = env.Roles.sort_roles{ env.R("Player"), env.R("Cluster Admin"), env.R("Regular") }
|
||||
eq(Suite.names(sorted), { "Cluster Admin", "Regular", "Player" }, "the list is sorted in place")
|
||||
|
||||
-- A role with the same order as Regular but a higher id sorts after it
|
||||
env.Roles.receive_role_updates{
|
||||
{ id = 10, name = "Twin", permissions = {}, meta = { id = 0, order = env.R("Regular").order } },
|
||||
}
|
||||
local tied = env.Roles.sort_roles{ env.R("Twin"), env.R("Regular") }
|
||||
eq(Suite.names(tied), { "Regular", "Twin" }, "order ties break on the id")
|
||||
end)
|
||||
|
||||
test("get_default_role() follows is_default", function(env)
|
||||
env.initialise{}
|
||||
check(env.Roles.get_default_role() == env.R("Player"), "the default role is known")
|
||||
end)
|
||||
|
||||
test("get_higher_roles() and get_lower_roles() include the role and exclude the default", function(env)
|
||||
env.initialise{}
|
||||
eq(Suite.sorted(Suite.names(env.Roles.get_higher_roles(env.R("Regular")))),
|
||||
{ "Cluster Admin", "Moderator", "Regular" }, "higher roles")
|
||||
eq(Suite.sorted(Suite.names(env.Roles.get_lower_roles(env.R("Regular")))),
|
||||
{ "Jail", "Regular" }, "lower roles")
|
||||
end)
|
||||
|
||||
test(".is_higher_than() and .is_lower_than() compare on order", function(env)
|
||||
env.initialise{}
|
||||
check(env.R("Moderator"):is_higher_than(env.R("Player")), "a lower order is more privileged")
|
||||
check(env.R("Player"):is_lower_than(env.R("Moderator")), "is_lower_than is the reverse")
|
||||
check(not env.R("Moderator"):is_higher_than(env.R("Moderator")), "a role is not higher than itself")
|
||||
end)
|
||||
|
||||
test("initialise() decodes the role records", function(env)
|
||||
env.initialise{}
|
||||
eq(env.R("Cluster Admin").short_hand, "SYS", "short hand decoded")
|
||||
eq(env.R("Moderator").short_hand, "Moderator", "short hand falls back to the name")
|
||||
eq(env.R("Moderator").color, { r = 0, g = 170, b = 0 }, "color decoded")
|
||||
check(env.R("Jail").priority == 1 and env.R("Jail").block_auto_assign, "priority and block auto assign decoded")
|
||||
end)
|
||||
|
||||
return Suite.run()
|
||||
@@ -0,0 +1,95 @@
|
||||
--- Tests for the player checks of module/control.lua
|
||||
local Suite = ... --- @type Suite The suite this file adds its tests to, see test/lua/framework.lua
|
||||
local test, check, eq = Suite.test, Suite.check, Suite.eq
|
||||
|
||||
--- alice is a moderator, bob is a regular, and carol has only the default role
|
||||
local function setup(env)
|
||||
local players = {
|
||||
alice = env.add_player("alice"),
|
||||
bob = env.add_player("bob"),
|
||||
carol = env.add_player("carol"),
|
||||
}
|
||||
env.initialise{
|
||||
env.assignment("alice", { "Moderator" }),
|
||||
env.assignment("bob", { "Regular" }),
|
||||
}
|
||||
return players
|
||||
end
|
||||
|
||||
test("get_player_roles() includes the default role", function(env)
|
||||
local players = setup(env)
|
||||
eq(Suite.sorted(Suite.names(env.Roles.get_player_roles(players.alice))), { "Moderator", "Player" },
|
||||
"held roles and the default role")
|
||||
eq(Suite.names(env.Roles.get_player_roles(players.carol)), { "Player" },
|
||||
"a player with no roles has the default role")
|
||||
end)
|
||||
|
||||
test("get_player_roles() treats nil and index 0 as the server", function(env)
|
||||
setup(env)
|
||||
eq(Suite.names(env.Roles.get_player_roles(nil)), { "<server>" }, "nil is the server")
|
||||
eq(Suite.names(env.Roles.get_player_roles(env.server)), { "<server>" }, "index 0 is the server")
|
||||
check(env.Roles.player_has_permission(nil, "anything.at.all"), "the server has every permission")
|
||||
check(not env.R("Player"):has_player(nil), "the server does not have the default role")
|
||||
end)
|
||||
|
||||
test("get_player_highest_role() returns the most privileged role", function(env)
|
||||
local players = setup(env)
|
||||
check(env.Roles.get_player_highest_role(players.alice) == env.R("Moderator"), "the highest held role")
|
||||
check(env.Roles.get_player_highest_role(players.carol) == env.R("Player"), "the default role when none are held")
|
||||
end)
|
||||
|
||||
test("get_player_highest_role() errors when a player has no roles", function(env)
|
||||
local players = setup(env)
|
||||
env.Roles.receive_role_updates{
|
||||
{ id = env.R("Player").id, name = "Player", permissions = {}, meta = { id = 0, order = 5 }, is_deleted = true },
|
||||
}
|
||||
Suite.throws(function()
|
||||
env.Roles.get_player_highest_role(players.carol)
|
||||
end, "Player has no roles", "no default role and no held roles errors")
|
||||
end)
|
||||
|
||||
test("player_has_permission()", function(env)
|
||||
local players = setup(env)
|
||||
check(env.Roles.player_has_permission(players.alice, "exp_scenario.command.kill"), "granted by a held role")
|
||||
check(env.Roles.player_has_permission(players.alice, "exp_scenario.gui.readme"), "granted by the default role")
|
||||
check(not env.Roles.player_has_permission(players.bob, "exp_scenario.command.jail"), "not granted")
|
||||
end)
|
||||
|
||||
test("player_has_any_permission() and player_has_all_permission()", function(env)
|
||||
local players = setup(env)
|
||||
local jail, kill = "exp_scenario.command.jail", "exp_scenario.command.kill"
|
||||
check(env.Roles.player_has_any_permission(players.bob, jail, kill), "any passes when one is granted")
|
||||
check(not env.Roles.player_has_any_permission(players.bob, jail, "exp_scenario.command.assign_role"),
|
||||
"any fails when none are granted")
|
||||
check(not env.Roles.player_has_any_permission(players.bob), "any of none is false")
|
||||
check(env.Roles.player_has_all_permission(players.alice, jail, kill), "all passes when every one is granted")
|
||||
check(not env.Roles.player_has_all_permission(players.bob, jail, kill), "all fails when one is missing")
|
||||
check(env.Roles.player_has_all_permission(players.bob), "all of none is true")
|
||||
check(env.Roles.player_has_any_permission(nil, "anything.at.all"), "the server passes any")
|
||||
check(env.Roles.player_has_all_permission(nil, "anything.at.all", "and.this.too"), "the server passes all")
|
||||
end)
|
||||
|
||||
test(".has_permission()", function(env)
|
||||
setup(env)
|
||||
check(env.R("Moderator"):has_permission("exp_scenario.command.kill"), "granted")
|
||||
check(not env.R("Regular"):has_permission("exp_scenario.command.jail"), "not granted")
|
||||
check(env.R("Cluster Admin"):has_permission("anything.at.all"), "core.admin grants everything")
|
||||
end)
|
||||
|
||||
test(".has_player()", function(env)
|
||||
local players = setup(env)
|
||||
check(env.R("Moderator"):has_player(players.alice), "a held role")
|
||||
check(not env.R("Moderator"):has_player(players.bob), "a role not held")
|
||||
check(env.R("Player"):has_player(players.carol), "everyone has the default role")
|
||||
end)
|
||||
|
||||
test("player_outranks()", function(env)
|
||||
local players = setup(env)
|
||||
check(env.Roles.player_outranks(players.alice, players.bob), "a higher role outranks a lower one")
|
||||
check(not env.Roles.player_outranks(players.bob, players.alice), "a lower role does not outrank a higher one")
|
||||
check(not env.Roles.player_outranks(players.alice, players.alice), "nobody outranks themselves")
|
||||
check(env.Roles.player_outranks(nil, players.alice), "the server outranks everyone")
|
||||
check(not env.Roles.player_outranks(players.alice, nil), "nobody outranks the server")
|
||||
end)
|
||||
|
||||
return Suite.run()
|
||||
@@ -0,0 +1,154 @@
|
||||
--- Tests for the sync entry points of module/control.lua
|
||||
local Suite = ... --- @type Suite The suite this file adds its tests to, see test/lua/framework.lua
|
||||
local test, check, eq, empty = Suite.test, Suite.check, Suite.eq, Suite.empty
|
||||
|
||||
--- alice is a moderator and carol has only the default role, both connected
|
||||
local function setup(env)
|
||||
local players = {
|
||||
alice = env.add_player("alice"),
|
||||
carol = env.add_player("carol"),
|
||||
}
|
||||
env.admin_state = {}
|
||||
env.Roles.define_permission_trigger("exp_scenario.player.admin", function(player, state)
|
||||
env.admin_state[player.name] = state
|
||||
end)
|
||||
env.initialise{
|
||||
env.assignment("alice", { "Moderator" }),
|
||||
env.assignment("zed", { "Moderator", "Regular" }), -- has never joined this map
|
||||
}
|
||||
env.Roles.set_emit_events(true)
|
||||
return players
|
||||
end
|
||||
|
||||
test("initialise() applies triggers and raises empty events", function(env)
|
||||
setup(env)
|
||||
eq(env.admin_state, { alice = true, carol = false }, "triggers run for connected players")
|
||||
eq(#env.events, 2, "the event is raised once per connected player")
|
||||
empty(env.events[1].assigned, "the events assign nothing")
|
||||
empty(env.events[1].unassigned, "the events unassign nothing")
|
||||
empty(env.printed, "initialise is silent")
|
||||
empty(env.sent, "initialise sends nothing")
|
||||
empty(env.sounds, "initialise plays no sounds")
|
||||
end)
|
||||
|
||||
test("initialise() skips deleted assignments", function(env)
|
||||
local players = setup(env)
|
||||
local record = env.assignment("carol", { "Moderator" })
|
||||
record.is_deleted = true
|
||||
env.initialise{ record }
|
||||
check(not env.R("Moderator"):has_player(players.carol), "a deleted assignment is ignored")
|
||||
end)
|
||||
|
||||
test("initialise() is authoritative for pending roles", function(env)
|
||||
local players = setup(env)
|
||||
env.R("Moderator"):assign(players.carol)
|
||||
env.R("Jail"):assign(players.carol, { silent = true, local_only = true })
|
||||
|
||||
local sd = env.Roles._script_data()
|
||||
eq(sd.pending.carol, { env.R("Moderator").id }, "the role is pending before initialise")
|
||||
|
||||
env.reset_log()
|
||||
env.initialise{ env.assignment("alice", { "Moderator" }) }
|
||||
eq(sd.pending.carol, nil, "pending roles are cleared")
|
||||
check(not env.R("Moderator"):has_player(players.carol), "an unconfirmed role is given up")
|
||||
eq(sd.local_players.carol, { env.R("Jail").id }, "local only roles are kept")
|
||||
empty(env.sent, "initialise sends nothing")
|
||||
end)
|
||||
|
||||
test("receive_assignment_updates() applies controller changes", function(env)
|
||||
local players = setup(env)
|
||||
env.reset_log()
|
||||
env.Roles.receive_assignment_updates{ env.assignment("carol", { "Moderator" }) }
|
||||
check(env.R("Moderator"):has_player(players.carol), "the assignment applies")
|
||||
eq(env.events, {
|
||||
{
|
||||
name = env.Roles.events.on_player_roles_changed,
|
||||
tick = 1,
|
||||
player_index = players.carol.index,
|
||||
by_player_index = 0,
|
||||
assigned = { env.R("Moderator").id },
|
||||
unassigned = {},
|
||||
},
|
||||
}, "the event carries the change with no by player")
|
||||
eq(env.printed, {
|
||||
{ "exp-roles.game-message-assign", "carol", "Moderator", "<server>" },
|
||||
}, "the change is announced by the server")
|
||||
check(env.admin_state.carol == true, "triggers follow the assignment")
|
||||
|
||||
env.reset_log()
|
||||
env.Roles.receive_assignment_updates{ { name = "carol", role_ids = {}, is_deleted = true } }
|
||||
check(not env.R("Moderator"):has_player(players.carol), "a removal applies")
|
||||
eq(env.events[1].unassigned, { env.R("Moderator").id }, "the removal raises the event")
|
||||
check(env.admin_state.carol == false, "triggers follow the removal")
|
||||
end)
|
||||
|
||||
test("receive_assignment_updates() for players not on this map raises nothing", function(env)
|
||||
setup(env)
|
||||
env.reset_log()
|
||||
env.Roles.receive_assignment_updates{ env.assignment("zed", { "Moderator" }) }
|
||||
empty(env.events, "no event is raised")
|
||||
empty(env.printed, "nothing is announced")
|
||||
end)
|
||||
|
||||
test("receive_role_updates() applies to the holders", function(env)
|
||||
setup(env)
|
||||
env.reset_log()
|
||||
local regular_id = env.R("Regular").id
|
||||
env.Roles.receive_role_updates{
|
||||
{ id = regular_id, name = "Regular", permissions = { "exp_scenario.command.jail" }, meta = { id = 0, order = 3 } },
|
||||
}
|
||||
check(env.R("Regular"):has_permission("exp_scenario.command.jail"), "the permission change applies")
|
||||
eq(#env.events, 2, "a role change raises for every connected player")
|
||||
empty(env.events[1].assigned, "role change events are empty")
|
||||
|
||||
env.Roles.receive_role_updates{
|
||||
{ id = regular_id, name = "Regular", permissions = {}, meta = { id = 0, order = 3 }, is_deleted = true },
|
||||
}
|
||||
eq(env.Roles.get_role(regular_id), nil, "a deleted role is removed")
|
||||
end)
|
||||
|
||||
test("receive_role_updates() moves the default role", function(env)
|
||||
local players = setup(env)
|
||||
env.Roles.receive_role_updates{
|
||||
{ id = env.R("Player").id, name = "Player", permissions = {}, meta = { id = 0, order = 5 } },
|
||||
{ id = 8, name = "Guest", permissions = {}, meta = { id = 0, order = 7 }, is_default = true },
|
||||
}
|
||||
check(env.Roles.get_default_role() == env.R("Guest"), "the new default role is known")
|
||||
eq(Suite.names(env.Roles.get_player_roles(players.carol)), { "Guest" }, "players pick up the new default")
|
||||
end)
|
||||
|
||||
test("set_emit_events() gates what is sent and defaults to enabled", function(env)
|
||||
local players = setup(env)
|
||||
env.Roles.set_emit_events(false)
|
||||
env.reset_log()
|
||||
env.R("Regular"):assign(players.alice)
|
||||
empty(env.sent, "nothing is sent while disabled")
|
||||
check(env.R("Regular"):has_player(players.alice), "the assignment still applies locally")
|
||||
|
||||
env.Roles.set_emit_events()
|
||||
env.R("Jail"):assign(players.alice, { silent = true })
|
||||
eq(env.sent, {
|
||||
{ channel = "exp_roles:assignment_update", data = { name = "alice", assign = { env.R("Jail").id } } },
|
||||
}, "no argument enables sending")
|
||||
end)
|
||||
|
||||
test("on_load() restores the state after a save and load", function(env)
|
||||
local players = setup(env)
|
||||
env.R("Jail"):assign(players.carol, { silent = true, local_only = true })
|
||||
env.save_load()
|
||||
env.Roles.on_load()
|
||||
|
||||
check(env.R("Moderator"):is_higher_than(env.R("Regular")), "role methods survive through the registered metatable")
|
||||
check(env.R("Moderator"):has_player(players.alice), "synced roles survive")
|
||||
check(env.R("Jail"):has_player(players.carol), "local roles survive")
|
||||
check(env.Roles.player_has_permission(players.alice, "exp_scenario.command.kill"), "permission checks still answer")
|
||||
end)
|
||||
|
||||
test("on_player_joined_game() runs the triggers", function(env)
|
||||
local players = setup(env)
|
||||
env.admin_state.alice = nil
|
||||
env.Roles.on_player_joined_game{ player_index = players.alice.index }
|
||||
check(env.admin_state.alice ~= nil, "triggers run when a player joins")
|
||||
end)
|
||||
|
||||
return Suite.run()
|
||||
Reference in New Issue
Block a user