local B=require("\046\046\047\099\114\101\097\116\101\083\105\103\110\097\108\046\114\111\098\108\111\120\046\108\117\097\117")local L=require("\064\112\107\103\047\064\106\115\100\111\116\108\117\097\047\106\101\115\116-\103\108\111\098\097\108\115")local a=L.expect local e=L.jest local z=L.it z("\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 L,z=B()local A=e.fn()local W=L(function(...)A(...)end);(a(A)).never.toBeCalled()local S=1 local I={}local M="\104\101\108\108\111"z(S,I,M);(a(A)).toBeCalledTimes(1);(a(A)).toBeCalledWith(S,I,M)W()z();(a(A)).toBeCalledTimes(1)end)z("\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 L,z=B()local A=e.fn()local W=e.fn()local S=L(function(...)A(...)end)local I=L(function(...)W(...)end);(a(A)).never.toBeCalled();(a(W)).never.toBeCalled()local M={}local O=67 z(M,O);(a(A)).toBeCalledTimes(1);(a(A)).toBeCalledWith(M,O);(a(W)).toBeCalledTimes(1);(a(W)).toBeCalledWith(M,O)S()z(O,M);(a(A)).toBeCalledTimes(1);(a(W)).toBeCalledTimes(2);(a(W)).toBeCalledWith(O,M)I()end)z("\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 L,z=B()local A local W local S=e.fn(function()W()end)local I=e.fn(function()A()end)A=L(function(...)S(...)end)W=L(function(...)I(...)end)z();(a(#S.mock.calls+#I.mock.calls)).toBe(1)end)
local createSignal = require("../createSignal.roblox.luau")

local JestGlobals = require("@pkg/@jsdotlua/jest-globals")
local jestExpect = JestGlobals.expect
local jest = JestGlobals.jest

local it = JestGlobals.it

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

	local spy = jest.fn()
	local disconnect = subscribe(function(...)
		spy(...)
	end)

	jestExpect(spy).never.toBeCalled()

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

	jestExpect(spy).toBeCalledTimes(1)
	jestExpect(spy).toBeCalledWith(a, b, c)

	disconnect()

	fire()

	jestExpect(spy).toBeCalledTimes(1)
end)

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

	local spyA = jest.fn()
	local spyB = jest.fn()

	local disconnectA = subscribe(function(...)
		spyA(...)
	end)
	local disconnectB = subscribe(function(...)
		spyB(...)
	end)

	jestExpect(spyA).never.toBeCalled()
	jestExpect(spyB).never.toBeCalled()

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

	jestExpect(spyA).toBeCalledTimes(1)
	jestExpect(spyA).toBeCalledWith(a, b)

	jestExpect(spyB).toBeCalledTimes(1)
	jestExpect(spyB).toBeCalledWith(a, b)

	disconnectA()

	fire(b, a)

	jestExpect(spyA).toBeCalledTimes(1)

	jestExpect(spyB).toBeCalledTimes(2)
	jestExpect(spyB).toBeCalledWith(b, a)

	disconnectB()
end)

it("should stop firing a connection if disconnected mid-fire", function()
	local subscribe, fire = 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 = jest.fn(function()
		disconnectB()
	end)

	local spyB = jest.fn(function()
		disconnectA()
	end)

	disconnectA = subscribe(function(...)
		spyA(...)
	end)
	disconnectB = subscribe(function(...)
		spyB(...)
	end)

	fire()

	jestExpect(#spyA.mock.calls + #spyB.mock.calls).toBe(1)
end)
