251 lines
5.6 KiB
Lua
251 lines
5.6 KiB
Lua
return function()
|
|
local connect2 = require(script.Parent.connect2)
|
|
|
|
local StoreProvider = require(script.Parent.StoreProvider)
|
|
|
|
local Roact = require(script.Parent.Parent.Roact)
|
|
local Rodux = require(script.Parent.Parent.Rodux)
|
|
|
|
local function noop()
|
|
return nil
|
|
end
|
|
|
|
local function NoopComponent()
|
|
return nil
|
|
end
|
|
|
|
local function countReducer(state, action)
|
|
state = state or 0
|
|
|
|
if action.type == "increment" then
|
|
return state + 1
|
|
end
|
|
|
|
return state
|
|
end
|
|
|
|
local reducer = Rodux.combineReducers({
|
|
count = countReducer,
|
|
})
|
|
|
|
describe("Argument validation", function()
|
|
it("should accept no arguments", function()
|
|
connect2()
|
|
end)
|
|
|
|
it("should accept one function", function()
|
|
connect2(noop)
|
|
end)
|
|
|
|
it("should accept two functions", function()
|
|
connect2(noop, noop)
|
|
end)
|
|
|
|
it("should accept only the second function", function()
|
|
connect2(nil, function() end)
|
|
end)
|
|
|
|
it("should throw if not passed a component", function()
|
|
local selector = function(store)
|
|
return {}
|
|
end
|
|
|
|
expect(function()
|
|
connect2(selector)(nil)
|
|
end).to.throw()
|
|
end)
|
|
end)
|
|
|
|
it("should throw if not mounted under a StoreProvider", function()
|
|
local ConnectedSomeComponent = connect2()(NoopComponent)
|
|
|
|
expect(function()
|
|
Roact.mount(Roact.createElement(ConnectedSomeComponent))
|
|
end).to.throw()
|
|
end)
|
|
|
|
it("should accept a higher-order function mapStateToProps", function()
|
|
local function mapStateToProps()
|
|
return function(state)
|
|
return {
|
|
count = state.count,
|
|
}
|
|
end
|
|
end
|
|
|
|
local ConnectedSomeComponent = connect2(mapStateToProps)(NoopComponent)
|
|
|
|
local store = Rodux.Store.new(reducer)
|
|
local tree = Roact.createElement(StoreProvider, {
|
|
store = store,
|
|
}, {
|
|
someComponent = Roact.createElement(ConnectedSomeComponent),
|
|
})
|
|
|
|
local handle = Roact.mount(tree)
|
|
|
|
Roact.unmount(handle)
|
|
end)
|
|
|
|
it("should not accept a higher-order mapStateToProps that returns a non-table value", function()
|
|
local function mapStateToProps()
|
|
return function(state)
|
|
return "nope"
|
|
end
|
|
end
|
|
|
|
local ConnectedSomeComponent = connect2(mapStateToProps)(NoopComponent)
|
|
|
|
local store = Rodux.Store.new(reducer)
|
|
local tree = Roact.createElement(StoreProvider, {
|
|
store = store,
|
|
}, {
|
|
someComponent = Roact.createElement(ConnectedSomeComponent),
|
|
})
|
|
|
|
expect(function()
|
|
Roact.mount(tree)
|
|
end).to.throw()
|
|
end)
|
|
|
|
it("should not accept a mapStateToProps that returns a non-table value", function()
|
|
local function mapStateToProps()
|
|
return "nah"
|
|
end
|
|
|
|
local ConnectedSomeComponent = connect2(mapStateToProps)(NoopComponent)
|
|
|
|
local store = Rodux.Store.new(reducer)
|
|
local tree = Roact.createElement(StoreProvider, {
|
|
store = store,
|
|
}, {
|
|
someComponent = Roact.createElement(ConnectedSomeComponent),
|
|
})
|
|
|
|
expect(function()
|
|
Roact.mount(tree)
|
|
end).to.throw()
|
|
end)
|
|
|
|
it("should abort renders when mapStateToProps returns the same data", function()
|
|
local function mapStateToProps(state)
|
|
return {
|
|
count = state.count,
|
|
}
|
|
end
|
|
|
|
local renderCount = 0
|
|
local function SomeComponent(props)
|
|
renderCount = renderCount + 1
|
|
end
|
|
|
|
local ConnectedSomeComponent = connect2(mapStateToProps)(SomeComponent)
|
|
|
|
local store = Rodux.Store.new(reducer)
|
|
local tree = Roact.createElement(StoreProvider, {
|
|
store = store,
|
|
}, {
|
|
someComponent = Roact.createElement(ConnectedSomeComponent),
|
|
})
|
|
|
|
local handle = Roact.mount(tree)
|
|
|
|
expect(renderCount).to.equal(1)
|
|
|
|
store:dispatch({ type = "an unknown action" })
|
|
store:flush()
|
|
|
|
expect(renderCount).to.equal(1)
|
|
|
|
store:dispatch({ type = "increment" })
|
|
store:flush()
|
|
|
|
expect(renderCount).to.equal(2)
|
|
|
|
Roact.unmount(handle)
|
|
end)
|
|
|
|
it("should only call mapDispatchToProps once and never re-render if no mapStateToProps was passed", function()
|
|
local dispatchCount = 0
|
|
local mapDispatchToProps = function(dispatch)
|
|
dispatchCount = dispatchCount + 1
|
|
|
|
return {
|
|
increment = function()
|
|
return dispatch({ type = "increment" })
|
|
end,
|
|
}
|
|
end
|
|
|
|
local renderCount = 0
|
|
local function SomeComponent(props)
|
|
renderCount = renderCount + 1
|
|
end
|
|
|
|
local ConnectedSomeComponent = connect2(nil, mapDispatchToProps)(SomeComponent)
|
|
|
|
local store = Rodux.Store.new(reducer)
|
|
local tree = Roact.createElement(StoreProvider, {
|
|
store = store,
|
|
}, {
|
|
someComponent = Roact.createElement(ConnectedSomeComponent),
|
|
})
|
|
|
|
local handle = Roact.mount(tree)
|
|
|
|
expect(dispatchCount).to.equal(1)
|
|
expect(renderCount).to.equal(1)
|
|
|
|
store:dispatch({ type = "an unknown action" })
|
|
store:flush()
|
|
|
|
expect(dispatchCount).to.equal(1)
|
|
expect(renderCount).to.equal(1)
|
|
|
|
store:dispatch({ type = "increment" })
|
|
store:flush()
|
|
|
|
expect(dispatchCount).to.equal(1)
|
|
expect(renderCount).to.equal(1)
|
|
|
|
Roact.unmount(handle)
|
|
end)
|
|
|
|
it("should return result values from the dispatch passed to mapDispatchToProps", function()
|
|
local function reducer()
|
|
return 0
|
|
end
|
|
|
|
local function fiveThunk()
|
|
return 5
|
|
end
|
|
|
|
local dispatch
|
|
local function SomeComponent(props)
|
|
dispatch = props.dispatch
|
|
end
|
|
|
|
local function mapDispatchToProps(dispatch)
|
|
return {
|
|
dispatch = dispatch
|
|
}
|
|
end
|
|
|
|
local ConnectedSomeComponent = connect2(nil, mapDispatchToProps)(SomeComponent)
|
|
|
|
-- We'll use the thunk middleware, as it should always return its result
|
|
local store = Rodux.Store.new(reducer, nil, { Rodux.thunkMiddleware })
|
|
local tree = Roact.createElement(StoreProvider, {
|
|
store = store,
|
|
}, {
|
|
someComponent = Roact.createElement(ConnectedSomeComponent)
|
|
})
|
|
|
|
local handle = Roact.mount(tree)
|
|
|
|
expect(dispatch).to.be.a("function")
|
|
expect(dispatch(fiveThunk)).to.equal(5)
|
|
|
|
Roact.unmount(handle)
|
|
end)
|
|
end |