local V=import("\046\047\083\105\103\110\097\108")describe("\083\105\103\110\097\108",function()it("\115\104\111\117\108\100 \098\101 \105\110\115\116\097\110\116\105\097\098\108\101",function()local k=V.new()assert.is_userdata(k)assert.is_function(k.Connect)assert.is_function(k.Wait)assert.is_function(k.Fire)end)it("\115\104\111\117\108\100 \104\097\110\100\108\101 \099\111\110\110\101\099\116\105\111\110\115",function()local k=V.new()local K=spy.new(function() end)local B=k:Connect(K)assert.not_nil(B)k:Fire();(assert.spy(K)).was_called(1)k:Fire();(assert.spy(K)).was_called(2)B:Disconnect()k:Fire();(assert.spy(K)).was_called(2)end)it("\115\104\111\117\108\100 \112\114\101\115\101\114\118\101 \111\116\104\101\114 \099\111\110\110\101\099\116\105\111\110\115 \111\110 \100\105\115\099\111\110\110\101\099\116",function()local k=V.new()local K=spy.new(function() end)local B=spy.new(function() end)local d=k:Connect(K)k:Connect(B)k:Fire();(assert.spy(K)).was_called(1);(assert.spy(B)).was_called(1)d:Disconnect()k:Fire();(assert.spy(K)).was_called(1);(assert.spy(B)).was_called(2)end)it("\115\104\111\117\108\100 \115\101\116 \067\111\110\110\101\099\116\101\100",function()local k=V.new()local K=k:Connect(function() end)assert.is_true(K.Connected)K:Disconnect()assert.is_false(K.Connected)end)it("\115\104\111\117\108\100 \099\097\116\099\104 \121\105\101\108\100\115",function()local k=V.new()k:Connect(function()coroutine.yield()end)local K=coroutine.create(function()k:Fire()end)assert(coroutine.resume(K))assert.equal(coroutine.status(K),"\100\101\097\100")end)it("\115\104\111\117\108\100 \099\097\116\099\104 \101\114\114\111\114\115",function()local k=V.new()k:Connect(function()error("\084\104\101 \116\101\115\116 \102\097\105\108\101\100\046")end)k:Fire()end)it("\115\104\111\117\108\100 \101\114\114\111\114 \111\110 \087\097\105\116",function()local k=V.new()assert.has.errors(function()k:Wait()end)end)end)
local Signal = import("./Signal")

describe("Signal", function()
	it("should be instantiable", function()
		local signal = Signal.new()

		assert.is_userdata(signal)
		assert.is_function(signal.Connect)
		assert.is_function(signal.Wait)

		-- This isn't a standard function, but it's how users of Signal fire it!
		assert.is_function(signal.Fire)
	end)

	it("should handle connections", function()
		local signal = Signal.new()
		local spy = spy.new(function() end)

		local connection = signal:Connect(spy)

		assert.not_nil(connection)

		signal:Fire()
		assert.spy(spy).was_called(1)

		signal:Fire()
		assert.spy(spy).was_called(2)

		connection:Disconnect()
		signal:Fire()
		assert.spy(spy).was_called(2)
	end)

	it("should preserve other connections on disconnect", function()
		local signal = Signal.new()
		local spyA = spy.new(function() end)
		local spyB = spy.new(function() end)

		local connectionA = signal:Connect(spyA)
		signal:Connect(spyB)

		signal:Fire()

		assert.spy(spyA).was_called(1)
		assert.spy(spyB).was_called(1)

		connectionA:Disconnect()
		signal:Fire()

		assert.spy(spyA).was_called(1)
		assert.spy(spyB).was_called(2)
	end)

	it("should set Connected", function()
		local signal = Signal.new()

		local connection = signal:Connect(function() end)
		assert.is_true(connection.Connected)

		connection:Disconnect()
		assert.is_false(connection.Connected)
	end)

	it("should catch yields", function()
		local signal = Signal.new()

		signal:Connect(function()
			coroutine.yield()
		end)

		local co = coroutine.create(function()
			signal:Fire()
		end)

		assert(coroutine.resume(co))
		assert.equal(coroutine.status(co), "dead")
	end)

	it("should catch errors", function()
		local signal = Signal.new()

		signal:Connect(function()
			error("The test failed.")
		end)

		signal:Fire()
	end)

	-- Remove this when the event loop is made
	it("should error on Wait", function()
		local signal = Signal.new()

		assert.has.errors(function()
			signal:Wait()
		end)
	end)
end)