local n=script.Parent.Parent local e=require(n.Parent.Fusion_v0_3_0)local B=(require(n.FusionUtil))["\048\046\051\046\048"]local G=e.scoped local R=e.Value local k=e.peek return function()describe("\101\110\115\117\114\101\073\115\083\116\097\116\101",function()it("\115\104\111\117\108\100 \114\101\116\117\114\110 \097 \115\116\097\116\101 \111\098\106\101\099\116 \105\102 \100\097\116\097 \105\115 \110\105\108",function()local n=G({})local e=B.ensureIsState(n,nil,10);(expect(k(e))).to.equal(10)end)it("\115\104\111\117\108\100 \114\101\116\117\114\110 \116\104\101 \115\097\109\101 \115\116\097\116\101 \111\098\106\101\099\116 \105\102 \100\097\116\097 \105\115 \097\108\114\101\097\100\121 \097 \115\116\097\116\101 \111\098\106\101\099\116",function()local n=G({})local e=R(n,5)local k=B.ensureIsState(n,e,10);(expect(k)).to.equal(e)end)it("\115\104\111\117\108\100 \119\114\097\112 \110\111\110-\115\116\097\116\101 \100\097\116\097 \105\110 \097 \115\116\097\116\101 \111\098\106\101\099\116",function()local n=G({})local e=B.ensureIsState(n,20,10);(expect(k(e))).to.equal(20)end)it("\115\104\111\117\108\100 \119\097\114\110 \097\110\100 \114\101\116\117\114\110 \100\101\102\097\117\108\116 \118\097\108\117\101 \105\102 \100\097\116\097 \116\121\112\101 \100\111\101\115 \110\111\116 \109\097\116\099\104",function()local n=G({})local e=B.ensureIsState(n,"\110\111\116 \097 \110\117\109\098\101\114",10,"\110\117\109\098\101\114");(expect(k(e))).to.equal(10)end)end)describe("\097\100\100\084\097\115\107",function()it("\115\104\111\117\108\100 \097\100\100 \097 \116\097\115\107 \116\111 \116\104\101 \115\099\111\112\101",function()local n=G({})local e=function() end B.addTask(n,e);(expect(#n)).to.equal(1)end)it("\115\104\111\117\108\100 \114\101\109\111\118\101 \101\120\105\115\116\105\110\103 \116\097\115\107 \119\105\116\104 \116\104\101 \115\097\109\101 \116\097\115\107\073\100",function()local n=G({})local e=function() end local R=function() end B.addTask(n,e,nil,"\084\097\115\107\073\068")B.addTask(n,R,nil,"\084\097\115\107\073\068");(expect(#n)).to.equal(1);(expect(n[1].Task)).to.equal(R)end)end)describe("\114\101\109\111\118\101\084\097\115\107",function()it("\115\104\111\117\108\100 \114\101\109\111\118\101 \116\104\101 \116\097\115\107 \102\114\111\109 \116\104\101 \115\099\111\112\101 \098\121 \116\097\115\107\073\100",function()local n=G({})local e=function() end B.addTask(n,e,nil,"\084\097\115\107\073\068")B.removeTask(n,"\084\097\115\107\073\068");(expect(#n)).to.equal(0)end)it("\115\104\111\117\108\100 \114\101\116\117\114\110 \116\104\101 \114\101\109\111\118\101\100 \116\097\115\107",function()local n=G({})local e=function() end B.addTask(n,e,nil,"\084\097\115\107\073\068")local R=B.removeTask(n,"\084\097\115\107\073\068");(expect(R)).to.equal(e)end)end)describe("\103\101\116\084\097\115\107",function()it("\115\104\111\117\108\100 \114\101\116\117\114\110 \116\104\101 \116\097\115\107 \119\105\116\104 \116\104\101 \115\112\101\099\105\102\105\101\100 \116\097\115\107\073\100",function()local n=G({})local e=function() end B.addTask(n,e,nil,"\084\097\115\107\073\068")local R=B.getTask(n,"\084\097\115\107\073\068");(expect(R)).to.equal(e)end)it("\115\104\111\117\108\100 \114\101\116\117\114\110 \110\105\108 \105\102 \116\104\101 \116\097\115\107\073\100 \100\111\101\115 \110\111\116 \101\120\105\115\116",function()local n=G({})local e=B.getTask(n,"\078\111\110\069\120\105\115\116\101\110\116\084\097\115\107\073\068");(expect(e)).to.equal(nil)end)end)describe("\115\121\110\099\086\097\108\117\101\115",function()it("\115\104\111\117\108\100 \115\121\110\099 \116\104\101 \118\097\108\117\101 \111\102 \111\110\101 \115\116\097\116\101 \116\111 \097\110\111\116\104\101\114",function()local n=G({})local e=R(n,123)local X=R(n,0)B.syncValues(n,e,X);(expect(k(X))).to.equal(123)e:set(456);(expect(k(X))).to.equal(456)end)end)describe("\102\111\114\109\097\116\065\115\115\101\116\073\100",function()it("\115\104\111\117\108\100 \102\111\114\109\097\116 \097 \115\116\114\105\110\103 \097\115\115\101\116 \105\100 \099\111\114\114\101\099\116\108\121",function()local n=G({})local e=B.formatAssetId(n,"\114\098\120\097\115\115\101\116\105\100\058\047\047\049\050\051\052\053\054\055\056\057\048");(expect(k(e))).to.equal("\114\098\120\097\115\115\101\116\105\100\058\047\047\049\050\051\052\053\054\055\056\057\048")end)it("\115\104\111\117\108\100 \102\111\114\109\097\116 \097 \110\117\109\101\114\105\099 \097\115\115\101\116 \105\100 \099\111\114\114\101\099\116\108\121",function()local n=G({})local e=B.formatAssetId(n,1234567890);(expect(k(e))).to.equal("\114\098\120\097\115\115\101\116\105\100\058\047\047\049\050\051\052\053\054\055\056\057\048")end)it("\115\104\111\117\108\100 \117\115\101 \116\104\101 \100\101\102\097\117\108\116 \118\097\108\117\101 \105\102 \116\104\101 \105\100 \105\115 \110\105\108",function()local n=G({})local e=B.formatAssetId(n,nil,1234567890);(expect(k(e))).to.equal("\114\098\120\097\115\115\101\116\105\100\058\047\047\049\050\051\052\053\054\055\056\057\048")end)end)describe("\114\097\116\105\111",function()it("\115\104\111\117\108\100 \099\111\109\112\117\116\101 \116\104\101 \114\097\116\105\111 \111\102 \116\119\111 \115\116\097\116\101\115",function()local n=G({})local e=R(n,100)local X=R(n,200)local O=B.ratio(n,e,X);(expect(k(O))).to.equal(.5)end)end)describe("\108\101\114\112\078\117\109\098\101\114",function()it("\115\104\111\117\108\100 \108\101\114\112 \098\101\116\119\101\101\110 \116\119\111 \110\117\109\098\101\114 \115\116\097\116\101\115",function()local n=G({})local e=R(n,10)local X=R(n,20)local O=R(n,.5)local M=B.lerpNumber(n,e,X,O);(expect(k(M))).to.equal(15)end)end)describe("\101\113",function()it("\115\104\111\117\108\100 \114\101\116\117\114\110 \116\114\117\101 \105\102 \116\119\111 \115\116\097\116\101\115 \097\114\101 \101\113\117\097\108",function()local n=G({})local e=R(n,10)local X=R(n,10)local O=B.eq(n,e,X);(expect(k(O))).to.equal(true)end)it("\115\104\111\117\108\100 \114\101\116\117\114\110 \102\097\108\115\101 \105\102 \116\119\111 \115\116\097\116\101\115 \097\114\101 \110\111\116 \101\113\117\097\108",function()local n=G({})local e=R(n,10)local X=R(n,20)local O=B.eq(n,e,X);(expect(k(O))).to.equal(false)end)end)describe("\111\098\115\101\114\118\101\083\116\097\116\101",function()it("\115\104\111\117\108\100 \111\098\115\101\114\118\101 \097 \115\116\097\116\101 \097\110\100 \099\097\108\108 \116\104\101 \099\097\108\108\098\097\099\107 \111\110 \099\104\097\110\103\101",function()local n=G({})local e=R(n,10)local k=false local X B.observeState(n,e,function(n)k=true X=n end);(expect(k)).to.equal(true);(expect(X)).to.equal(10)e:set(20);(expect(X)).to.equal(20)end)end)end
-- Logan Hunt (Raildex)
-- Aug 19, 2024

local RailUtil = script.Parent.Parent
local Fusion = require(RailUtil.Parent["Fusion_v0_3_0"])
local FusionUtil = require(RailUtil.FusionUtil)["0.3.0"]

local scoped = Fusion.scoped
local Value = Fusion.Value
local peek = Fusion.peek

return function()
    describe("ensureIsState", function()
        it("should return a state object if data is nil", function()
            local scope = scoped({})
            local result = FusionUtil.ensureIsState(scope, nil, 10)
            expect(peek(result)).to.equal(10)
        end)

        it("should return the same state object if data is already a state object", function()
            local scope = scoped({})
            local originalState = Value(scope, 5)
            local result = FusionUtil.ensureIsState(scope, originalState, 10)
            expect(result).to.equal(originalState)
        end)

        it("should wrap non-state data in a state object", function()
            local scope = scoped({})
            local result = FusionUtil.ensureIsState(scope, 20, 10)
            expect(peek(result)).to.equal(20)
        end)

        it("should warn and return default value if data type does not match", function()
            local scope = scoped({})
            local result = FusionUtil.ensureIsState(scope, "not a number", 10, "number")
            expect(peek(result)).to.equal(10)
        end)
    end)

    describe("addTask", function()
        it("should add a task to the scope", function()
            local scope = scoped({})
            local task = function() end
            FusionUtil.addTask(scope, task)
            expect(#scope).to.equal(1)
        end)

        it("should remove existing task with the same taskId", function()
            local scope = scoped({})
            local task1 = function() end
            local task2 = function() end
            FusionUtil.addTask(scope, task1, nil, "TaskID")
            FusionUtil.addTask(scope, task2, nil, "TaskID")
            expect(#scope).to.equal(1)
            expect(scope[1].Task).to.equal(task2)
        end)
    end)

    describe("removeTask", function()
        it("should remove the task from the scope by taskId", function()
            local scope = scoped({})
            local task = function() end
            FusionUtil.addTask(scope, task, nil, "TaskID")
            FusionUtil.removeTask(scope, "TaskID")
            expect(#scope).to.equal(0)
        end)

        it("should return the removed task", function()
            local scope = scoped({})
            local task = function() end
            FusionUtil.addTask(scope, task, nil, "TaskID")
            local removedTask = FusionUtil.removeTask(scope, "TaskID")
            expect(removedTask).to.equal(task)
        end)
    end)

    describe("getTask", function()
        it("should return the task with the specified taskId", function()
            local scope = scoped({})
            local task = function() end
            FusionUtil.addTask(scope, task, nil, "TaskID")
            local foundTask = FusionUtil.getTask(scope, "TaskID")
            expect(foundTask).to.equal(task)
        end)

        it("should return nil if the taskId does not exist", function()
            local scope = scoped({})
            local foundTask = FusionUtil.getTask(scope, "NonExistentTaskID")
            expect(foundTask).to.equal(nil)
        end)
    end)

    describe("syncValues", function()
        it("should sync the value of one state to another", function()
            local scope = scoped({})
            local stateA = Value(scope, 123)
            local stateB = Value(scope, 0)
            FusionUtil.syncValues(scope, stateA, stateB)
            expect(peek(stateB)).to.equal(123)
            stateA:set(456)
            expect(peek(stateB)).to.equal(456)
        end)
    end)

    describe("formatAssetId", function()
        it("should format a string asset id correctly", function()
            local scope = scoped({})
            local formatted = FusionUtil.formatAssetId(scope, "rbxassetid://1234567890")
            expect(peek(formatted)).to.equal("rbxassetid://1234567890")
        end)

        it("should format a numeric asset id correctly", function()
            local scope = scoped({})
            local formatted = FusionUtil.formatAssetId(scope, 1234567890)
            expect(peek(formatted)).to.equal("rbxassetid://1234567890")
        end)

        it("should use the default value if the id is nil", function()
            local scope = scoped({})
            local formatted = FusionUtil.formatAssetId(scope, nil, 1234567890)
            expect(peek(formatted)).to.equal("rbxassetid://1234567890")
        end)
    end)

    describe("ratio", function()
        it("should compute the ratio of two states", function()
            local scope = scoped({})
            local numerator = Value(scope, 100)
            local denominator = Value(scope, 200)
            local ratio = FusionUtil.ratio(scope, numerator, denominator)
            expect(peek(ratio)).to.equal(0.5)
        end)
    end)

    describe("lerpNumber", function()
        it("should lerp between two number states", function()
            local scope = scoped({})
            local n1 = Value(scope, 10)
            local n2 = Value(scope, 20)
            local alpha = Value(scope, 0.5)
            local result = FusionUtil.lerpNumber(scope, n1, n2, alpha)
            expect(peek(result)).to.equal(15)
        end)
    end)

    describe("eq", function()
        it("should return true if two states are equal", function()
            local scope = scoped({})
            local stateA = Value(scope, 10)
            local stateB = Value(scope, 10)
            local isEqual = FusionUtil.eq(scope, stateA, stateB)
            expect(peek(isEqual)).to.equal(true)
        end)

        it("should return false if two states are not equal", function()
            local scope = scoped({})
            local stateA = Value(scope, 10)
            local stateB = Value(scope, 20)
            local isEqual = FusionUtil.eq(scope, stateA, stateB)
            expect(peek(isEqual)).to.equal(false)
        end)
    end)

    describe("observeState", function()
        it("should observe a state and call the callback on change", function()
            local scope = scoped({})
            local state = Value(scope, 10)
            local callbackCalled = false
            local callbackValue
            FusionUtil.observeState(scope, state, function(value)
                callbackCalled = true
                callbackValue = value
            end)
            expect(callbackCalled).to.equal(true)
            expect(callbackValue).to.equal(10)

            state:set(20)
            expect(callbackValue).to.equal(20)
        end)
    end)
end
