return function()local u=require(script.Parent.Parent.GlobalConfig)local q=require(script.Parent)it("\115\104\111\117\108\100 \101\120\112\111\115\101 \097 \116\097\098\108\101",function()(expect(q)).to.be.a("\116\097\098\108\101")end)it("\115\104\111\117\108\100 \110\111\116 \099\111\110\116\097\105\110 \097 \109\101\116\097\116\097\098\108\101",function()(expect(getmetatable(q))).to.equal(nil)end)it("\115\104\111\117\108\100 \116\104\114\111\119 \097\110 \101\114\114\111\114 \111\110 \097\116\116\101\109\112\116 \116\111 \109\111\100\105\102\121 \116\104\101 \101\120\112\111\114\116 \116\097\098\108\101",function()(expect(function()q._={}end)).to.throw();(expect(function()setmetatable(q,{})end)).to.throw()end)it("\115\104\111\117\108\100 \102\105\114\101 \099\111\110\110\101\099\116\101\100 \099\097\108\108\098\097\099\107\115",function()local u=0 local l="\072\101\108\108\111 \087\111\114\108\100"local r=7 local P=function(q,P)(expect(q)).to.equal(l);(expect(P)).to.equal(r)u+=1 end local y=q.new()local T=y:connect(P)y:fire(l,r);(expect(u)).to.equal(1)T()y:fire(l,r);(expect(u)).to.equal(1)end)it("\115\104\111\117\108\100 \100\105\115\099\111\110\110\101\099\116 \104\097\110\100\108\101\114\115",function()local u=function()error("\067\097\108\108\098\097\099\107 \119\097\115 \099\097\108\108\101\100 \097\102\116\101\114 \100\105\115\099\111\110\110\101\099\116\033")end local l=q.new()local r=l:connect(u)r()l:fire()end)it("\115\104\111\117\108\100 \102\105\114\101 \104\097\110\100\108\101\114\115 \105\110 \111\114\100\101\114",function()local u=q.new()local l=0 local r=0 local P=function()(expect(l)).to.equal(0);(expect(r)).to.equal(0)l+=1 end local y=function()(expect(l)).to.equal(1);(expect(r)).to.equal(0)r+=1 end u:connect(P)u:connect(y)u:fire();(expect(l)).to.equal(1);(expect(r)).to.equal(1)end)it("\115\104\111\117\108\100 \099\111\110\116\105\110\117\101 \102\105\114\105\110\103 \100\101\115\112\105\116\101 \109\105\100-\101\118\101\110\116 \100\105\115\099\111\110\110\101\099\116\105\111\110",function()local u=q.new()local l=0 local r=0 local P P=u:connect(function()P()l=l+1 end)u:connect(function()r=r+1 end)u:fire();(expect(l)).to.equal(1);(expect(r)).to.equal(1)end)it("\115\104\111\117\108\100 \115\107\105\112 \108\105\115\116\101\110\101\114\115 \116\104\097\116 \119\101\114\101 \100\105\115\099\111\110\110\101\099\116\101\100 \100\117\114\105\110\103 \101\118\101\110\116 \101\118\097\108\117\097\116\105\111\110",function()local u=q.new()local l=0 local r=0 local P u:connect(function()l+=1 P()end)P=u:connect(function()r+=1 end)u:fire();(expect(l)).to.equal(1);(expect(r)).to.equal(0)end)it("\115\104\111\117\108\100 \116\104\114\111\119 \097\110 \101\114\114\111\114 \105\102 \116\104\101 \097\114\103\117\109\101\110\116 \116\111 \096\099\111\110\110\101\099\116\096 \105\115 \110\111\116 \097 \102\117\110\099\116\105\111\110",function()u.set({typeChecks=true})local l=q.new();(expect(function()l:connect("\110\111\116 \097 \102\117\110\099\116\105\111\110")end)).to.throw()end)it("\115\104\111\117\108\100 \116\104\114\111\119 \097\110 \101\114\114\111\114 \119\104\101\110 \100\105\115\099\111\110\110\101\099\116\105\110\103 \109\111\114\101 \116\104\097\110 \111\110\099\101",function()local u=q.new()local l=u:connect(function() end);(expect(l)).never.to.throw();(expect(l)).to.throw()end)it("\115\104\111\117\108\100 \116\104\114\111\119 \097\110 \101\114\114\111\114 \119\104\101\110 \115\117\098\115\099\114\105\098\105\110\103 \100\117\114\105\110\103 \100\105\115\112\097\116\099\104",function()local u={_isDispatching=false}local l=q.new(u)l:connect(function()l:connect(function() end)end)u._isDispatching=true;(expect(function()l:fire()end)).to.throw()end)it("\115\104\111\117\108\100 \116\104\114\111\119 \097\110 \101\114\114\111\114 \119\104\101\110 \117\110\115\117\098\115\099\114\105\098\105\110\103 \100\117\114\105\110\103 \100\105\115\112\097\116\099\104",function()local u={_isDispatching=false}local l=q.new(u)local r r=l:connect(function()r.disconnect()end)u._isDispatching=true;(expect(function()l:fire()end)).to.throw()end)end
return function()
	local GlobalConfig = require(script.Parent.Parent.GlobalConfig)

	local Signal = require(script.Parent)

	it("should expose a table", function()
		expect(Signal).to.be.a("table")
	end)

	it("should not contain a metatable", function()
		expect(getmetatable(Signal)).to.equal(nil)
	end)

	it("should throw an error on attempt to modify the export table", function()
		expect(function()
			Signal._ = {}
		end).to.throw()

		expect(function()
			setmetatable(Signal, {})
		end).to.throw()
	end)

	it("should fire connected callbacks", function()
		local callCount = 0
		local value1 = "Hello World"
		local value2 = 7

		local callback = function(arg1, arg2)
			expect(arg1).to.equal(value1)
			expect(arg2).to.equal(value2)
			callCount += 1
		end

		local signal = Signal.new()

		local disconnect = signal:connect(callback)
		signal:fire(value1, value2)

		expect(callCount).to.equal(1)

		disconnect()
		signal:fire(value1, value2)

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

	it("should disconnect handlers", function()
		local callback = function()
			error("Callback was called after disconnect!")
		end

		local signal = Signal.new()

		local disconnect = signal:connect(callback)
		disconnect()

		signal:fire()
	end)

	it("should fire handlers in order", function()
		local signal = Signal.new()
		local x = 0
		local y = 0

		local callback1 = function()
			expect(x).to.equal(0)
			expect(y).to.equal(0)
			x += 1
		end

		local callback2 = function()
			expect(x).to.equal(1)
			expect(y).to.equal(0)
			y += 1
		end

		signal:connect(callback1)
		signal:connect(callback2)
		signal:fire()

		expect(x).to.equal(1)
		expect(y).to.equal(1)
	end)

	it("should continue firing despite mid-event disconnection", function()
		local signal = Signal.new()
		local countA = 0
		local countB = 0

		local disconnect
		disconnect = signal:connect(function()
			disconnect()
			countA = countA + 1
		end)

		signal:connect(function()
			countB = countB + 1
		end)

		signal:fire()

		expect(countA).to.equal(1)
		expect(countB).to.equal(1)
	end)

	it("should skip listeners that were disconnected during event evaluation", function()
		local signal = Signal.new()
		local countA = 0
		local countB = 0

		local disconnect
		signal:connect(function()
			countA += 1
			disconnect()
		end)

		disconnect = signal:connect(function()
			countB += 1
		end)

		signal:fire()

		expect(countA).to.equal(1)
		expect(countB).to.equal(0)
	end)

	it("should throw an error if the argument to `connect` is not a function", function()
		GlobalConfig.set({
			typeChecks = true,
		})

		local signal = Signal.new()

		expect(function()
			signal:connect("not a function")
		end).to.throw()
	end)

	it("should throw an error when disconnecting more than once", function()
		local signal = Signal.new()

		local disconnect = signal:connect(function() end)

		-- Okay to disconnect once
		expect(disconnect).never.to.throw()

		-- Throw an error if we disconnect twice
		expect(disconnect).to.throw()
	end)

	it("should throw an error when subscribing during dispatch", function()
		local mockStore = {
			_isDispatching = false,
		}
		local signal = Signal.new(mockStore)

		signal:connect(function()
			-- Subscribe while listeners are being fired
			signal:connect(function() end)
		end)

		mockStore._isDispatching = true
		expect(function()
			signal:fire()
		end).to.throw()
	end)

	it("should throw an error when unsubscribing during dispatch", function()
		local mockStore = {
			_isDispatching = false,
		}
		local signal = Signal.new(mockStore)

		local connection
		connection = signal:connect(function()
			connection.disconnect()
		end)

		mockStore._isDispatching = true
		expect(function()
			signal:fire()
		end).to.throw()
	end)
end
