charm/packages/charm/test/mapped.test.luau

128 lines
3.5 KiB
Text

local Charm = require("../src")
local test = require("../../../tests/test")
local signal = Charm.signal
local mapped = Charm.mapped
test("should map state", function()
local src, setSrc = signal({ 1, 2, 3 })
local map = mapped(src, function(value: number)
return value + 1
end)
assert(table.concat(map()) == "234", table.concat(map()))
setSrc({ 4, 5, 6 })
assert(table.concat(map()) == "567", table.concat(map()))
end)
test("should not map unchanged values", function()
local calls = 0
local src, setSrc = signal({ 1, 2, 3 })
local map = mapped(src, function(value: number)
calls += 1
return value + 1
end)
assert(table.concat(map()) == "234", table.concat(map()))
assert(calls == 3, "should map 3 values")
setSrc({ 1, 3, 3 })
assert(table.concat(map()) == "244", table.concat(map()))
assert(calls == 4, "should map 1 change")
setSrc({})
assert(#map() == 0, "should be empty")
assert(calls == 4, "should not map for removed values")
end)
test("should not update if no values change", function()
local calls = 0
local src, setSrc = signal({ 1, 2, 3 })
local map = mapped(src, function(value: number)
calls += 1
return value + 1
end)
local prev = map()
assert(calls == 3, "should map 3 values")
assert(table.concat(map()) == "234", table.concat(map()))
setSrc({ 4, 5, 6, 7 })
setSrc({ 1, 2, 3 })
map()
assert(calls == 3, "should not map unchanged values")
assert(table.concat(map()) == "234", table.concat(map()))
assert(prev == map(), "should not create new table")
end)
test("should filter values", function()
local calls = 0
local src, setSrc = signal({ a = 1, b = 2, c = 3 })
local map = mapped(src, function(value: number)
calls += 1
return if value < 0 then nil else value
end)
local state = map()
assert(calls == 3, "should map 3 values")
assert(state.a and state.b and state.c, "should map all values")
calls = 0
setSrc({ a = -1, b = 2, c = 3, d = 4 })
state = map()
assert(calls == 2, "should map 2 values")
assert(state.a == nil, "should remove a")
assert(state.b and state.c, "should keep b and c")
assert(state.d == 4, "should add d")
end)
test("should map keys", function()
local calls = 0
local src, setSrc = signal({ a = 1, b = 2, c = 3 })
local map = mapped(src, function(value: number, key: string)
calls += 1
return if value < 0 then nil else value, string.upper(key)
end)
local state = map()
assert(calls == 3, "should map 3 values")
assert(not (state.a and state.b and state.c), "should discard old keys")
assert(state.A == 1, "should map a")
assert(state.B == 2, "should map b")
assert(state.C == 3, "should map c")
calls = 0
setSrc({ a = -1, b = 2, c = 3, d = 4 })
state = map()
assert(calls == 2, "should map 2 values")
assert(state.A == nil and state.a == nil, "should remove a")
assert(state.B and state.C, "should keep b and c")
assert(state.D == 4, "should add d")
end)
test("should remove old key if mapper returns a new key", function()
local src, setSrc = signal({ 1 })
local map = mapped(src, function(value: number, index: number)
return true, `{index}={value}`
end)
local state = map()
assert(state["1=1"], "should have mapped first element to key 1=1")
setSrc({ 2 })
state = map()
assert(state["1=1"] == nil, "should have removed old key 1=1")
assert(state["1=2"], "should have remapped element to key 1=2")
setSrc({ 3, 1 })
state = map()
assert(state["1=2"] == nil, "should have removed old key 1=2")
assert(state["1=3"], "should have remapped element to key 1=3")
assert(state["2=1"], "should have mapped second element to key 2=1")
end)
return {}