refactor: move test directories

This commit is contained in:
littensy 2026-02-19 22:31:40 -08:00
parent 0d1e85754a
commit 10521d05c2
35 changed files with 81 additions and 77 deletions

View file

@ -1,136 +0,0 @@
local Charm = require("../../Charm")
local client = require("../client")
local test = require("../../../../tests/test")
test.afterEach(function()
client.removeAllSignals()
end)
test("should hydrate atom", function()
local a = Charm.atom(1)
client.addSignals({ a = a })
client.patch({
{ type = "init", data = { a = 2 } },
})
assert(a() == 2, "should set a to the initial value")
end)
test("should merge patch", function()
local a = Charm.atom({ b = 1, c = 2 })
local previous = a()
client.addSignals({ a = a })
client.patch({
{ type = "init", data = { a = a() } },
})
assert(a() == previous, "should set a to the initial value")
client.patch({
{ type = "patch", data = { a = { b = 3 } } },
})
assert(a() ~= previous, "should apply patch")
assert(a().b == 3, "should set b to the new value")
assert(a().c == 2, "should not change c")
end)
test("should merge patch (reactive)", function()
local a = Charm.reactive({ b = 1, c = 2 })
local runs = 0
Charm.effect(function()
local _ = a.b + a.c
runs += 1
end)
client.addSignals({ a = a })
client.patch({
{ type = "init", data = { a = { b = a.b, c = a.c } } },
})
assert(runs == 1, "should not trigger effect for redundant init")
client.patch({
{ type = "patch", data = { a = { b = 3 } } },
})
assert(a.b == 3, "should set b to the new value")
assert(a.c == 2, "should not change c")
assert(runs == 2, "should trigger effect for patch")
end)
test("should fix sparse array patches", function()
local a = Charm.atom({ 1 })
client.addSignals({ a = a })
client.patch({
{ type = "init", data = { a = a() } },
})
-- This patch would be the result of a diff between { 1 } and { 1, 2 } that
-- was JSON-serialized and deserialized. The client should be able to catch
-- this and convert the string key back to a number.
client.patch({
{ type = "patch", data = { a = { ["2"] = 2 } } },
})
assert(a()["2" :: any] == nil, "should convert serialized arrays to use numbers")
assert(a()[2] == 2, "should convert serialized arrays to use numbers")
end)
test("should merge multiple patches", function()
local a = Charm.atom(1)
local calls = {}
client.addSignals({ a = a })
Charm.subscribe(a, function(value)
table.insert(calls, value)
end)
client.patch({
{ type = "init", data = { a = a() } },
})
client.patch({
{ type = "patch", data = { a = 2 } },
{ type = "patch", data = { a = 3 } },
})
assert(a() == 3, "should apply the last patch")
assert(table.concat(calls) == "23", `wrong order: {table.concat(calls)}`)
end)
test("should batch patches", function()
local a = Charm.atom(0)
local b = Charm.atom(0)
local states = {}
client.addSignals({ a = a, b = b })
Charm.subscribe(a, function()
states.b = b()
end)
Charm.subscribe(b, function()
states.a = a()
end)
client.patch({
{ type = "init", data = { a = a(), b = b() } },
})
client.patch({
{ type = "patch", data = { a = 1, b = 2 } },
})
assert(a() == 1, "should set a to the new value")
assert(b() == 2, "should set b to the new value")
assert(states.a == 1, "sub to a should run after b updates")
assert(states.b == 2, "sub to b should run after a updates")
end)
return {}

View file

