local I=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 B=I.describe local Q=I.beforeEach local X=I.jest local r=I.it local u=I.xit local i=I.expect local O=(require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\115\104\097\114\101\100")).console local C=require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\112\114\111\109\105\115\101")B("\068\101\098\117\103\084\114\097\099\105\110\103",function()local I local B local n Q(function()X.resetModules()local Q=(require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\115\104\097\114\101\100")).ReactFeatureFlags Q.enableDebugTracing=true Q.enableSchedulingProfiler=true Q.enableProfilerTimer=true Q.replayFailedUnitOfWorkWithInvokeGuardedCallback=true Q.enableSuspenseServerRenderer=true Q.decoupleUpdatePriorityFromScheduler=true I=require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\114\101\097\099\116")B=require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\114\101\097\099\116-\116\101\115\116-\114\101\110\100\101\114\101\114")n=require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\115\099\104\101\100\117\108\101\114")end)r("\115\104\111\117\108\100 \110\111\116 \108\111\103 \097\110\121\116\104\105\110\103 \102\111\114 \115\121\110\099 \114\101\110\100\101\114 \119\105\116\104\111\117\116 \115\117\115\112\101\110\100\115 \111\114 \115\116\097\116\101 \117\112\100\097\116\101\115",function()(i(function()B.create(I.createElement(I.unstable_DebugTracingMode,nil,I.createElement("\100\105\118")))end)).toLogDev({})end)r("\115\104\111\117\108\100 \110\111\116 \108\111\103 \097\110\121\116\104\105\110\103 \102\111\114 \099\111\110\099\117\114\114\101\110\116 \114\101\110\100\101\114 \119\105\116\104\111\117\116 \115\117\115\112\101\110\100\115 \111\114 \115\116\097\116\101 \117\112\100\097\116\101\115",function()(i(function()B.create(I.createElement(I.unstable_DebugTracingMode,nil,I.createElement("\100\105\118")),{unstable_isConcurrent=true})end)).toLogDev({});(i(function()(i(n)).toFlushUntilNextPaint({})end)).toLogDev({})end)u("\115\104\111\117\108\100 \108\111\103 \115\121\110\099 \114\101\110\100\101\114 \119\105\116\104 \115\117\115\112\101\110\115\101",function()local Q=(C.delay(0)):andThen(function()return true end)local function X()error(Q)end;(i(function()B.create(I.createElement(I.unstable_DebugTracingMode,nil,I.createElement(I.Suspense,{fallback={}},I.createElement(X))))end)).toLogDev({"\042 \069\120\097\109\112\108\101 \115\117\115\112\101\110\100\101\100"},{withoutStack=true});(i(function()Q:await()end)).toLogDev({"\042 \069\120\097\109\112\108\101 \114\101\115\111\108\118\101\100"},{withoutStack=true})end)r.skip("\115\104\111\117\108\100 \108\111\103 \115\121\110\099 \114\101\110\100\101\114 \119\105\116\104 \067\080\085 \115\117\115\112\101\110\115\101",function()local function Q()O.log("\060\069\120\097\109\112\108\101\047\062")return nil end local function X(I)local B=I.children O.log("\060\087\114\097\112\112\101\114\047\062")return B end;(i(function()B.create(I.createElement(I.unstable_DebugTracingMode,nil,I.createElement(X,nil,I.createElement(I.Suspense,{fallback={};unstable_expectedLoadTime=1},I.createElement(Q)))))end)).toLogDev({"\060\087\114\097\112\112\101\114\047\062"},{withoutStack=true});(i(function()(i(n)).toFlushUntilNextPaint({})end)).toLogDev({"\060\069\120\097\109\112\108\101\047\062"},{withoutStack=true})end)u("\115\104\111\117\108\100 \108\111\103 \099\111\110\099\117\114\114\101\110\116 \114\101\110\100\101\114 \119\105\116\104 \115\117\115\112\101\110\115\101",function()local Q=(C.delay(0)):andThen(function()return true end)local function X()error(Q)end;(i(function()B.create(I.createElement(I.unstable_DebugTracingMode,nil,I.createElement(I.Suspense,{fallback={}},I.createElement(X))),{unstable_isConcurrent=true})end)).toLogDev({});(i(function()(i(n)).toFlushUntilNextPaint({})end)).toLogDev({"\042 \069\120\097\109\112\108\101 \115\117\115\112\101\110\100\101\100"},{withoutStack=true});(i(function()Q:await()end)).toLogDev({"\042 \069\120\097\109\112\108\101 \114\101\115\111\108\118\101\100"},{withoutStack=true})end)u("\115\104\111\117\108\100 \108\111\103 \099\111\110\099\117\114\114\101\110\116 \114\101\110\100\101\114 \119\105\116\104 \067\080\085 \115\117\115\112\101\110\115\101",function()local function Q()O.log("\060\069\120\097\109\112\108\101\047\062")return nil end local function X(I)local B=I.children O.log("\060\087\114\097\112\112\101\114\047\062")return B end;(i(function()B.create(I.createElement(I.unstable_DebugTracingMode,nil,I.createElement(X,nil,I.createElement(I.Suspense,{fallback={};unstable_expectedLoadTime=1},I.createElement(Q)))),{unstable_isConcurrent=true})end)).toLogDev({});(i(function()(i(n)).toFlushUntilNextPaint({})end)).toLogDev({"\060\087\114\097\112\112\101\114\047\062"},{withoutStack=true});(i(function()(i(n)).toFlushUntilNextPaint({})end)).toLogDev({"\060\069\120\097\109\112\108\101\047\062"},{withoutStack=true})end)r("\115\104\111\117\108\100 \108\111\103 \099\097\115\099\097\100\105\110\103 \099\108\097\115\115 \099\111\109\112\111\110\101\110\116 \117\112\100\097\116\101\115",function()local Q=I.Component:extend("\069\120\097\109\112\108\101")function Q.init(I)I.state={didMount=false}end function Q.componentDidMount(I)I:setState({didMount=true})end function Q.render(I)return nil end;(i(function()B.create(I.createElement(I.unstable_DebugTracingMode,nil,I.createElement(Q)),{unstable_isConcurrent=true})end)).toLogDev({});(i(function()(i(n)).toFlushUntilNextPaint({})end)).toLogDev({"\042 \069\120\097\109\112\108\101 \117\112\100\097\116\101\100 \115\116\097\116\101 \040\048\098\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\049\041"},{withoutStack=true})end)r("\115\104\111\117\108\100 \108\111\103 \114\101\110\100\101\114 \112\104\097\115\101 \115\116\097\116\101 \117\112\100\097\116\101\115 \102\111\114 \099\108\097\115\115 \099\111\109\112\111\110\101\110\116",function()local Q=I.Component:extend("\069\120\097\109\112\108\101")function Q.init(I)I.state={didRender=false}end function Q.render(I)if I.state.didRender==false then I:setState({didRender=true})end return nil end;(i(function()B.create(I.createElement(I.unstable_DebugTracingMode,nil,I.createElement(Q)),{unstable_isConcurrent=true})end)).toLogDev({});(i(function()(i(function()(i(n)).toFlushUntilNextPaint({})end)).toErrorDev("\067\097\110\110\111\116 \117\112\100\097\116\101 \100\117\114\105\110\103 \097\110 \101\120\105\115\116\105\110\103 \115\116\097\116\101 \116\114\097\110\115\105\116\105\111\110")end)).toLogDev({"\042 \069\120\097\109\112\108\101 \117\112\100\097\116\101\100 \115\116\097\116\101 \040\048\098\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\049\048\048\048\048\048\048\048\048\048\041";"\042 \069\120\097\109\112\108\101 \117\112\100\097\116\101\100 \115\116\097\116\101 \040\048\098\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\049\048\048\048\048\048\048\048\048\048\041"},{withoutStack=true})end)r("\115\104\111\117\108\100 \108\111\103 \099\097\115\099\097\100\105\110\103 \108\097\121\111\117\116 \117\112\100\097\116\101\115",function()local function Q()local B,Q=I.useState(false)I.useLayoutEffect(function()Q(true)end,{})return B end;(i(function()B.create(I.createElement(I.unstable_DebugTracingMode,nil,I.createElement(Q)),{unstable_isConcurrent=true})end)).toLogDev({});(i(function()(i(n)).toFlushUntilNextPaint({})end)).toLogDev({"\042 \069\120\097\109\112\108\101 \117\112\100\097\116\101\100 \115\116\097\116\101 \040\048\098\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\049\041"},{withoutStack=true})end)r("\115\104\111\117\108\100 \108\111\103 \099\097\115\099\097\100\105\110\103 \112\097\115\115\105\118\101 \117\112\100\097\116\101\115",function()local function Q()local B,Q=I.useState(false)I.useEffect(function()Q(true)end,{})return B end;(i(function()B.act(function()B.create(I.createElement(I.unstable_DebugTracingMode,nil,I.createElement(Q)),{unstable_isConcurrent=true})end)end)).toLogDev({"\042 \069\120\097\109\112\108\101 \117\112\100\097\116\101\100 \115\116\097\116\101 \040\048\098\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\049\048\048\048\048\048\048\048\048\048\048\041"},{withoutStack=true})end)r("\115\104\111\117\108\100 \108\111\103 \114\101\110\100\101\114 \112\104\097\115\101 \117\112\100\097\116\101\115",function()local function Q()local B,Q=I.useState(false)if not B then Q(true)end return B end;(i(function()B.act(function()B.create(I.createElement(I.unstable_DebugTracingMode,nil,I.createElement(Q)),{unstable_isConcurrent=true})end)end)).toLogDev({"\042 \069\120\097\109\112\108\101 \117\112\100\097\116\101\100 \115\116\097\116\101 \040\048\098\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\049\048\048\048\048\048\048\048\048\048\041","\042 \069\120\097\109\112\108\101 \117\112\100\097\116\101\100 \115\116\097\116\101 \040\048\098\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\048\049\048\048\048\048\048\048\048\048\048\041"},{withoutStack=true})end)u("\115\104\111\117\108\100 \108\111\103 \119\104\101\110 \117\115\101\114 \099\111\100\101 \108\111\103\115",function()local function Q()O.log("\072\101\108\108\111 \102\114\111\109 \117\115\101\114 \099\111\100\101")return nil end;(i(function()B.create(I.createElement(I.unstable_DebugTracingMode,nil,I.createElement(Q)),{unstable_isConcurrent=true})end)).toLogDev({});(i(function()(i(n)).toFlushUntilNextPaint({})end)).toLogDev({"\072\101\108\108\111 \102\114\111\109 \117\115\101\114 \099\111\100\101"})end)r("\115\104\111\117\108\100 \110\111\116 \108\111\103 \097\110\121\116\104\105\110\103 \111\117\116\115\105\100\101 \111\102 \097 \117\110\115\116\097\098\108\101\095\068\101\098\117\103\084\114\097\099\105\110\103\077\111\100\101 \115\117\098\116\114\101\101",function()local function Q()local B,Q=I.useState(false)I.useLayoutEffect(function()Q(true)end,{})return B end local X=C.new(function()return{}end)local function r()error(X)end local function u()return nil end;(i(function()B.create(I.createElement(I.Fragment,nil,I.createElement(Q),I.createElement(I.Suspense,{fallback={}},nil,I.createElement(r)),I.createElement(I.unstable_DebugTracingMode,nil,I.createElement(u))))end)).toLogDev({})end)end)
-- ROBLOX upstream: https://github.com/facebook/react/blob/8af27aeedbc6b00bc2ef49729fc84f116c70a27c/packages/react-reconciler/src/__tests__/DebugTracing-test.internal.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.
--  *
--  * @emails react-core
--  * @jest-environment node
--  */

