diff --git a/lib/spec/enum.js b/lib/spec/enum.js new file mode 100644 index 0000000..0b8ce77 --- /dev/null +++ b/lib/spec/enum.js @@ -0,0 +1,39 @@ +import Spec from './spec' +import { getName } from '../util' +import { invalid } from '../symbols' + +export class Enum extends Spec { + conform(value) { + if (this.options.values.indexOf(value) !== -1) { + return value + } + return invalid + } + + toString() { + return this.name || `Enum(${this.options.values.map(p => getName(p)).join(", ")})` + } + + explain(path, via, value) { + if (this.options.values.indexOf(value) === -1) { + return [{ + path, + via: [...via, getName(this)], + value, + predicate: function contains(x) { + return this.options.values.indexOf(x) !== -1 + } + }] + } + return null + } +} + +export default function oneOf(...values) { + if (values.length === 0) { + throw new Error(`Cannot use Enum spec without values`) + } + return new Enum({ + values + }) +} diff --git a/test/spec/enum.test.js b/test/spec/enum.test.js new file mode 100644 index 0000000..f387eb9 --- /dev/null +++ b/test/spec/enum.test.js @@ -0,0 +1,45 @@ +import { expect } from 'chai' +import oneOf from '../../lib/spec/enum' +import * as p from '../../lib/predicates' +import { invalid } from '../../lib/symbols' +import { explainData } from '../../lib/util' + +describe("enum", () => { + describe("conform", () => { + it("works with numbers", () => { + const e = oneOf(1, 2, 3) + expect(e.conform(1)).to.equal(1) + expect(e.conform(2)).to.equal(2) + expect(e.conform(3)).to.equal(3) + expect(e.conform("3")).to.equal(invalid) + expect(e.conform(4)).to.equal(invalid) + }) + + it("works with symbols", () => { + const s1 = Symbol() + const s2 = Symbol() + const e = oneOf(s1, s2) + + expect(e.conform(s1)).to.equal(s1) + expect(e.conform(s2)).to.equal(s2) + expect(e.conform(Symbol())).to.equal(invalid) + }) + }) + + describe("explain", () => { + it("outputs expected data", () => { + const e = oneOf(1, 2, 3) + const problems = explainData(e, 4) + + expect(problems).to.be.an("array").and.have.length(1) + expect(problems).to.have.deep.property("[0].via") + .that.deep.equals(["Enum(1, 2, 3)"]) + expect(problems).to.have.deep.property("[0].path") + .that.deep.equals([]) + expect(problems).to.have.deep.property("[0].predicate") + .that.is.a("function") + expect(problems).to.have.deep.property("[0].value") + .that.deep.equals(4) + }) + }) +})