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>
This commit is contained in:
bbassie
2026-09-01 06:09:40 +00:00
co-authored by Claude Fable 5
parent 59df8bdff3
commit 08fe6b688e
8 changed files with 109 additions and 37 deletions
+13 -4
View File
@@ -51,11 +51,15 @@ end
--- Create an independent set of stubs, installed as the lua globals
function Stubs.new()
--- @class Stubs
--- @field events table[] Events raised through script.raise_event, name and tick filled in
--- @field printed (LocalisedString | { to: string, [1]: LocalisedString })[] Messages from game.print and player.print
--- @field sent { channel: string, data: table }[] Payloads sent through the clusterio api
--- @field sounds string[] Sounds played to players, as "player:path"
local stubs = {
events = {}, -- events raised through script.raise_event
printed = {}, -- game.print and player.print messages
sent = {}, -- payloads sent through the clusterio api
sounds = {}, -- sounds played to players
events = {},
printed = {},
sent = {},
sounds = {},
}
local next_event_id = 100
@@ -97,8 +101,12 @@ function Stubs.new()
}, { "player" })
--- Add a player to the stubbed game, indexes are assigned in join order
--- @param name string
--- @param is_connected boolean? Defaults to connected
--- @return Stubs.Player
function stubs.add_player(name, is_connected)
local index = #players_by_index + 1
--- @class Stubs.Player
local player = Stubs.strict("LuaPlayer " .. name, {
name = name,
index = index,
@@ -118,6 +126,7 @@ function Stubs.new()
end
--- A player object which represents the server
--- @type Stubs.Player
stubs.server = Stubs.strict("LuaPlayer <server>", { index = 0, name = "<server>" })
--- Modules resolved by the stubbed require, add to them with extend_requires