SyntaxGameServer/RCCService2018/content/LuaPackages/RoduxImpl/Store.spec.lua

343 lines
6.9 KiB
Lua

return function()
local Store = require(script.Parent.Store)
describe("new", function()
it("should instantiate with a reducer", function()
local store = Store.new(function(state, action)
return "hello, world"
end)
expect(store).to.be.ok()
expect(store:getState()).to.equal("hello, world")
store:destruct()
end)
it("should instantiate with a reducer and an initial state", function()
local store = Store.new(function(state, action)
return state
end, "initial state")
expect(store).to.be.ok()
expect(store:getState()).to.equal("initial state")
store:destruct()
end)
it("should instantiate with a reducer, initial state, and middlewares", function()
local store = Store.new(function(state, action)
return state
end, "initial state", {})
expect(store).to.be.ok()
expect(store:getState()).to.equal("initial state")
store:destruct()
end)
itFIXME("should modify the dispatch method when middlewares are passed", function()
local middlewareInstantiateCount = 0
local middlewareInvokeCount = 0
local passedDispatch
local passedStore
local passedAction
local function reducer(state, action)
if action.type == "test" then
return "test state"
end
return state
end
local function testMiddleware(nextDispatch, store)
middlewareInstantiateCount = middlewareInstantiateCount + 1
passedDispatch = nextDispatch
passedStore = store
return function(action)
middlewareInvokeCount = middlewareInvokeCount + 1
passedAction = action
nextDispatch(action)
end
end
local store = Store.new(reducer, "initial state", { testMiddleware })
expect(middlewareInstantiateCount).to.equal(1)
expect(middlewareInvokeCount).to.equal(0)
expect(passedDispatch).to.be.a("function")
expect(passedStore).to.equal(store)
store:dispatch({
type = "test",
})
expect(middlewareInstantiateCount).to.equal(1)
expect(middlewareInvokeCount).to.equal(1)
expect(passedAction.type).to.equal("test")
store:flush()
expect(store:getState()).to.equal("test state")
store:destruct()
end)
itFIXME("should execute middleware left-to-right", function()
local events = {}
local function reducer(state)
return state
end
local function middlewareA(nextDispatch, store)
table.insert(events, "instantiate a")
return function(action)
table.insert(events, "execute a")
return nextDispatch(action)
end
end
local function middlewareB(nextDispatch, store)
table.insert(events, "instantiate b")
return function(action)
table.insert(events, "execute b")
return nextDispatch(action)
end
end
local store = Store.new(reducer, 5, { middlewareA, middlewareB })
expect(#events).to.equal(2)
expect(events[1]).to.equal("instantiate b")
expect(events[2]).to.equal("instantiate a")
store:dispatch({
type = "test",
})
expect(#events).to.equal(4)
expect(events[3]).to.equal("execute a")
expect(events[4]).to.equal("execute b")
end)
it("should send an initial action with a 'type' field", function()
local lastAction
local callCount = 0
local store = Store.new(function(state, action)
lastAction = action
callCount = callCount + 1
return state
end)
expect(callCount).to.equal(1)
expect(lastAction).to.be.a("table")
expect(lastAction.type).to.be.ok()
store:destruct()
end)
end)
describe("getState", function()
it("should get the current state", function()
local store = Store.new(function(state, action)
return "foo"
end)
local state = store:getState()
expect(state).to.equal("foo")
store:destruct()
end)
end)
describe("dispatch", function()
it("should be sent through the reducer", function()
local store = Store.new(function(state, action)
state = state or "foo"
if action.type == "act" then
return "bar"
end
return state
end)
expect(store).to.be.ok()
expect(store:getState()).to.equal("foo")
store:dispatch({
type = "act",
})
store:flush()
expect(store:getState()).to.equal("bar")
store:destruct()
end)
it("should trigger the changed event after a flush", function()
local store = Store.new(function(state, action)
state = state or 0
if action.type == "increment" then
return state + 1
end
return state
end)
local callCount = 0
store.changed:connect(function(state, oldState)
expect(oldState).to.equal(0)
expect(state).to.equal(1)
callCount = callCount + 1
end)
store:dispatch({
type = "increment",
})
store:flush()
expect(callCount).to.equal(1)
store:destruct()
end)
it("should handle actions dispatched within the changed event", function()
local store = Store.new(function(state, action)
state = state or {
value = 0,
}
if action.type == "increment" then
return {
value = state.value + 1,
}
elseif action.type == "decrement" then
return {
value = state.value - 1,
}
end
return state
end)
local changeCount = 0
store.changed:connect(function(state, oldState)
expect(state).never.to.equal(oldState)
if state.value > 0 then
store:dispatch({
type = "decrement",
})
end
changeCount = changeCount + 1
end)
store:dispatch({
type = "increment",
})
store:flush()
store:flush()
expect(changeCount).to.equal(2)
store:destruct()
end)
it("should prevent yielding from changed handler", function()
local preCount = 0
local postCount = 0
local store = Store.new(function(state, action)
state = state or 0
return state + 1
end)
store.changed:connect(function(state, oldState)
preCount = preCount + 1
wait()
postCount = postCount + 1
end)
store:dispatch({
type = "increment",
})
expect(function()
store:flush()
end).to.throw()
expect(preCount).to.equal(1)
expect(postCount).to.equal(0)
store:destruct()
end)
it("should throw if an action is dispatched without a type field", function()
local store = Store.new(function(state, action)
return state
end)
expect(function()
store:dispatch({})
end).to.throw()
store:destruct()
end)
it("should throw if the action is not a function or table", function()
local store = Store.new(function(state, action)
return state
end)
expect(function()
store:dispatch(1)
end).to.throw()
store:destruct()
end)
end)
describe("flush", function()
it("should not fire a changed event if there were no dispatches", function()
local store = Store.new(function()
end)
local count = 0
store.changed:connect(function()
count = count + 1
end)
store:flush()
expect(count).to.equal(0)
store:dispatch({
type = "increment",
})
store:flush()
expect(count).to.equal(1)
store:flush()
expect(count).to.equal(1)
store:destruct()
end)
end)
end