return function()local m=require(script.Parent.Server)local q=require(script.Parent.RemoteEventClient)describe("\082\101\109\111\116\101\069\118\101\110\116\067\108\105\101\110\116\058\102\105\114\101\083\101\114\118\101\114",function()it("\115\104\111\117\108\100 \102\105\114\101 \116\104\101 \114\101\109\111\116\101\069\118\101\110\116\083\101\114\118\101\114 \079\110\083\101\114\118\101\114\069\118\101\110\116 \115\105\103\110\097\108 \119\105\116\104 \116\104\101 \099\108\105\101\110\116 \097\110\100 \112\097\115\115\101\100 \097\114\103\115",function()local q=m.new()local x=q:connect("\117\115\101\114");(q:createRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116")).OnServerEvent:connect(function(m,q)(expect(m)).to.equal(x);(expect(q)).to.equal(0)end);(x:getRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116")):fireServer(0)q:destroy()end)it("\115\104\111\117\108\100 \113\117\101\117\101 \112\097\115\115\101\100 \097\114\103\115 \111\110 \115\101\114\118\101\114 \117\110\116\105\108 \097\110 \097\099\116\105\118\097\116\105\110\103 \099\111\110\110\101\099\116\105\111\110 \105\115 \109\097\100\101 \116\111 \116\104\101 \114\101\109\111\116\101\069\118\101\110\116\083\101\114\118\101\114 \079\110\083\101\114\118\101\114\069\118\101\110\116 \115\105\103\110\097\108",function()local q=m.new()local x=q:connect("\117\115\101\114")local L=q:createRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116")local E={};(x:getRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116")):fireServer(2);(x:getRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116")):fireServer(1)local A=0 L.OnServerEvent:connect(function(m,q)(expect(m)).to.equal(x)A+=q end);(expect(A)).to.equal(3)q:destroy()end)it("\115\104\111\117\108\100 \116\104\114\111\119 \105\102 \116\097\098\108\101\115 \119\105\116\104 \099\121\099\108\105\099 \118\097\108\117\101\115 \097\114\101 \112\097\115\115\101\100",function()local q=m.new()local x=q:connect("\117\115\101\114")q:createRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116")local L=x:getRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116")local E={a=1}E.b=E;(expect(function()L:fireServer(E)end)).to.throw()q:destroy()end)it("\115\104\111\117\108\100 \112\097\115\115 \100\101\101\112 \099\111\112\105\101\115 \111\102 \100\097\116\097 \097\110\100 \099\111\110\118\101\114\116 \105\110\115\116\097\110\099\101 \097\110\100 \116\097\098\108\101 \107\101\121\115 \116\111 \115\116\114\105\110\103\115",function()local q=m.new()local x=q:connect("\117\115\101\114")local L=q:createRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116")local E=Instance.new("\080\097\114\116")local A={ok=1}local b={a={[E]=1},b={key=2};[A]=3};(x:getRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116")):fireServer(b,b,E)local i,t,I,z=L.OnServerEvent:wait();(expect(t)).to.never.equal(b);(expect(I)).to.never.equal(b);(expect(t)).to.never.equal(I);(expect(t.a[E])).to.never.be.ok();(expect(t.a["\060\073\110\115\116\097\110\099\101\062 \040\080\097\114\116\041"])).to.equal(1);(expect(I.a[E])).to.never.be.ok();(expect(I.a["\060\073\110\115\116\097\110\099\101\062 \040\080\097\114\116\041"])).to.equal(1);(expect(t[A])).to.never.be.ok();(expect(t["\060\084\097\098\108\101\062 \040"..(tostring(A).."\041")])).to.equal(3);(expect(I[A])).to.never.be.ok();(expect(I["\060\084\097\098\108\101\062 \040"..(tostring(A).."\041")])).to.equal(3);(expect(z)).to.equal(E)E:Destroy()q:destroy()end)end)end
return function()
    local Server = require(script.Parent.Server)
    local RemoteEventClient = require(script.Parent.RemoteEventClient)

    describe("RemoteEventClient:fireServer", function()
        it("should fire the remoteEventServer OnServerEvent signal with the client and passed args", function()
            local server = Server.new()
            local user = server:connect("user")

            server:createRemoteEvent("remoteEvent").OnServerEvent:connect(function(client, value)
                expect(client).to.equal(user)
                expect(value).to.equal(0)
            end)

            user:getRemoteEvent("remoteEvent"):fireServer(0)
            server:destroy()
        end)

        it("should queue passed args on server until an activating connection is made to the remoteEventServer OnServerEvent signal", function()
            local server = Server.new()
            local user = server:connect("user")

            local remoteEvent = server:createRemoteEvent("remoteEvent")
            local done = {}

            user:getRemoteEvent("remoteEvent"):fireServer(2)
            user:getRemoteEvent("remoteEvent"):fireServer(1)

            local count = 0

            remoteEvent.OnServerEvent:connect(function(client, value)
                expect(client).to.equal(user)
                count += value
            end)
            
            expect(count).to.equal(3)

            server:destroy()
        end)

        it("should throw if tables with cyclic values are passed", function()
            local server = Server.new()
            local user = server:connect("user")
            
            server:createRemoteEvent("remoteEvent")

            local remoteEvent = user:getRemoteEvent("remoteEvent")

            local data = {
                a = 1,
            }

            data.b = data

            expect(function()
                remoteEvent:fireServer(data)
            end).to.throw()

            server:destroy()
        end)

        it("should pass deep copies of data and convert instance and table keys to strings", function()
            local server = Server.new()
            local user = server:connect("user")
            
            local remoteEvent = server:createRemoteEvent("remoteEvent")

            local part = Instance.new("Part")

            local tab = {ok = 1}

            local data = {
                a = {[part] = 1},
                b = {key = 2},
                [tab] = 3,
            }

            user:getRemoteEvent("remoteEvent"):fireServer(data, data, part)

            local _, data1, data2, passedPart = remoteEvent.OnServerEvent:wait()

            expect(data1).to.never.equal(data)
            expect(data2).to.never.equal(data)

            expect(data1).to.never.equal(data2)

            expect(data1.a[part]).to.never.be.ok()
            expect(data1.a["<Instance> (Part)"]).to.equal(1)

            expect(data2.a[part]).to.never.be.ok()
            expect(data2.a["<Instance> (Part)"]).to.equal(1)

            expect(data1[tab]).to.never.be.ok()
            expect(data1["<Table> ("..tostring(tab)..")"]).to.equal(3)

            expect(data2[tab]).to.never.be.ok()
            expect(data2["<Table> ("..tostring(tab)..")"]).to.equal(3)

            expect(passedPart).to.equal(part)

            part:Destroy()
            server:destroy()
        end)
    end)
end