local B=require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\106\101\115\116-\103\108\111\098\097\108\115")local P=B.describe local Y=B.xit local z=B.beforeEach local H=B.expect local q=B.jest local t=_G local n={patch=function(...)print("\067\111\110\115\111\108\101\046\112\097\116\099\104",...)end;unpatch=function(...)print("\067\111\110\115\111\108\101\046\117\110\112\097\116\099\104",...)end;dangerous_setTargetConsoleForTesting=function(...) end,registerRenderer=function(...) end}local y local O local D=require("\046\047\117\116\105\108\115")P("\099\111\110\115\111\108\101",function()local B local P local e local N local L local F local w local I z(function()q.resetModules()w=n.patch I=n.unpatch e=q.fn()N=q.fn()L=q.fn()F=q.fn()P={error=e,info=N,log=L;warn=F}n.dangerous_setTargetConsoleForTesting(P)w({appendComponentStack=true,breakOnWarn=false})local Y=t.__REACT_DEVTOOLS_GLOBAL_HOOK__.inject t.__REACT_DEVTOOLS_GLOBAL_HOOK__.inject=function(B)Y(B)n.registerRenderer(B)end y=require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\114\101\097\099\116")O=require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\114\101\097\099\116-\114\111\098\108\111\120")B=D.act end)local function M(B)return B end Y("\115\104\111\117\108\100 \110\111\116 \112\097\116\099\104 \099\111\110\115\111\108\101 \109\101\116\104\111\100\115 \116\104\097\116 \100\111 \110\111\116 \114\101\099\101\105\118\101 \099\111\109\112\111\110\101\110\116 \115\116\097\099\107\115",function()(H(P.error)).never.toBe(e);(H(P.info)).toBe(N);(H(P.log)).toBe(L);(H(P.warn)).never.toBe(F)end)Y("\115\104\111\117\108\100 \111\110\108\121 \112\097\116\099\104 \116\104\101 \099\111\110\115\111\108\101 \111\110\099\101",function()local B=P.error local Y=P.warn w({appendComponentStack=true,breakOnWarn=false});(H(P.error)).toBe(B);(H(P.warn)).toBe(Y)end)Y("\115\104\111\117\108\100 \117\110-\112\097\116\099\104 \119\104\101\110 \114\101\113\117\101\115\116\101\100",function()(H(P.error)).never.toBe(e);(H(P.warn)).never.toBe(F)I();(H(P.error)).toBe(e);(H(P.warn)).toBe(F)end)Y("\115\104\111\117\108\100 \112\097\115\115 \116\104\114\111\117\103\104 \108\111\103\115 \119\104\101\110 \116\104\101\114\101 \105\115 \110\111 \099\117\114\114\101\110\116 \102\105\098\101\114",function()(H(L)).toHaveBeenCalledTimes(0);(H(F)).toHaveBeenCalledTimes(0);(H(e)).toHaveBeenCalledTimes(0)P.log("\108\111\103")P.warn("\119\097\114\110")P.error("\101\114\114\111\114");(H(L)).toHaveBeenCalledTimes(1);(H(L.mock.calls[0])).toHaveLength(1);(H(L.mock.calls[0][0])).toBe("\108\111\103");(H(F)).toHaveBeenCalledTimes(1);(H(F.mock.calls[0])).toHaveLength(1);(H(F.mock.calls[0][0])).toBe("\119\097\114\110");(H(e)).toHaveBeenCalledTimes(1);(H(e.mock.calls[0])).toHaveLength(1);(H(e.mock.calls[0][0])).toBe("\101\114\114\111\114")end)Y("\115\104\111\117\108\100 \110\111\116 \097\112\112\101\110\100 \109\117\108\116\105\112\108\101 \115\116\097\099\107\115",function()local Y=function()P.warn("\119\097\114\110\n    \105\110 \067\104\105\108\100 \040\097\116 \102\097\107\101\046\106\115\058\049\050\051\041")P.error("\101\114\114\111\114","\n    \105\110 \067\104\105\108\100 \040\097\116 \102\097\107\101\046\106\115\058\049\050\051\041")return nil end local z=O.createRoot(Instance.new("\070\114\097\109\101"))B(function()return z:render(y.createElement(Y))end);(H(F)).toHaveBeenCalledTimes(1);(H(F.mock.calls[0])).toHaveLength(1);(H(F.mock.calls[0][0])).toBe("\119\097\114\110\n    \105\110 \067\104\105\108\100 \040\097\116 \102\097\107\101\046\106\115\058\049\050\051\041");(H(e)).toHaveBeenCalledTimes(1);(H(e.mock.calls[0])).toHaveLength(2);(H(e.mock.calls[0][0])).toBe("\101\114\114\111\114");(H(e.mock.calls[0][1])).toBe("\n    \105\110 \067\104\105\108\100 \040\097\116 \102\097\107\101\046\106\115\058\049\050\051\041")end)Y("\115\104\111\117\108\100 \097\112\112\101\110\100 \099\111\109\112\111\110\101\110\116 \115\116\097\099\107\115 \116\111 \101\114\114\111\114\115 \097\110\100 \119\097\114\110\105\110\103\115 \108\111\103\103\101\100 \100\117\114\105\110\103 \114\101\110\100\101\114",function()local Y=function(B)local P=B.children return P end local z=function(B)local Y=B.children P.error("\101\114\114\111\114")P.log("\108\111\103")P.warn("\119\097\114\110")return nil end local q=function(B)local P=B.children return y.createElement(Y,nil,y.createElement(z,nil))end local t=O.createRoot(Instance.new("\070\114\097\109\101"))B(function()return t:render(y.createElement(q,nil))end);(H(L)).toHaveBeenCalledTimes(1);(H(L.mock.calls[0])).toHaveLength(1);(H(L.mock.calls[0][0])).toBe("\108\111\103");(H(F)).toHaveBeenCalledTimes(1);(H(F.mock.calls[0])).toHaveLength(2);(H(F.mock.calls[0][0])).toBe("\119\097\114\110");(H(M(F.mock.calls[0][1]))).toEqual("\n    \105\110 \067\104\105\108\100 \040\097\116 \042\042\041\n    \105\110 \073\110\116\101\114\109\101\100\105\097\116\101 \040\097\116 \042\042\041\n    \105\110 \080\097\114\101\110\116 \040\097\116 \042\042\041");(H(e)).toHaveBeenCalledTimes(1);(H(e.mock.calls[0])).toHaveLength(2);(H(e.mock.calls[0][0])).toBe("\101\114\114\111\114");(H(M(e.mock.calls[0][1]))).toBe("\n    \105\110 \067\104\105\108\100 \040\097\116 \042\042\041\n    \105\110 \073\110\116\101\114\109\101\100\105\097\116\101 \040\097\116 \042\042\041\n    \105\110 \080\097\114\101\110\116 \040\097\116 \042\042\041")end)Y("\115\104\111\117\108\100 \097\112\112\101\110\100 \099\111\109\112\111\110\101\110\116 \115\116\097\099\107\115 \116\111 \101\114\114\111\114\115 \097\110\100 \119\097\114\110\105\110\103\115 \108\111\103\103\101\100 \102\114\111\109 \101\102\102\101\099\116\115",function()local Y=function(B)local P=B.children return P end local z=function(B)local Y=B.children y.useLayoutEffect(function()P.error("\097\099\116\105\118\101 \101\114\114\111\114")P.log("\097\099\116\105\118\101 \108\111\103")P.warn("\097\099\116\105\118\101 \119\097\114\110")end)y.useEffect(function()P.error("\112\097\115\115\105\118\101 \101\114\114\111\114")P.log("\112\097\115\115\105\118\101 \108\111\103")P.warn("\112\097\115\115\105\118\101 \119\097\114\110")end)return nil end local q=function(B)local P=B.children return y.createElement(Y,nil,y.createElement(z,nil))end local t=O.createRoot(Instance.new("\070\114\097\109\101"))B(function()return t:render(y.createElement(q,nil))end);(H(L)).toHaveBeenCalledTimes(2);(H(L.mock.calls[0])).toHaveLength(1);(H(L.mock.calls[0][0])).toBe("\097\099\116\105\118\101 \108\111\103");(H(L.mock.calls[1])).toHaveLength(1);(H(L.mock.calls[1][0])).toBe("\112\097\115\115\105\118\101 \108\111\103");(H(F)).toHaveBeenCalledTimes(2);(H(F.mock.calls[0])).toHaveLength(2);(H(F.mock.calls[0][0])).toBe("\097\099\116\105\118\101 \119\097\114\110");(H(M(F.mock.calls[0][1]))).toEqual("\n    \105\110 \067\104\105\108\100 \040\097\116 \042\042\041\n    \105\110 \073\110\116\101\114\109\101\100\105\097\116\101 \040\097\116 \042\042\041\n    \105\110 \080\097\114\101\110\116 \040\097\116 \042\042\041");(H(F.mock.calls[1])).toHaveLength(2);(H(F.mock.calls[1][0])).toBe("\112\097\115\115\105\118\101 \119\097\114\110");(H(M(F.mock.calls[1][1]))).toEqual("\n    \105\110 \067\104\105\108\100 \040\097\116 \042\042\041\n    \105\110 \073\110\116\101\114\109\101\100\105\097\116\101 \040\097\116 \042\042\041\n    \105\110 \080\097\114\101\110\116 \040\097\116 \042\042\041");(H(e)).toHaveBeenCalledTimes(2);(H(e.mock.calls[0])).toHaveLength(2);(H(e.mock.calls[0][0])).toBe("\097\099\116\105\118\101 \101\114\114\111\114");(H(M(e.mock.calls[0][1]))).toBe("\n    \105\110 \067\104\105\108\100 \040\097\116 \042\042\041\n    \105\110 \073\110\116\101\114\109\101\100\105\097\116\101 \040\097\116 \042\042\041\n    \105\110 \080\097\114\101\110\116 \040\097\116 \042\042\041");(H(e.mock.calls[1])).toHaveLength(2);(H(e.mock.calls[1][0])).toBe("\112\097\115\115\105\118\101 \101\114\114\111\114");(H(M(e.mock.calls[1][1]))).toBe("\n    \105\110 \067\104\105\108\100 \040\097\116 \042\042\041\n    \105\110 \073\110\116\101\114\109\101\100\105\097\116\101 \040\097\116 \042\042\041\n    \105\110 \080\097\114\101\110\116 \040\097\116 \042\042\041")end)Y("\115\104\111\117\108\100 \097\112\112\101\110\100 \099\111\109\112\111\110\101\110\116 \115\116\097\099\107\115 \116\111 \101\114\114\111\114\115 \097\110\100 \119\097\114\110\105\110\103\115 \108\111\103\103\101\100 \102\114\111\109 \099\111\109\109\105\116 \104\111\111\107\115",function()local Y=function(B)local P=B.children return P end local z=y.Component:extend("\067\104\105\108\100")local q=function(B)local P=B.children return y.createElement(Y,nil,y.createElement(z,nil))end function z.componentDidMount(B)P.error("\100\105\100\077\111\117\110\116 \101\114\114\111\114")P.log("\100\105\100\077\111\117\110\116 \108\111\103")P.warn("\100\105\100\077\111\117\110\116 \119\097\114\110")end function z.componentDidUpdate(B)P.error("\100\105\100\085\112\100\097\116\101 \101\114\114\111\114")P.log("\100\105\100\085\112\100\097\116\101 \108\111\103")P.warn("\100\105\100\085\112\100\097\116\101 \119\097\114\110")end function z.render(B)return nil end local t=O.createRoot(Instance.new("\070\114\097\109\101"))B(function()return t:render(y.createElement(q,nil))end)B(function()return t:render(y.createElement(q,nil))end);(H(L)).toHaveBeenCalledTimes(2);(H(L.mock.calls[0])).toHaveLength(1);(H(L.mock.calls[0][0])).toBe("\100\105\100\077\111\117\110\116 \108\111\103");(H(L.mock.calls[1])).toHaveLength(1);(H(L.mock.calls[1][0])).toBe("\100\105\100\085\112\100\097\116\101 \108\111\103");(H(F)).toHaveBeenCalledTimes(2);(H(F.mock.calls[0])).toHaveLength(2);(H(F.mock.calls[0][0])).toBe("\100\105\100\077\111\117\110\116 \119\097\114\110");(H(M(F.mock.calls[0][1]))).toEqual("\n    \105\110 \067\104\105\108\100 \040\097\116 \042\042\041\n    \105\110 \073\110\116\101\114\109\101\100\105\097\116\101 \040\097\116 \042\042\041\n    \105\110 \080\097\114\101\110\116 \040\097\116 \042\042\041");(H(F.mock.calls[1])).toHaveLength(2);(H(F.mock.calls[1][0])).toBe("\100\105\100\085\112\100\097\116\101 \119\097\114\110");(H(M(F.mock.calls[1][1]))).toEqual("\n    \105\110 \067\104\105\108\100 \040\097\116 \042\042\041\n    \105\110 \073\110\116\101\114\109\101\100\105\097\116\101 \040\097\116 \042\042\041\n    \105\110 \080\097\114\101\110\116 \040\097\116 \042\042\041");(H(e)).toHaveBeenCalledTimes(2);(H(e.mock.calls[0])).toHaveLength(2);(H(e.mock.calls[0][0])).toBe("\100\105\100\077\111\117\110\116 \101\114\114\111\114");(H(M(e.mock.calls[0][1]))).toBe("\n    \105\110 \067\104\105\108\100 \040\097\116 \042\042\041\n    \105\110 \073\110\116\101\114\109\101\100\105\097\116\101 \040\097\116 \042\042\041\n    \105\110 \080\097\114\101\110\116 \040\097\116 \042\042\041");(H(e.mock.calls[1])).toHaveLength(2);(H(e.mock.calls[1][0])).toBe("\100\105\100\085\112\100\097\116\101 \101\114\114\111\114");(H(M(e.mock.calls[1][1]))).toBe("\n    \105\110 \067\104\105\108\100 \040\097\116 \042\042\041\n    \105\110 \073\110\116\101\114\109\101\100\105\097\116\101 \040\097\116 \042\042\041\n    \105\110 \080\097\114\101\110\116 \040\097\116 \042\042\041")end)Y("\115\104\111\117\108\100 \097\112\112\101\110\100 \099\111\109\112\111\110\101\110\116 \115\116\097\099\107\115 \116\111 \101\114\114\111\114\115 \097\110\100 \119\097\114\110\105\110\103\115 \108\111\103\103\101\100 \102\114\111\109 \103\068\083\070\080",function()local Y=function(B)local P=B.children return P end local z=y.Component:extend("\067\104\105\108\100")local q=function(B)local P=B.children return y.createElement(Y,nil,y.createElement(z))end function z.getDerivedStateFromProps()P.error("\101\114\114\111\114")P.log("\108\111\103")P.warn("\119\097\114\110")return nil end function z.render(B)return nil end local t=O.createRoot(Instance.new("\070\114\097\109\101"))B(function()return t:render(y.createElement(q,nil))end);(H(L)).toHaveBeenCalledTimes(1);(H(L.mock.calls[0])).toHaveLength(1);(H(L.mock.calls[0][0])).toBe("\108\111\103");(H(F)).toHaveBeenCalledTimes(1);(H(F.mock.calls[0])).toHaveLength(2);(H(F.mock.calls[0][0])).toBe("\119\097\114\110");(H(M(F.mock.calls[0][1]))).toEqual("\n    \105\110 \067\104\105\108\100 \040\097\116 \042\042\041\n    \105\110 \073\110\116\101\114\109\101\100\105\097\116\101 \040\097\116 \042\042\041\n    \105\110 \080\097\114\101\110\116 \040\097\116 \042\042\041");(H(e)).toHaveBeenCalledTimes(1);(H(e.mock.calls[0])).toHaveLength(2);(H(e.mock.calls[0][0])).toBe("\101\114\114\111\114");(H(M(e.mock.calls[0][1]))).toBe("\n    \105\110 \067\104\105\108\100 \040\097\116 \042\042\041\n    \105\110 \073\110\116\101\114\109\101\100\105\097\116\101 \040\097\116 \042\042\041\n    \105\110 \080\097\114\101\110\116 \040\097\116 \042\042\041")end)Y("\115\104\111\117\108\100 \097\112\112\101\110\100 \115\116\097\099\107\115 \097\102\116\101\114 \098\101\105\110\103 \117\110\105\110\115\116\097\108\108\101\100 \097\110\100 \114\101\105\110\115\116\097\108\108\101\100",function()local Y=function(B)local Y=B.children P.warn("\119\097\114\110")P.error("\101\114\114\111\114")return nil end I()local z=O.createRoot(Instance.new("\070\114\097\109\101"))B(function()return z:render(y.createElement(Y,nil))end);(H(F)).toHaveBeenCalledTimes(1);(H(F.mock.calls[0])).toHaveLength(1);(H(F.mock.calls[0][0])).toBe("\119\097\114\110");(H(e)).toHaveBeenCalledTimes(1);(H(e.mock.calls[0])).toHaveLength(1);(H(e.mock.calls[0][0])).toBe("\101\114\114\111\114")w({appendComponentStack=true,breakOnWarn=false})B(function()return z:render(y.createElement(Y,nil))end);(H(F)).toHaveBeenCalledTimes(2);(H(F.mock.calls[1])).toHaveLength(2);(H(F.mock.calls[1][0])).toBe("\119\097\114\110");(H(M(F.mock.calls[1][1]))).toEqual("\n    \105\110 \067\104\105\108\100 \040\097\116 \042\042\041");(H(e)).toHaveBeenCalledTimes(2);(H(e.mock.calls[1])).toHaveLength(2);(H(e.mock.calls[1][0])).toBe("\101\114\114\111\114");(H(M(e.mock.calls[1][1]))).toBe("\n    \105\110 \067\104\105\108\100 \040\097\116 \042\042\041")end)Y("\115\104\111\117\108\100 \098\101 \114\101\115\105\108\105\101\110\116 \116\111 \112\114\101\112\097\114\101\083\116\097\099\107\084\114\097\099\101",function()local Y=function(B)local P=B.children return P end local z=function(B)P.error("\101\114\114\111\114")P.log("\108\111\103")P.warn("\119\097\114\110")return nil end local q=function(B)local P=B.children return y.createElement(Y,nil,y.createElement(z,nil))end local t=O.createRoot(Instance.new("\070\114\097\109\101"))B(function()return t:render(y.createElement(q,nil))end);(H(L)).toHaveBeenCalledTimes(1);(H(L.mock.calls[0])).toHaveLength(1);(H(L.mock.calls[0][0])).toBe("\108\111\103");(H(F)).toHaveBeenCalledTimes(1);(H(F.mock.calls[0])).toHaveLength(2);(H(F.mock.calls[0][0])).toBe("\119\097\114\110");(H(M(F.mock.calls[0][1]))).toEqual("\n    \105\110 \067\104\105\108\100 \040\097\116 \042\042\041\n    \105\110 \073\110\116\101\114\109\101\100\105\097\116\101 \040\097\116 \042\042\041\n    \105\110 \080\097\114\101\110\116 \040\097\116 \042\042\041");(H(e)).toHaveBeenCalledTimes(1);(H(e.mock.calls[0])).toHaveLength(2);(H(e.mock.calls[0][0])).toBe("\101\114\114\111\114");(H(M(e.mock.calls[0][1]))).toBe("\n    \105\110 \067\104\105\108\100 \040\097\116 \042\042\041\n    \105\110 \073\110\116\101\114\109\101\100\105\097\116\101 \040\097\116 \042\042\041\n    \105\110 \080\097\114\101\110\116 \040\097\116 \042\042\041")end)end)
-- ROBLOX upstream: https://github.com/facebook/react/blob/v17.0.1/packages/react-devtools-shared/src/__tests__/console-test.js
--[[*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
]]
local JestGlobals = require("@pkg/@jsdotlua/jest-globals")
local describe = JestGlobals.describe
local xit = JestGlobals.xit
local beforeEach = JestGlobals.beforeEach
local jestExpect = JestGlobals.expect
local jest = JestGlobals.jest