@ -1,96 +0,0 @@
local Charm = require("../../Charm")
local client = require("../client")
local config = require("../config")
local server = require("../server")
local test = require("../../../../tests/test")
test.afterEach(function()
server.reset()
client.removeAllSignals()
config.preserveHistory = false
end)
test("should replicate server state to client", function()
local target = {}
local serverA = Charm.atom({ count = 0 })
local serverB = Charm.reactive({ count = 0 })
local clientA = Charm.atom({ count = -1 })
local clientB = Charm.reactive({ count = -1 })
client.addSignals({ a = clientA, b = clientB })
server.addSignalsToClient(target, { a = serverA, b = serverB })
server.connect(function(syncTarget, payloads)
if syncTarget == target then
client.patch(payloads)
end
end)
server.flush()
assert(clientA().count == 0, "Client atom A should be initialized to 0")
assert(clientB.count == 0, "Client reactive B should be initialized to 0")
serverA({ count = 1 })
serverB.count = 1
server.flush()
assert(clientA().count == 1, "Client atom A should be updated to 1")
assert(clientB.count == 1, "Client reactive B should be updated to 1")
local runs = -1
Charm.effect(function()
local _ = clientB.count
runs += 1
end)
serverA({ count = 2 })
server.flush()
assert(clientA().count == 2, "Client atom A should be updated to 2")
assert(runs == 0, "Client reactive B should not trigger update")
end)
test("should replicate historical server state to client", function()
local target = {}
local serverA = Charm.atom({ count = 0 })
local serverB = Charm.reactive({ count = 0 })
local clientA = Charm.atom({ count = -1 })
local clientB = Charm.reactive({ count = -1 })
config.preserveHistory = true
client.addSignals({ a = clientA, b = clientB })
server.addSignalsToClient(target, { a = serverA, b = serverB })
server.connect(function(syncTarget, payloads)
if syncTarget == target then
client.patch(payloads)
end
end)
local expectedA = { -1, 0, 1, 2, 3, 4 }
local expectedB = { -1, 0, 1, 2 }
Charm.effect(function()
local expected = table.remove(expectedA, 1)
assert(expected == clientA().count, `Client reactive A should be {expected}`)
end)
Charm.effect(function()
local expected = table.remove(expectedB, 1)
assert(expected == clientB.count, `Client reactive B should be {expected}`)
end)
server.flush()
serverA({ count = 1 })
serverA({ count = 2 })
serverB.count = 1
serverB.count = 2
server.flush()
assert(clientA().count == 2, "Client atom A should be updated to 2")
assert(clientB.count == 2, "Client reactive B should be updated to 2")
serverA({ count = 3 })
serverA({ count = 4 })
server.flush()
assert(clientA().count == 4, "Client atom A should be updated to 4")
end)
return {}

View file

@ -1,23 +0,0 @@
local test = require("../../../tests/test")
test.describe("client", function()
require("@self/client.test")
end)
test.describe("e2e", function()
require("@self/e2e.test")
end)
test.describe("utils", function()
require("@self/utils.test")
end)
test.describe("patch", function()
require("@self/patch.test")
end)
test.describe("server", function()
require("@self/server.test")
end)
return {}

View file

