--[[
	deviation: the toStrictEqual matcher in Jest adds three features beyond
	that of the toEqual matcher:
		1) Checking for undefined properties
		2) Checking array sparseness
		3) Type checking

	Of these, Jest-Roblox's version of the toStrictEqual matcher only
	applies type checking
]]

local function toStrictEqual(
	-- ROBLOX deviation: self param in Lua needs to be explicitely defined
	self: MatcherState,
	received: any,
	expected: any
)
	local matcherName = "toStrictEqual"
	local options: MatcherHintOptions = {
		comment = "deep equality",
		isNot = self.isNot,
		promise = self.promise,
	}

	local pass = equals(received, expected, toStrictEqualTesters, true)

	local message
	if pass then
		message = function()
			local retval = matcherHint(matcherName, nil, nil, options)
				.. "\n\n"
				.. string.format("Expected: not %s\n", printExpected(expected))

			if stringify(expected) ~= stringify(received) then
				retval = retval .. string.format("Received:     %s", printReceived(received))
			end

			return retval
		end
	else
		message = function()
			return matcherHint(matcherName, nil, nil, options)
				.. "\n\n"
				.. printDiffOrStringify(expected, received, EXPECTED_LABEL, RECEIVED_LABEL, isExpand(self.expand))
		end
	end
	-- Passing the actual and expected objects so that a custom reporter
	-- could access them, for example in order to display a custom visual diff,
	-- or create a different error message
	return { actual = received, expected = expected, message = message, name = matcherName, pass = pass }
end
