return function()local h=require(script.Parent.Server)local z=require(script.Parent.Client)local r=require(script.Parent.RemoteEventServer)local k=require(script.Parent.RemoteEventClient)local P=require(script.Parent.RemoteFunctionServer)local x=require(script.Parent.RemoteFunctionClient)describe("\083\101\114\118\101\114\046\110\101\119",function()it("\115\104\111\117\108\100 \114\101\116\117\114\110 \097 \110\101\119 \083\101\114\118\101\114 \111\098\106\101\099\116",function()local z=h.new();(expect(z)).to.be.a("\116\097\098\108\101");(expect(getmetatable(z))).to.equal(h)z:destroy()end)it("\115\104\111\117\108\100 \099\114\101\097\116\101 \099\108\105\101\110\116\115 \102\114\111\109 \112\097\115\115\101\100 \105\100\115 \105\102 \097\110\121 \097\114\101 \112\097\115\115\101\100",function()local z=h.new({"\117\115\101\114\048","\117\115\101\114\049"});(expect(z:getClient("\117\115\101\114\048"))).to.be.ok();(expect(z:getClient("\117\115\101\114\049"))).to.be.ok()z:destroy()end)end)describe("\083\101\114\118\101\114\058\099\114\101\097\116\101\082\101\109\111\116\101\069\118\101\110\116",function()it("\115\104\111\117\108\100 \099\114\101\097\116\101 \097 \082\101\109\111\116\101\069\118\101\110\116 \111\098\106\101\099\116 \111\110 \115\101\114\118\101\114 \097\110\100 \101\097\099\104 \099\108\105\101\110\116",function()local z=h.new()local P=z:connect("\117\115\101\114\049")local x=z:connect("\117\115\101\114\050")z:createRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116");(expect(z:getRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116"))).to.be.a("\116\097\098\108\101");(expect(getmetatable(z:getRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116")))).to.equal(r);(expect(P:getRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116"))).to.be.a("\116\097\098\108\101");(expect(getmetatable(P:getRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116")))).to.equal(k);(expect(x:getRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116"))).to.be.a("\116\097\098\108\101");(expect(getmetatable(x:getRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116")))).to.equal(k)z:destroy()end)end)describe("\083\101\114\118\101\114\058\103\101\116\082\101\109\111\116\101\069\118\101\110\116",function()it("\115\104\111\117\108\100 \103\101\116 \116\104\101 \082\101\109\111\116\101\069\118\101\110\116 \111\098\106\101\099\116 \102\114\111\109 \116\104\101 \115\101\114\118\101\114",function()local z=h.new()local r=z:createRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116");(expect(z:getRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116"))).to.equal(r)z:destroy()end)it("\115\104\111\117\108\100 \116\104\114\111\119 \105\102 \097 \082\101\109\111\116\101\069\118\101\110\116 \119\105\116\104 \116\104\101 \112\097\115\115\101\100 \110\097\109\101 \100\111\101\115\110\'\116 \101\120\105\115\116",function()local z=h.new();(expect(function()z:getRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116")end)).to.throw()z:destroy()end)end)describe("\083\101\114\118\101\114\058\099\114\101\097\116\101\082\101\109\111\116\101\070\117\110\099\116\105\111\110",function()it("\115\104\111\117\108\100 \099\114\101\097\116\101 \097 \082\101\109\111\116\101\070\117\110\099\116\105\111\110 \111\098\106\101\099\116 \111\110 \115\101\114\118\101\114 \097\110\100 \101\097\099\104 \099\108\105\101\110\116",function()local z=h.new()local r=z:connect("\117\115\101\114\049")local k=z:connect("\117\115\101\114\050")z:createRemoteFunction("\114\101\109\111\116\101\070\117\110\099\116\105\111\110");(expect(z:getRemoteFunction("\114\101\109\111\116\101\070\117\110\099\116\105\111\110"))).to.be.a("\116\097\098\108\101");(expect(getmetatable(z:getRemoteFunction("\114\101\109\111\116\101\070\117\110\099\116\105\111\110")))).to.equal(P);(expect(r:getRemoteFunction("\114\101\109\111\116\101\070\117\110\099\116\105\111\110"))).to.be.a("\116\097\098\108\101");(expect(getmetatable(r:getRemoteFunction("\114\101\109\111\116\101\070\117\110\099\116\105\111\110")))).to.equal(x);(expect(k:getRemoteFunction("\114\101\109\111\116\101\070\117\110\099\116\105\111\110"))).to.be.a("\116\097\098\108\101");(expect(getmetatable(k:getRemoteFunction("\114\101\109\111\116\101\070\117\110\099\116\105\111\110")))).to.equal(x)z:destroy()end)end)describe("\083\101\114\118\101\114\058\103\101\116\082\101\109\111\116\101\070\117\110\099\116\105\111\110",function()it("\115\104\111\117\108\100 \103\101\116 \116\104\101 \082\101\109\111\116\101\070\117\110\099\116\105\111\110 \111\098\106\101\099\116 \102\114\111\109 \116\104\101 \115\101\114\118\101\114",function()local z=h.new()local r=z:createRemoteFunction("\114\101\109\111\116\101\070\117\110\099\116\105\111\110");(expect(z:getRemoteFunction("\114\101\109\111\116\101\070\117\110\099\116\105\111\110"))).to.equal(r)z:destroy()end)it("\115\104\111\117\108\100 \116\104\114\111\119 \105\102 \097 \082\101\109\111\116\101\070\117\110\099\116\105\111\110 \119\105\116\104 \116\104\101 \112\097\115\115\101\100 \110\097\109\101 \100\111\101\115\110\'\116 \101\120\105\115\116",function()local z=h.new();(expect(function()z:getRemoteFunction("\114\101\109\111\116\101\070\117\110\099\116\105\111\110")end)).to.throw()z:destroy()end)end)describe("\083\101\114\118\101\114\058\099\111\110\110\101\099\116",function()it("\115\104\111\117\108\100 \114\101\116\117\114\110 \097 \099\108\105\101\110\116 \111\098\106\101\099\116 \119\105\116\104 \116\104\101 \105\100",function()local r=h.new()local k=r:connect("\117\115\101\114");(expect(k)).to.be.a("\116\097\098\108\101");(expect(getmetatable(k))).to.equal(z);(expect(k.id)).to.equal("\117\115\101\114")r:destroy()end)it("\115\104\111\117\108\100 \114\101\116\117\114\110 \097 \099\108\105\101\110\116 \116\104\097\116 \104\097\115 \097\108\108 \116\104\101 \114\101\109\111\116\101 \111\098\106\101\099\116\115 \119\105\116\104 \105\116",function()local z=h.new()z:createRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116")z:createRemoteFunction("\114\101\109\111\116\101\070\117\110\099\116\105\111\110")local r=z:connect("\117\115\101\114");(expect(r:getRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116"))).to.be.a("\116\097\098\108\101");(expect(getmetatable(r:getRemoteEvent("\114\101\109\111\116\101\069\118\101\110\116")))).to.equal(k);(expect(r:getRemoteFunction("\114\101\109\111\116\101\070\117\110\099\116\105\111\110"))).to.be.a("\116\097\098\108\101");(expect(getmetatable(r:getRemoteFunction("\114\101\109\111\116\101\070\117\110\099\116\105\111\110")))).to.equal(x)z:destroy()end)it("\115\104\111\117\108\100 \102\105\114\101 \116\104\101 \099\108\105\101\110\116\067\111\110\110\101\099\116\101\100 \101\118\101\110\116 \119\105\116\104 \116\104\101 \099\108\105\101\110\116 \111\098\106\101\099\116",function()local z=h.new()local r z.clientConnected:connect(function(h)r=h end)z:connect("\117\115\101\114");(expect(r)).to.be.ok();(expect(r.id)).to.equal("\117\115\101\114")z:destroy()end)it("\115\104\111\117\108\100 \116\104\114\111\119 \105\102 \097 \099\111\110\110\101\099\116\101\100 \099\108\105\101\110\116 \101\120\105\115\116\115 \119\105\116\104 \116\104\101 \105\100",function()local z=h.new()z:connect("\117\115\101\114");(expect(function()z:connect("\117\115\101\114")end)).to.throw()z:destroy()end)end)describe("\083\101\114\118\101\114\058\100\105\115\099\111\110\110\101\099\116",function()it("\115\104\111\117\108\100 \100\105\115\099\111\110\110\101\099\116 \116\104\101 \099\108\105\101\110\116 \119\105\116\104 \116\104\101 \105\100 \097\110\100 \115\101\116 \099\108\105\101\110\116\'\115 \099\111\110\110\101\099\116\101\100 \102\105\101\108\100 \116\111 \102\097\108\115\101",function()local z=h.new()local r=z:connect("\117\115\101\114");(expect(function()z:disconnect("\117\115\101\114")end)).to.never.throw();(expect(r.connected)).to.equal(false);(expect(z:getClient("\117\115\101\114"))).to.equal(nil)z:destroy()end)it("\115\104\111\117\108\100 \102\105\114\101 \116\104\101 \099\108\105\101\110\116\068\105\115\099\111\110\110\101\099\116\105\110\103 \101\118\101\110\116 \119\105\116\104 \116\104\101 \099\108\105\101\110\116 \111\098\106\101\099\116",function()local z=h.new()local r=z:connect("\117\115\101\114")z.clientDisconnecting:connect(function(h)(expect(r)).to.equal(h)end)z:disconnect("\117\115\101\114")z:destroy()end)it("\115\104\111\117\108\100 \116\104\114\111\119 \105\102 \110\111 \099\111\110\110\101\099\116\101\100 \099\108\105\101\110\116 \101\120\105\115\116\115 \119\105\116\104 \116\104\101 \105\100",function()local z=h.new();(expect(function()z:disconnect("\117\115\101\114")end)).to.throw()z:destroy()end)end)describe("\083\101\114\118\101\114\058\103\101\116\067\108\105\101\110\116",function()it("\115\104\111\117\108\100 \114\101\116\117\114\110 \116\104\101 \099\108\105\101\110\116 \119\105\116\104 \116\104\101 \105\100",function()local z=h.new()z:connect("\117\115\101\114");(expect(z:getClient("\117\115\101\114"))).to.be.ok();(expect((z:getClient("\117\115\101\114")).id)).to.equal("\117\115\101\114")z:destroy()end)it("\115\104\111\117\108\100 \114\101\116\117\114\110 \110\105\108 \105\102 \116\104\101 \099\108\105\101\110\116 \119\105\116\104 \116\104\101 \112\097\115\115\101\100 \105\100 \100\111\101\115\110\'\116 \101\120\105\115\116",function()local z=h.new();(expect(z:getClient("\117\115\101\114"))).to.equal(nil)z:destroy()end)end)describe("\083\101\114\118\101\114\058\103\101\116\067\108\105\101\110\116\115",function()it("\115\104\111\117\108\100 \114\101\116\117\114\110 \097 \108\105\115\116 \111\102 \099\117\114\114\101\110\116\108\121 \099\111\110\110\101\099\116\101\100 \099\108\105\101\110\116\115",function()local z=h.new({"\117\115\101\114\049","\117\115\101\114\050","\117\115\101\114\051"})local r=z:getClients()local k,P,x=z:getClient("\117\115\101\114\049"),z:getClient("\117\115\101\114\050"),z:getClient("\117\115\101\114\051");(expect(table.find(r,k))).to.be.ok();(expect(table.find(r,P))).to.be.ok();(expect(table.find(r,x))).to.be.ok()z:destroy()end)end)describe("\083\101\114\118\101\114\058\109\097\112\067\108\105\101\110\116\115",function()it("\115\104\111\117\108\100 \114\101\116\117\114\110 \097 \100\105\099\116\105\111\110\097\114\121 \116\104\097\116 \109\097\112\115 \116\104\101 \099\108\105\101\110\116 \105\100 \116\111 \116\104\101 \111\098\106\101\099\116 \105\102 \110\111 \102\117\110\099\116\105\111\110 \105\115 \112\097\115\115\101\100",function()local z=h.new({"\117\115\101\114\049";"\117\115\101\114\050";"\117\115\101\114\051"})local r=z:mapClients();(expect(r.user1)).to.equal(z:getClient("\117\115\101\114\049"));(expect(r.user2)).to.equal(z:getClient("\117\115\101\114\050"));(expect(r.user3)).to.equal(z:getClient("\117\115\101\114\051"))z:destroy()end)it("\115\104\111\117\108\100 \114\101\116\117\114\110 \097 \100\105\099\116\105\111\110\097\114\121 \116\104\097\116 \105\115 \112\114\111\112\101\114\108\121 \109\097\112\112\101\100 \105\102 \097 \102\117\110\099\116\105\111\110 \105\115 \112\097\115\115\101\100",function()local z=h.new({"\117\115\101\114\049","\117\115\101\114\050","\117\115\101\114\051"})local r=z:mapClients(function(h,z)return string.upper(h),typeof(z)end);(expect(r.user1)).to.never.be.ok();(expect(r.user2)).to.never.be.ok();(expect(r.user3)).to.never.be.ok();(expect(r.USER1)).to.equal("\116\097\098\108\101");(expect(r.USER2)).to.equal("\116\097\098\108\101");(expect(r.USER3)).to.equal("\116\097\098\108\101")z:destroy()end)end)describe("\083\101\114\118\101\114\058\103\101\116\067\108\105\101\110\116\115",function()it("\115\104\111\117\108\100 \114\101\116\117\114\110 \097 \108\105\115\116 \111\102 \099\117\114\114\101\110\116\108\121 \099\111\110\110\101\099\116\101\100 \099\108\105\101\110\116\115",function()local z=h.new({"\117\115\101\114\049";"\117\115\101\114\050","\117\115\101\114\051"})local r=z:getClients()local k,P,x=z:getClient("\117\115\101\114\049"),z:getClient("\117\115\101\114\050"),z:getClient("\117\115\101\114\051");(expect(table.find(r,k))).to.be.ok();(expect(table.find(r,P))).to.be.ok();(expect(table.find(r,x))).to.be.ok()z:destroy()end)end)describe("\083\101\114\118\101\114\058\100\101\115\116\114\111\121",function()it("\115\104\111\117\108\100 \100\105\115\099\111\110\110\101\099\116 \097\108\108 \099\108\105\101\110\116\115 \097\110\100 \102\105\114\101 \099\108\105\101\110\116\068\105\115\099\111\110\110\101\099\116\105\110\103 \102\111\114 \097\108\108 \111\102 \116\104\101\109",function()local z=h.new()local r={}local k=z:connect("\117\115\101\114\049")local P=z:connect("\117\115\101\114\050")local x=z:connect("\117\115\101\114\051")local w=z.clientDisconnecting:connect(function(h)r[h]=true end)z:destroy();(expect(k.connected)).to.equal(false);(expect(P.connected)).to.equal(false);(expect(x.connected)).to.equal(false);(expect(r[k])).to.equal(true);(expect(r[P])).to.equal(true);(expect(r[x])).to.equal(true)end)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 z=h.new()z:destroy();(expect(z.destroyed)).to.equal(true)end)end)end
return function()
    local Server = require(script.Parent.Server)
    local Client = require(script.Parent.Client)

    local RemoteEventServer = require(script.Parent.RemoteEventServer)
    local RemoteEventClient = require(script.Parent.RemoteEventClient)
    local RemoteFunctionServer = require(script.Parent.RemoteFunctionServer)
    local RemoteFunctionClient = require(script.Parent.RemoteFunctionClient)

    describe("Server.new", function()
        it("should return a new Server object", function()
            local server = Server.new()

            expect(server).to.be.a("table")
            expect(getmetatable(server)).to.equal(Server)

            server:destroy()
        end)

        it("should create clients from passed ids if any are passed", function()
            local server = Server.new({"user0", "user1"})

            expect(server:getClient("user0")).to.be.ok()
            expect(server:getClient("user1")).to.be.ok()

            server:destroy()
        end)
    end)

    describe("Server:createRemoteEvent", function()
        it("should create a RemoteEvent object on server and each client", function()
            local server = Server.new()

            local user1 = server:connect("user1")
            local user2 = server:connect("user2")

            server:createRemoteEvent("remoteEvent")

            expect(server:getRemoteEvent("remoteEvent")).to.be.a("table")
            expect(getmetatable(server:getRemoteEvent("remoteEvent"))).to.equal(RemoteEventServer)
            
            expect(user1:getRemoteEvent("remoteEvent")).to.be.a("table")
            expect(getmetatable(user1:getRemoteEvent("remoteEvent"))).to.equal(RemoteEventClient)

            expect(user2:getRemoteEvent("remoteEvent")).to.be.a("table")
            expect(getmetatable(user2:getRemoteEvent("remoteEvent"))).to.equal(RemoteEventClient)

            server:destroy()
        end)
    end)

    describe("Server:getRemoteEvent", function()
        it("should get the RemoteEvent object from the server", function()
            local server = Server.new()

            local remote = server:createRemoteEvent("remoteEvent")

            expect(server:getRemoteEvent("remoteEvent")).to.equal(remote)

            server:destroy()
        end)

        it("should throw if a RemoteEvent with the passed name doesn't exist", function()
            local server = Server.new()

            expect(function()
                server:getRemoteEvent("remoteEvent")
            end).to.throw()

            server:destroy()
        end)
    end)

    describe("Server:createRemoteFunction", function()
        it("should create a RemoteFunction object on server and each client", function()
            local server = Server.new()

            local user1 = server:connect("user1")
            local user2 = server:connect("user2")

            server:createRemoteFunction("remoteFunction")

            expect(server:getRemoteFunction("remoteFunction")).to.be.a("table")
            expect(getmetatable(server:getRemoteFunction("remoteFunction"))).to.equal(RemoteFunctionServer)
            
            expect(user1:getRemoteFunction("remoteFunction")).to.be.a("table")
            expect(getmetatable(user1:getRemoteFunction("remoteFunction"))).to.equal(RemoteFunctionClient)

            expect(user2:getRemoteFunction("remoteFunction")).to.be.a("table")
            expect(getmetatable(user2:getRemoteFunction("remoteFunction"))).to.equal(RemoteFunctionClient)

            server:destroy()
        end)
    end)

    describe("Server:getRemoteFunction", function()
        it("should get the RemoteFunction object from the server", function()
            local server = Server.new()

            local remote = server:createRemoteFunction("remoteFunction")

            expect(server:getRemoteFunction("remoteFunction")).to.equal(remote)

            server:destroy()
        end)

        it("should throw if a RemoteFunction with the passed name doesn't exist", function()
            local server = Server.new()

            expect(function()
                server:getRemoteFunction("remoteFunction")
            end).to.throw()

            server:destroy()
        end)
    end)
    
    describe("Server:connect", function()
        it("should return a client object with the id", function()
            local server = Server.new()
            
            local client = server:connect("user")

            expect(client).to.be.a("table")
            expect(getmetatable(client)).to.equal(Client)
            expect(client.id).to.equal("user")

            server:destroy()
        end)

        it("should return a client that has all the remote objects with it", function()
            local server = Server.new()

            server:createRemoteEvent("remoteEvent")
            server:createRemoteFunction("remoteFunction")

            local client = server:connect("user")

            expect(client:getRemoteEvent("remoteEvent")).to.be.a("table")
            expect(getmetatable(client:getRemoteEvent("remoteEvent"))).to.equal(RemoteEventClient)

            expect(client:getRemoteFunction("remoteFunction")).to.be.a("table")
            expect(getmetatable(client:getRemoteFunction("remoteFunction"))).to.equal(RemoteFunctionClient)

            server:destroy()
        end)

        it("should fire the clientConnected event with the client object", function()
            local server = Server.new()
            local client

            server.clientConnected:connect(function(connectedClient)
                client = connectedClient
            end)

            server:connect("user")

            expect(client).to.be.ok()
            expect(client.id).to.equal("user")

            server:destroy()
        end)

        it("should throw if a connected client exists with the id", function()
            local server = Server.new()

            server:connect("user")

            expect(function()
                server:connect("user")
            end).to.throw()

            server:destroy()
        end)
    end)

    describe("Server:disconnect", function()
        it("should disconnect the client with the id and set client's connected field to false", function()
            local server = Server.new()

            local client = server:connect("user")

            expect(function()
                server:disconnect("user")
            end).to.never.throw()

            expect(client.connected).to.equal(false)
            expect(server:getClient("user")).to.equal(nil)

            server:destroy()
        end)

        it("should fire the clientDisconnecting event with the client object", function()
            local server = Server.new()

            local client = server:connect("user")

            server.clientDisconnecting:connect(function(disconnectingClient)
                expect(client).to.equal(disconnectingClient)
            end)

            server:disconnect("user")

            server:destroy()
        end)

        it("should throw if no connected client exists with the id", function()
            local server = Server.new()

            expect(function()
                server:disconnect("user")
            end).to.throw()

            server:destroy()
        end)
    end)

    describe("Server:getClient", function()
        it("should return the client with the id", function()
            local server = Server.new()

            server:connect("user")
            expect(server:getClient("user")).to.be.ok()
            expect(server:getClient("user").id).to.equal("user")

            server:destroy()
        end)

        it("should return nil if the client with the passed id doesn't exist", function()
            local server = Server.new()

            expect(server:getClient("user")).to.equal(nil)

            server:destroy()
        end)
    end)

    describe("Server:getClients", function()
        it("should return a list of currently connected clients", function()
            local server = Server.new({"user1", "user2", "user3"})
            local clients = server:getClients()
            
            local user1, user2, user3 = server:getClient("user1"), server:getClient("user2"), server:getClient("user3")

            expect(table.find(clients, user1)).to.be.ok()
            expect(table.find(clients, user2)).to.be.ok()
            expect(table.find(clients, user3)).to.be.ok()

            server:destroy()
        end)
    end)

    describe("Server:mapClients", function()
        it("should return a dictionary that maps the client id to the object if no function is passed", function()
            local server = Server.new({"user1", "user2", "user3"})
            local clients = server:mapClients()
            
            expect(clients.user1).to.equal(server:getClient("user1"))
            expect(clients.user2).to.equal(server:getClient("user2"))
            expect(clients.user3).to.equal(server:getClient("user3"))

            server:destroy()
        end)
        
        it("should return a dictionary that is properly mapped if a function is passed", function()
            local server = Server.new({"user1", "user2", "user3"})

            local clients = server:mapClients(function(id, client)
                return string.upper(id), typeof(client)
            end)
            
            expect(clients.user1).to.never.be.ok()
            expect(clients.user2).to.never.be.ok()
            expect(clients.user3).to.never.be.ok()

            expect(clients.USER1).to.equal("table")
            expect(clients.USER2).to.equal("table")
            expect(clients.USER3).to.equal("table")

            server:destroy()
        end)
    end)

    describe("Server:getClients", function()
        it("should return a list of currently connected clients", function()
            local server = Server.new({"user1", "user2", "user3"})
            local clients = server:getClients()
            
            local user1, user2, user3 = server:getClient("user1"), server:getClient("user2"), server:getClient("user3")

            expect(table.find(clients, user1)).to.be.ok()
            expect(table.find(clients, user2)).to.be.ok()
            expect(table.find(clients, user3)).to.be.ok()

            server:destroy()
        end)
    end)

    describe("Server:destroy", function()
        it("should disconnect all clients and fire clientDisconnecting for all of them", function()
            local server = Server.new()
            local done = {}

            local user1 = server:connect("user1")
            local user2 = server:connect("user2")
            local user3 = server:connect("user3")

            local conn = server.clientDisconnecting:connect(function(client)
                done[client] = true
            end)

            server:destroy()

            expect(user1.connected).to.equal(false)
            expect(user2.connected).to.equal(false)
            expect(user3.connected).to.equal(false)

            expect(done[user1]).to.equal(true)
            expect(done[user2]).to.equal(true)
            expect(done[user3]).to.equal(true)
        end)

        it("should set destroyed field to true", function()
            local server = Server.new()

            server:destroy()

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