return function()local d=require(script.Parent.createSignal)local o=require(script.Parent.createSpy)it("\115\104\111\117\108\100 \102\105\114\101 \115\117\098\115\099\114\105\098\101\114\115 \097\110\100 \100\105\115\099\111\110\110\101\099\116 \116\104\101\109",function()local H=d()local E=o()local r=H:subscribe(E.value);(expect(E.callCount)).to.equal(0)local D=1 local N={}local S="\104\101\108\108\111"H:fire(D,N,S);(expect(E.callCount)).to.equal(1)E:assertCalledWith(D,N,S)r()H:fire();(expect(E.callCount)).to.equal(1)end)it("\115\104\111\117\108\100 \104\097\110\100\108\101 \109\117\108\116\105\112\108\101 \115\117\098\115\099\114\105\098\101\114\115",function()local H=d()local E=o()local r=o()local D=H:subscribe(E.value)local N=H:subscribe(r.value);(expect(E.callCount)).to.equal(0);(expect(r.callCount)).to.equal(0)local S={}local h=67 H:fire(S,h);(expect(E.callCount)).to.equal(1)E:assertCalledWith(S,h);(expect(r.callCount)).to.equal(1)r:assertCalledWith(S,h)D()H:fire(h,S);(expect(E.callCount)).to.equal(1);(expect(r.callCount)).to.equal(2)r:assertCalledWith(h,S)N()end)it("\115\104\111\117\108\100 \115\116\111\112 \102\105\114\105\110\103 \097 \099\111\110\110\101\099\116\105\111\110 \105\102 \100\105\115\099\111\110\110\101\099\116\101\100 \109\105\100-\102\105\114\101",function()local H=d()local E local r local D=o(function()r()end)local N=o(function()E()end)E=H:subscribe(D.value)r=H:subscribe(N.value)H:fire();(expect(D.callCount+N.callCount)).to.equal(1)end)it("\115\104\111\117\108\100 \097\108\108\111\119 \097\100\100\105\110\103 \108\105\115\116\101\110\101\114 \105\110 \116\104\101 \109\105\100\100\108\101 \111\102 \102\105\114\105\110\103",function()local H=d()local E local r=o()local D=function(d,o)E=H:subscribe(r.value)end local N=H:subscribe(D);(expect(r.callCount)).to.equal(0)local S={}local h=67 H:fire(S,h);(expect(r.callCount)).to.equal(0)H:fire(h,S);(expect(r.callCount)).to.equal(1)r:assertCalledWith(h,S)E()N()H:fire(S);(expect(r.callCount)).to.equal(1)end)it("\115\104\111\117\108\100 \104\097\118\101 \111\110\101 \099\111\110\110\101\099\116\105\111\110 \105\110\115\116\097\110\099\101 \119\104\101\110 \097\100\100 \116\104\101 \115\097\109\101 \108\105\115\116\101\110\101\114 \109\117\108\116\105\112\108\101 \116\105\109\101\115",function()local H=d()local E=o()local r=H:subscribe(E.value);(expect(E.callCount)).to.equal(0)local D={}local N=67 H:fire(D,N);(expect(E.callCount)).to.equal(1)E:assertCalledWith(D,N)local S=H:subscribe(E.value)H:fire(N,D);(expect(E.callCount)).to.equal(2)E:assertCalledWith(N,D)S()H:fire(D);(expect(E.callCount)).to.equal(2)r()H:fire(D);(expect(E.callCount)).to.equal(2)end)end
return function()
	local createSignal = require(script.Parent.createSignal)

	local createSpy = require(script.Parent.createSpy)

	it("should fire subscribers and disconnect them", function()
		local signal = createSignal()

		local spy = createSpy()
		local disconnect = signal:subscribe(spy.value)

		expect(spy.callCount).to.equal(0)

		local a = 1
		local b = {}
		local c = "hello"
		signal:fire(a, b, c)

		expect(spy.callCount).to.equal(1)
		spy:assertCalledWith(a, b, c)

		disconnect()

		signal:fire()

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

	it("should handle multiple subscribers", function()
		local signal = createSignal()

		local spyA = createSpy()
		local spyB = createSpy()

		local disconnectA = signal:subscribe(spyA.value)
		local disconnectB = signal:subscribe(spyB.value)

		expect(spyA.callCount).to.equal(0)
		expect(spyB.callCount).to.equal(0)

		local a = {}
		local b = 67
		signal:fire(a, b)

		expect(spyA.callCount).to.equal(1)
		spyA:assertCalledWith(a, b)

		expect(spyB.callCount).to.equal(1)
		spyB:assertCalledWith(a, b)

		disconnectA()

		signal:fire(b, a)

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

		expect(spyB.callCount).to.equal(2)
		spyB:assertCalledWith(b, a)

		disconnectB()
	end)

	it("should stop firing a connection if disconnected mid-fire", function()
		local signal = createSignal()

		-- In this test, we'll connect two listeners that each try to disconnect
		-- the other. Because the order of listeners firing isn't defined, we
		-- have to be careful to handle either case.

		local disconnectA
		local disconnectB

		local spyA = createSpy(function()
			disconnectB()
		end)

		local spyB = createSpy(function()
			disconnectA()
		end)

		disconnectA = signal:subscribe(spyA.value)
		disconnectB = signal:subscribe(spyB.value)

		signal:fire()

		-- Exactly once listener should have been called.
		expect(spyA.callCount + spyB.callCount).to.equal(1)
	end)

	it("should allow adding listener in the middle of firing", function()
		local signal = createSignal()

		local disconnectA
		local spyA = createSpy()
		local listener = function(_a, _b)
			disconnectA = signal:subscribe(spyA.value)
		end

		local disconnectListener = signal:subscribe(listener)

		expect(spyA.callCount).to.equal(0)

		local a = {}
		local b = 67
		signal:fire(a, b)

		expect(spyA.callCount).to.equal(0)

		-- The new listener should be picked up in next fire.
		signal:fire(b, a)
		expect(spyA.callCount).to.equal(1)
		spyA:assertCalledWith(b, a)

		disconnectA()
		disconnectListener()

		signal:fire(a)

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

	it("should have one connection instance when add the same listener multiple times", function()
		local signal = createSignal()

		local spyA = createSpy()
		local disconnect1 = signal:subscribe(spyA.value)

		expect(spyA.callCount).to.equal(0)

		local a = {}
		local b = 67
		signal:fire(a, b)

		expect(spyA.callCount).to.equal(1)
		spyA:assertCalledWith(a, b)

		local disconnect2 = signal:subscribe(spyA.value)

		signal:fire(b, a)
		expect(spyA.callCount).to.equal(2)
		spyA:assertCalledWith(b, a)

		disconnect2()

		signal:fire(a)

		expect(spyA.callCount).to.equal(2)

		-- should have no effect.
		disconnect1()
		signal:fire(a)
		expect(spyA.callCount).to.equal(2)
	end)
end
