return function()local K=require(script.Parent.assertDeepEqual)local e=require(script.Parent.Binding)local B=require(script.Parent.PropMarkers.Children)local M=require(script.Parent.Component)local x=require(script.Parent.createElement)local u=require(script.Parent.createFragment)local P=require(script.Parent.createReconciler)local J=require(script.Parent.createRef)local C=require(script.Parent.createSpy)local g=require(script.Parent.GlobalConfig)local p=require(script.Parent.Portal)local j=require(script.Parent.PropMarkers.Ref)local U=require(script.Parent.RobloxRenderer)local v=P(U)describe("\109\111\117\110\116\072\111\115\116\078\111\100\101",function()it("\115\104\111\117\108\100 \099\114\101\097\116\101 \105\110\115\116\097\110\099\101\115 \119\105\116\104 \099\111\114\114\101\099\116 \112\114\111\112\115",function()local K=Instance.new("\070\111\108\100\101\114")local e="\072\101\108\108\111\033"local B="\083\111\109\101 \075\101\121"local M=x("\083\116\114\105\110\103\086\097\108\117\101",{Value=e})local u=v.createVirtualNode(M,K,B)U.mountHostNode(v,u);(expect(#K:GetChildren())).to.equal(1)local P=(K:GetChildren())[1];(expect(P.ClassName)).to.equal("\083\116\114\105\110\103\086\097\108\117\101");(expect(P.Value)).to.equal(e);(expect(P.Name)).to.equal(B)end)it("\115\104\111\117\108\100 \099\114\101\097\116\101 \099\104\105\108\100\114\101\110 \119\105\116\104 \099\111\114\114\101\099\116 \110\097\109\101\115 \097\110\100 \112\114\111\112\115",function()local K=Instance.new("\070\111\108\100\101\114")local e="\072\101\121 \116\104\101\114\101\033"local B=173 local M="\083\111\109\101 \075\101\121"local u=x("\083\116\114\105\110\103\086\097\108\117\101",{Value=e},{ChildA=x("\073\110\116\086\097\108\117\101",{Value=B});ChildB=x("\070\111\108\100\101\114")})local P=v.createVirtualNode(u,K,M)U.mountHostNode(v,P);(expect(#K:GetChildren())).to.equal(1)local J=(K:GetChildren())[1];(expect(J.ClassName)).to.equal("\083\116\114\105\110\103\086\097\108\117\101");(expect(J.Value)).to.equal(e);(expect(J.Name)).to.equal(M);(expect(#J:GetChildren())).to.equal(2)local C=J.ChildA local g=J.ChildB;(expect(C)).to.be.ok();(expect(g)).to.be.ok();(expect(C.ClassName)).to.equal("\073\110\116\086\097\108\117\101");(expect(C.Value)).to.equal(B);(expect(g.ClassName)).to.equal("\070\111\108\100\101\114")end)it("\115\104\111\117\108\100 \097\116\116\097\099\104 \066\105\110\100\105\110\103\115 \116\111 \082\111\098\108\111\120 \112\114\111\112\101\114\116\105\101\115",function()local K=Instance.new("\070\111\108\100\101\114")local B="\083\111\109\101 \075\101\121"local M,u=e.create(10)local P=x("\073\110\116\086\097\108\117\101",{Value=M})local J=v.createVirtualNode(P,K,B)U.mountHostNode(v,J);(expect(#K:GetChildren())).to.equal(1)local C=(K:GetChildren())[1];(expect(C.ClassName)).to.equal("\073\110\116\086\097\108\117\101");(expect(C.Value)).to.equal(10)u(20);(expect(C.Value)).to.equal(20)U.unmountHostNode(v,J)end)it("\115\104\111\117\108\100 \099\111\110\110\101\099\116 \066\105\110\100\105\110\103 \114\101\102\115",function()local K=Instance.new("\070\111\108\100\101\114")local e="\083\111\109\101 \075\101\121"local B=J()local M=x("\070\114\097\109\101",{[j]=B})local u=v.createVirtualNode(M,K,e)U.mountHostNode(v,u);(expect(#K:GetChildren())).to.equal(1)local P=(K:GetChildren())[1];(expect(B.current)).to.be.ok();(expect(B.current)).to.equal(P)U.unmountHostNode(v,u)end)it("\115\104\111\117\108\100 \099\097\108\108 \102\117\110\099\116\105\111\110 \114\101\102\115",function()local K=Instance.new("\070\111\108\100\101\114")local e="\083\111\109\101 \075\101\121"local B=C()local M=x("\070\114\097\109\101",{[j]=B.value})local u=v.createVirtualNode(M,K,e)U.mountHostNode(v,u);(expect(#K:GetChildren())).to.equal(1)local P=(K:GetChildren())[1];(expect(B.callCount)).to.equal(1)B:assertCalledWith(P)U.unmountHostNode(v,u)end)it("\115\104\111\117\108\100 \116\104\114\111\119 \105\102 \115\101\116\116\105\110\103 \105\110\118\097\108\105\100 \105\110\115\116\097\110\099\101 \112\114\111\112\101\114\116\105\101\115",function()local K={elementTracing=true}g.scoped(K,function()local K=Instance.new("\070\111\108\100\101\114")local e="\083\111\109\101 \075\101\121"local B=x("\070\114\097\109\101",{Frob=6})local M=v.createVirtualNode(B,K,e)local u,P=pcall(U.mountHostNode,v,M)assert(not u,"\069\120\112\101\099\116\101\100 \099\097\108\108 \116\111 \102\097\105\108");(expect(P:find("\070\114\111\098"))).to.be.ok();(expect(P:find("\070\114\097\109\101"))).to.be.ok();(expect(P:find("\082\111\098\108\111\120\082\101\110\100\101\114\101\114\037\046\115\112\101\099"))).to.be.ok()end)end)end)describe("\117\112\100\097\116\101\072\111\115\116\078\111\100\101",function()it("\115\104\111\117\108\100 \117\112\100\097\116\101 \110\111\100\101 \112\114\111\112\115 \097\110\100 \099\104\105\108\100\114\101\110",function()local K=Instance.new("\070\111\108\100\101\114")local e="\117\112\100\097\116\101\072\111\115\116\078\111\100\101\084\101\115\116"local B="\102\111\111"local M="\098\097\114"local u=(Instance.new("\083\116\114\105\110\103\086\097\108\117\101")).Value local P=x("\083\116\114\105\110\103\086\097\108\117\101",{Value=B},{ChildA=x("\073\110\116\086\097\108\117\101",{Value=1});ChildB=x("\066\111\111\108\086\097\108\117\101",{Value=true});ChildC=x("\083\116\114\105\110\103\086\097\108\117\101",{Value="\116\101\115\116"}),ChildD=x("\083\116\114\105\110\103\086\097\108\117\101",{Value="\116\101\115\116"})})local J=v.createVirtualNode(P,K,e)U.mountHostNode(v,J)local C=x("\083\116\114\105\110\103\086\097\108\117\101",{Value=M},{ChildA=x("\083\116\114\105\110\103\086\097\108\117\101",{Value="\116\101\115\116"});ChildB=x("\066\111\111\108\086\097\108\117\101",{Value=false});ChildC=x("\083\116\114\105\110\103\086\097\108\117\101",{});ChildE=x("\070\111\108\100\101\114",{})})U.updateHostNode(v,J,C)local g=K[e];(expect(g.ClassName)).to.equal("\083\116\114\105\110\103\086\097\108\117\101");(expect(g.Value)).to.equal(M);(expect(#g:GetChildren())).to.equal(4)local p=g.ChildA;(expect(p.ClassName)).to.equal("\083\116\114\105\110\103\086\097\108\117\101");(expect(p.Value)).to.equal("\116\101\115\116")local j=g.ChildB;(expect(j.ClassName)).to.equal("\066\111\111\108\086\097\108\117\101");(expect(j.Value)).to.equal(false)local r=g.ChildC;(expect(r.ClassName)).to.equal("\083\116\114\105\110\103\086\097\108\117\101");(expect(r.Value)).to.equal(u)local n=g.ChildE;(expect(n.ClassName)).to.equal("\070\111\108\100\101\114")end)it("\115\104\111\117\108\100 \117\112\100\097\116\101 \066\105\110\100\105\110\103\115",function()local K=Instance.new("\070\111\108\100\101\114")local B="\083\111\109\101 \075\101\121"local M,u=e.create(10)local P=x("\073\110\116\086\097\108\117\101",{Value=M})local J=v.createVirtualNode(P,K,B)U.mountHostNode(v,J)local C=(K:GetChildren())[1];(expect(C.Value)).to.equal(10)local g,p=e.create(99)local j=x("\073\110\116\086\097\108\117\101",{Value=g})U.updateHostNode(v,J,j);(expect(C.Value)).to.equal(99)u(123);(expect(C.Value)).to.equal(99)p(123);(expect(C.Value)).to.equal(123)U.unmountHostNode(v,J)end)it("\115\104\111\117\108\100 \117\112\100\097\116\101 \066\105\110\100\105\110\103 \114\101\102\115",function()local K=Instance.new("\070\111\108\100\101\114")local e="\083\111\109\101 \075\101\121"local B=J()local M=J()local u=x("\070\114\097\109\101",{[j]=B})local P=v.createVirtualNode(u,K,e)U.mountHostNode(v,P);(expect(#K:GetChildren())).to.equal(1)local C=(K:GetChildren())[1];(expect(B.current)).to.equal(C);(expect(M.current)).never.to.be.ok()local g=x("\070\114\097\109\101",{[j]=M})U.updateHostNode(v,P,g);(expect(B.current)).never.to.be.ok();(expect(M.current)).to.equal(C)U.unmountHostNode(v,P)end)it("\115\104\111\117\108\100 \099\097\108\108 \111\108\100 \102\117\110\099\116\105\111\110 \114\101\102\115 \119\105\116\104 \110\105\108 \097\110\100 \110\101\119 \102\117\110\099\116\105\111\110 \114\101\102\115 \119\105\116\104 \097 \118\097\108\105\100 \114\098\120",function()local K=Instance.new("\070\111\108\100\101\114")local e="\083\111\109\101 \075\101\121"local B=C()local M=C()local u=x("\070\114\097\109\101",{[j]=B.value})local P=v.createVirtualNode(u,K,e)U.mountHostNode(v,P);(expect(#K:GetChildren())).to.equal(1)local J=(K:GetChildren())[1];(expect(B.callCount)).to.equal(1)B:assertCalledWith(J);(expect(M.callCount)).to.equal(0)local g=x("\070\114\097\109\101",{[j]=M.value})U.updateHostNode(v,P,g);(expect(B.callCount)).to.equal(2)B:assertCalledWith(nil);(expect(M.callCount)).to.equal(1)M:assertCalledWith(J)U.unmountHostNode(v,P)end)it("\115\104\111\117\108\100 \110\111\116 \099\097\108\108 \102\117\110\099\116\105\111\110 \114\101\102\115 \097\103\097\105\110 \105\102 \116\104\101\121 \100\105\100\110\'\116 \099\104\097\110\103\101",function()local K=Instance.new("\070\111\108\100\101\114")local e="\083\111\109\101 \075\101\121"local B=C()local M=x("\070\114\097\109\101",{Size=UDim2.new(1,0,1,0);[j]=B.value})local u=v.createVirtualNode(M,K,e)U.mountHostNode(v,u);(expect(#K:GetChildren())).to.equal(1)local P=(K:GetChildren())[1];(expect(B.callCount)).to.equal(1)B:assertCalledWith(P)local J=x("\070\114\097\109\101",{Size=UDim2.new(.5,0,.5,0),[j]=B.value})U.updateHostNode(v,u,J);(expect(B.callCount)).to.equal(1)end)it("\115\104\111\117\108\100 \116\104\114\111\119 \105\102 \115\101\116\116\105\110\103 \105\110\118\097\108\105\100 \105\110\115\116\097\110\099\101 \112\114\111\112\101\114\116\105\101\115",function()local K={elementTracing=true}g.scoped(K,function()local K=Instance.new("\070\111\108\100\101\114")local e="\083\111\109\101 \075\101\121"local B=x("\070\114\097\109\101")local M=x("\070\114\097\109\101",{Frob=6})local u=v.createVirtualNode(B,K,e)U.mountHostNode(v,u)local P,J=pcall(U.updateHostNode,v,u,M)assert(not P,"\069\120\112\101\099\116\101\100 \099\097\108\108 \116\111 \102\097\105\108");(expect(J:find("\070\114\111\098"))).to.be.ok();(expect(J:find("\070\114\097\109\101"))).to.be.ok();(expect(J:find("\082\111\098\108\111\120\082\101\110\100\101\114\101\114\037\046\115\112\101\099"))).to.be.ok()end)end)it("\115\104\111\117\108\100 \100\101\108\101\116\101 \105\110\115\116\097\110\099\101\115 \119\104\101\110 \114\101\099\111\110\099\105\108\105\110\103 \116\111 \110\105\108 \099\104\105\108\100\114\101\110",function()local K=Instance.new("\070\111\108\100\101\114")local e="\083\111\109\101 \075\101\121"local B=x("\070\114\097\109\101",{Size=UDim2.new(1,0,1,0)},{child=x("\070\114\097\109\101")})local M=v.createVirtualNode(B,K,e)U.mountHostNode(v,M);(expect(#K:GetChildren())).to.equal(1)local u=(K:GetChildren())[1];(expect(#u:GetChildren())).to.equal(1)local P=x("\070\114\097\109\101",{Size=UDim2.new(.5,0,.5,0)})U.updateHostNode(v,M,P);(expect(#u:GetChildren())).to.equal(0)end)end)describe("\117\110\109\111\117\110\116\072\111\115\116\078\111\100\101",function()it("\115\104\111\117\108\100 \100\101\108\101\116\101 \105\110\115\116\097\110\099\101\115 \102\114\111\109 \116\104\101 \105\110\115\105\100\101-\111\117\116",function()local K=Instance.new("\070\111\108\100\101\114")local e="\082\111\111\116"local B=x("\070\111\108\100\101\114",nil,{Child=x("\070\111\108\100\101\114",nil,{Grandchild=x("\070\111\108\100\101\114")})})local M=v.mountVirtualNode(B,K,e);(expect(#K:GetChildren())).to.equal(1)local u=(K:GetChildren())[1];(expect(#u:GetChildren())).to.equal(1)local P=(u:GetChildren())[1];(expect(#P:GetChildren())).to.equal(1)local J=(P:GetChildren())[1]U.unmountHostNode(v,M);(expect(J.Parent)).to.equal(nil);(expect(P.Parent)).to.equal(nil);(expect(u.Parent)).to.equal(nil)end)it("\115\104\111\117\108\100 \117\110\115\117\098\115\099\114\105\098\101 \102\114\111\109 \097\110\121 \066\105\110\100\105\110\103\115",function()local K=Instance.new("\070\111\108\100\101\114")local B="\083\111\109\101 \075\101\121"local M,u=e.create(10)local P=x("\073\110\116\086\097\108\117\101",{Value=M})local J=v.createVirtualNode(P,K,B)U.mountHostNode(v,J)local C=(K:GetChildren())[1];(expect(C.Value)).to.equal(10)U.unmountHostNode(v,J)u(56);(expect(C.Value)).to.equal(10)end)it("\115\104\111\117\108\100 \099\108\101\097\114 \066\105\110\100\105\110\103 \114\101\102\115",function()local K=Instance.new("\070\111\108\100\101\114")local e="\083\111\109\101 \075\101\121"local B=J()local M=x("\070\114\097\109\101",{[j]=B})local u=v.createVirtualNode(M,K,e)U.mountHostNode(v,u);(expect(B.current)).to.be.ok()U.unmountHostNode(v,u);(expect(B.current)).never.to.be.ok()end)it("\115\104\111\117\108\100 \099\097\108\108 \102\117\110\099\116\105\111\110 \114\101\102\115 \119\105\116\104 \110\105\108",function()local K=Instance.new("\070\111\108\100\101\114")local e="\083\111\109\101 \075\101\121"local B=C()local M=x("\070\114\097\109\101",{[j]=B.value})local u=v.createVirtualNode(M,K,e)U.mountHostNode(v,u);(expect(B.callCount)).to.equal(1)U.unmountHostNode(v,u);(expect(B.callCount)).to.equal(2)B:assertCalledWith(nil)end)end)describe("\080\111\114\116\097\108\115",function()it("\115\104\111\117\108\100 \099\114\101\097\116\101 \097\110\100 \100\101\115\116\114\111\121 \105\110\115\116\097\110\099\101\115 \097\115 \099\104\105\108\100\114\101\110 \111\102 \096\116\097\114\103\101\116\096",function()local K=Instance.new("\070\111\108\100\101\114")local function e(K)return x("\073\110\116\086\097\108\117\101",{Value=K.value})end local B=x(p,{target=K},{folderOne=x("\070\111\108\100\101\114"),folderTwo=x("\070\111\108\100\101\114"),intValueOne=x(e,{value=42})})local M=nil local u="\083\111\109\101 \075\101\121"local P=v.mountVirtualNode(B,M,u);(expect(#K:GetChildren())).to.equal(3);(expect(K:FindFirstChild("\102\111\108\100\101\114\079\110\101"))).to.be.ok();(expect(K:FindFirstChild("\102\111\108\100\101\114\084\119\111"))).to.be.ok();(expect(K:FindFirstChild("\105\110\116\086\097\108\117\101\079\110\101"))).to.be.ok();(expect((K:FindFirstChild("\105\110\116\086\097\108\117\101\079\110\101")).Value)).to.equal(42)v.unmountVirtualNode(P);(expect(#K:GetChildren())).to.equal(0)end)it("\115\104\111\117\108\100 \112\097\115\115 \112\114\111\112 \117\112\100\097\116\101\115 \116\104\114\111\117\103\104 \116\111 \099\104\105\108\100\114\101\110",function()local K=Instance.new("\070\111\108\100\101\114")local e=x(p,{target=K},{ChildValue=x("\073\110\116\086\097\108\117\101",{Value=1})})local B=x(p,{target=K},{ChildValue=x("\073\110\116\086\097\108\117\101",{Value=2})})local M=nil local u="\065 \072\111\115\116 \075\101\121"local P=v.mountVirtualNode(e,M,u);(expect(#K:GetChildren())).to.equal(1)local J=K.ChildValue;(expect(J.Value)).to.equal(1)P=v.updateVirtualNode(P,B);(expect(#K:GetChildren())).to.equal(1)local C=K.ChildValue;(expect(J)).to.equal(C);(expect(C.Value)).to.equal(2)v.unmountVirtualNode(P);(expect(#K:GetChildren())).to.equal(0)end)it("\115\104\111\117\108\100 \116\104\114\111\119 \105\102 \096\116\097\114\103\101\116\096 \105\115 \110\105\108",function()local K=x(p)local e=nil local B="\075\101\121\115 \102\111\114 \069\118\101\114\121\111\110\101";(expect(function()v.mountVirtualNode(K,e,B)end)).to.throw()end)it("\115\104\111\117\108\100 \116\104\114\111\119 \105\102 \096\116\097\114\103\101\116\096 \105\115 \110\111\116 \097 \082\111\098\108\111\120 \105\110\115\116\097\110\099\101",function()local K=x(p,{target={}})local e=nil local B="\085\110\108\101\097\115\104 \116\104\101 \107\101\121\115\033";(expect(function()v.mountVirtualNode(K,e,B)end)).to.throw()end)it("\115\104\111\117\108\100 \114\101\099\114\101\097\116\101 \105\110\115\116\097\110\099\101\115 \105\102 \096\116\097\114\103\101\116\096 \099\104\097\110\103\101\115 \105\110 \097\110 \117\112\100\097\116\101",function()local K=Instance.new("\070\111\108\100\101\114")local e=Instance.new("\070\111\108\100\101\114")local B=x(p,{target=K},{ChildValue=x("\073\110\116\086\097\108\117\101",{Value=1})})local M=x(p,{target=e},{ChildValue=x("\073\110\116\086\097\108\117\101",{Value=2})})local u=nil local P="\083\111\109\101 \075\101\121"local J=v.mountVirtualNode(B,u,P);(expect(#K:GetChildren())).to.equal(1);(expect(#e:GetChildren())).to.equal(0)local C=K.ChildValue;(expect(C.Value)).to.equal(1)J=v.updateVirtualNode(J,M);(expect(#K:GetChildren())).to.equal(0);(expect(#e:GetChildren())).to.equal(1)local g=e.ChildValue;(expect(g.Value)).to.equal(2)v.unmountVirtualNode(J);(expect(#K:GetChildren())).to.equal(0);(expect(#e:GetChildren())).to.equal(0)end)end)describe("\070\114\097\103\109\101\110\116\115",function()it("\115\104\111\117\108\100 \112\097\114\101\110\116 \116\104\101 \102\114\097\103\109\101\110\116\'\115 \101\108\101\109\101\110\116\115 \105\110\116\111 \116\104\101 \102\114\097\103\109\101\110\116\'\115 \112\097\114\101\110\116",function()local K=Instance.new("\070\111\108\100\101\114")local e=u({key=x("\073\110\116\086\097\108\117\101",{Value=1});key2=x("\073\110\116\086\097\108\117\101",{Value=2})})local B=v.mountVirtualNode(e,K,"\116\101\115\116");(expect(K:FindFirstChild("\107\101\121"))).to.be.ok();(expect(K.key.ClassName)).to.equal("\073\110\116\086\097\108\117\101");(expect(K.key.Value)).to.equal(1);(expect(K:FindFirstChild("\107\101\121\050"))).to.be.ok();(expect(K.key2.ClassName)).to.equal("\073\110\116\086\097\108\117\101");(expect(K.key2.Value)).to.equal(2)v.unmountVirtualNode(B);(expect(#K:GetChildren())).to.equal(0)end)it("\115\104\111\117\108\100 \097\108\108\111\119 \115\105\098\108\105\110\103 \102\114\097\103\109\101\110\116 \116\111 \104\097\118\101 \099\111\109\109\111\110 \107\101\121\115",function()local K=Instance.new("\070\111\108\100\101\114")local e="\084\101\115\116"local function B(K)return x("\073\110\116\086\097\108\117\101",{},{fragmentA=u({key=x("\083\116\114\105\110\103\086\097\108\117\101",{Value="\065"}),key2=x("\083\116\114\105\110\103\086\097\108\117\101",{Value="\066"})}),fragmentB=u({key=x("\083\116\114\105\110\103\086\097\108\117\101",{Value="\067"});key2=x("\083\116\114\105\110\103\086\097\108\117\101",{Value="\068"})})})end local M=v.mountVirtualNode(x(B),K,e)local P=K[e]:GetChildren();(expect(#P)).to.equal(4)local J={}for K,e in pairs(P)do(expect(e.ClassName)).to.equal("\083\116\114\105\110\103\086\097\108\117\101")J[e.Value]=1+(J[e.Value]or 0)end;(expect(J.A)).to.equal(1);(expect(J.B)).to.equal(1);(expect(J.C)).to.equal(1);(expect(J.D)).to.equal(1)v.unmountVirtualNode(M);(expect(#K:GetChildren())).to.equal(0)end)it("\115\104\111\117\108\100 \114\101\110\100\101\114 \110\101\115\116\101\100 \102\114\097\103\109\101\110\116\115",function()local K=Instance.new("\070\111\108\100\101\114")local e=u({key=u({TheValue=x("\073\110\116\086\097\108\117\101",{Value=1});TheOtherValue=x("\073\110\116\086\097\108\117\101",{Value=2})})})local B=v.mountVirtualNode(e,K,"\084\101\115\116");(expect(K:FindFirstChild("\084\104\101\086\097\108\117\101"))).to.be.ok();(expect(K.TheValue.ClassName)).to.equal("\073\110\116\086\097\108\117\101");(expect(K.TheValue.Value)).to.equal(1);(expect(K:FindFirstChild("\084\104\101\079\116\104\101\114\086\097\108\117\101"))).to.be.ok();(expect(K.TheOtherValue.ClassName)).to.equal("\073\110\116\086\097\108\117\101");(expect(K.TheOtherValue.Value)).to.equal(2)v.unmountVirtualNode(B);(expect(#K:GetChildren())).to.equal(0)end)it("\115\104\111\117\108\100 \110\111\116 \097\100\100 \097\110\121 \105\110\115\116\097\110\099\101\115 \105\102 \116\104\101 \102\114\097\103\109\101\110\116 \105\115 \101\109\112\116\121",function()local K=Instance.new("\070\111\108\100\101\114")local e=v.mountVirtualNode(u({}),K,"\116\101\115\116");(expect(#K:GetChildren())).to.equal(0)v.unmountVirtualNode(e);(expect(#K:GetChildren())).to.equal(0)end)end)describe("\067\111\110\116\101\120\116",function()it("\115\104\111\117\108\100 \112\097\115\115 \099\111\110\116\101\120\116 \118\097\108\117\101\115 \116\104\114\111\117\103\104 \082\111\098\108\111\120 \104\111\115\116 \110\111\100\101\115",function()local e=M:extend("\067\111\110\115\117\109\101\114")local B function e.init(K)B={hello=K:__getContext("\104\101\108\108\111")}end function e.render(K) end local u=x("\070\111\108\100\101\114",nil,{Consumer=x(e)})local P=nil local J="\067\111\110\116\101\120\116 \084\101\115\116"local C={hello="\119\111\114\108\100"}local g=v.mountVirtualNode(u,P,J,C);(expect(B)).never.to.equal(C)K(B,C)v.unmountVirtualNode(g)end)it("\115\104\111\117\108\100 \112\097\115\115 \099\111\110\116\101\120\116 \118\097\108\117\101\115 \116\104\114\111\117\103\104 \112\111\114\116\097\108 \110\111\100\101\115",function()local e=Instance.new("\070\111\108\100\101\114")local u=M:extend("\080\114\111\118\105\100\101\114")function u.init(K)K:__addContext("\102\111\111","\098\097\114")end function u.render(K)return x("\070\111\108\100\101\114",nil,K.props[B])end local P=M:extend("\067\111\110\115\117\109\101\114")local J function P.init(K)J={foo=K:__getContext("\102\111\111")}end function P.render(K)return nil end local C=x(u,nil,{Portal=x(p,{target=e},{Consumer=x(P)})})local g=nil local j="\083\111\109\101 \075\101\121"v.mountVirtualNode(C,g,j)K(J,{foo="\098\097\114"})end)end)describe("\076\101\103\097\099\121 \099\111\110\116\101\120\116",function()it("\115\104\111\117\108\100 \112\097\115\115 \099\111\110\116\101\120\116 \118\097\108\117\101\115 \116\104\114\111\117\103\104 \082\111\098\108\111\120 \104\111\115\116 \110\111\100\101\115",function()local e=M:extend("\067\111\110\115\117\109\101\114")local B function e.init(K)B=K._context end function e.render(K) end local u=x("\070\111\108\100\101\114",nil,{Consumer=x(e)})local P=nil local J="\067\111\110\116\101\120\116 \084\101\115\116"local C={hello="\119\111\114\108\100"}local g=v.mountVirtualNode(u,P,J,nil,C);(expect(B)).never.to.equal(C)K(B,C)v.unmountVirtualNode(g)end)it("\115\104\111\117\108\100 \112\097\115\115 \099\111\110\116\101\120\116 \118\097\108\117\101\115 \116\104\114\111\117\103\104 \112\111\114\116\097\108 \110\111\100\101\115",function()local e=Instance.new("\070\111\108\100\101\114")local u=M:extend("\080\114\111\118\105\100\101\114")function u.init(K)K._context.foo="\098\097\114"end function u.render(K)return x("\070\111\108\100\101\114",nil,K.props[B])end local P=M:extend("\067\111\110\115\117\109\101\114")local J function P.init(K)J=K._context end function P.render(K)return nil end local C=x(u,nil,{Portal=x(p,{target=e},{Consumer=x(P)})})local g=nil local j="\083\111\109\101 \075\101\121"v.mountVirtualNode(C,g,j)K(J,{foo="\098\097\114"})end)end)end
return function()
	local assertDeepEqual = require(script.Parent.assertDeepEqual)
	local Binding = require(script.Parent.Binding)
	local Children = require(script.Parent.PropMarkers.Children)
	local Component = require(script.Parent.Component)
	local createElement = require(script.Parent.createElement)
	local createFragment = require(script.Parent.createFragment)
	local createReconciler = require(script.Parent.createReconciler)
	local createRef = require(script.Parent.createRef)
	local createSpy = require(script.Parent.createSpy)
	local GlobalConfig = require(script.Parent.GlobalConfig)
	local Portal = require(script.Parent.Portal)
	local Ref = require(script.Parent.PropMarkers.Ref)

	local RobloxRenderer = require(script.Parent.RobloxRenderer)

	local reconciler = createReconciler(RobloxRenderer)

	describe("mountHostNode", function()
		it("should create instances with correct props", function()
			local parent = Instance.new("Folder")
			local value = "Hello!"
			local key = "Some Key"

			local element = createElement("StringValue", {
				Value = value,
			})

			local node = reconciler.createVirtualNode(element, parent, key)

			RobloxRenderer.mountHostNode(reconciler, node)

			expect(#parent:GetChildren()).to.equal(1)

			local root = parent:GetChildren()[1]

			expect(root.ClassName).to.equal("StringValue")
			expect(root.Value).to.equal(value)
			expect(root.Name).to.equal(key)
		end)

		it("should create children with correct names and props", function()
			local parent = Instance.new("Folder")
			local rootValue = "Hey there!"
			local childValue = 173
			local key = "Some Key"

			local element = createElement("StringValue", {
				Value = rootValue,
			}, {
				ChildA = createElement("IntValue", {
					Value = childValue,
				}),

				ChildB = createElement("Folder"),
			})

			local node = reconciler.createVirtualNode(element, parent, key)

			RobloxRenderer.mountHostNode(reconciler, node)

			expect(#parent:GetChildren()).to.equal(1)

			local root = parent:GetChildren()[1]

			expect(root.ClassName).to.equal("StringValue")
			expect(root.Value).to.equal(rootValue)
			expect(root.Name).to.equal(key)

			expect(#root:GetChildren()).to.equal(2)

			local childA = root.ChildA
			local childB = root.ChildB

			expect(childA).to.be.ok()
			expect(childB).to.be.ok()

			expect(childA.ClassName).to.equal("IntValue")
			expect(childA.Value).to.equal(childValue)

			expect(childB.ClassName).to.equal("Folder")
		end)

		it("should attach Bindings to Roblox properties", function()
			local parent = Instance.new("Folder")
			local key = "Some Key"

			local binding, update = Binding.create(10)
			local element = createElement("IntValue", {
				Value = binding,
			})

			local node = reconciler.createVirtualNode(element, parent, key)

			RobloxRenderer.mountHostNode(reconciler, node)

			expect(#parent:GetChildren()).to.equal(1)

			local instance = parent:GetChildren()[1]

			expect(instance.ClassName).to.equal("IntValue")
			expect(instance.Value).to.equal(10)

			update(20)

			expect(instance.Value).to.equal(20)

			RobloxRenderer.unmountHostNode(reconciler, node)
		end)

		it("should connect Binding refs", function()
			local parent = Instance.new("Folder")
			local key = "Some Key"

			local ref = createRef()
			local element = createElement("Frame", {
				[Ref] = ref,
			})

			local node = reconciler.createVirtualNode(element, parent, key)

			RobloxRenderer.mountHostNode(reconciler, node)

			expect(#parent:GetChildren()).to.equal(1)

			local instance = parent:GetChildren()[1]

			expect(ref.current).to.be.ok()
			expect(ref.current).to.equal(instance)

			RobloxRenderer.unmountHostNode(reconciler, node)
		end)

		it("should call function refs", function()
			local parent = Instance.new("Folder")
			local key = "Some Key"

			local spyRef = createSpy()
			local element = createElement("Frame", {
				[Ref] = spyRef.value,
			})

			local node = reconciler.createVirtualNode(element, parent, key)

			RobloxRenderer.mountHostNode(reconciler, node)

			expect(#parent:GetChildren()).to.equal(1)

			local instance = parent:GetChildren()[1]

			expect(spyRef.callCount).to.equal(1)
			spyRef:assertCalledWith(instance)

			RobloxRenderer.unmountHostNode(reconciler, node)
		end)

		it("should throw if setting invalid instance properties", function()
			local configValues = {
				elementTracing = true,
			}

			GlobalConfig.scoped(configValues, function()
				local parent = Instance.new("Folder")
				local key = "Some Key"

				local element = createElement("Frame", {
					Frob = 6,
				})

				local node = reconciler.createVirtualNode(element, parent, key)

				local success, message = pcall(RobloxRenderer.mountHostNode, reconciler, node)
				assert(not success, "Expected call to fail")

				expect(message:find("Frob")).to.be.ok()
				expect(message:find("Frame")).to.be.ok()
				expect(message:find("RobloxRenderer%.spec")).to.be.ok()
			end)
		end)
	end)

	describe("updateHostNode", function()
		it("should update node props and children", function()
			-- TODO: Break up test

			local parent = Instance.new("Folder")
			local key = "updateHostNodeTest"
			local firstValue = "foo"
			local newValue = "bar"

			local defaultStringValue = Instance.new("StringValue").Value

			local element = createElement("StringValue", {
				Value = firstValue
			}, {
				ChildA = createElement("IntValue", {
					Value = 1
				}),
				ChildB = createElement("BoolValue", {
					Value = true,
				}),
				ChildC = createElement("StringValue", {
					Value = "test",
				}),
				ChildD = createElement("StringValue", {
					Value = "test",
				})
			})

			local node = reconciler.createVirtualNode(element, parent, key)
			RobloxRenderer.mountHostNode(reconciler, node)

			-- Not testing mountHostNode's work here, only testing that the
			-- node is properly updated.

			local newElement = createElement("StringValue", {
				Value = newValue,
			}, {
				-- ChildA changes element type.
				ChildA = createElement("StringValue", {
					Value = "test"
				}),
				-- ChildB changes child properties.
				ChildB = createElement("BoolValue", {
					Value = false,
				}),
				-- ChildC should reset its Value property back to the default.
				ChildC = createElement("StringValue", {}),
				-- ChildD is deleted.
				-- ChildE is added.
				ChildE = createElement("Folder", {}),
			})

			RobloxRenderer.updateHostNode(reconciler, node, newElement)

			local root = parent[key]
			expect(root.ClassName).to.equal("StringValue")
			expect(root.Value).to.equal(newValue)
			expect(#root:GetChildren()).to.equal(4)

			local childA = root.ChildA
			expect(childA.ClassName).to.equal("StringValue")
			expect(childA.Value).to.equal("test")

			local childB = root.ChildB
			expect(childB.ClassName).to.equal("BoolValue")
			expect(childB.Value).to.equal(false)

			local childC = root.ChildC
			expect(childC.ClassName).to.equal("StringValue")
			expect(childC.Value).to.equal(defaultStringValue)

			local childE = root.ChildE
			expect(childE.ClassName).to.equal("Folder")
		end)

		it("should update Bindings", function()
			local parent = Instance.new("Folder")
			local key = "Some Key"

			local bindingA, updateA = Binding.create(10)
			local element = createElement("IntValue", {
				Value = bindingA,
			})

			local node = reconciler.createVirtualNode(element, parent, key)

			RobloxRenderer.mountHostNode(reconciler, node)

			local instance = parent:GetChildren()[1]

			expect(instance.Value).to.equal(10)

			local bindingB, updateB = Binding.create(99)
			local newElement = createElement("IntValue", {
				Value = bindingB,
			})

			RobloxRenderer.updateHostNode(reconciler, node, newElement)

			expect(instance.Value).to.equal(99)

			updateA(123)

			expect(instance.Value).to.equal(99)

			updateB(123)

			expect(instance.Value).to.equal(123)

			RobloxRenderer.unmountHostNode(reconciler, node)
		end)

		it("should update Binding refs", function()
			local parent = Instance.new("Folder")
			local key = "Some Key"

			local refA = createRef()
			local refB = createRef()

			local element = createElement("Frame", {
				[Ref] = refA,
			})

			local node = reconciler.createVirtualNode(element, parent, key)

			RobloxRenderer.mountHostNode(reconciler, node)

			expect(#parent:GetChildren()).to.equal(1)

			local instance = parent:GetChildren()[1]

			expect(refA.current).to.equal(instance)
			expect(refB.current).never.to.be.ok()

			local newElement = createElement("Frame", {
				[Ref] = refB,
			})

			RobloxRenderer.updateHostNode(reconciler, node, newElement)

			expect(refA.current).never.to.be.ok()
			expect(refB.current).to.equal(instance)

			RobloxRenderer.unmountHostNode(reconciler, node)
		end)

		it("should call old function refs with nil and new function refs with a valid rbx", function()
			local parent = Instance.new("Folder")
			local key = "Some Key"

			local spyRefA = createSpy()
			local spyRefB = createSpy()

			local element = createElement("Frame", {
				[Ref] = spyRefA.value,
			})

			local node = reconciler.createVirtualNode(element, parent, key)

			RobloxRenderer.mountHostNode(reconciler, node)

			expect(#parent:GetChildren()).to.equal(1)

			local instance = parent:GetChildren()[1]

			expect(spyRefA.callCount).to.equal(1)
			spyRefA:assertCalledWith(instance)
			expect(spyRefB.callCount).to.equal(0)

			local newElement = createElement("Frame", {
				[Ref] = spyRefB.value,
			})

			RobloxRenderer.updateHostNode(reconciler, node, newElement)

			expect(spyRefA.callCount).to.equal(2)
			spyRefA:assertCalledWith(nil)
			expect(spyRefB.callCount).to.equal(1)
			spyRefB:assertCalledWith(instance)

			RobloxRenderer.unmountHostNode(reconciler, node)
		end)

		it("should not call function refs again if they didn't change", function()
			local parent = Instance.new("Folder")
			local key = "Some Key"

			local spyRef = createSpy()

			local element = createElement("Frame", {
				Size = UDim2.new(1, 0, 1, 0),
				[Ref] = spyRef.value,
			})

			local node = reconciler.createVirtualNode(element, parent, key)

			RobloxRenderer.mountHostNode(reconciler, node)

			expect(#parent:GetChildren()).to.equal(1)

			local instance = parent:GetChildren()[1]

			expect(spyRef.callCount).to.equal(1)
			spyRef:assertCalledWith(instance)

			local newElement = createElement("Frame", {
				Size = UDim2.new(0.5, 0, 0.5, 0),
				[Ref] = spyRef.value,
			})

			RobloxRenderer.updateHostNode(reconciler, node, newElement)

			-- Not called again
			expect(spyRef.callCount).to.equal(1)
		end)

		it("should throw if setting invalid instance properties", function()
			local configValues = {
				elementTracing = true,
			}

			GlobalConfig.scoped(configValues, function()
				local parent = Instance.new("Folder")
				local key = "Some Key"

				local firstElement = createElement("Frame")
				local secondElement = createElement("Frame", {
					Frob = 6,
				})

				local node = reconciler.createVirtualNode(firstElement, parent, key)
				RobloxRenderer.mountHostNode(reconciler, node)

				local success, message = pcall(RobloxRenderer.updateHostNode, reconciler, node, secondElement)
				assert(not success, "Expected call to fail")

				expect(message:find("Frob")).to.be.ok()
				expect(message:find("Frame")).to.be.ok()
				expect(message:find("RobloxRenderer%.spec")).to.be.ok()
			end)
		end)

		it("should delete instances when reconciling to nil children", function()
			local parent = Instance.new("Folder")
			local key = "Some Key"

			local element = createElement("Frame", {
				Size = UDim2.new(1, 0, 1, 0),
			}, {
				child = createElement("Frame"),
			})

			local node = reconciler.createVirtualNode(element, parent, key)

			RobloxRenderer.mountHostNode(reconciler, node)

			expect(#parent:GetChildren()).to.equal(1)

			local instance = parent:GetChildren()[1]
			expect(#instance:GetChildren()).to.equal(1)

			local newElement = createElement("Frame", {
				Size = UDim2.new(0.5, 0, 0.5, 0),
			})

			RobloxRenderer.updateHostNode(reconciler, node, newElement)
			expect(#instance:GetChildren()).to.equal(0)
		end)
	end)

	describe("unmountHostNode", function()
		it("should delete instances from the inside-out", function()
			local parent = Instance.new("Folder")
			local key = "Root"
			local element = createElement("Folder", nil, {
				Child = createElement("Folder", nil, {
					Grandchild = createElement("Folder"),
				}),
			})

			local node = reconciler.mountVirtualNode(element, parent, key)

			expect(#parent:GetChildren()).to.equal(1)

			local root = parent:GetChildren()[1]
			expect(#root:GetChildren()).to.equal(1)

			local child = root:GetChildren()[1]
			expect(#child:GetChildren()).to.equal(1)

			local grandchild = child:GetChildren()[1]

			RobloxRenderer.unmountHostNode(reconciler, node)

			expect(grandchild.Parent).to.equal(nil)
			expect(child.Parent).to.equal(nil)
			expect(root.Parent).to.equal(nil)
		end)

		it("should unsubscribe from any Bindings", function()
			local parent = Instance.new("Folder")
			local key = "Some Key"

			local binding, update = Binding.create(10)
			local element = createElement("IntValue", {
				Value = binding,
			})

			local node = reconciler.createVirtualNode(element, parent, key)

			RobloxRenderer.mountHostNode(reconciler, node)

			local instance = parent:GetChildren()[1]

			expect(instance.Value).to.equal(10)

			RobloxRenderer.unmountHostNode(reconciler, node)
			update(56)

			expect(instance.Value).to.equal(10)
		end)

		it("should clear Binding refs", function()
			local parent = Instance.new("Folder")
			local key = "Some Key"

			local ref = createRef()
			local element = createElement("Frame", {
				[Ref] = ref,
			})

			local node = reconciler.createVirtualNode(element, parent, key)

			RobloxRenderer.mountHostNode(reconciler, node)

			expect(ref.current).to.be.ok()

			RobloxRenderer.unmountHostNode(reconciler, node)

			expect(ref.current).never.to.be.ok()
		end)

		it("should call function refs with nil", function()
			local parent = Instance.new("Folder")
			local key = "Some Key"

			local spyRef = createSpy()
			local element = createElement("Frame", {
				[Ref] = spyRef.value,
			})

			local node = reconciler.createVirtualNode(element, parent, key)

			RobloxRenderer.mountHostNode(reconciler, node)

			expect(spyRef.callCount).to.equal(1)

			RobloxRenderer.unmountHostNode(reconciler, node)

			expect(spyRef.callCount).to.equal(2)
			spyRef:assertCalledWith(nil)
		end)
	end)

	describe("Portals", function()
		it("should create and destroy instances as children of `target`", function()
			local target = Instance.new("Folder")

			local function FunctionComponent(props)
				return createElement("IntValue", {
					Value = props.value,
				})
			end

			local element = createElement(Portal, {
				target = target,
			}, {
				folderOne = createElement("Folder"),
				folderTwo = createElement("Folder"),
				intValueOne = createElement(FunctionComponent, {
					value = 42,
				}),
			})
			local hostParent = nil
			local hostKey = "Some Key"
			local node = reconciler.mountVirtualNode(element, hostParent, hostKey)

			expect(#target:GetChildren()).to.equal(3)

			expect(target:FindFirstChild("folderOne")).to.be.ok()
			expect(target:FindFirstChild("folderTwo")).to.be.ok()
			expect(target:FindFirstChild("intValueOne")).to.be.ok()
			expect(target:FindFirstChild("intValueOne").Value).to.equal(42)

			reconciler.unmountVirtualNode(node)

			expect(#target:GetChildren()).to.equal(0)
		end)

		it("should pass prop updates through to children", function()
			local target = Instance.new("Folder")

			local firstElement = createElement(Portal, {
				target = target,
			}, {
				ChildValue = createElement("IntValue", {
					Value = 1,
				}),
			})

			local secondElement = createElement(Portal, {
				target = target,
			}, {
				ChildValue = createElement("IntValue", {
					Value = 2,
				}),
			})

			local hostParent = nil
			local hostKey = "A Host Key"
			local node = reconciler.mountVirtualNode(firstElement, hostParent, hostKey)

			expect(#target:GetChildren()).to.equal(1)

			local firstValue = target.ChildValue
			expect(firstValue.Value).to.equal(1)

			node = reconciler.updateVirtualNode(node, secondElement)

			expect(#target:GetChildren()).to.equal(1)

			local secondValue = target.ChildValue
			expect(firstValue).to.equal(secondValue)
			expect(secondValue.Value).to.equal(2)

			reconciler.unmountVirtualNode(node)

			expect(#target:GetChildren()).to.equal(0)
		end)

		it("should throw if `target` is nil", function()
			-- TODO: Relax this restriction?
			local element = createElement(Portal)
			local hostParent = nil
			local hostKey = "Keys for Everyone"

			expect(function()
				reconciler.mountVirtualNode(element, hostParent, hostKey)
			end).to.throw()
		end)

		it("should throw if `target` is not a Roblox instance", function()
			local element = createElement(Portal, {
				target = {},
			})
			local hostParent = nil
			local hostKey = "Unleash the keys!"

			expect(function()
				reconciler.mountVirtualNode(element, hostParent, hostKey)
			end).to.throw()
		end)

		it("should recreate instances if `target` changes in an update", function()
			local firstTarget = Instance.new("Folder")
			local secondTarget = Instance.new("Folder")

			local firstElement = createElement(Portal, {
				target = firstTarget,
			}, {
				ChildValue = createElement("IntValue", {
					Value = 1,
				}),
			})

			local secondElement = createElement(Portal, {
				target = secondTarget,
			}, {
				ChildValue = createElement("IntValue", {
					Value = 2,
				}),
			})

			local hostParent = nil
			local hostKey = "Some Key"
			local node = reconciler.mountVirtualNode(firstElement, hostParent, hostKey)

			expect(#firstTarget:GetChildren()).to.equal(1)
			expect(#secondTarget:GetChildren()).to.equal(0)

			local firstChild = firstTarget.ChildValue
			expect(firstChild.Value).to.equal(1)

			node = reconciler.updateVirtualNode(node, secondElement)

			expect(#firstTarget:GetChildren()).to.equal(0)
			expect(#secondTarget:GetChildren()).to.equal(1)

			local secondChild = secondTarget.ChildValue
			expect(secondChild.Value).to.equal(2)

			reconciler.unmountVirtualNode(node)

			expect(#firstTarget:GetChildren()).to.equal(0)
			expect(#secondTarget:GetChildren()).to.equal(0)
		end)
	end)

	describe("Fragments", function()
		it("should parent the fragment's elements into the fragment's parent", function()
			local hostParent = Instance.new("Folder")

			local fragment = createFragment({
				key = createElement("IntValue", {
					Value = 1,
				}),
				key2 = createElement("IntValue", {
					Value = 2,
				}),
			})

			local node = reconciler.mountVirtualNode(fragment, hostParent, "test")

			expect(hostParent:FindFirstChild("key")).to.be.ok()
			expect(hostParent.key.ClassName).to.equal("IntValue")
			expect(hostParent.key.Value).to.equal(1)

			expect(hostParent:FindFirstChild("key2")).to.be.ok()
			expect(hostParent.key2.ClassName).to.equal("IntValue")
			expect(hostParent.key2.Value).to.equal(2)

			reconciler.unmountVirtualNode(node)

			expect(#hostParent:GetChildren()).to.equal(0)
		end)

		it("should allow sibling fragment to have common keys", function()
			local hostParent = Instance.new("Folder")
			local hostKey = "Test"

			local function parent(props)
				return createElement("IntValue", {}, {
					fragmentA = createFragment({
						key = createElement("StringValue", {
							Value = "A",
						}),
						key2 = createElement("StringValue", {
							Value = "B",
						}),
					}),
					fragmentB = createFragment({
						key = createElement("StringValue", {
							Value = "C",
						}),
						key2 = createElement("StringValue", {
							Value = "D",
						}),
					}),
				})
			end

			local node = reconciler.mountVirtualNode(createElement(parent), hostParent, hostKey)
			local parentChildren = hostParent[hostKey]:GetChildren()

			expect(#parentChildren).to.equal(4)

			local childValues = {}

			for _, child in pairs(parentChildren) do
				expect(child.ClassName).to.equal("StringValue")
				childValues[child.Value] = 1 + (childValues[child.Value] or 0)
			end

			-- check if the StringValues have not collided
			expect(childValues.A).to.equal(1)
			expect(childValues.B).to.equal(1)
			expect(childValues.C).to.equal(1)
			expect(childValues.D).to.equal(1)

			reconciler.unmountVirtualNode(node)

			expect(#hostParent:GetChildren()).to.equal(0)
		end)

		it("should render nested fragments", function()
			local hostParent = Instance.new("Folder")

			local fragment = createFragment({
				key = createFragment({
					TheValue = createElement("IntValue", {
						Value = 1,
					}),
					TheOtherValue = createElement("IntValue", {
						Value = 2,
					})
				})
			})

			local node = reconciler.mountVirtualNode(fragment, hostParent, "Test")

			expect(hostParent:FindFirstChild("TheValue")).to.be.ok()
			expect(hostParent.TheValue.ClassName).to.equal("IntValue")
			expect(hostParent.TheValue.Value).to.equal(1)

			expect(hostParent:FindFirstChild("TheOtherValue")).to.be.ok()
			expect(hostParent.TheOtherValue.ClassName).to.equal("IntValue")
			expect(hostParent.TheOtherValue.Value).to.equal(2)

			reconciler.unmountVirtualNode(node)

			expect(#hostParent:GetChildren()).to.equal(0)
		end)

		it("should not add any instances if the fragment is empty", function()
			local hostParent = Instance.new("Folder")

			local node = reconciler.mountVirtualNode(createFragment({}), hostParent, "test")

			expect(#hostParent:GetChildren()).to.equal(0)

			reconciler.unmountVirtualNode(node)

			expect(#hostParent:GetChildren()).to.equal(0)
		end)
	end)

	describe("Context", function()
		it("should pass context values through Roblox host nodes", function()
			local Consumer = Component:extend("Consumer")

			local capturedContext
			function Consumer:init()
				capturedContext = {
					hello = self:__getContext("hello")
				}
			end

			function Consumer:render()
			end

			local element = createElement("Folder", nil, {
				Consumer = createElement(Consumer)
			})
			local hostParent = nil
			local hostKey = "Context Test"
			local context = {
				hello = "world",
			}
			local node = reconciler.mountVirtualNode(element, hostParent, hostKey, context)

			expect(capturedContext).never.to.equal(context)
			assertDeepEqual(capturedContext, context)

			reconciler.unmountVirtualNode(node)
		end)

		it("should pass context values through portal nodes", function()
			local target = Instance.new("Folder")

			local Provider = Component:extend("Provider")

			function Provider:init()
				self:__addContext("foo", "bar")
			end

			function Provider:render()
				return createElement("Folder", nil, self.props[Children])
			end

			local Consumer = Component:extend("Consumer")

			local capturedContext
			function Consumer:init()
				capturedContext = {
					foo = self:__getContext("foo"),
				}
			end

			function Consumer:render()
				return nil
			end

			local element = createElement(Provider, nil, {
				Portal = createElement(Portal, {
					target = target,
				}, {
					Consumer = createElement(Consumer),
				})
			})
			local hostParent = nil
			local hostKey = "Some Key"
			reconciler.mountVirtualNode(element, hostParent, hostKey)

			assertDeepEqual(capturedContext, {
				foo = "bar"
			})
		end)
	end)

	describe("Legacy context", function()
		it("should pass context values through Roblox host nodes", function()
			local Consumer = Component:extend("Consumer")

			local capturedContext
			function Consumer:init()
				capturedContext = self._context
			end

			function Consumer:render()
			end

			local element = createElement("Folder", nil, {
				Consumer = createElement(Consumer)
			})
			local hostParent = nil
			local hostKey = "Context Test"
			local context = {
				hello = "world",
			}
			local node = reconciler.mountVirtualNode(element, hostParent, hostKey, nil, context)

			expect(capturedContext).never.to.equal(context)
			assertDeepEqual(capturedContext, context)

			reconciler.unmountVirtualNode(node)
		end)

		it("should pass context values through portal nodes", function()
			local target = Instance.new("Folder")

			local Provider = Component:extend("Provider")

			function Provider:init()
				self._context.foo = "bar"
			end

			function Provider:render()
				return createElement("Folder", nil, self.props[Children])
			end

			local Consumer = Component:extend("Consumer")

			local capturedContext
			function Consumer:init()
				capturedContext = self._context
			end

			function Consumer:render()
				return nil
			end

			local element = createElement(Provider, nil, {
				Portal = createElement(Portal, {
					target = target,
				}, {
					Consumer = createElement(Consumer),
				})
			})
			local hostParent = nil
			local hostKey = "Some Key"
			reconciler.mountVirtualNode(element, hostParent, hostKey)

			assertDeepEqual(capturedContext, {
				foo = "bar"
			})
		end)
	end)
end