return function()local z=require(script.Parent)it("\115\104\111\117\108\100 \099\114\101\097\116\101 \097 \117\110\105\113\117\101 \110\101\119 \116\097\098\108\101",function()local U=z("\067\108\097\115\115");(expect(U)).to.be.a("\116\097\098\108\101");(expect(U)).to.never.equal(z("\070\111\111"))end)it("\115\104\111\117\108\100 \101\114\114\111\114 \119\104\101\110 \097 \110\097\109\101 \105\115\110\'\116 \115\117\112\112\108\105\101\100",function()(expect(function()z()end)).to.throw()end)it("\115\104\111\117\108\100 \105\110\115\116\097\110\116\105\097\116\101 \097 \110\101\119 \099\108\097\115\115 \119\105\116\104 \110\101\119\040\041",function()local U=z("\067\108\097\115\115")function U.foo(z)return"\102\111\111"end local Q=U.new();(expect(Q:foo())).to.equal("\102\111\111")end)it("\115\104\111\117\108\100 \111\112\116\105\111\110\097\108\108\121 \097\108\108\111\119 \112\097\114\097\109\101\116\101\114\115 \116\111 \098\101 \097\115\115\105\103\110\101\100 \105\110 \095\095\105\110\105\116\040\041",function()local U=z("\080\101\114\115\111\110")function U.__init(Q,z,U)Q.name=z Q.age=U end local Q=U.new("\074\111\104\110",18);(expect(Q.name)).to.equal("\074\111\104\110");(expect(Q.age)).to.equal(18)end)it("\115\104\111\117\108\100 \097\108\108\111\119 \115\116\097\116\105\099 \102\117\110\099\116\105\111\110\115",function()local U=z("\067\108\097\115\115")function U.staticFunction()return true end local Q=U.new();(expect(U.staticFunction())).to.equal(true);(expect(Q.staticFunction())).to.equal(true)end)it("\115\104\111\117\108\100 \104\097\118\101 \097 \067\108\097\115\115\078\097\109\101 \112\114\111\112\101\114\116\121 \115\101\116 \116\111 \116\104\101 \110\097\109\101 \111\102 \116\104\101 \099\108\097\115\115",function()local U=z("\067\108\097\115\115");(expect(U.ClassName)).to.equal("\067\108\097\115\115")end)it("\115\104\111\117\108\100 \114\101\117\115\101 \116\104\101 \109\101\116\097\116\097\098\108\101 \102\111\114 \101\097\099\104 \105\110\115\116\097\110\099\101 \111\102 \097 \099\108\097\115\115",function()local U=z("\067\108\097\115\115")local Q=U.new()local M=U.new();(expect(Q)).to.never.equal(M);(expect(getmetatable(Q))).to.equal(getmetatable(M))end)describe("\115\117\098\099\108\097\115\115\101\115",function()it("\115\104\111\117\108\100 \114\101\116\117\114\110 \116\104\101 \115\117\112\101\114\099\108\097\115\115 \102\111\114 \101\097\115\121 \114\101\102\101\114\101\110\099\105\110\103",function()local U=z("\066\097\115\101")local Q,M=z("\083\117\098",U);(expect(M)).to.equal(U);(expect(Q)).to.never.equal(U)end)it("\115\104\111\117\108\100 \097\108\108\111\119 \116\119\111 \099\108\097\115\115\101\115 \116\111 \100\101\102\105\110\101 \116\104\101 \112\114\111\112\101\114\116\105\101\115 \116\104\101\121 \116\097\107\101",function()local U=z("\066\097\115\101")function U.__init(U,z)U.foo=z end local Q,M=z("\083\117\098",U)function Q.__init(Q,z,U)M.__init(Q,z)Q.bar=U end local v=Q.new("\102\111\111","\098\097\114");(expect(v.foo)).to.equal("\102\111\111");(expect(v.bar)).to.equal("\098\097\114")end)it("\115\104\111\117\108\100 \108\111\111\107 \117\112 \109\101\116\104\111\100\115 \105\110 \116\104\101 \115\117\112\101\114\099\108\097\115\115",function()local U=z("\066\097\115\101")function U.foo(z)return"\102\111\111"end local Q=z("\083\117\098",U)local M=Q.new();(expect(M:foo())).to.equal("\102\111\111")end)it("\115\104\111\117\108\100 \117\115\101 \116\104\101 \095\095\105\110\105\116 \109\101\116\104\111\100 \111\102 \116\104\101 \115\117\112\101\114\099\108\097\115\115",function()local U=z("\066\097\115\101")function U.__init(U,z)U.foo=z end local Q=z("\083\117\098",U)local M=Q.new("\102\111\111");(expect(M.foo)).to.equal("\102\111\111")end)it("\115\104\111\117\108\100 \115\117\112\112\111\114\116 \109\117\108\116\105\112\108\101 \108\101\118\101\108\115 \111\102 \105\110\104\101\114\105\116\097\110\099\101",function()local U=z("\066\097\115\101")function U.__init(U,z)U.arg=z end local Q=z("\083\117\098\049",U)function Q.foo(z)return"\102\111\111"end local M=z("\083\117\098\050",Q)local v=M.new("\097\114\103");(expect(v.arg)).to.equal("\097\114\103");(expect(v:foo())).to.equal("\102\111\111")end)it("\115\104\111\117\108\100 \105\110\104\101\114\101\116 \109\101\116\097\109\101\116\104\111\100\115",function()local U=z("\066\097\115\101")function U.__tostring(z)return z.ClassName end function U.__call(z)return 1 end local Q=z("\083\117\098",U)local M=Q.new();(expect(tostring(M))).to.equal("\083\117\098");(expect(M())).to.equal(1)end)end)end
return function()
	local class = require(script.Parent)

	it("should create a unique new table", function()
		local Class = class("Class")

		expect(Class).to.be.a("table")
		expect(Class).to.never.equal(class("Foo"))
	end)

	it("should error when a name isn't supplied", function()
		expect(function()
			class()
		end).to.throw()
	end)

	it("should instantiate a new class with new()", function()
		local Class = class("Class")

		function Class:foo()
			return "foo"
		end

		local instance = Class.new()

		expect(instance:foo()).to.equal("foo")
	end)

	it("should optionally allow parameters to be assigned in __init()", function()
		local Person = class("Person")

		function Person:__init(name, age)
			self.name = name
			self.age = age
		end

		local person = Person.new("John", 18)

		expect(person.name).to.equal("John")
		expect(person.age).to.equal(18)
	end)

	it("should allow static functions", function()
		local Class = class("Class")

		function Class.staticFunction()
			return true
		end

		local instance = Class.new()

		expect(Class.staticFunction()).to.equal(true)
		expect(instance.staticFunction()).to.equal(true)
	end)

	it("should have a ClassName property set to the name of the class", function()
		local Class = class("Class")
		expect(Class.ClassName).to.equal("Class")
	end)

	it("should reuse the metatable for each instance of a class", function()
		local Class = class("Class")

		local inst1 = Class.new()
		local inst2 = Class.new()

		expect(inst1).to.never.equal(inst2)
		expect(getmetatable(inst1)).to.equal(getmetatable(inst2))
	end)

	describe("subclasses", function()
		it("should return the superclass for easy referencing", function()
			local Base = class("Base")
			local Sub, super = class("Sub", Base)

			expect(super).to.equal(Base)
			expect(Sub).to.never.equal(Base)
		end)

		it("should allow two classes to define the properties they take", function()
			local Base = class("Base")

			function Base:__init(foo)
				self.foo = foo
			end

			local Sub, super = class("Sub", Base)

			function Sub:__init(foo, bar)
				super.__init(self, foo)

				self.bar = bar
			end

			local instance = Sub.new("foo", "bar")

			expect(instance.foo).to.equal("foo")
			expect(instance.bar).to.equal("bar")
		end)

		it("should look up methods in the superclass", function()
			local Base = class("Base")

			function Base:foo()
				return "foo"
			end

			local Sub = class("Sub", Base)

			local instance = Sub.new()

			expect(instance:foo()).to.equal("foo")
		end)

		it("should use the __init method of the superclass", function()
			local Base = class("Base")

			function Base:__init(foo)
				self.foo = foo
			end

			local Sub = class("Sub", Base)

			local instance = Sub.new("foo")

			expect(instance.foo).to.equal("foo")
		end)

		-- Be aware that if you're getting down to 3+ levels of inheritance,
		-- your objects are going to be very complex and hard to reason about.
		-- Consider using composition instead.
		it("should support multiple levels of inheritance", function()
			local Base = class("Base")

			function Base:__init(arg)
				self.arg = arg
			end

			local Sub1 = class("Sub1", Base)

			function Sub1:foo()
				return "foo"
			end

			local Sub2 = class("Sub2", Sub1)

			local instance = Sub2.new("arg")

			expect(instance.arg).to.equal("arg")
			expect(instance:foo()).to.equal("foo")
		end)

		it("should inheret metamethods", function()
			local Base = class("Base")

			function Base:__tostring()
				return self.ClassName
			end

			function Base:__call()
				return 1
			end

			local Sub = class("Sub", Base)
			local instance = Sub.new()

			expect(tostring(instance)).to.equal("Sub")
			expect(instance()).to.equal(1)
		end)
	end)
end