-- ROBLOX deviation: Use lua's _G global table
local global = _G

-- ROBLOX deviation: Stub for now
local Console = {
	patch = function(...)
		print("Console.patch", ...)
	end,
	unpatch = function(...)
		print("Console.unpatch", ...)
	end,
	dangerous_setTargetConsoleForTesting = function(...) end,
	registerRenderer = function(...) end,
}

local React
local ReactRoblox
local utils = require("./utils")

describe("console", function()
	local act
	local fakeConsole
	local mockError
	local mockInfo
	local mockLog
	local mockWarn
	local patchConsole
	local unpatchConsole

	beforeEach(function()
		jest.resetModules()

		patchConsole = Console.patch
		unpatchConsole = Console.unpatch

		-- Patch a fake console so we can verify with tests below.
		-- Patching the real console is too complicated,
		-- because Jest itself has hooks into it as does our test env setup.
		mockError = jest.fn()
		mockInfo = jest.fn()
		mockLog = jest.fn()
		mockWarn = jest.fn()
		fakeConsole = {
			error = mockError,
			info = mockInfo,
			log = mockLog,
			warn = mockWarn,
		}

		Console.dangerous_setTargetConsoleForTesting(fakeConsole)

		-- Note the Console module only patches once,
		-- so it's important to patch the test console before injection.
		patchConsole({
			appendComponentStack = true,
			breakOnWarn = false,
		})

		local inject = global.__REACT_DEVTOOLS_GLOBAL_HOOK__.inject
		global.__REACT_DEVTOOLS_GLOBAL_HOOK__.inject = function(internals)
			inject(internals)

			Console.registerRenderer(internals)
		end

		React = require("@pkg/@jsdotlua/react")
		ReactRoblox = require("@pkg/@jsdotlua/react-roblox")

		act = utils.act
	end)

	local function normalizeCodeLocInfo(str)
		-- ROBLOX deviation: Lua stack traces won't match JS ones
		-- ROBLOX TODO: verify this
		return str
	end

	xit(
		"should not patch console methods that do not receive component stacks",
		function()
			jestExpect(fakeConsole.error).never.toBe(mockError)
			jestExpect(fakeConsole.info).toBe(mockInfo)
			jestExpect(fakeConsole.log).toBe(mockLog)
			jestExpect(fakeConsole.warn).never.toBe(mockWarn)
		end
	)

	xit("should only patch the console once", function()
		local prevError = fakeConsole.error
		local prevWarn = fakeConsole.warn

		patchConsole({
			appendComponentStack = true,
			breakOnWarn = false,
		})
		jestExpect(fakeConsole.error).toBe(prevError)
		jestExpect(fakeConsole.warn).toBe(prevWarn)
	end)

	xit("should un-patch when requested", function()
		jestExpect(fakeConsole.error).never.toBe(mockError)
		jestExpect(fakeConsole.warn).never.toBe(mockWarn)
		unpatchConsole()
		jestExpect(fakeConsole.error).toBe(mockError)
		jestExpect(fakeConsole.warn).toBe(mockWarn)
	end)

	xit("should pass through logs when there is no current fiber", function()
		jestExpect(mockLog).toHaveBeenCalledTimes(0)
		jestExpect(mockWarn).toHaveBeenCalledTimes(0)
		jestExpect(mockError).toHaveBeenCalledTimes(0)
		fakeConsole.log("log")
		fakeConsole.warn("warn")
		fakeConsole.error("error")
		jestExpect(mockLog).toHaveBeenCalledTimes(1)
		jestExpect(mockLog.mock.calls[0]).toHaveLength(1)
		jestExpect(mockLog.mock.calls[0][0]).toBe("log")
		jestExpect(mockWarn).toHaveBeenCalledTimes(1)
		jestExpect(mockWarn.mock.calls[0]).toHaveLength(1)
		jestExpect(mockWarn.mock.calls[0][0]).toBe("warn")
		jestExpect(mockError).toHaveBeenCalledTimes(1)
		jestExpect(mockError.mock.calls[0]).toHaveLength(1)
		jestExpect(mockError.mock.calls[0][0]).toBe("error")
	end)

	xit("should not append multiple stacks", function()
		local Child = function()
			fakeConsole.warn("warn\n    in Child (at fake.js:123)")
			fakeConsole.error("error", "\n    in Child (at fake.js:123)")
			return nil
		end

		-- ROBLOX deviation: Use createRoot instead of DOM element
		local root = ReactRoblox.createRoot(Instance.new("Frame"))

		act(function()
			return root:render(React.createElement(Child))
		end)
		jestExpect(mockWarn).toHaveBeenCalledTimes(1)
		jestExpect(mockWarn.mock.calls[0]).toHaveLength(1)
		-- ROBLOX TODO: What is printed instead of this?
		jestExpect(mockWarn.mock.calls[0][0]).toBe("warn\n    in Child (at fake.js:123)")
		jestExpect(mockError).toHaveBeenCalledTimes(1)
		jestExpect(mockError.mock.calls[0]).toHaveLength(2)
		jestExpect(mockError.mock.calls[0][0]).toBe("error")
		jestExpect(mockError.mock.calls[0][1]).toBe("\n    in Child (at fake.js:123)")
	end)

	xit(
		"should append component stacks to errors and warnings logged during render",
		function()
			local Intermediate = function(_ref2)
				local children = _ref2.children
				return children
			end
			-- ROBLOX deviation: switched ordering for variable definition order
			local Child = function(_ref4)
				local _children = _ref4.children

				fakeConsole.error("error")
				fakeConsole.log("log")
				fakeConsole.warn("warn")

				return nil
			end
			local Parent = function(_ref3)
				local _children = _ref3.children
				return React.createElement(
					Intermediate,
					nil,
					React.createElement(Child, nil)
				)
			end

			-- ROBLOX deviation: Use createRoot instead of DOM element
			local root = ReactRoblox.createRoot(Instance.new("Frame"))

			act(function()
				return root:render(React.createElement(Parent, nil))
			end)
			jestExpect(mockLog).toHaveBeenCalledTimes(1)
			jestExpect(mockLog.mock.calls[0]).toHaveLength(1)
			jestExpect(mockLog.mock.calls[0][0]).toBe("log")
			jestExpect(mockWarn).toHaveBeenCalledTimes(1)
			jestExpect(mockWarn.mock.calls[0]).toHaveLength(2)
			jestExpect(mockWarn.mock.calls[0][0]).toBe("warn")
			-- ROBLOX TODO: What is printed instead of this?
			jestExpect(normalizeCodeLocInfo(mockWarn.mock.calls[0][1])).toEqual(
				"\n    in Child (at **)\n    in Intermediate (at **)\n    in Parent (at **)"
			)
			jestExpect(mockError).toHaveBeenCalledTimes(1)
			jestExpect(mockError.mock.calls[0]).toHaveLength(2)
			jestExpect(mockError.mock.calls[0][0]).toBe("error")
			jestExpect(normalizeCodeLocInfo(mockError.mock.calls[0][1])).toBe(
				"\n    in Child (at **)\n    in Intermediate (at **)\n    in Parent (at **)"
			)
		end
	)
	xit(
		"should append component stacks to errors and warnings logged from effects",
		function()
			local Intermediate = function(_ref5)
				local children = _ref5.children
				return children
			end
			-- ROBLOX deviation: switched ordering for variable definition order
			local Child = function(_ref7)
				local _children = _ref7.children

				React.useLayoutEffect(function()
					fakeConsole.error("active error")
					fakeConsole.log("active log")
					fakeConsole.warn("active warn")
				end)
				React.useEffect(function()
					fakeConsole.error("passive error")
					fakeConsole.log("passive log")
					fakeConsole.warn("passive warn")
				end)

				return nil
			end
			local Parent = function(_ref6)
				local _children = _ref6.children

				return React.createElement(
					Intermediate,
					nil,
					React.createElement(Child, nil)
				)
			end

			-- ROBLOX deviation: Use createRoot instead of DOM element
			local root = ReactRoblox.createRoot(Instance.new("Frame"))

			act(function()
				return root:render(React.createElement(Parent, nil))
			end)
			jestExpect(mockLog).toHaveBeenCalledTimes(2)
			jestExpect(mockLog.mock.calls[0]).toHaveLength(1)
			jestExpect(mockLog.mock.calls[0][0]).toBe("active log")
			jestExpect(mockLog.mock.calls[1]).toHaveLength(1)
			jestExpect(mockLog.mock.calls[1][0]).toBe("passive log")
			jestExpect(mockWarn).toHaveBeenCalledTimes(2)
			jestExpect(mockWarn.mock.calls[0]).toHaveLength(2)
			jestExpect(mockWarn.mock.calls[0][0]).toBe("active warn")
			-- ROBLOX TODO: What is printed instead of this?
			jestExpect(normalizeCodeLocInfo(mockWarn.mock.calls[0][1])).toEqual(
				"\n    in Child (at **)\n    in Intermediate (at **)\n    in Parent (at **)"
			)
			jestExpect(mockWarn.mock.calls[1]).toHaveLength(2)
			jestExpect(mockWarn.mock.calls[1][0]).toBe("passive warn")
			jestExpect(normalizeCodeLocInfo(mockWarn.mock.calls[1][1])).toEqual(
				"\n    in Child (at **)\n    in Intermediate (at **)\n    in Parent (at **)"
			)
			jestExpect(mockError).toHaveBeenCalledTimes(2)
			jestExpect(mockError.mock.calls[0]).toHaveLength(2)
			jestExpect(mockError.mock.calls[0][0]).toBe("active error")
			jestExpect(normalizeCodeLocInfo(mockError.mock.calls[0][1])).toBe(
				"\n    in Child (at **)\n    in Intermediate (at **)\n    in Parent (at **)"
			)
			jestExpect(mockError.mock.calls[1]).toHaveLength(2)
			jestExpect(mockError.mock.calls[1][0]).toBe("passive error")
			jestExpect(normalizeCodeLocInfo(mockError.mock.calls[1][1])).toBe(
				"\n    in Child (at **)\n    in Intermediate (at **)\n    in Parent (at **)"
			)
		end
	)
	xit(
		"should append component stacks to errors and warnings logged from commit hooks",
		function()
			local Intermediate = function(_ref8)
				local children = _ref8.children

				return children
			end
			-- ROBLOX deviation: switched ordering for variable definition order
			local Child = React.Component:extend("Child")
			local Parent = function(_ref9)
				local _children = _ref9.children

				return React.createElement(
					Intermediate,
					nil,
					React.createElement(Child, nil)
				)
			end

			function Child:componentDidMount()
				fakeConsole.error("didMount error")
				fakeConsole.log("didMount log")
				fakeConsole.warn("didMount warn")
			end
			function Child:componentDidUpdate()
				fakeConsole.error("didUpdate error")
				fakeConsole.log("didUpdate log")
				fakeConsole.warn("didUpdate warn")
			end
			function Child:render()
				return nil
			end

			-- ROBLOX deviation: Use createRoot instead of DOM element
			local root = ReactRoblox.createRoot(Instance.new("Frame"))

			act(function()
				return root:render(React.createElement(Parent, nil))
			end)
			act(function()
				return root:render(React.createElement(Parent, nil))
			end)
			jestExpect(mockLog).toHaveBeenCalledTimes(2)
			jestExpect(mockLog.mock.calls[0]).toHaveLength(1)
			jestExpect(mockLog.mock.calls[0][0]).toBe("didMount log")
			jestExpect(mockLog.mock.calls[1]).toHaveLength(1)
			jestExpect(mockLog.mock.calls[1][0]).toBe("didUpdate log")
			jestExpect(mockWarn).toHaveBeenCalledTimes(2)
			jestExpect(mockWarn.mock.calls[0]).toHaveLength(2)
			jestExpect(mockWarn.mock.calls[0][0]).toBe("didMount warn")
			-- ROBLOX TODO: What is printed instead of this?
			jestExpect(normalizeCodeLocInfo(mockWarn.mock.calls[0][1])).toEqual(
				"\n    in Child (at **)\n    in Intermediate (at **)\n    in Parent (at **)"
			)
			jestExpect(mockWarn.mock.calls[1]).toHaveLength(2)
			jestExpect(mockWarn.mock.calls[1][0]).toBe("didUpdate warn")
			jestExpect(normalizeCodeLocInfo(mockWarn.mock.calls[1][1])).toEqual(
				"\n    in Child (at **)\n    in Intermediate (at **)\n    in Parent (at **)"
			)
			jestExpect(mockError).toHaveBeenCalledTimes(2)
			jestExpect(mockError.mock.calls[0]).toHaveLength(2)
			jestExpect(mockError.mock.calls[0][0]).toBe("didMount error")
			jestExpect(normalizeCodeLocInfo(mockError.mock.calls[0][1])).toBe(
				"\n    in Child (at **)\n    in Intermediate (at **)\n    in Parent (at **)"
			)
			jestExpect(mockError.mock.calls[1]).toHaveLength(2)
			jestExpect(mockError.mock.calls[1][0]).toBe("didUpdate error")
			jestExpect(normalizeCodeLocInfo(mockError.mock.calls[1][1])).toBe(
				"\n    in Child (at **)\n    in Intermediate (at **)\n    in Parent (at **)"
			)
		end
	)
	xit(
		"should append component stacks to errors and warnings logged from gDSFP",
		function()
			local Intermediate = function(props)
				local children = props.children
				return children
			end
			-- ROBLOX deviation: switched ordering for variable definition order
			local Child = React.Component:extend("Child")
			local Parent = function(props)
				local _children = props.children
				return React.createElement(Intermediate, nil, React.createElement(Child))
			end

			function Child.getDerivedStateFromProps()
				fakeConsole.error("error")
				fakeConsole.log("log")
				fakeConsole.warn("warn")
				return nil
			end
			function Child:render()
				return nil
			end

			-- ROBLOX deviation: Use createRoot instead of DOM element
			local root = ReactRoblox.createRoot(Instance.new("Frame"))

			act(function()
				return root:render(React.createElement(Parent, nil))
			end)
			jestExpect(mockLog).toHaveBeenCalledTimes(1)
			jestExpect(mockLog.mock.calls[0]).toHaveLength(1)
			jestExpect(mockLog.mock.calls[0][0]).toBe("log")
			jestExpect(mockWarn).toHaveBeenCalledTimes(1)
			jestExpect(mockWarn.mock.calls[0]).toHaveLength(2)
			jestExpect(mockWarn.mock.calls[0][0]).toBe("warn")
			-- ROBLOX TODO: What is printed instead of this?
			jestExpect(normalizeCodeLocInfo(mockWarn.mock.calls[0][1])).toEqual(
				"\n    in Child (at **)\n    in Intermediate (at **)\n    in Parent (at **)"
			)
			jestExpect(mockError).toHaveBeenCalledTimes(1)
			jestExpect(mockError.mock.calls[0]).toHaveLength(2)
			jestExpect(mockError.mock.calls[0][0]).toBe("error")
			jestExpect(normalizeCodeLocInfo(mockError.mock.calls[0][1])).toBe(
				"\n    in Child (at **)\n    in Intermediate (at **)\n    in Parent (at **)"
			)
		end
	)
	xit("should append stacks after being uninstalled and reinstalled", function()
		local Child = function(_ref12)
			local _children = _ref12.children

			fakeConsole.warn("warn")
			fakeConsole.error("error")

			return nil
		end

		unpatchConsole()

		-- ROBLOX deviation: Use createRoot instead of DOM element
		local root = ReactRoblox.createRoot(Instance.new("Frame"))

		act(function()
			return root:render(React.createElement(Child, nil))
		end)
		jestExpect(mockWarn).toHaveBeenCalledTimes(1)
		jestExpect(mockWarn.mock.calls[0]).toHaveLength(1)
		jestExpect(mockWarn.mock.calls[0][0]).toBe("warn")
		jestExpect(mockError).toHaveBeenCalledTimes(1)
		jestExpect(mockError.mock.calls[0]).toHaveLength(1)
		jestExpect(mockError.mock.calls[0][0]).toBe("error")
		patchConsole({
			appendComponentStack = true,
			breakOnWarn = false,
		})
		act(function()
			return root:render(React.createElement(Child, nil))
		end)
		jestExpect(mockWarn).toHaveBeenCalledTimes(2)
		jestExpect(mockWarn.mock.calls[1]).toHaveLength(2)
		jestExpect(mockWarn.mock.calls[1][0]).toBe("warn")
		-- ROBLOX TODO: What is printed instead of this?
		jestExpect(normalizeCodeLocInfo(mockWarn.mock.calls[1][1])).toEqual(
			"\n    in Child (at **)"
		)
		jestExpect(mockError).toHaveBeenCalledTimes(2)
		jestExpect(mockError.mock.calls[1]).toHaveLength(2)
		jestExpect(mockError.mock.calls[1][0]).toBe("error")
		jestExpect(normalizeCodeLocInfo(mockError.mock.calls[1][1])).toBe(
			"\n    in Child (at **)"
		)
	end)
	xit("should be resilient to prepareStackTrace", function()
		-- ROBLOX TODO: what is a suitable alternative for this?
		-- Error.prepareStackTrace = function(error, callsites)
		-- 	local stack = {
		-- 		'An error occurred:',
		-- 		error.message,
		-- 	}

		-- 	for i=0, callsites.length - 1 do
		-- 		local callsite = callsites[i]

		-- 		stack.push('\t' + callsite.getFunctionName(), '\t\tat ' + callsite.getFileName(), '\t\ton line ' + callsite.getLineNumber())
		-- 	end

		-- 	return stack.join('\n')
		-- end

		local Intermediate = function(_ref13)
			local children = _ref13.children
			return children
		end
		-- ROBLOX deviation: switched ordering for variable definition order
		local Child = function(_ref15)
			fakeConsole.error("error")
			fakeConsole.log("log")
			fakeConsole.warn("warn")

			return nil
		end
		local Parent = function(_ref14)
			local _children = _ref14.children
			return React.createElement(Intermediate, nil, React.createElement(Child, nil))
		end

		-- ROBLOX deviation: Use createRoot instead of DOM element
		local root = ReactRoblox.createRoot(Instance.new("Frame"))

		act(function()
			return root:render(React.createElement(Parent, nil))
		end)
		jestExpect(mockLog).toHaveBeenCalledTimes(1)
		jestExpect(mockLog.mock.calls[0]).toHaveLength(1)
		jestExpect(mockLog.mock.calls[0][0]).toBe("log")
		jestExpect(mockWarn).toHaveBeenCalledTimes(1)
		jestExpect(mockWarn.mock.calls[0]).toHaveLength(2)
		jestExpect(mockWarn.mock.calls[0][0]).toBe("warn")
		-- ROBLOX TODO: What is printed instead of this?
		jestExpect(normalizeCodeLocInfo(mockWarn.mock.calls[0][1])).toEqual(
			"\n    in Child (at **)\n    in Intermediate (at **)\n    in Parent (at **)"
		)
		jestExpect(mockError).toHaveBeenCalledTimes(1)
		jestExpect(mockError.mock.calls[0]).toHaveLength(2)
		jestExpect(mockError.mock.calls[0][0]).toBe("error")
		jestExpect(normalizeCodeLocInfo(mockError.mock.calls[0][1])).toBe(
			"\n    in Child (at **)\n    in Intermediate (at **)\n    in Parent (at **)"
		)
	end)
end)
