return function()local f=require(script.Parent.spring)it("\115\104\111\117\108\100 \104\097\118\101 \097\108\108 \101\120\112\101\099\116\101\100 \065\080\073\115",function()(expect(f)).to.be.a("\102\117\110\099\116\105\111\110")local e=f(1,{dampingRatio=.1,frequency=10});(expect(e)).to.be.a("\116\097\098\108\101");(expect(e.step)).to.be.a("\102\117\110\099\116\105\111\110")e=f(1);(expect(e)).to.be.a("\116\097\098\108\101");(expect(e.step)).to.be.a("\102\117\110\099\116\105\111\110")end)it("\115\104\111\117\108\100 \104\097\110\100\108\101 \098\101\105\110\103 \115\116\105\108\108 \099\111\114\114\101\099\116\108\121",function()local e=f(1,{dampingRatio=.1,frequency=10})local t=e:step({value=1;velocity=0;complete=false},1);(expect(t.value)).to.equal(1);(expect(t.velocity)).to.equal(0);(expect(t.complete)).to.equal(true)end)it("\115\104\111\117\108\100 \114\101\116\117\114\110 \110\111\116 \099\111\109\112\108\101\116\101 \119\104\101\110 \105\110 \109\111\116\105\111\110",function()local e=f(100,{dampingRatio=.1;frequency=10})local t={value=1,velocity=0,complete=false}t=e:step(t,.001);(expect(t.value<100)).to.equal(true);(expect(t.velocity>0)).to.equal(true);(expect(t.complete)).to.equal(false)end)describe("\115\104\111\117\108\100 \101\118\101\110\116\097\117\108\108\121 \099\111\109\112\108\101\116\101 \119\104\101\110",function()it("\105\115 \099\114\105\116\105\099\097\108\108\121 \100\097\109\112\101\100",function()local e=f(3,{dampingRatio=1,frequency=.5})local t={value=1;velocity=0;complete=false}while not t.complete do t=e:step(t,.5)end;(expect(t.complete)).to.equal(true);(expect(t.value)).to.equal(3);(expect(t.velocity)).to.equal(0)end)it("\105\115 \111\118\101\114 \100\097\109\112\101\100",function()local e=f(3,{dampingRatio=10,frequency=.5})local t={value=1,velocity=0;complete=false}while not t.complete do t=e:step(t,.5)end;(expect(t.complete)).to.equal(true);(expect(t.value)).to.equal(3);(expect(t.velocity)).to.equal(0)end)it("\105\115 \117\110\100\101\114 \100\097\109\112\101\100",function()local e=f(3,{dampingRatio=.1;frequency=.5})local t={value=1,velocity=0,complete=false}while not t.complete do t=e:step(t,.5)end;(expect(t.complete)).to.equal(true);(expect(t.value)).to.equal(3);(expect(t.velocity)).to.equal(0)end)end)it("\115\104\111\117\108\100 \114\101\109\097\105\110 \099\111\109\112\108\101\116\101 \119\104\101\110 \099\111\109\112\108\101\116\101\100",function()local e=f(3,{dampingRatio=1,frequency=.5})local t={value=1,velocity=0;complete=false}while not t.complete do t=e:step(t,.5)end t=e:step(t,.5);(expect(t.complete)).to.equal(true);(expect(t.value)).to.equal(3);(expect(t.velocity)).to.equal(0)end)end
return function()
	local spring = require(script.Parent.spring)

	it("should have all expected APIs", function()
		expect(spring).to.be.a("function")

		local s = spring(1, {
			dampingRatio = 0.1,
			frequency = 10,
		})

		expect(s).to.be.a("table")
		expect(s.step).to.be.a("function")

		-- handle when spring lacks option table
		s = spring(1)

		expect(s).to.be.a("table")
		expect(s.step).to.be.a("function")
	end)

	it("should handle being still correctly", function()
		local s = spring(1, {
			dampingRatio = 0.1,
			frequency = 10,
		})

		local state = s:step({
			value = 1,
			velocity = 0,
			complete = false,
		}, 1)

		expect(state.value).to.equal(1)
		expect(state.velocity).to.equal(0)
		expect(state.complete).to.equal(true)
	end)

	it("should return not complete when in motion", function()
		local goal = spring(100, {
			dampingRatio = 0.1,
			frequency = 10,
		})

		local state = {
			value = 1,
			velocity = 0,
			complete = false,
		}

		state = goal:step(state, 1e-3)

		expect(state.value < 100).to.equal(true)
		expect(state.velocity > 0).to.equal(true)
		expect(state.complete).to.equal(false)
	end)

	describe("should eventaully complete when", function()
		it("is critically damped", function()
			local s = spring(3, {
				dampingRatio = 1,
				frequency = 0.5,
			})

			local state = {
				value = 1,
				velocity = 0,
				complete = false,
			}

			while not state.complete do
				state = s:step(state, 0.5)
			end

			expect(state.complete).to.equal(true)
			expect(state.value).to.equal(3)
			expect(state.velocity).to.equal(0)
		end)

		it("is over damped", function()
			local s = spring(3, {
				dampingRatio = 10,
				frequency = 0.5,
			})

			local state = {
				value = 1,
				velocity = 0,
				complete = false,
			}

			while not state.complete do
				state = s:step(state, 0.5)
			end

			expect(state.complete).to.equal(true)
			expect(state.value).to.equal(3)
			expect(state.velocity).to.equal(0)
		end)

		it("is under damped", function()
			local s = spring(3, {
				dampingRatio = 0.1,
				frequency = 0.5,
			})

			local state = {
				value = 1,
				velocity = 0,
				complete = false,
			}

			while not state.complete do
				state = s:step(state, 0.5)
			end

			expect(state.complete).to.equal(true)
			expect(state.value).to.equal(3)
			expect(state.velocity).to.equal(0)
		end)
	end)

	it("should remain complete when completed", function()
		local s = spring(3, {
			dampingRatio = 1,
			frequency = 0.5,
		})

		local state = {
			value = 1,
			velocity = 0,
			complete = false,
		}

		while not state.complete do
			state = s:step(state, 0.5)
		end
		state = s:step(state, 0.5)

		expect(state.complete).to.equal(true)
		expect(state.value).to.equal(3)
		expect(state.velocity).to.equal(0)
	end)
end