local e local k local p local f=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=f.expect local A=f.beforeEach local M=f.it local O=f.jest local X=f.describe local o X("\117\115\101\082\101\102",function()A(function()O.resetModules()e=require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\114\101\097\099\116")k=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")p=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")o=e.useRef end)M("\115\104\111\117\108\100 \097\115\115\105\103\110 \105\110\105\116\105\097\108 \118\097\108\117\101 \116\111 \116\104\101 \114\101\102",function()local f local A local function M()f=o(123)A=o("\072\101\108\108\111\082\101\102")return nil end local O=Instance.new("\070\111\108\100\101\114")local X=k.createRoot(O)X:render(e.createElement(M))p.unstable_flushAll();(S(f)).toBeDefined();(S(f.current)).toBe(123);(S(A)).toBeDefined();(S(A.current)).toBe("\072\101\108\108\111\082\101\102")X:unmount()end)M("\115\104\111\117\108\100 \097\108\108\111\119 \099\117\114\114\101\110\116 \118\097\108\117\101 \116\111 \098\101 \117\112\100\097\116\101\100",function()local f local function A()f=o(123)e.useEffect(function()f.current=456 end,{})return nil end local M=Instance.new("\070\111\108\100\101\114")local O=k.createRoot(M)O:render(e.createElement(A))p.unstable_flushAll();(S(f)).toBeDefined();(S(f.current)).toBe(456)end)M("\115\104\111\117\108\100 \114\101\109\101\109\098\101\114 \099\117\114\114\101\110\116 \118\097\108\117\101 \098\101\116\119\101\101\110 \114\101\110\100\101\114\115",function()local f local function A()f=o(0)f.current+=1 return nil end local M=Instance.new("\070\111\108\100\101\114")local O=k.createRoot(M)O:render(e.createElement(A))p.unstable_flushAll();(S(f)).toBeDefined()local X=f.current;(S(X)).toBeGreaterThan(0)O:render(e.createElement(A))p.unstable_flushAll()local L=f.current;(S(L)).toBeGreaterThan(X)O:render(e.createElement(A))p.unstable_flushAll()local r=f.current;(S(r)).toBeGreaterThan(L)O:unmount()end)M("\115\104\111\117\108\100 \098\105\110\100 \116\111 \078\101\120\116\083\101\108\101\099\116\105\111\110 \112\114\111\112\115 \119\105\116\104\111\117\116 \101\114\114\111\114",function()local f local function A()f=o(nil)return e.createElement(e.Fragment,{},{Top=e.createElement("\070\114\097\109\101",{Size=UDim2.fromScale(1,.5);NextSelectionUp=f;NextSelectionDown=f;NextSelectionLeft=f,NextSelectionRight=f});Bottom=e.createElement("\070\114\097\109\101",{Size=UDim2.fromScale(1,.5),Position=UDim2.fromScale(0,.5);ref=f})})end local M=Instance.new("\070\111\108\100\101\114")local O=k.createRoot(M)O:render(e.createElement(A))p.unstable_flushAll();(S(f)).toBeDefined();(S(f.current)).toMatchInstance({Name="\066\111\116\116\111\109"})O:unmount()end)M("\115\104\111\117\108\100 \115\116\114\105\110\103\105\102\121 \114\101\102\115 \099\111\114\114\101\099\116\108\121",function()local f local function A()f=o(nil)return e.createElement("\070\114\097\109\101",{Size=UDim2.new(1,0,1,0);ref=f})end local M=Instance.new("\070\111\108\100\101\114")local O=k.createRoot(M)O:render(e.createElement(A))p.unstable_flushAll();(S(f)).toBeDefined();(S(tostring(f))).toEqual("\082\101\102\040\070\114\097\109\101\041")O:unmount()end)end)
local React
local ReactRoblox
local Scheduler

--ROBLOX NOTE: Tests for the Bindings-based useRef approach
local JestGlobals = require("@pkg/@jsdotlua/jest-globals")
local jestExpect = JestGlobals.expect
local beforeEach = JestGlobals.beforeEach
local it = JestGlobals.it
local jest = JestGlobals.jest
local describe = JestGlobals.describe
local useRef

describe("useRef", function()
	beforeEach(function()
		jest.resetModules()

		React = require("@pkg/@jsdotlua/react")
		ReactRoblox = require("@pkg/@jsdotlua/react-roblox")
		Scheduler = require("@pkg/@jsdotlua/scheduler")
		useRef = React.useRef
	end)

	it("should assign initial value to the ref", function()
		local refNumber
		local refString
		local function component()
			refNumber = useRef(123)
			refString = useRef("HelloRef")
			return nil
		end

		local container = Instance.new("Folder")
		local root = ReactRoblox.createRoot(container)

		root:render(React.createElement(component))

		Scheduler.unstable_flushAll()

		jestExpect(refNumber).toBeDefined()
		jestExpect(refNumber.current).toBe(123)
		jestExpect(refString).toBeDefined()
		jestExpect(refString.current).toBe("HelloRef")

		root:unmount()
	end)

	it("should allow current value to be updated", function()
		local refNumber
		local function component()
			refNumber = useRef(123)

			React.useEffect(function()
				refNumber.current = 456
			end, {})

			return nil
		end

		local container = Instance.new("Folder")
		local root = ReactRoblox.createRoot(container)

		root:render(React.createElement(component))

		-- ROBLOX Test Noise: jest setup config hides "act not enabled in
		-- prod" warnings (scripts/jest/setupTests.js:72)
		Scheduler.unstable_flushAll()

		jestExpect(refNumber).toBeDefined()
		jestExpect(refNumber.current).toBe(456)
	end)

	it("should remember current value between renders", function()
		local countRef
		local function component()
			countRef = useRef(0)
			countRef.current += 1
			return nil
		end

		local container = Instance.new("Folder")
		local root = ReactRoblox.createRoot(container)

		root:render(React.createElement(component))

		Scheduler.unstable_flushAll()

		jestExpect(countRef).toBeDefined()
		local count1 = countRef.current
		jestExpect(count1).toBeGreaterThan(0)

		root:render(React.createElement(component))

		Scheduler.unstable_flushAll()

		local count2 = countRef.current
		jestExpect(count2).toBeGreaterThan(count1)

		root:render(React.createElement(component))

		Scheduler.unstable_flushAll()

		local count3 = countRef.current
		jestExpect(count3).toBeGreaterThan(count2)

		root:unmount()
	end)

	it("should bind to NextSelection props without error", function()
		local bottomRef
		local function component()
			bottomRef = useRef(nil)

			return React.createElement(React.Fragment, {}, {
				Top = React.createElement("Frame", {
					Size = UDim2.fromScale(1, 0.5),
					NextSelectionUp = bottomRef,
					NextSelectionDown = bottomRef,
					NextSelectionLeft = bottomRef,
					NextSelectionRight = bottomRef,
				}),
				Bottom = React.createElement("Frame", {
					Size = UDim2.fromScale(1, 0.5),
					Position = UDim2.fromScale(0, 0.5),
					ref = bottomRef,
				}),
			})
		end

		local container = Instance.new("Folder")
		local root = ReactRoblox.createRoot(container)

		root:render(React.createElement(component))

		Scheduler.unstable_flushAll()

		jestExpect(bottomRef).toBeDefined()
		jestExpect(bottomRef.current).toMatchInstance({
			Name = "Bottom",
		})

		root:unmount()
	end)

	it("should stringify refs correctly", function()
		local frameRef
		local function component()
			frameRef = useRef(nil)

			return React.createElement("Frame", {
				Size = UDim2.new(1, 0, 1, 0),
				ref = frameRef,
			})
		end

		local container = Instance.new("Folder")
		local root = ReactRoblox.createRoot(container)

		root:render(React.createElement(component))

		Scheduler.unstable_flushAll()

		jestExpect(frameRef).toBeDefined()
		jestExpect(tostring(frameRef)).toEqual("Ref(Frame)")

		root:unmount()
	end)
end)
