local U=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 S=U.beforeEach local Z=U.expect local q=U.describe local i=U.it local r=U.jest local x=require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\108\117\097\117-\112\111\108\121\102\105\108\108")local N=x.Set q("\084\114\097\099\105\110\103",function()local U local x local w local b local function D(S)local Z=S.enableSchedulerTracing r.resetModules()r.useFakeTimers()b=os.time w=r.advanceTimersByTime x=(require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\115\104\097\114\101\100")).ReactFeatureFlags x.enableSchedulerTracing=Z U=(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")).tracing end q("\101\110\097\098\108\101\083\099\104\101\100\117\108\101\114\084\114\097\099\105\110\103 \101\110\097\098\108\101\100",function()S(function()D({enableSchedulerTracing=true})end)i("\115\104\111\117\108\100 \114\101\116\117\114\110 \116\104\101 \118\097\108\117\101 \111\102 \097 \116\114\097\099\101\100 \102\117\110\099\116\105\111\110",function()(Z(U.unstable_trace("\097\114\098\105\116\114\097\114\121",b(),function()return 123 end))).toBe(123)end)i("\115\104\111\117\108\100 \114\101\116\117\114\110 \116\104\101 \118\097\108\117\101 \111\102 \097 \099\108\101\097\114 \102\117\110\099\116\105\111\110",function()(Z(U.unstable_clear(function()return 123 end))).toBe(123)end)i("\115\104\111\117\108\100 \114\101\116\117\114\110 \116\104\101 \118\097\108\117\101 \111\102 \097 \119\114\097\112\112\101\100 \102\117\110\099\116\105\111\110",function()local S U.unstable_trace("\097\114\098\105\116\114\097\114\121",b(),function()S=U.unstable_wrap(function()return 123 end)end)r.runAllTimers();(Z(S())).toBe(123)end)i("\115\104\111\117\108\100 \112\097\115\115 \097\114\103\117\109\101\110\116\115 \116\104\114\111\117\103\104 \116\111 \097 \119\114\097\112\112\101\100 \102\117\110\099\116\105\111\110",function()local S local q=false U.unstable_trace("\097\114\098\105\116\114\097\114\121",b(),function()S=U.unstable_wrap(function(U,S)(Z(U)).toBe("\102\111\111");(Z(S)).toBe("\098\097\114")q=true end)end)S("\102\111\111","\098\097\114")r.runAllTimers();(Z(q)).toBe(true)end)i("\115\104\111\117\108\100 \114\101\116\117\114\110 \097\110 \101\109\112\116\121 \115\101\116 \119\104\101\110 \111\117\116\115\105\100\101 \111\102 \097 \116\114\097\099\101\100 \101\118\101\110\116",function()(Z(U.unstable_getCurrent())).toContainNoInteractions()end)i("\115\104\111\117\108\100 \114\101\112\111\114\116 \116\104\101 \116\114\097\099\101\100 \105\110\116\101\114\097\099\116\105\111\110 \102\114\111\109 \119\105\116\104\105\110 \116\104\101 \116\114\097\099\101 \099\097\108\108\098\097\099\107",function()local S=false w(100)U.unstable_trace("\115\111\109\101 \101\118\101\110\116",b(),function()local q=U.unstable_getCurrent();(Z(q)).toMatchInteractions({{name="\115\111\109\101 \101\118\101\110\116",timestamp=100}})S=true end);(Z(S)).toBe(true)end)i("\115\104\111\117\108\100 \114\101\112\111\114\116 \116\104\101 \116\114\097\099\101\100 \105\110\116\101\114\097\099\116\105\111\110 \102\114\111\109 \119\105\116\104\105\110 \119\114\097\112\112\101\100 \099\097\108\108\098\097\099\107\115",function()local S=false local q local function i()local q=U.unstable_getCurrent();(Z(q)).toMatchInteractions({{name="\115\111\109\101 \101\118\101\110\116",timestamp=100}})S=true end w(100)U.unstable_trace("\115\111\109\101 \101\118\101\110\116",b(),function()q=U.unstable_wrap(i)end)w(50)q();(Z(S)).toBe(true)end)i("\115\104\111\117\108\100 \099\108\101\097\114 \116\104\101 \105\110\116\101\114\097\099\116\105\111\110 \115\116\097\099\107 \102\111\114 \116\114\097\099\101\100 \099\097\108\108\098\097\099\107\115",function()local S=false U.unstable_trace("\111\117\116\101\114 \101\118\101\110\116",b(),function()(Z(U.unstable_getCurrent())).toMatchInteractions({{name="\111\117\116\101\114 \101\118\101\110\116"}})U.unstable_clear(function()(Z(U.unstable_getCurrent())).toMatchInteractions({})U.unstable_trace("\105\110\110\101\114 \101\118\101\110\116",b(),function()(Z(U.unstable_getCurrent())).toMatchInteractions({{name="\105\110\110\101\114 \101\118\101\110\116"}})S=true end)end);(Z(U.unstable_getCurrent())).toMatchInteractions({{name="\111\117\116\101\114 \101\118\101\110\116"}})end);(Z(S)).toBe(true)end)i("\115\104\111\117\108\100 \099\108\101\097\114 \116\104\101 \105\110\116\101\114\097\099\116\105\111\110 \115\116\097\099\107 \102\111\114 \119\114\097\112\112\101\100 \099\097\108\108\098\097\099\107\115",function()local S=false local q local i=r.fn(function()(Z(U.unstable_getCurrent())).toMatchInteractions({{name="\111\117\116\101\114 \101\118\101\110\116"}})U.unstable_clear(function()(Z(U.unstable_getCurrent())).toMatchInteractions({})U.unstable_trace("\105\110\110\101\114 \101\118\101\110\116",b(),function()(Z(U.unstable_getCurrent())).toMatchInteractions({{name="\105\110\110\101\114 \101\118\101\110\116"}})S=true end)end);(Z(U.unstable_getCurrent())).toMatchInteractions({{name="\111\117\116\101\114 \101\118\101\110\116"}})end)U.unstable_trace("\111\117\116\101\114 \101\118\101\110\116",b(),function()q=U.unstable_wrap(i)end)q();(Z(S)).toBe(true)end)i("\115\104\111\117\108\100 \115\117\112\112\111\114\116 \110\101\115\116\101\100 \116\114\097\099\101\100 \101\118\101\110\116\115",function()local S=false w(100)local q=false local i=false local function r()local S=U.unstable_getCurrent();(Z(S)).toMatchInteractions({{name="\111\117\116\101\114 \101\118\101\110\116";timestamp=100},{name="\105\110\110\101\114 \101\118\101\110\116";timestamp=150}})q=true end local function x()local S=U.unstable_getCurrent();(Z(S)).toMatchInteractions({{name="\111\117\116\101\114 \101\118\101\110\116";timestamp=100}})i=true end U.unstable_trace("\111\117\116\101\114 \101\118\101\110\116",b(),function()local N=U.unstable_getCurrent();(Z(N)).toMatchInteractions({{name="\111\117\116\101\114 \101\118\101\110\116";timestamp=100}})w(50)local D=U.unstable_wrap(x)local l local m=false U.unstable_trace("\105\110\110\101\114 \101\118\101\110\116",b(),function()N=U.unstable_getCurrent();(Z(N)).toMatchInteractions({{name="\111\117\116\101\114 \101\118\101\110\116";timestamp=100};{name="\105\110\110\101\114 \101\118\101\110\116",timestamp=150}})D();(Z(i)).toBe(true)l=U.unstable_wrap(r)m=true end);(Z(m)).toBe(true)N=U.unstable_getCurrent();(Z(N)).toMatchInteractions({{name="\111\117\116\101\114 \101\118\101\110\116";timestamp=100}})l();(Z(q)).toBe(true)S=true end);(Z(S)).toBe(true)end)q("\101\114\114\111\114 \104\097\110\100\108\105\110\103",function()i("\115\104\111\117\108\100 \114\101\115\101\116 \115\116\097\116\101 \097\112\112\114\111\112\114\105\097\116\101\108\121 \119\104\101\110 \097\110 \101\114\114\111\114 \111\099\099\117\114\115 \105\110 \097 \116\114\097\099\101 \099\097\108\108\098\097\099\107",function()local S=false w(100)U.unstable_trace("\111\117\116\101\114 \101\118\101\110\116",b(),function()(Z(function()U.unstable_trace("\105\110\110\101\114 \101\118\101\110\116",b(),function()error("\105\110\116\101\110\116\105\111\110\097\108")end)end)).toThrow();(Z(U.unstable_getCurrent())).toMatchInteractions({{name="\111\117\116\101\114 \101\118\101\110\116",timestamp=100}})S=true end);(Z(S)).toBe(true)end)i("\115\104\111\117\108\100 \114\101\115\101\116 \115\116\097\116\101 \097\112\112\114\111\112\114\105\097\116\101\108\121 \119\104\101\110 \097\110 \101\114\114\111\114 \111\099\099\117\114\115 \105\110 \097 \119\114\097\112\112\101\100 \099\097\108\108\098\097\099\107",function()local S=false w(100)U.unstable_trace("\111\117\116\101\114 \101\118\101\110\116",b(),function()local q U.unstable_trace("\105\110\110\101\114 \101\118\101\110\116",b(),function()q=U.unstable_wrap(function()error("\105\110\116\101\110\116\105\111\110\097\108")end)end);(Z(function()q()end)).toThrow();(Z(U.unstable_getCurrent())).toMatchInteractions({{name="\111\117\116\101\114 \101\118\101\110\116",timestamp=100}})S=true end);(Z(S)).toBe(true)end)end)q("\097\100\118\097\110\099\101\100 \105\110\116\101\103\114\097\116\105\111\110",function()i("\115\104\111\117\108\100 \114\101\116\117\114\110 \097 \117\110\105\113\117\101 \116\104\114\101\097\100\073\068 \112\101\114 \114\101\113\117\101\115\116",function()(Z(U.unstable_getThreadID())).never.toBe(U.unstable_getThreadID())end)i("\115\104\111\117\108\100 \101\120\112\111\115\101 \116\104\101 \099\117\114\114\101\110\116 \115\101\116 \111\102 \105\110\116\101\114\097\099\116\105\111\110\115 \116\111 \098\101 \101\120\116\101\114\110\097\108\108\121 \109\097\110\105\112\117\108\097\116\101\100",function()U.unstable_trace("\111\117\116\101\114 \101\118\101\110\116",b(),function()(Z(U.__interactionsRef.current)).toBe(U.unstable_getCurrent())U.__interactionsRef.current=N.new({{name="\111\118\101\114\114\105\100\101 \101\118\101\110\116"}});(Z(U.unstable_getCurrent())).toMatchInteractions({{name="\111\118\101\114\114\105\100\101 \101\118\101\110\116"}})end)end)i("\115\104\111\117\108\100 \101\120\112\111\115\101 \097 \115\117\098\115\099\114\105\098\101\114 \114\101\102 \116\111 \098\101 \101\120\116\101\114\110\097\108\108\121 \109\097\110\105\112\117\108\097\116\101\100",function()U.unstable_trace("\111\117\116\101\114 \101\118\101\110\116",b(),function()(Z(U.__subscriberRef)).toEqual({current=nil})end)end)end)end)q("\101\110\097\098\108\101\083\099\104\101\100\117\108\101\114\084\114\097\099\105\110\103 \100\105\115\097\098\108\101\100",function()S(function()D({enableSchedulerTracing=false})end)i("\115\104\111\117\108\100 \114\101\116\117\114\110 \116\104\101 \118\097\108\117\101 \111\102 \097 \116\114\097\099\101\100 \102\117\110\099\116\105\111\110",function()(Z(U.unstable_trace("\097\114\098\105\116\114\097\114\121",b(),function()return 123 end))).toBe(123)end)i("\115\104\111\117\108\100 \114\101\116\117\114\110 \116\104\101 \118\097\108\117\101 \111\102 \097 \119\114\097\112\112\101\100 \102\117\110\099\116\105\111\110",function()local S U.unstable_trace("\097\114\098\105\116\114\097\114\121",b(),function()S=U.unstable_wrap(function()return 123 end)end);(Z(S())).toBe(123)end)i("\115\104\111\117\108\100 \114\101\116\117\114\110 \110\105\108 \102\111\114 \116\114\097\099\101\100 \105\110\116\101\114\097\099\116\105\111\110\115",function()(Z(U.unstable_getCurrent())).toBe(nil)end)i("\115\104\111\117\108\100 \101\120\101\099\117\116\101 \116\114\097\099\101\100 \099\097\108\108\098\097\099\107\115",function()local S=false U.unstable_trace("\115\111\109\101 \101\118\101\110\116",b(),function()(Z(U.unstable_getCurrent())).toBe(nil)S=true end);(Z(S)).toBe(true)end)i("\115\104\111\117\108\100 \114\101\116\117\114\110 \116\104\101 \118\097\108\117\101 \111\102 \097 \099\108\101\097\114 \102\117\110\099\116\105\111\110",function()(Z(U.unstable_clear(function()return 123 end))).toBe(123)end)i("\115\104\111\117\108\100 \101\120\101\099\117\116\101 \119\114\097\112\112\101\100 \099\097\108\108\098\097\099\107\115",function()local S=false local q=U.unstable_wrap(function()(Z(U.unstable_getCurrent())).toBe(nil)S=true end)q();(Z(S)).toBe(true)end)q("\097\100\118\097\110\099\101\100 \105\110\116\101\103\114\097\116\105\111\110",function()i("\115\104\111\117\108\100 \110\111\116 \099\114\101\097\116\101 \117\110\110\101\099\101\115\115\097\114\121 \111\098\106\101\099\116\115",function()(Z(U.__interactionsRef)).toBe(nil)end)end)end)end)
-- ROBLOX upstream: https://github.com/facebook/react/blob/9abc2785cb070148d64fae81e523246b90b92016/packages/scheduler/src/__tests__/Tracing-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.
--  *
--  * @jest-environment node
--  */

local JestGlobals = require("@pkg/@jsdotlua/jest-globals")
local beforeEach = JestGlobals.beforeEach
local jestExpect = JestGlobals.expect
local describe = JestGlobals.describe
local it = JestGlobals.it
local jest = JestGlobals.jest
local LuauPolyfill = require("@pkg/@jsdotlua/luau-polyfill")
local Set = LuauPolyfill.Set

describe("Tracing", function()
	local SchedulerTracing
	local ReactFeatureFlags

	local advanceTimeBy
	local currentTime

	local function loadModules(config)
		local enableSchedulerTracing = config.enableSchedulerTracing
		jest.resetModules()
		jest.useFakeTimers()

		currentTime = os.time

		advanceTimeBy = jest.advanceTimersByTime

		ReactFeatureFlags = require("@pkg/@jsdotlua/shared").ReactFeatureFlags
		ReactFeatureFlags.enableSchedulerTracing = enableSchedulerTracing

		SchedulerTracing = require("@pkg/@jsdotlua/scheduler").tracing
	end

	describe("enableSchedulerTracing enabled", function()
		beforeEach(function()
			loadModules({ enableSchedulerTracing = true })
		end)

		it("should return the value of a traced function", function()
			jestExpect(
				SchedulerTracing.unstable_trace("arbitrary", currentTime(), function()
					return 123
				end)
			).toBe(123)
		end)

		it("should return the value of a clear function", function()
			jestExpect(SchedulerTracing.unstable_clear(function()
				return 123
			end)).toBe(123)
		end)

		it("should return the value of a wrapped function", function()
			local wrapped
			SchedulerTracing.unstable_trace("arbitrary", currentTime(), function()
				wrapped = SchedulerTracing.unstable_wrap(function()
					return 123
				end)
			end)
			jest.runAllTimers()

			jestExpect(wrapped()).toBe(123)
		end)

		it("should pass arguments through to a wrapped function", function()
			local wrapped
			local done = false
			SchedulerTracing.unstable_trace("arbitrary", currentTime(), function()
				wrapped = SchedulerTracing.unstable_wrap(function(param1, param2)
					jestExpect(param1).toBe("foo")
					jestExpect(param2).toBe("bar")
					done = true
				end)
			end)
			wrapped("foo", "bar")
			jest.runAllTimers()
			jestExpect(done).toBe(true)
		end)

		it("should return an empty set when outside of a traced event", function()
			jestExpect(SchedulerTracing.unstable_getCurrent()).toContainNoInteractions()
		end)

		it(
			"should report the traced interaction from within the trace callback",
			function()
				local done = false
				advanceTimeBy(100)

				SchedulerTracing.unstable_trace("some event", currentTime(), function()
					local interactions = SchedulerTracing.unstable_getCurrent()
					jestExpect(interactions).toMatchInteractions({
						{ name = "some event", timestamp = 100 },
					})

					done = true
				end)

				jestExpect(done).toBe(true)
			end
		)

		it(
			"should report the traced interaction from within wrapped callbacks",
			function()
				local done = false
				local wrappedIndirection

				local function indirection()
					local interactions = SchedulerTracing.unstable_getCurrent()
					jestExpect(interactions).toMatchInteractions({
						{ name = "some event", timestamp = 100 },
					})

					done = true
				end

				advanceTimeBy(100)

				SchedulerTracing.unstable_trace("some event", currentTime(), function()
					wrappedIndirection = SchedulerTracing.unstable_wrap(indirection)
				end)

				advanceTimeBy(50)

				wrappedIndirection()
				jestExpect(done).toBe(true)
			end
		)

		it("should clear the interaction stack for traced callbacks", function()
			local innerTestReached = false

			SchedulerTracing.unstable_trace("outer event", currentTime(), function()
				jestExpect(SchedulerTracing.unstable_getCurrent()).toMatchInteractions({
					{ name = "outer event" },
				})

				SchedulerTracing.unstable_clear(function()
					jestExpect(SchedulerTracing.unstable_getCurrent()).toMatchInteractions({})

					SchedulerTracing.unstable_trace(
						"inner event",
						currentTime(),
						function()
							jestExpect(SchedulerTracing.unstable_getCurrent()).toMatchInteractions({
								{ name = "inner event" },
							})

							innerTestReached = true
						end
					)
				end)

				jestExpect(SchedulerTracing.unstable_getCurrent()).toMatchInteractions({
					{ name = "outer event" },
				})
			end)

			jestExpect(innerTestReached).toBe(true)
		end)

		it("should clear the interaction stack for wrapped callbacks", function()
			local innerTestReached = false
			local wrappedIndirection

			local indirection = jest.fn(function()
				jestExpect(SchedulerTracing.unstable_getCurrent()).toMatchInteractions({
					{ name = "outer event" },
				})

				SchedulerTracing.unstable_clear(function()
					jestExpect(SchedulerTracing.unstable_getCurrent()).toMatchInteractions({})

					SchedulerTracing.unstable_trace(
						"inner event",
						currentTime(),
						function()
							jestExpect(SchedulerTracing.unstable_getCurrent()).toMatchInteractions({
								{ name = "inner event" },
							})

							innerTestReached = true
						end
					)
				end)

				jestExpect(SchedulerTracing.unstable_getCurrent()).toMatchInteractions({
					{ name = "outer event" },
				})
			end)

			SchedulerTracing.unstable_trace("outer event", currentTime(), function()
				wrappedIndirection = SchedulerTracing.unstable_wrap(indirection)
			end)

			wrappedIndirection()

			jestExpect(innerTestReached).toBe(true)
		end)

		it("should support nested traced events", function()
			local done = false
			advanceTimeBy(100)

			local innerIndirectionTraced = false
			local outerIndirectionTraced = false

			local function innerIndirection()
				local interactions = SchedulerTracing.unstable_getCurrent()
				jestExpect(interactions).toMatchInteractions({
					{ name = "outer event", timestamp = 100 },
					{ name = "inner event", timestamp = 150 },
				})

				innerIndirectionTraced = true
			end

			local function outerIndirection()
				local interactions = SchedulerTracing.unstable_getCurrent()
				jestExpect(interactions).toMatchInteractions({
					{ name = "outer event", timestamp = 100 },
				})

				outerIndirectionTraced = true
			end

			SchedulerTracing.unstable_trace("outer event", currentTime(), function()
				-- Verify the current traced event
				local interactions = SchedulerTracing.unstable_getCurrent()
				jestExpect(interactions).toMatchInteractions({
					{ name = "outer event", timestamp = 100 },
				})

				advanceTimeBy(50)

				local wrapperOuterIndirection =
					SchedulerTracing.unstable_wrap(outerIndirection)

				local wrapperInnerIndirection
				local innerEventTraced = false

				-- Verify that a nested event is properly traced
				SchedulerTracing.unstable_trace("inner event", currentTime(), function()
					interactions = SchedulerTracing.unstable_getCurrent()
					jestExpect(interactions).toMatchInteractions({
						{ name = "outer event", timestamp = 100 },
						{ name = "inner event", timestamp = 150 },
					})

					-- Verify that a wrapped outer callback is properly traced
					wrapperOuterIndirection()
					jestExpect(outerIndirectionTraced).toBe(true)

					wrapperInnerIndirection =
						SchedulerTracing.unstable_wrap(innerIndirection)

					innerEventTraced = true
				end)

				jestExpect(innerEventTraced).toBe(true)

				-- Verify that the original event is restored
				interactions = SchedulerTracing.unstable_getCurrent()
				jestExpect(interactions).toMatchInteractions({
					{ name = "outer event", timestamp = 100 },
				})

				-- Verify that a wrapped nested callback is properly traced
				wrapperInnerIndirection()
				jestExpect(innerIndirectionTraced).toBe(true)

				done = true
			end)
			jestExpect(done).toBe(true)
		end)

		describe("error handling", function()
			it(
				"should reset state appropriately when an error occurs in a trace callback",
				function()
					local done = false
					advanceTimeBy(100)

					SchedulerTracing.unstable_trace(
						"outer event",
						currentTime(),
						function()
							jestExpect(function()
								SchedulerTracing.unstable_trace(
									"inner event",
									currentTime(),
									function()
										error("intentional")
									end
								)
							end).toThrow()

							jestExpect(SchedulerTracing.unstable_getCurrent()).toMatchInteractions({
								{ name = "outer event", timestamp = 100 },
							})

							done = true
						end
					)
					jestExpect(done).toBe(true)
				end
			)

			it(
				"should reset state appropriately when an error occurs in a wrapped callback",
				function()
					local done = false
					advanceTimeBy(100)

					SchedulerTracing.unstable_trace(
						"outer event",
						currentTime(),
						function()
							local wrappedCallback

							SchedulerTracing.unstable_trace(
								"inner event",
								currentTime(),
								function()
									wrappedCallback = SchedulerTracing.unstable_wrap(
										function()
											error("intentional")
										end
									)
								end
							)

							-- ROBLOX deviation: unstable_wrap returns a table with a __call metamethod so it can have a cancel field
							jestExpect(function()
								wrappedCallback()
							end).toThrow()

							jestExpect(SchedulerTracing.unstable_getCurrent()).toMatchInteractions({
								{ name = "outer event", timestamp = 100 },
							})

							done = true
						end
					)
					jestExpect(done).toBe(true)
				end
			)
		end)

		describe("advanced integration", function()
			it("should return a unique threadID per request", function()
				jestExpect(SchedulerTracing.unstable_getThreadID()).never.toBe(
					SchedulerTracing.unstable_getThreadID()
				)
			end)

			it(
				"should expose the current set of interactions to be externally manipulated",
				function()
					SchedulerTracing.unstable_trace(
						"outer event",
						currentTime(),
						function()
							jestExpect(SchedulerTracing.__interactionsRef.current).toBe(
								SchedulerTracing.unstable_getCurrent()
							)

							SchedulerTracing.__interactionsRef.current = Set.new({
								{ name = "override event" },
							})

							jestExpect(SchedulerTracing.unstable_getCurrent()).toMatchInteractions({
								{ name = "override event" },
							})
						end
					)
				end
			)

			it("should expose a subscriber ref to be externally manipulated", function()
				SchedulerTracing.unstable_trace("outer event", currentTime(), function()
					jestExpect(SchedulerTracing.__subscriberRef).toEqual({
						current = nil,
					})
				end)
			end)
		end)
	end)

	describe("enableSchedulerTracing disabled", function()
		beforeEach(function()
			loadModules({ enableSchedulerTracing = false })
		end)

		it("should return the value of a traced function", function()
			jestExpect(
				SchedulerTracing.unstable_trace("arbitrary", currentTime(), function()
					return 123
				end)
			).toBe(123)
		end)

		it("should return the value of a wrapped function", function()
			local wrapped
			SchedulerTracing.unstable_trace("arbitrary", currentTime(), function()
				wrapped = SchedulerTracing.unstable_wrap(function()
					return 123
				end)
			end)
			jestExpect(wrapped()).toBe(123)
		end)

		it("should return nil for traced interactions", function()
			jestExpect(SchedulerTracing.unstable_getCurrent()).toBe(nil)
		end)

		it("should execute traced callbacks", function()
			local done = false
			SchedulerTracing.unstable_trace("some event", currentTime(), function()
				jestExpect(SchedulerTracing.unstable_getCurrent()).toBe(nil)

				done = true
			end)
			jestExpect(done).toBe(true)
		end)

		it("should return the value of a clear function", function()
			jestExpect(SchedulerTracing.unstable_clear(function()
				return 123
			end)).toBe(123)
		end)

		it("should execute wrapped callbacks", function()
			local done = false
			local wrappedCallback = SchedulerTracing.unstable_wrap(function()
				jestExpect(SchedulerTracing.unstable_getCurrent()).toBe(nil)

				done = true
			end)

			wrappedCallback()
			jestExpect(done).toBe(true)
		end)

		describe("advanced integration", function()
			it("should not create unnecessary objects", function()
				jestExpect(SchedulerTracing.__interactionsRef).toBe(nil)
			end)
		end)
	end)
end)