-- local function spyOnDevAndProd(object, methodName, fake)
-- 	local originalMethods = originalObjects[tostring(object)]
-- 	if originalMethods == nil then
-- 		originalMethods = {}
-- 		originalObjects[tostring(object)] = originalMethods
-- 	end
-- 	originalMethods[methodName] = object[methodName]
-- 	object[methodName] = jest:fn(fake)
-- 	return object[methodName]
-- end

-- local function restoreDevAndProd()
-- 	for originalObjectString, originalObject in originalObjects do
-- 		for methodName, originalMethod in originalObjects[originalObjectString] do
-- 			originalObject[methodName] = originalMethod
-- 		end
-- 	end
-- 	originalObjects = nil
-- end

local JestGlobals = require("@pkg/@jsdotlua/jest-globals")
local describe = JestGlobals.describe
local beforeEach = JestGlobals.beforeEach
local jest = JestGlobals.jest
local it = JestGlobals.it
local xit = JestGlobals.xit
local jestExpect = JestGlobals.expect
local console = require("@pkg/@jsdotlua/shared").console
local Promise = require("@pkg/@jsdotlua/promise")

-- ROBLOX Test Noise: jest capabilities needed to spy on console
describe("DebugTracing", function()
	local React
	local ReactTestRenderer
	local Scheduler
	beforeEach(function()
		jest.resetModules()

		-- ROBLOX deviation: upstream uses special comments to know which flags to flip. we do it manually.
		local ReactFeatureFlags = require("@pkg/@jsdotlua/shared").ReactFeatureFlags
		ReactFeatureFlags.enableDebugTracing = true
		ReactFeatureFlags.enableSchedulingProfiler = true
		ReactFeatureFlags.enableProfilerTimer = true
		ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = true
		ReactFeatureFlags.enableSuspenseServerRenderer = true
		ReactFeatureFlags.decoupleUpdatePriorityFromScheduler = true
		React = require("@pkg/@jsdotlua/react")
		ReactTestRenderer = require("@pkg/@jsdotlua/react-test-renderer")
		Scheduler = require("@pkg/@jsdotlua/scheduler")

		-- local groups = {}

		-- ROBLOX deviation: we currently don't have a good way to intercept
		-- console.log, group, or groupEnd in a reasonably-aligned way

		-- spyOnDevAndProd(console, "log", function(message)
		-- 	table.insert(logs, "log: " .. message)
		-- end)
		-- spyOnDevAndProd(console, "group", function(message)
		-- 	table.insert(logs, "group: " .. message)
		-- 	table.insert(groups, message)
		-- end)
		-- spyOnDevAndProd(console, "groupEnd", function()
		-- 	local message = table.remove(groups, 1)
		-- 	table.insert(logs, "groupEnd: " .. message)
		-- end)
	end)

	-- @gate experimental
	it(
		"should not log anything for sync render without suspends or state updates",
		function()
			jestExpect(function()
				ReactTestRenderer.create(
					React.createElement(
						React.unstable_DebugTracingMode,
						nil,
						React.createElement("div")
					)
				)
			end).toLogDev({})
		end
	)

	-- @gate experimental
	it(
		"should not log anything for concurrent render without suspends or state updates",
		function()
			jestExpect(function()
				ReactTestRenderer.create(
					React.createElement(
						React.unstable_DebugTracingMode,
						nil,
						React.createElement("div")
					),
					{ unstable_isConcurrent = true }
				)
			end).toLogDev({})

			jestExpect(function()
				jestExpect(Scheduler).toFlushUntilNextPaint({})
			end).toLogDev({})
		end
	)

	-- ROBLOX FIXME: we never receive "Example resolved", might be a Promise emulation issue
	-- @gate experimental && build === 'development' && enableDebugTracing
	xit("should log sync render with suspense", function()
		-- ROBLOX deviation: evaera Prosmise.resolve doesn't match JS Promise, so we delay(0) to match
		local fakeSuspensePromise = Promise.delay(0):andThen(function()
			return true
		end)
		local function Example()
			error(fakeSuspensePromise)
		end

		jestExpect(function()
			ReactTestRenderer.create(
				React.createElement(
					React.unstable_DebugTracingMode,
					nil,
					React.createElement(
						React.Suspense,
						{ fallback = {} },
						React.createElement(Example)
					)
				)
			)
		end).toLogDev({
			-- "* render (0b0000000000000000000000000000001)",
			"* Example suspended",
			-- "* render (0b0000000000000000000000000000001)"
		}, { withoutStack = true })

		jestExpect(function()
			fakeSuspensePromise:await()
		end).toLogDev({
			"* Example resolved",
		}, { withoutStack = true })
	end)

	-- @gate experimental && build === 'development' && enableDebugTracing
	it.skip("should log sync render with CPU suspense", function()
		local function Example()
			console.log("<Example/>")
			return nil
		end

		local function Wrapper(props)
			local children = props.children
			console.log("<Wrapper/>")
			return children
		end

		jestExpect(function()
			ReactTestRenderer.create(
				React.createElement(
					React.unstable_DebugTracingMode,
					nil,
					React.createElement(
						Wrapper,
						nil,
						React.createElement(
							React.Suspense,
							{ fallback = {}, unstable_expectedLoadTime = 1 },
							React.createElement(Example)
						)
					)
				)
			)
		end).toLogDev({
			-- 	"group: * render (0b0000000000000000000000000000001)",
			"<Wrapper/>",
			-- 	"groupEnd: * render (0b0000000000000000000000000000001)",
		}, { withoutStack = true })

		jestExpect(function()
			jestExpect(Scheduler).toFlushUntilNextPaint({})
		end).toLogDev({
			-- 	"group: * render (0b0000010000000000000000000000000)",
			"<Example/>",
			-- 	"groupEnd: * render (0b0000010000000000000000000000000)",
		}, { withoutStack = true })
	end)

	-- @gate experimental && build === 'development' && enableDebugTracing
	xit("should log concurrent render with suspense", function()
		-- ROBLOX deviation: evaera Prosmise.resolve doesn't match JS Promise, so we delay(0) to match
		local fakeSuspensePromise = Promise.delay(0):andThen(function()
			return true
		end)
		local function Example()
			error(fakeSuspensePromise)
		end

		jestExpect(function()
			ReactTestRenderer.create(
				React.createElement(
					React.unstable_DebugTracingMode,
					nil,
					React.createElement(
						React.Suspense,
						{ fallback = {} },
						React.createElement(Example)
					)
				),
				{ unstable_isConcurrent = true }
			)
		end).toLogDev({})

		jestExpect(function()
			jestExpect(Scheduler).toFlushUntilNextPaint({})
		end).toLogDev({
			-- 	"group: * render (0b0000000000000000000001000000000)",
			"* Example suspended",
			-- 	"groupEnd: * render (0b0000000000000000000001000000000)",
		}, { withoutStack = true })

		jestExpect(function()
			fakeSuspensePromise:await()
		end).toLogDev({ "* Example resolved" }, { withoutStack = true })
	end)

	-- @gate experimental && build === 'development' && enableDebugTracing
	xit("should log concurrent render with CPU suspense", function()
		local function Example()
			console.log("<Example/>")
			return nil
		end

		local function Wrapper(props)
			local children = props.children
			console.log("<Wrapper/>")
			return children
		end

		jestExpect(function()
			ReactTestRenderer.create(
				React.createElement(
					React.unstable_DebugTracingMode,
					nil,
					React.createElement(
						Wrapper,
						nil,
						React.createElement(
							React.Suspense,
							{ fallback = {}, unstable_expectedLoadTime = 1 },
							React.createElement(Example)
						)
					)
				),
				{ unstable_isConcurrent = true }
			)
		end).toLogDev({})

		jestExpect(function()
			jestExpect(Scheduler).toFlushUntilNextPaint({})
		end).toLogDev({
			-- 	"group: * render (0b0000000000000000000001000000000)",
			"<Wrapper/>",
			-- 	"groupEnd: * render (0b0000000000000000000001000000000)",
		}, { withoutStack = true })

		jestExpect(function()
			jestExpect(Scheduler).toFlushUntilNextPaint({})
		end).toLogDev({
			-- 	"group: * render (0b0000010000000000000000000000000)",
			"<Example/>",
			-- 	"groupEnd: * render (0b0000010000000000000000000000000)",
		}, { withoutStack = true })
	end)

	-- @gate experimental && build === 'development' && enableDebugTracing
	it("should log cascading class component updates", function()
		local Example = React.Component:extend("Example")
		function Example:init()
			self.state = { didMount = false }
		end
		function Example:componentDidMount()
			self:setState({ didMount = true })
		end
		function Example:render()
			return nil
		end

		jestExpect(function()
			ReactTestRenderer.create(
				React.createElement(
					React.unstable_DebugTracingMode,
					nil,
					React.createElement(Example)
				),
				{ unstable_isConcurrent = true }
			)
		end).toLogDev({})

		jestExpect(function()
			jestExpect(Scheduler).toFlushUntilNextPaint({})
		end).toLogDev({
			-- 	"group: * commit (0b0000000000000000000001000000000)",
			-- 	"group: * layout effects (0b0000000000000000000001000000000)",
			"* Example updated state (0b0000000000000000000000000000001)",
			-- 	"groupEnd: * layout effects (0b0000000000000000000001000000000)",
			-- 	"groupEnd: * commit (0b0000000000000000000001000000000)",
		}, { withoutStack = true })
	end)

	-- @gate experimental && build === 'development' && enableDebugTracing
	it("should log render phase state updates for class component", function()
		local Example = React.Component:extend("Example")
		function Example:init()
			self.state = { didRender = false }
		end
		function Example:render()
			if self.state.didRender == false then
				self:setState({ didRender = true })
			end
			return nil
		end

		jestExpect(function()
			ReactTestRenderer.create(
				React.createElement(
					React.unstable_DebugTracingMode,
					nil,
					React.createElement(Example)
				),
				{ unstable_isConcurrent = true }
			)
		end).toLogDev({})

		jestExpect(function()
			jestExpect(function()
				jestExpect(Scheduler).toFlushUntilNextPaint({})
			end).toErrorDev("Cannot update during an existing state transition")
		end).toLogDev({
			-- 	"group: * render (0b0000000000000000000001000000000)",
			"* Example updated state (0b0000000000000000000001000000000)",
			"* Example updated state (0b0000000000000000000001000000000)",
		}, { withoutStack = true })
	end)

	-- @gate experimental && build === 'development' && enableDebugTracing
	it("should log cascading layout updates", function()
		local function Example()
			local didMount, setDidMount = React.useState(false)
			React.useLayoutEffect(function()
				setDidMount(true)
			end, {})
			return didMount
		end

		jestExpect(function()
			ReactTestRenderer.create(
				React.createElement(
					React.unstable_DebugTracingMode,
					nil,
					React.createElement(Example)
				),
				{ unstable_isConcurrent = true }
			)
		end).toLogDev({})

		jestExpect(function()
			jestExpect(Scheduler).toFlushUntilNextPaint({})
		end).toLogDev({
			-- 	"group: * commit (0b0000000000000000000001000000000)",
			-- 	"group: * layout effects (0b0000000000000000000001000000000)",
			"* Example updated state (0b0000000000000000000000000000001)",
			-- 	"groupEnd: * layout effects (0b0000000000000000000001000000000)",
			-- 	"groupEnd: * commit (0b0000000000000000000001000000000)",
		}, { withoutStack = true })
	end)

	-- @gate experimental && build === 'development' && enableDebugTracing
	it("should log cascading passive updates", function()
		local function Example()
			local didMount, setDidMount = React.useState(false)
			React.useEffect(function()
				setDidMount(true)
			end, {})
			return didMount
		end

		jestExpect(function()
			ReactTestRenderer.act(function()
				ReactTestRenderer.create(
					React.createElement(
						React.unstable_DebugTracingMode,
						nil,
						React.createElement(Example)
					),
					{ unstable_isConcurrent = true }
				)
			end)
		end).toLogDev({
			-- 	"group: * passive effects (0b0000000000000000000001000000000)",
			"* Example updated state (0b0000000000000000000010000000000)",
			-- 	"groupEnd: * passive effects (0b0000000000000000000001000000000)",
		}, { withoutStack = true })
	end)

	-- @gate experimental && build === 'development' && enableDebugTracing
	it("should log render phase updates", function()
		local function Example()
			local didRender, setDidRender = React.useState(false)
			if not didRender then
				setDidRender(true)
			end
			return didRender
		end

		jestExpect(function()
			ReactTestRenderer.act(function()
				ReactTestRenderer.create(
					React.createElement(
						React.unstable_DebugTracingMode,
						nil,
						React.createElement(Example)
					),
					{ unstable_isConcurrent = true }
				)
			end)
		end).toLogDev({
			-- 	"group: * render (0b0000000000000000000001000000000)",
			"* Example updated state (0b0000000000000000000001000000000)",
			"* Example updated state (0b0000000000000000000001000000000)",
			-- 	"groupEnd: * render (0b0000000000000000000001000000000)",
		}, { withoutStack = true })

		-- ROBLOX deviation: we don't have build-time gating like upstream
		-- gate(function(flags)
		-- 	if flags.new then
		-- jestExpect(logs).toEqual({
		-- })
		-- 	else
		-- 		jestExpect(logs).toEqual({
		-- 			"group: * render (0b0000000000000000000001000000000)",
		-- 			"log: * Example updated state (0b0000000000000000000010000000000)",
		-- 			"log: * Example updated state (0b0000000000000000000010000000000)",
		-- 			"groupEnd: * render (0b0000000000000000000001000000000)",
		-- 		})
		-- 	end
		-- end)
	end)

	-- @gate experimental && build === 'development' && enableDebugTracing
	xit("should log when user code logs", function()
		local function Example()
			console.log("Hello from user code")
			return nil
		end

		jestExpect(function()
			ReactTestRenderer.create(
				React.createElement(
					React.unstable_DebugTracingMode,
					nil,
					React.createElement(Example)
				),
				{ unstable_isConcurrent = true }
			)
		end).toLogDev({})

		jestExpect(function()
			jestExpect(Scheduler).toFlushUntilNextPaint({})
		end).toLogDev({
			-- 	"group: * render (0b0000000000000000000001000000000)",
			"Hello from user code",
			-- 	"groupEnd: * render (0b0000000000000000000001000000000)",
		})
	end)

	-- @gate experimental
	it(
		"should not log anything outside of a unstable_DebugTracingMode subtree",
		function()
			local function ExampleThatCascades()
				local didMount, setDidMount = React.useState(false)
				React.useLayoutEffect(function()
					setDidMount(true)
				end, {})
				return didMount
			end

			local fakeSuspensePromise = Promise.new(function()
				return {}
			end)
			local function ExampleThatSuspends()
				error(fakeSuspensePromise)
			end

			local function Example()
				return nil
			end

			jestExpect(function()
				ReactTestRenderer.create(
					React.createElement(
						React.Fragment,
						nil,
						React.createElement(ExampleThatCascades),
						React.createElement(
							React.Suspense,
							{ fallback = {} },
							nil,
							React.createElement(ExampleThatSuspends)
						),
						React.createElement(
							React.unstable_DebugTracingMode,
							nil,
							React.createElement(Example)
						)
					)
				)
			end).toLogDev({})
		end
	)
end)
