-- Cat Haven - Test Helper -- LOVR API mocks and test utilities local mocks = {} -- Mock LOVR graphics API mocks.lovr = { graphics = { newImage = function(pixels, width, height, options) return { type = 'image', pixels = pixels, width = width, height = height } end, newTexture = function(image) return { type = 'texture', image = image } end, newMesh = function(vertices, indices, mode) return { type = 'mesh', vertices = vertices, indices = indices, mode = mode } end, newMaterial = function(texture) return { type = 'material', texture = texture } end, newModel = function(mesh) return { type = 'model', mesh = mesh } end, box = function(mode, x, y, z, w, h, d, color, thickness) return { type = 'box', mode = mode, x = x, y = y, z = z, w = w, h = h, d = d, color = color } end, text = function(text, x, y, z, size, color, align) return { type = 'text', text = text, x = x, y = y, z = z, size = size, color = color, align = align } end }, audio = { newSource = function(data, bufferType, sampleRate, channels) return { type = 'source', data = data, bufferType = bufferType, sampleRate = sampleRate, channels = channels, spatial = false, looping = false, volume = 1.0, position = { 0, 0, 0 }, rolloff = 1.0, maxDistance = 10.0 } end }, system = { getWindowDimensions = function() return 1280, 720 end, getMousePosition = function() return 640, 360 end }, headset = { isDown = function(button) return false end }, filesystem = { newFile = function(filename, mode) return { filename = filename, mode = mode, content = '', write = function(self, data) self.content = self.content .. data end, read = function(self, spec) if spec == '*a' then return self.content end end, close = function(self) end } end }, data = { newImage = function(pixels, width, height, options) return { type = 'image', pixels = pixels, width = width, height = height } end, newModelData = function() return { type = 'modeldata' } end } } -- Mock LOVR filesystem for save/load tests mocks.setupFilesystem = function(saveData) local originalNewFile = mocks.lovr.filesystem.newFile mocks.lovr.filesystem.newFile = function(filename, mode) if filename == 'savegame.json' then if mode == 'w' then return { filename = filename, mode = mode, content = '', write = function(self, data) self.content = data end, read = function(self, spec) return saveData or '' end, close = function(self) end } elseif mode == 'r' then return { filename = filename, mode = mode, content = saveData or '', write = function(self, data) end, read = function(self, spec) if spec == '*a' then return self.content end end, close = function(self) end } end end return originalNewFile(filename, mode) end end -- Reset mocks mocks.reset = function() mocks.lovr.filesystem.newFile = function(filename, mode) return { filename = filename, mode = mode, content = '', write = function(self, data) self.content = self.content .. data end, read = function(self, spec) if spec == '*a' then return self.content end end, close = function(self) end } end end -- Test utilities local utils = {} utils.assertDeepEqual = function(actual, expected, msg) if type(actual) ~= 'table' or type(expected) ~= 'table' then assert(actual == expected, msg or 'Values not equal') return end for k, v in pairs(actual) do if type(v) == 'table' then utils.assertDeepEqual(v, expected[k], msg .. ': table[' .. k .. ']') else assert(v == expected[k], msg .. ': field[' .. k .. '] expected ' .. tostring(expected[k]) .. ', got ' .. tostring(v)) end end for k, v in pairs(expected) do if actual[k] == nil then assert(false, msg .. ': missing field[' .. k .. ']') end end end utils.createMockPass = function() return { box = function(mode, x, y, z, w, h, d, color, thickness) return { mode = mode, x = x, y = y, z = z, w = w, h = h, d = d, color = color } end, text = function(text, x, y, z, size, color, align) return { text = text, x = x, y = y, z = z, size = size, color = color, align = align } end } end utils.createMockCat = function(overrides) return { id = overrides.id or 1, name = overrides.name or 'Test Cat', personality = overrides.personality or { id = 'social', color = { 0.9, 0.6, 0.7 } }, position = overrides.position or { x = 0, y = 0, z = 0 }, targetPosition = overrides.targetPosition, state = overrides.state or 'idle', mood = overrides.mood or 0.8, needs = overrides.needs or { comfort = 0.7, social = 0.7, hunger = 0.7, fun = 0.7 }, favoriteSpots = overrides.favoriteSpots or {}, history = overrides.history or { arrivals = 1, departures = 0, totalHappiness = 0 }, animationTime = overrides.animationTime or 0, isSleeping = overrides.isSleeping or false, sleepTimer = overrides.sleepTimer or 0, update = function(self, dt) end, updateNeeds = function(self) end, serialize = function(self) return { id = self.id, name = self.name, personalityId = self.personality.id, position = self.position, state = self.state, mood = self.mood, needs = self.needs, favoriteSpots = self.favoriteSpots, history = self.history, isSleeping = self.isSleeping } end } end utils.createMockFurniture = function(overrides) return { type = overrides.type or { id = 'bed', name = 'Cozy Bed', baseHappiness = 0.7, comfortBonus = 0.6, socialBonus = 0.1, funBonus = 0.1, maxOccupants = 2, color = { 0.8, 0.6, 0.7 }, size = { 1, 0.3, 1 } }, position = overrides.position or { x = 0, y = 0, z = 0 }, state = overrides.state or 'placed', upgradeLevel = overrides.upgradeLevel or 1, occupant = overrides.occupant, happinessContribution = overrides.happinessContribution or 0.7, upgrade = function(self) if self.upgradeLevel < 3 then self.upgradeLevel = self.upgradeLevel + 1 self.happinessContribution = self.type.baseHappiness * self.upgradeLevel * 0.8 return true end return false end, serialize = function(self) return { typeId = self.type.id, position = self.position, state = self.state, upgradeLevel = self.upgradeLevel, occupant = self.occupant and self.occupant.id or nil, happinessContribution = self.happinessContribution } end } end return { mocks = mocks, utils = utils }