return function()local m=require(script.Parent.MockRemoteEvent)describe("\077\111\099\107\082\101\109\111\116\101\069\118\101\110\116\046\110\101\119",function()it("\115\104\111\117\108\100 \099\114\101\097\116\101 \097 \110\101\119 \077\111\099\107\082\101\109\111\116\101\069\118\101\110\116",function()local q=m.new();(expect(q)).to.be.a("\116\097\098\108\101");(expect(getmetatable(q))).to.equal(m)q:destroy()end)it("\115\104\111\117\108\100 \099\114\101\097\116\101 \097 \110\101\119 \077\111\099\107\082\101\109\111\116\101\069\118\101\110\116 \119\105\116\104 \097 \099\108\105\101\110\116 \105\100 \105\102 \112\097\115\115\101\100",function()local q=m.new("\117\115\101\114");(expect(q:getClient())).to.equal("\117\115\101\114")q:destroy()end)end)describe("\077\111\099\107\082\101\109\111\116\101\069\118\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 \079\110\083\101\114\118\101\114\069\118\101\110\116 \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("\117\115\101\114")local x,L task.spawn(function()x,L=q.OnServerEvent:wait()end)q:fireServer(true);(expect(x)).to.equal("\117\115\101\114");(expect(L)).to.equal(true)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 \116\104\101 \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",function()local q=m.new("\117\115\101\114")local x=0 q:fireServer(1)q:fireServer(2)q.OnServerEvent:connect(function(m,q)x+=q end);(expect(x)).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("\117\115\101\114")local x={a=1}x.b=x;(expect(function()q:fireServer(x)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("\117\115\101\114")local x=Instance.new("\080\097\114\116")local L={ok=1}local E={a={[x]=1},b={key=2};[L]=3}q:fireServer(E,E,x)local A,b,i,t=q.OnServerEvent:wait();(expect(b)).to.never.equal(E);(expect(i)).to.never.equal(E);(expect(b)).to.never.equal(i);(expect(b.a[x])).to.never.be.ok();(expect(b.a["\060\073\110\115\116\097\110\099\101\062 \040\080\097\114\116\041"])).to.equal(1);(expect(i.a[x])).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(b[L])).to.never.be.ok();(expect(b["\060\084\097\098\108\101\062 \040"..(tostring(L).."\041")])).to.equal(3);(expect(i[L])).to.never.be.ok();(expect(i["\060\084\097\098\108\101\062 \040"..(tostring(L).."\041")])).to.equal(3);(expect(t)).to.equal(x)x:Destroy()q:destroy()end)end)describe("\077\111\099\107\082\101\109\111\116\101\069\118\101\110\116\058\102\105\114\101\067\108\105\101\110\116",function()it("\115\104\111\117\108\100 \102\105\114\101 \079\110\067\108\105\101\110\116\069\118\101\110\116 \119\105\116\104 \116\104\101 \112\097\115\115\101\100 \097\114\103\115 \105\102 \105\110\105\116\105\097\108 \099\108\105\101\110\116 \097\114\103 \105\115 \116\104\101 \099\108\105\101\110\116 \112\097\115\115\101\100 \105\110 \116\104\101 \099\111\110\115\116\114\117\099\116\111\114",function()local q=m.new("\117\115\101\114")local x,L task.spawn(function()x,L=q.OnClientEvent:wait()end)q:fireClient("\117\115\101\114",0,1);(expect(x)).to.equal(0);(expect(L)).to.equal(1)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 \099\108\105\101\110\116 \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",function()local q=m.new("\117\115\101\114")local x,L q:fireClient("\117\115\101\114",0,1)x,L=q.OnClientEvent:wait();(expect(x)).to.equal(0);(expect(L)).to.equal(1)q:destroy()end)it("\115\104\111\117\108\100 \116\104\114\111\119 \105\102 \116\104\101 \105\110\105\116\105\097\108 \099\108\105\101\110\116 \097\114\103 \105\115 \105\110\099\111\114\114\101\099\116",function()local q=m.new();(expect(function()q:fireClient("\117\115\101\114",0,1)end)).to.throw()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("\117\115\101\114")local x={a=1}x.b=x;(expect(function()q:fireClient("\117\115\101\114",x)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("\117\115\101\114")local x=Instance.new("\080\097\114\116")local L={ok=1}local E={a={[x]=1},b={key=2};[L]=3}q:fireClient("\117\115\101\114",E,E,x)local A,b,i=q.OnClientEvent:wait();(expect(A)).to.never.equal(E);(expect(b)).to.never.equal(E);(expect(A)).to.never.equal(b);(expect(A.a[x])).to.never.be.ok();(expect(A.a["\060\073\110\115\116\097\110\099\101\062 \040\080\097\114\116\041"])).to.equal(1);(expect(b.a[x])).to.never.be.ok();(expect(b.a["\060\073\110\115\116\097\110\099\101\062 \040\080\097\114\116\041"])).to.equal(1);(expect(A[L])).to.never.be.ok();(expect(A["\060\084\097\098\108\101\062 \040"..(tostring(L).."\041")])).to.equal(3);(expect(b[L])).to.never.be.ok();(expect(b["\060\084\097\098\108\101\062 \040"..(tostring(L).."\041")])).to.equal(3);(expect(i)).to.equal(x)x:Destroy()q:destroy()end)end)describe("\077\111\099\107\082\101\109\111\116\101\069\118\101\110\116\058\102\105\114\101\065\108\108\067\108\105\101\110\116\115",function()it("\115\104\111\117\108\100 \102\105\114\101 \079\110\067\108\105\101\110\116\069\118\101\110\116 \119\105\116\104 \116\104\101 \112\097\115\115\101\100 \097\114\103\115",function()local q=m.new()local x,L task.spawn(function()x,L=q.OnClientEvent:wait()end)q:fireAllClients(0,1);(expect(x)).to.equal(0);(expect(L)).to.equal(1)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 \099\108\105\101\110\116 \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",function()local q=m.new()local x,L q:fireAllClients(0,1)x,L=q.OnClientEvent:wait();(expect(x)).to.equal(0);(expect(L)).to.equal(1)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("\117\115\101\114")local x={a=1}x.b=x;(expect(function()q:fireAllClients(x)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("\117\115\101\114")local x=Instance.new("\080\097\114\116")local L={ok=1}local E={a={[x]=1},b={key=2};[L]=3}q:fireAllClients(E,E,x)local A,b,i=q.OnClientEvent:wait();(expect(A)).to.never.equal(E);(expect(b)).to.never.equal(E);(expect(A)).to.never.equal(b);(expect(A.a[x])).to.never.be.ok();(expect(A.a["\060\073\110\115\116\097\110\099\101\062 \040\080\097\114\116\041"])).to.equal(1);(expect(b.a[x])).to.never.be.ok();(expect(b.a["\060\073\110\115\116\097\110\099\101\062 \040\080\097\114\116\041"])).to.equal(1);(expect(A[L])).to.never.be.ok();(expect(A["\060\084\097\098\108\101\062 \040"..(tostring(L).."\041")])).to.equal(3);(expect(b[L])).to.never.be.ok();(expect(b["\060\084\097\098\108\101\062 \040"..(tostring(L).."\041")])).to.equal(3);(expect(i)).to.equal(x)x:Destroy()q:destroy()end)end)describe("\077\111\099\107\082\101\109\111\116\101\069\118\101\110\116\058\103\101\116\067\108\105\101\110\116",function()it("\115\104\111\117\108\100 \114\101\116\117\114\110 \099\108\105\101\110\116 \112\097\115\115\101\100 \105\110 \099\111\110\115\116\114\117\099\116\111\114",function()local q=m.new("\117\115\101\114");(expect(q:getClient())).to.equal("\117\115\101\114")q:destroy()end)end)describe("\077\111\099\107\082\101\109\111\116\101\069\118\101\110\116\058\100\101\115\116\114\111\121",function()it("\115\104\111\117\108\100 \115\101\116 \100\101\115\116\114\111\121\101\100 \102\105\101\108\100 \116\111 \116\114\117\101",function()local q=m.new("\117\115\101\114")q:destroy();(expect(q.destroyed)).to.equal(true)end)end)end
return function()
    local MockRemoteEvent = require(script.Parent.MockRemoteEvent)

    describe("MockRemoteEvent.new", function()
        it("should create a new MockRemoteEvent", function()
            local mockRemoteEvent = MockRemoteEvent.new()

            expect(mockRemoteEvent).to.be.a("table")
            expect(getmetatable(mockRemoteEvent)).to.equal(MockRemoteEvent)

            mockRemoteEvent:destroy()
        end)

        it("should create a new MockRemoteEvent with a client id if passed", function()
            local mockRemoteEvent = MockRemoteEvent.new("user")

            expect(mockRemoteEvent:getClient()).to.equal("user")

            mockRemoteEvent:destroy()
        end)
    end)

    describe("MockRemoteEvent:fireServer", function()
        it("should fire OnServerEvent with the client and passed args", function()
            local mockRemoteEvent = MockRemoteEvent.new("user")
            local client, value

            task.spawn(function()
                client, value = mockRemoteEvent.OnServerEvent:wait()
            end)

            mockRemoteEvent:fireServer(true)

            expect(client).to.equal("user")
            expect(value).to.equal(true)

            mockRemoteEvent:destroy()
        end)

        it("should queue passed args on the server until an activating connection is made", function()
            local mockRemoteEvent = MockRemoteEvent.new("user")
            local count = 0

            mockRemoteEvent:fireServer(1)
            mockRemoteEvent:fireServer(2)

            mockRemoteEvent.OnServerEvent:connect(function(_, value)
                count += value
            end)

            expect(count).to.equal(3)

            mockRemoteEvent:destroy()
        end)

        it("should throw if tables with cyclic values are passed", function()
            local mockRemoteEvent = MockRemoteEvent.new("user")

            local data = {
                a = 1,
            }

            data.b = data

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

            mockRemoteEvent:destroy()
        end)

        it("should pass deep copies of data and convert instance and table keys to strings", function()
            local mockRemoteEvent = MockRemoteEvent.new("user")
            local part = Instance.new("Part")

            local tab = {ok = 1}

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

            mockRemoteEvent:fireServer(data, data, part)

            local _, data1, data2, passedPart = mockRemoteEvent.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()
            mockRemoteEvent:destroy()
        end)
    end)

    describe("MockRemoteEvent:fireClient", function()
        it("should fire OnClientEvent with the passed args if initial client arg is the client passed in the constructor", function()
            local mockRemoteEvent = MockRemoteEvent.new("user")
            local value0, value1

            task.spawn(function()
                value0, value1 = mockRemoteEvent.OnClientEvent:wait()
            end)

            mockRemoteEvent:fireClient("user", 0, 1)
            
            expect(value0).to.equal(0)
            expect(value1).to.equal(1)

            mockRemoteEvent:destroy()
        end)

        it("should queue passed args on client until an activating connection is made", function()
            local mockRemoteEvent = MockRemoteEvent.new("user")
            local value0, value1

            mockRemoteEvent:fireClient("user", 0, 1)

            value0, value1 = mockRemoteEvent.OnClientEvent:wait()

            expect(value0).to.equal(0)
            expect(value1).to.equal(1)

            mockRemoteEvent:destroy()
        end)

        it("should throw if the initial client arg is incorrect", function()
            local mockRemoteEvent = MockRemoteEvent.new()
            
            expect(function()
                mockRemoteEvent:fireClient("user", 0, 1)
            end).to.throw()

            mockRemoteEvent:destroy()
        end)

        it("should throw if tables with cyclic values are passed", function()
            local mockRemoteEvent = MockRemoteEvent.new("user")

            local data = {
                a = 1,
            }

            data.b = data

            expect(function()
                mockRemoteEvent:fireClient("user", data)
            end).to.throw()

            mockRemoteEvent:destroy()
        end)

        it("should pass deep copies of data and convert instance and table keys to strings", function()
            local mockRemoteEvent = MockRemoteEvent.new("user")
            local part = Instance.new("Part")

            local tab = {ok = 1}

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

            mockRemoteEvent:fireClient("user", data, data, part)

            local data1, data2, passedPart = mockRemoteEvent.OnClientEvent: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()
            mockRemoteEvent:destroy()
        end)
    end)

    describe("MockRemoteEvent:fireAllClients", function()
        it("should fire OnClientEvent with the passed args", function()
            local mockRemoteEvent = MockRemoteEvent.new()
            local value0, value1

            task.spawn(function()
                value0, value1 = mockRemoteEvent.OnClientEvent:wait()
            end)

            mockRemoteEvent:fireAllClients(0, 1)
            
            expect(value0).to.equal(0)
            expect(value1).to.equal(1)

            mockRemoteEvent:destroy()
        end)

        it("should queue passed args on client until an activating connection is made", function()
            local mockRemoteEvent = MockRemoteEvent.new()
            local value0, value1

            mockRemoteEvent:fireAllClients(0, 1)

            value0, value1 = mockRemoteEvent.OnClientEvent:wait()

            expect(value0).to.equal(0)
            expect(value1).to.equal(1)

            mockRemoteEvent:destroy()
        end)

        it("should throw if tables with cyclic values are passed", function()
            local mockRemoteEvent = MockRemoteEvent.new("user")

            local data = {
                a = 1,
            }

            data.b = data

            expect(function()
                mockRemoteEvent:fireAllClients(data)
            end).to.throw()

            mockRemoteEvent:destroy()
        end)

        it("should pass deep copies of data and convert instance and table keys to strings", function()
            local mockRemoteEvent = MockRemoteEvent.new("user")
            local part = Instance.new("Part")

            local tab = {ok = 1}

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

            mockRemoteEvent:fireAllClients(data, data, part)

            local data1, data2, passedPart = mockRemoteEvent.OnClientEvent: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()
            mockRemoteEvent:destroy()
        end)
    end)

    describe("MockRemoteEvent:getClient", function()
        it("should return client passed in constructor", function()
            local mockRemoteEvent = MockRemoteEvent.new("user")

            expect(mockRemoteEvent:getClient()).to.equal("user")

            mockRemoteEvent:destroy()
        end)
    end)

    describe("MockRemoteEvent:destroy", function()
        it("should set destroyed field to true", function()
            local mockRemoteEvent = MockRemoteEvent.new("user")

            mockRemoteEvent:destroy()

            expect(mockRemoteEvent.destroyed).to.equal(true)
        end)
    end)
end