return function()
local assertDeepEqual = require(script.Parent.assertDeepEqual)
local createSpy = require(script.Parent.createSpy)
local Logging = require(script.Parent.Logging)
local SingleEventManager = require(script.Parent.SingleEventManager)
describe("new", function()
it("should create a SingleEventManager", function()
local manager = SingleEventManager.new()
expect(manager).to.be.ok()
end)
end)
describe("connectEvent", function()
it("should connect to events", function()
local instance = Instance.new("BindableEvent")
local manager = SingleEventManager.new(instance)
local eventSpy = createSpy()
manager:connectEvent("Event", eventSpy.value)
manager:resume()
instance:Fire("foo")
expect(eventSpy.callCount).to.equal(1)
eventSpy:assertCalledWith(instance, "foo")
instance:Fire("bar")
expect(eventSpy.callCount).to.equal(2)
eventSpy:assertCalledWith(instance, "bar")
manager:connectEvent("Event", nil)
instance:Fire("baz")
expect(eventSpy.callCount).to.equal(2)
end)
it("should drop events until resumed initially", function()
local instance = Instance.new("BindableEvent")
local manager = SingleEventManager.new(instance)
local eventSpy = createSpy()
manager:connectEvent("Event", eventSpy.value)
instance:Fire("foo")
expect(eventSpy.callCount).to.equal(0)
manager:resume()
instance:Fire("bar")
expect(eventSpy.callCount).to.equal(1)
eventSpy:assertCalledWith(instance, "bar")
end)
it("should invoke suspended events when resumed", function()
local instance = Instance.new("BindableEvent")
local manager = SingleEventManager.new(instance)
local eventSpy = createSpy()
manager:connectEvent("Event", eventSpy.value)
manager:resume()
instance:Fire("foo")
expect(eventSpy.callCount).to.equal(1)
eventSpy:assertCalledWith(instance, "foo")
manager:suspend()
instance:Fire("bar")
expect(eventSpy.callCount).to.equal(1)
manager:resume()
expect(eventSpy.callCount).to.equal(2)
eventSpy:assertCalledWith(instance, "bar")
end)
it("should invoke events triggered during resumption in the correct order", function()
local instance = Instance.new("BindableEvent")
local manager = SingleEventManager.new(instance)
local recordedValues = {}
local eventSpy = createSpy(function(_, value)
table.insert(recordedValues, value)
if value == 2 then
instance:Fire(3)
elseif value == 3 then
instance:Fire(4)
end
end)
manager:connectEvent("Event", eventSpy.value)
manager:suspend()
instance:Fire(1)
instance:Fire(2)
manager:resume()
expect(eventSpy.callCount).to.equal(4)
assertDeepEqual(recordedValues, { 1, 2, 3, 4 })
end)
it("should not invoke events fired during suspension but disconnected before resumption", function()
local instance = Instance.new("BindableEvent")
local manager = SingleEventManager.new(instance)
local eventSpy = createSpy()
manager:connectEvent("Event", eventSpy.value)
manager:suspend()
instance:Fire(1)
manager:connectEvent("Event", nil)
manager:resume()
expect(eventSpy.callCount).to.equal(0)
end)
it("should not yield events through the SingleEventManager when resuming", function()
local instance = Instance.new("BindableEvent")
local manager = SingleEventManager.new(instance)
manager:connectEvent("Event", function()
coroutine.yield()
end)
manager:resume()
local co = coroutine.create(function()
instance:Fire(5)
end)
assert(coroutine.resume(co))
expect(coroutine.status(co)).to.equal("dead")
manager:suspend()
instance:Fire(5)
co = coroutine.create(function()
manager:resume()
end)
assert(coroutine.resume(co))
expect(coroutine.status(co)).to.equal("dead")
end)
it("should not throw errors through SingleEventManager when resuming", function()
local errorText = "Error from SingleEventManager test"
local instance = Instance.new("BindableEvent")
local manager = SingleEventManager.new(instance)
manager:connectEvent("Event", function()
error(errorText)
end)
manager:resume()
manager:suspend()
instance:Fire(5)
local logInfo = Logging.capture(function()
manager:resume()
end)
expect(#logInfo.errors).to.equal(0)
expect(#logInfo.warnings).to.equal(1)
expect(#logInfo.infos).to.equal(0)
expect(logInfo.warnings[1]:find(errorText)).to.be.ok()
end)
it("should not overflow with events if manager:resume() is invoked when resuming a suspended event", function()
local instance = Instance.new("BindableEvent")
local manager = SingleEventManager.new(instance)
local eventSpy = createSpy(function(_, value)
if value == 1 then
manager:suspend()
instance:Fire(2)
manager:resume()
end
end)
manager:connectEvent("Event", eventSpy.value)
manager:suspend()
instance:Fire(1)
manager:resume()
expect(eventSpy.callCount).to.equal(2)
end)
end)
describe("connectPropertyChange", function()
it("should connect to property changes", function()
local instance = Instance.new("Folder")
local manager = SingleEventManager.new(instance)
local eventSpy = createSpy()
manager:connectPropertyChange("Name", eventSpy.value)
manager:resume()
instance.Name = "foo"
expect(eventSpy.callCount).to.equal(1)
eventSpy:assertCalledWith(instance)
instance.Name = "bar"
expect(eventSpy.callCount).to.equal(2)
eventSpy:assertCalledWith(instance)
manager:connectPropertyChange("Name")
instance.Name = "baz"
expect(eventSpy.callCount).to.equal(2)
end)
it("should throw an error if the property is invalid", function()
local instance = Instance.new("Folder")
local manager = SingleEventManager.new(instance)
expect(function()
manager:connectPropertyChange("foo", function() end)
end).to.throw()
end)
end)
end