@ -1,133 +0,0 @@
local config = require("../config")
local patch = require("../patch")
local test = require("../../../../tests/test")
local function mockArraySerdes(object: {}): {}
if object[1] then
local copy = {}
for index = 1, #object do
copy[index] = object[index]
end
return copy
elseif table.maxn(object) ~= #object then
local copy = {}
for key, value in object do
copy[tostring(key)] = value
end
return copy
else
return object
end
end
test.afterEach(function()
config.fixArrays = true
config.validatePatches = true
end)
test("returns a patch", function()
local prevState = { foo = "bar", baz = "qux" }
local nextState = { foo = "bar", baz = "quux" }
local diffs = patch.diff(prevState, nextState)
assert(diffs ~= nil, "should return a patch")
assert(diffs.baz == "quux", "should return the changed value")
assert(diffs.foo == nil, "should omit unchanged values")
end)
test("applies a patch", function()
local prevState = { foo = "bar", baz = "qux" }
local diffs = { baz = "quux", qaz = "qux" }
local applied = patch.apply(prevState, diffs)
assert(applied ~= nil, "should return a new state")
assert(applied.baz == "quux", "should apply the changed value")
assert(applied.foo == "bar", "should keep the unchanged value")
assert(applied.qaz == "qux", "should add the new value")
end)
test("allows nested diffs", function()
local prevState = { foo = { bar = "baz" } }
local nextState = { foo = { bar = "qux" } }
local diffs = patch.diff(prevState, nextState)
local applied = patch.apply(prevState, diffs)
assert(applied.foo.bar == "qux", "should apply the nested patch")
end)
test("preserves array density when applying", function()
local prevState = { "a", "b", "c", "d" }
local nextState = { ["2"] = "B", ["4"] = "D" }
local applied = patch.apply(prevState, nextState)
assert(applied[1] == "a", "should keep a")
assert(applied[2] == "B", "should apply B")
assert(applied[3] == "c", "should keep c")
assert(applied[4] == "D", "should apply D")
assert(applied["2"] == nil, "should convert serialized arrays to use numbers")
assert(applied["4"] == nil, "should convert serialized arrays to use numbers")
end)
test("preserves array density after serdes", function()
-- This particular change results in a patch that cannot be serialized
-- without losing information. Charm resolves this issue internally.
local prevState = { "a", "b", "c", "d", "e" }
local nextState = { "A", "b", "c", "D" }
local diffs = mockArraySerdes(patch.diff(prevState, nextState))
local applied = patch.apply(prevState, diffs)
for index in prevState do
assert(applied[index] == nextState[index], `expected {applied[index]} to be {nextState[index]}`)
end
for index in applied do
assert(applied[index] == nextState[index], `expected {applied[index]} to be {nextState[index]}`)
end
end)
test("cannot preserve sparse arrays", function()
config.validatePatches = false
local prevState = {}
local nextState = { [2] = "foo" }
local diffs = mockArraySerdes(patch.diff(prevState, nextState))
local applied = patch.apply(prevState, diffs)
-- Not enough information is available to determine whether 'diffs'
-- should keep the string keys added during remote event serialization.
assert(applied["2"] ~= nil, "will fail to convert string keys to numbers")
assert(applied[2] == nil, "will fail to convert string keys to numbers")
end)
test("optionally fixes sparse arrays", function()
config.fixArrays = true
for index in patch.diff({ 1, 1, 1, 1, 1 }, { 2, 1, 1, 2 }) do
assert(type(index) == "string", `expected {type(index)} {index} to be string`)
end
config.fixArrays = false
for index in patch.diff({ 1, 1, 1, 1, 1 }, { 2, 1, 1, 2 }) do
assert(type(index) == "number", `expected {type(index)} {index} to be number`)
end
end)
test("patches mutable state", function()
local targetState: { [string]: string } = { foo = "bar", baz = "qux" }
patch.applyMutable(targetState, { baz = "quux", qaz = "qux" })
assert(targetState.baz == "quux", "should apply the changed value")
assert(targetState.foo == "bar", "should keep the unchanged value")
assert(targetState.qaz == "qux", "should add the new value")
end)
test("removes table from mutable state", function()
local targetState = { foo = { bar = "baz" } }
patch.applyMutable(targetState, { foo = { __none = "__none" } })
assert(targetState.foo == nil, "should remove the table")
end)
return {}

View file

