local L=require(script.Parent.symbols)local A=require(script.Parent.isAMagicMock)local g={}g.__index=g g.__call=function(L,...)return L.inner(...)end local E={}setmetatable(E,{__mode="\107\118"})function g.new(A)local m={[L.isSpy]=true;[L.Calls]={}}setmetatable(m,g)local r=function(...)local g={args=table.pack(...),result=table.pack(A(...))}table.insert(m[L.Calls],g)return table.unpack(g.result)end m.inner=r E[r]=m return m,r end function g.lookup(L)return E[L]end function g.is(g)if not A(g)then return type(g)=="\116\097\098\108\101"and g[L.isSpy]~=nil end return false end return g
-- Create a wrapper around a function to capture what arguments it was called
-- with.

local symbols = require(script.Parent.symbols)
local isAMagicMock = require(script.Parent.isAMagicMock)

local Spy = {}
Spy.__index = Spy
Spy.__call = function(self, ...)
	return self.inner(...)
end

local spyLookup = {}
setmetatable(spyLookup, { __mode = "kv" })

function Spy.new(inner)
	local spy = {
		[symbols.isSpy] = true,
		[symbols.Calls] = {},
	}
	setmetatable(spy, Spy)

	local wrapper = function(...)
		local call = {
			args = table.pack(...),
			result = table.pack(inner(...)),
		}
		table.insert(spy[symbols.Calls], call)
		return table.unpack(call.result)
	end

	spy.inner = wrapper
	spyLookup[wrapper] = spy

	return spy, wrapper
end

function Spy.lookup(wrapper)
	return spyLookup[wrapper]
end

function Spy.is(object)
	if not isAMagicMock(object) then
		return type(object) == "table" and object[symbols.isSpy] ~= nil
	end

	return false
end

return Spy
