diff --git a/features/death_corpse_tags_tests.lua b/features/death_corpse_tags_tests.lua index 0ce7f81fa..d2f830182 100644 --- a/features/death_corpse_tags_tests.lua +++ b/features/death_corpse_tags_tests.lua @@ -69,13 +69,17 @@ Declare.module({'features', 'death_corpse_tags'}, function() local actual_text - Helper.modify_lua_object(context, player, 'print', function(text) - actual_text = text - end) - - Helper.modify_lua_object(context, game, 'get_player', function() - return player - end) + local fake_player = Helper.fake_lua_object(player, { + print = function(text) + actual_text = text + end + }) + + Helper.modify_global(context, 'game', Helper.fake_lua_object(game, { + get_player = function() + return fake_player + end + })) local event = fake_death(player, false) diff --git a/features/landfill_remover_tests.lua b/features/landfill_remover_tests.lua index 45716c23c..14286085e 100644 --- a/features/landfill_remover_tests.lua +++ b/features/landfill_remover_tests.lua @@ -727,13 +727,17 @@ Declare.module( local messages = {} - Helper.modify_lua_object(context, player, 'print', function(text) - messages[#messages+1] = text - end) - - Helper.modify_lua_object(context, game, 'get_player', function() - return player - end) + local fake_player = Helper.fake_lua_object(player, { + print = function(text) + messages[#messages+1] = text + end + }) + + Helper.modify_global(context, 'game', Helper.fake_lua_object(game, { + get_player = function() + return fake_player + end + })) -- Act EventFactory.do_player_deconstruct_area(cursor, player, area) @@ -765,13 +769,17 @@ Declare.module( local messages = {} - Helper.modify_lua_object(context, player, 'print', function(text) - messages[#messages+1] = text - end) - - Helper.modify_lua_object(context, game, 'get_player', function() - return player - end) + local fake_player = Helper.fake_lua_object(player, { + print = function(text) + messages[#messages+1] = text + end + }) + + Helper.modify_global(context, 'game', Helper.fake_lua_object(game, { + get_player = function() + return fake_player + end + })) -- Act EventFactory.do_player_deconstruct_area(cursor, player, area) diff --git a/features/restart_command_tests.lua b/features/restart_command_tests.lua index b3150d12c..9958fbf0a 100644 --- a/features/restart_command_tests.lua +++ b/features/restart_command_tests.lua @@ -137,10 +137,12 @@ Declare.module({'features', 'restart_command'}, function() declare_test('Requires admin to run command.', function(context) -- Arrange. local player = context.player - Helper.modify_lua_object(context, player, 'admin', false) - Helper.modify_lua_object(context, game, 'get_player', function() - return player - end) + local fake_player = Helper.fake_lua_object(player, { admin = false }) + Helper.modify_global(context, 'game', Helper.fake_lua_object(game, { + get_player = function() + return fake_player + end + })) -- Act. run_config_command(player) @@ -155,12 +157,16 @@ Declare.module({'features', 'restart_command'}, function() -- Arrange. local player = context.player local actual = nil - Helper.modify_lua_object(context, player, 'print', function(str) - actual = str - end) - Helper.modify_lua_object(context, game, 'get_player', function() - return player - end) + local fake_player = Helper.fake_lua_object(player, { + print = function(str) + actual = str + end + }) + Helper.modify_global(context, 'game', Helper.fake_lua_object(game, { + get_player = function() + return fake_player + end + })) local start_game_data = { type = RestartCommand.game_types.scenario, @@ -345,7 +351,7 @@ Mod Pack: some_mod_pack]] output[#output + 1] = str end - Helper.modify_lua_object(context, game, 'print', game_print) + Helper.modify_global(context, 'game', Helper.fake_lua_object(game, { print = game_print })) -- Act. run_restart_command(player) @@ -376,7 +382,7 @@ Mod Pack: some_mod_pack]] output[#output + 1] = str end - Helper.modify_lua_object(context, game, 'print', game_print) + Helper.modify_global(context, 'game', Helper.fake_lua_object(game, { print = game_print })) -- Act. run_restart_command(player, argument) diff --git a/utils/gui_tests.lua b/utils/gui_tests.lua index bc0577b11..5854d83c7 100644 --- a/utils/gui_tests.lua +++ b/utils/gui_tests.lua @@ -6,9 +6,19 @@ local Helper = require 'utils.test.helper' Declare.module({'utils', 'Gui'}, function() Declare.module('can toggle top buttons', function() local function count_gui_elements(player) - -- local gui = player.gui - -- return #gui.top.children + #gui.left.children + #gui.center.children + #gui.screen.children - return #Gui.get_top_flow(player).children + #Gui.get_left_flow(player).children + #player.gui.center.children + #player.gui.screen.children + local roots = {Gui.get_top_flow(player), Gui.get_left_flow(player), player.gui.center, player.gui.screen} + local count = 0 + for _, root in pairs(roots) do + for _, child in pairs(root.children) do + -- Only visible elements count as open: some GUIs, such as the + -- production hud, hide their frame on close instead of + -- destroying it, to preserve its screen position. + if child.visible then + count = count + 1 + end + end + end + return count end local function is_ignored_element(element) diff --git a/utils/test/helper.lua b/utils/test/helper.lua index 5edaf6056..eec1ed06b 100644 --- a/utils/test/helper.lua +++ b/utils/test/helper.lua @@ -91,6 +91,10 @@ function Public.wait_for_chunk_to_be_charted(context, force, surface, chunk_posi end function Public.modify_lua_object(context, object, key, value) + if type(object) ~= 'table' then + error('LuaObjects are userdata since Factorio 2.0 and cannot be modified; use Helper.fake_lua_object and Helper.modify_global instead.', 2) + end + local old_value = object[key] rawset(object, key, value) @@ -99,6 +103,30 @@ function Public.modify_lua_object(context, object, key, value) end) end +-- LuaObjects are userdata since Factorio 2.0, so their fields cannot be +-- replaced. Returns a table that reads and writes through to the given object, +-- except for the overridden fields. +function Public.fake_lua_object(object, overrides) + return setmetatable(overrides or {}, { + __index = function(_, key) + return object[key] + end, + __newindex = function(_, key, value) + object[key] = value + end + }) +end + +-- Replaces a global variable, e.g. the 'game' object, until test teardown. +function Public.modify_global(context, name, value) + local old_value = _G[name] + rawset(_G, name, value) + + context:add_teardown(function() + rawset(_G, name, old_value) + end) +end + local function get_gui_element_by_name(parent, name) if parent.name == name then return parent