@ -1,406 +0,0 @@
local Charm = require("../../Charm")
local config = require("../config")
local patch = require("../patch")
local server = require("../server")
local test = require("../../../../tests/test")
test.afterEach(function()
server.reset()
end)
test("should replicate state changes", function()
local client = {}
local a = Charm.atom(0)
local b = Charm.atom(0)
local c = Charm.atom(0)
local target, payloads
server.addSignalsToClient(client, { a = a, b = b, c = c })
server.connect(function(...)
target, payloads = ...
end)
server.flush()
assert(target == client, "Expected target to be the client")
assert(payloads[1].type == "init", "Expected first payload to be init")
assert(payloads[1].data.a == a(), "Expected init payload to contain atom 'a'")
assert(payloads[1].data.b == b(), "Expected init payload to contain atom 'b'")
assert(payloads[1].data.c == c(), "Expected init payload to contain atom 'c'")
a(1)
b(2)
server.flush()
assert(target == client, "Expected target to be the client")
assert(payloads[1].type == "patch", "Expected first payload to be patch")
assert(payloads[1].data.a == a(), "Expected patch payload to contain atom 'a'")
assert(payloads[1].data.b == b(), "Expected patch payload to contain atom 'b'")
end)
test("should replicate partial state patches", function()
local client = {}
local a = Charm.atom({ x = 0, y = 0 })
local b = Charm.atom(0 :: number?)
local target, payloads
server.addSignalsToClient(client, { a = a, b = b })
server.connect(function(...)
target, payloads = ...
end)
server.flush()
assert(target == client, "Expected target to be the client")
assert(payloads[1].type == "init", "Expected first payload to be init")
assert(payloads[1].data.a.x == a().x, "Expected init payload to contain atom 'a.x'")
assert(payloads[1].data.a.y == a().y, "Expected init payload to contain atom 'a.y'")
assert(payloads[1].data.b == b(), "Expected init payload to contain atom 'b'")
a({ x = 1, y = 0 })
b(nil)
server.flush()
assert(target == client, "Expected target to be the client")
assert(payloads[1].type == "patch", "Expected first payload to be patch")
assert(payloads[1].data.a.x == 1, "Expected patch payload to contain atom 'a.x'")
assert(payloads[1].data.a.y == nil, "Expected patch payload to not contain atom 'a.y'")
assert(patch.isNone(payloads[1].data.b), "Expected patch payload to contain atom 'b' as None")
end)
test("should replicate partial state patches (reactive)", function()
local client = {}
local a = Charm.reactive({ x = { y = 0 }, z = 0 :: number? })
local target, payloads
server.addSignalsToClient(client, { a = a })
server.connect(function(...)
target, payloads = ...
end)
server.flush()
assert(target == client, "Expected target to be the client")
assert(payloads[1].type == "init", "Expected first payload to be init")
assert(payloads[1].data.a.x ~= nil, "Expected init payload to contain value 'a.x'")
assert(payloads[1].data.a.x.y == a.x.y, "Expected init payload to contain value 'a.x.y'")
assert(payloads[1].data.a.z == a.z, "Expected init payload to contain value 'a.z'")
a.x.y = 1
a.z = nil
server.flush()
assert(target == client, "Expected target to be the client")
assert(payloads[1].type == "patch", "Expected first payload to be patch")
assert(payloads[1].data.a.x.y == 1, "Expected patch payload to contain value 'a.x'")
assert(patch.isNone(payloads[1].data.a.z), "Expected patch payload to contain value 'a.z' as None")
a.z = 1
server.flush()
assert(target == client, "Expected target to be the client")
assert(payloads[1].type == "patch", "Expected first payload to be patch")
assert(payloads[1].data.a.z == 1, "Expected patch payload to contain value 'a.z'")
assert(payloads[1].data.a.x == nil, "Expected patch payload to not contain value 'a.x'")
end)
test("should handle nested proxies", function()
local client = {}
local src = Charm.reactive({ (Charm.reactive({})) })
local payloads: {}? = nil
server.addSignalsToClient(client, { src = src })
server.connect(function(_, newPayloads)
payloads = newPayloads
end)
server.flush()
payloads = nil
server.flush()
assert(payloads == nil, "Expected no payloads to be sent for unchanged nested proxy")
end)
test("should init new clients", function()
local clientA = {}
local clientB = {}
local a = Charm.atom(0)
local payloadsA, payloadsB
server.addSignalsToClient(clientA, { a = a })
server.connect(function(target, payloads)
if target == clientA then
payloadsA = payloads
elseif target == clientB then
payloadsB = payloads
end
end)
a(1)
server.flush()
assert(payloadsA[1].type == "init", "Expected first payload to be init for client A")
assert(payloadsA[1].data.a == a(), "Expected init payload to contain atom 'a' for client A")
a(2)
server.addSignalsToClient(clientB, { a = a })
server.flush()
assert(payloadsA[1].type == "patch", "Expected first payload to be patch for client A")
assert(payloadsA[1].data.a == a(), "Expected patch payload to contain atom 'a' for client A")
assert(payloadsB[1].type == "init", "Expected first payload to be init for client B")
assert(payloadsB[1].data.a == a(), "Expected init payload to contain atom 'a' for client B")
end)
test("should init new atoms", function()
local client = {}
local a = Charm.atom(0)
local b = Charm.atom(0)
local target, payloads
server.addSignalsToClient(client, { a = a })
server.connect(function(...)
target, payloads = ...
end)
server.flush()
server.addSignalsToClient(client, { b = b })
a(1)
b(1)
server.flush()
assert(target == client, "Expected target to be the client")
assert(payloads[1].type == "init", "Expected first payload to be init")
assert(payloads[1].data.b == b(), "Expected init payload to contain atom 'b'")
assert(payloads[2].type == "patch", "Expected second payload to be patch")
assert(payloads[2].data.a == a(), "Expected patch payload to contain atom 'a'")
assert(payloads[2].data.b == nil, "Expected patch payload to not contain atom 'b'")
end)
test("should only replicate to synced clients", function()
local clientA = {}
local clientB = {}
local a = Charm.atom(0)
local b = Charm.atom(0)
local payloadsA, payloadsB
server.addSignalsToClient(clientA, { a = a })
server.addSignalsToClient(clientB, { b = b })
server.connect(function(target, payloads)
if target == clientA then
payloadsA = payloads
elseif target == clientB then
payloadsB = payloads
end
end)
server.flush()
assert(payloadsA[1].type == "init", "Expected first payload to be init for client A")
assert(payloadsA[1].data.a == a(), "Expected init payload to contain atom 'a' for client A")
assert(payloadsA[1].data.b == nil, "Expected init payload to not contain atom 'b' for client A")
assert(payloadsB[1].type == "init", "Expected first payload to be init for client B")
assert(payloadsB[1].data.b == b(), "Expected init payload to contain atom 'b' for client B")
assert(payloadsB[1].data.a == nil, "Expected init payload to not contain atom 'a' for client B")
payloadsA = {}
payloadsB = {}
a(1)
server.flush()
assert(payloadsA[1].type == "patch", "Expected first payload to be patch for client A")
assert(payloadsA[1].data.a == a(), "Expected patch payload to contain atom 'a' for client A")
assert(payloadsA[1].data.b == nil, "Expected patch payload to not contain atom 'b' for client A")
assert(#payloadsB == 0, "Expected no payloads for client B")
payloadsA = {}
payloadsB = {}
b(1)
server.flush()
assert(#payloadsA == 0, "Expected no payloads for client A")
assert(payloadsB[1].type == "patch", "Expected first payload to be patch for client B")
assert(payloadsB[1].data.b == b(), "Expected patch payload to contain atom 'b' for client B")
assert(payloadsB[1].data.a == nil, "Expected patch payload to not contain atom 'a' for client B")
end)
test("should serialize state", function()
local client = {}
local a = Charm.atom({ 1, 2, 3, 4, 5 })
local payloads
server.addSignalsToClient(client, { a = a })
server.connect(function(_, p)
payloads = p
end)
server.flush()
a({ 1, 2, 0, 4 })
server.flush()
assert(payloads[1].data.a["3"] == 0, "Expected index 3 to be serialized as string key")
assert(patch.isNone(payloads[1].data.a["5"]), "Expected index 5 to be serialized as string key")
end)
test("should not send unchanged state", function()
local client = {}
local a = Charm.atom(0)
local payloads
server.addSignalsToClient(client, { a = a })
server.connect(function(_, p)
payloads = p
end)
server.flush()
assert(payloads[1].type == "init", "Expected first payload to be init")
assert(payloads[1].data.a == 0, "Expected init payload to contain atom 'a'")
payloads = {}
a(0)
server.flush()
assert(#payloads == 0, "Expected no payloads to be sent for unchanged state")
end)
test.describe("historical", function()
test.beforeEach(function()
config.preserveHistory = true
end)
test.afterEach(function()
config.preserveHistory = false
end)
test("should replicate granular state changes", function()
local client = {}
local a = Charm.atom(0)
local b = Charm.atom(0)
local c = Charm.atom(0)
local target, payloads
server.addSignalsToClient(client, { a = a, b = b, c = c })
server.connect(function(...)
target, payloads = ...
end)
server.flush()
assert(target == client, "Expected target to be the client")
assert(payloads[1].type == "init", "Expected first payload to be init")
assert(payloads[1].data.a == 0, "Expected init payload to contain atom 'a'")
assert(payloads[1].data.b == 0, "Expected init payload to contain atom 'b'")
assert(payloads[1].data.c == 0, "Expected init payload to contain atom 'c'")
a(1)
a(2)
b(2)
server.flush()
assert(target == client, "Expected target to be the client")
assert(payloads[1].type == "patch", "Expected first payload to be patch")
assert(payloads[1].data.a == 1, "Expected patch payload to contain atom 'a'")
assert(payloads[2].data.a == 2, "Expected patch payload to contain atom 'a'")
assert(payloads[3].data.b == 2, "Expected patch payload to contain atom 'b'")
end)
test("should replicate granular state changes (reactive)", function()
local client = {}
local a = Charm.reactive({ value = 0 })
local b = Charm.reactive({ value = 0 })
local c = Charm.reactive({ value = 0 })
local target, payloads
server.addSignalsToClient(client, { a = a, b = b, c = c })
server.connect(function(...)
target, payloads = ...
end)
server.flush()
assert(target == client, "Expected target to be the client")
assert(payloads[1].type == "init", "Expected first payload to be init")
assert(payloads[1].data.a.value == 0, "Expected init payload to contain atom 'a'")
assert(payloads[1].data.b.value == 0, "Expected init payload to contain atom 'b'")
assert(payloads[1].data.c.value == 0, "Expected init payload to contain atom 'c'")
a.value = 1
a.value = 2
b.value = 2
server.flush()
assert(target == client, "Expected target to be the client")
assert(payloads[1].type == "patch", "Expected first payload to be patch")
assert(payloads[1].data.a.value == 1, "Expected patch payload to contain atom 'a'")
assert(payloads[2].data.a.value == 2, "Expected patch payload to contain atom 'a'")
assert(payloads[3].data.b.value == 2, "Expected patch payload to contain atom 'b'")
end)
test("should init new clients", function()
local clientA = {}
local clientB = {}
local a = Charm.atom(0)
local payloadsA, payloadsB
server.addSignalsToClient(clientA, { a = a })
server.connect(function(target, payloads)
if target == clientA then
payloadsA = payloads
elseif target == clientB then
payloadsB = payloads
end
end)
a(1)
a(2)
server.flush()
assert(payloadsA[1].type == "init", "Expected first payload to be init for client A")
assert(payloadsA[1].data.a == 1, "Expected init payload to contain atom 'a' for client A")
assert(payloadsA[2].type == "patch", "Expected second payload to be patch for client A")
assert(payloadsA[2].data.a == 2, "Expected second patch payload to contain atom 'a' with value 1 for client A")
server.addSignalsToClient(clientB, { a = a })
a(3)
a(4)
server.flush()
assert(payloadsA[1].type == "patch", "Expected first payload to be patch for client A")
assert(payloadsA[1].data.a == 3, "Expected patch payload to contain atom 'a' for client A")
assert(payloadsA[2].data.a == 4, "Expected patch payload to contain atom 'a' for client A")
assert(payloadsB[1].type == "init", "Expected first payload to be init for client B")
assert(payloadsB[1].data.a == 3, "Expected init payload to contain atom 'a' for client B")
assert(payloadsB[2].type == "patch", "Expected second payload to be patch for client B")
assert(payloadsB[2].data.a == 4, "Expected second patch payload to contain atom 'a' with value 3 for client B")
end)
test("should init new atoms", function()
local client = {}
local a = Charm.atom(0)
local b = Charm.atom(0)
local payloads
server.addSignalsToClient(client, { a = a })
server.connect(function(_, ...)
payloads = ...
end)
server.flush()
assert(payloads[1].type == "init", "Expected first payload to be init")
assert(payloads[1].data.a == 0, "Expected init payload to contain atom 'a'")
server.addSignalsToClient(client, { b = b })
a(1)
a(2)
b(1)
b(2)
server.flush()
assert(payloads[1].type == "patch", "Expected first payload to be patch")
assert(payloads[1].data.a == 1, "Expected patch payload to contain atom 'a'")
assert(payloads[2].data.a == 2, "Expected patch payload to contain atom 'a'")
assert(payloads[3].type == "init", "Expected third payload to be init")
assert(payloads[3].data.b == 1, "Expected init payload to contain atom 'b'")
assert(payloads[4].type == "patch", "Expected fourth payload to be patch")
assert(payloads[4].data.b == 2, "Expected patch payload to contain atom 'b'")
end)
test("should not send unchanged state", function()
local client = {}
local a = Charm.atom(0)
local payloads
server.addSignalsToClient(client, { a = a })
server.connect(function(_, p)
payloads = p
end)
server.flush()
assert(payloads[1].type == "init", "Expected first payload to be init")
assert(payloads[1].data.a == 0, "Expected init payload to contain atom 'a'")
payloads = {}
a(0)
server.flush()
assert(#payloads == 0, "Expected no payloads to be sent for unchanged state")
end)
end)
return {}

View file

@ -1,21 +0,0 @@
local Charm = require("../../Charm")
local test = require("../../../../tests/test")
local utils = require("../utils")
test("should flatten functions", function()
local input = {
a = Charm.atom(0),
b = { c = Charm.atom(0) },
d = { e = { f = utils.signalToAtom(Charm.signal(0)) } },
}
local result = utils.flatten(input)
assert(result.a == input.a, "should flatten the first level")
assert(result["b/c"] == input.b.c, "should flatten the second level")
assert(result["d/e/f"] == input.d.e.f, "should flatten the third level")
assert(result.b == nil, "should remove the original nested tables")
assert(result.d == nil, "should remove the original nested tables")
end)
return {}