
describe "internal/Type", ->

	Type = require "./../Type"
	Null = require "./../../Null"
	Undefined = require "./../../Undefined"

	describe "of()", ->
		valueTypeMap = [
			{ value: null, 			type: Null },
			{ value: undefined, type: Undefined },
			{ value: 0, 				type: Number },
			{ value: "", 				type: String },
			{ value: true, 			type: Boolean },
			{ value: {}, 				type: Object },
			{ value: (->), 			type: Function },
			{ value: [], 				type: Array },
			{ value: /.*/,			type: RegExp },
		]
		for { value, type } in valueTypeMap
			it "returns #{type.name} for a certain value", ->
				expect(Type.of value).toBe type

	describe "validate()", ->

		it "doesnt overwrite keys with defined values that have expected types", ->
			target =
				foo: 1
			specs =
				foo: [Number, 0]
			Type.validate target, specs
			expect(target.foo).not.toBe specs.foo[1]

		it "throws an error if a key has a value with an invalid type", ->
			target =
				foo: true
			specs =
				foo: [Number, 0]
			try Type.validate target, specs
			catch error then expect(error?).toBe true

		it "overwrites keys with undefined values", ->
			target = {}
			specs =
				foo: [Boolean, true]
			Type.validate target, specs
			expect(target.foo).toBe specs.foo[1]

		it "validates recursively with nested objects", ->
			target = {}
			specs =
				foo:
					bar: [Boolean, true]
			Type.validate target, specs
			expect(target.foo.bar).toBe specs.foo.bar[1]

		it "supports custom validation", ->
			Range = (min, max) ->
				return (target, key, value) ->
					target[key] = Math.min max, Math.max(min, value)
			target =
				foo: -100
			specs =
				foo: Range 0, 10
			Type.validate target, specs
			expect(target.foo).toBe 0

