michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: const apiUtils = require("sdk/deprecated/api-utils"); michael@0: michael@0: exports.testValidateOptionsEmpty = function (assert) { michael@0: let val = apiUtils.validateOptions(null, {}); michael@0: michael@0: assert.deepEqual(val, {}); michael@0: michael@0: val = apiUtils.validateOptions(null, { foo: {} }); michael@0: assert.deepEqual(val, {}); michael@0: michael@0: val = apiUtils.validateOptions({}, {}); michael@0: assert.deepEqual(val, {}); michael@0: michael@0: val = apiUtils.validateOptions({}, { foo: {} }); michael@0: assert.deepEqual(val, {}); michael@0: }; michael@0: michael@0: exports.testValidateOptionsNonempty = function (assert) { michael@0: let val = apiUtils.validateOptions({ foo: 123 }, {}); michael@0: assert.deepEqual(val, {}); michael@0: michael@0: val = apiUtils.validateOptions({ foo: 123, bar: 456 }, michael@0: { foo: {}, bar: {}, baz: {} }); michael@0: michael@0: assert.deepEqual(val, { foo: 123, bar: 456 }); michael@0: }; michael@0: michael@0: exports.testValidateOptionsMap = function (assert) { michael@0: let val = apiUtils.validateOptions({ foo: 3, bar: 2 }, { michael@0: foo: { map: function (v) v * v }, michael@0: bar: { map: function (v) undefined } michael@0: }); michael@0: assert.deepEqual(val, { foo: 9, bar: undefined }); michael@0: }; michael@0: michael@0: exports.testValidateOptionsMapException = function (assert) { michael@0: let val = apiUtils.validateOptions({ foo: 3 }, { michael@0: foo: { map: function () { throw new Error(); }} michael@0: }); michael@0: assert.deepEqual(val, { foo: 3 }); michael@0: }; michael@0: michael@0: exports.testValidateOptionsOk = function (assert) { michael@0: let val = apiUtils.validateOptions({ foo: 3, bar: 2, baz: 1 }, { michael@0: foo: { ok: function (v) v }, michael@0: bar: { ok: function (v) v } michael@0: }); michael@0: assert.deepEqual(val, { foo: 3, bar: 2 }); michael@0: michael@0: assert.throws( michael@0: function () apiUtils.validateOptions({ foo: 2, bar: 2 }, { michael@0: bar: { ok: function (v) v > 2 } michael@0: }), michael@0: /^The option "bar" is invalid/, michael@0: "ok should raise exception on invalid option" michael@0: ); michael@0: michael@0: assert.throws( michael@0: function () apiUtils.validateOptions(null, { foo: { ok: function (v) v }}), michael@0: /^The option "foo" is invalid/, michael@0: "ok should raise exception on invalid option" michael@0: ); michael@0: }; michael@0: michael@0: exports.testValidateOptionsIs = function (assert) { michael@0: let opts = { michael@0: array: [], michael@0: boolean: true, michael@0: func: function () {}, michael@0: nul: null, michael@0: number: 1337, michael@0: object: {}, michael@0: string: "foo", michael@0: undef1: undefined michael@0: }; michael@0: let requirements = { michael@0: array: { is: ["array"] }, michael@0: boolean: { is: ["boolean"] }, michael@0: func: { is: ["function"] }, michael@0: nul: { is: ["null"] }, michael@0: number: { is: ["number"] }, michael@0: object: { is: ["object"] }, michael@0: string: { is: ["string"] }, michael@0: undef1: { is: ["undefined"] }, michael@0: undef2: { is: ["undefined"] } michael@0: }; michael@0: let val = apiUtils.validateOptions(opts, requirements); michael@0: assert.deepEqual(val, opts); michael@0: michael@0: assert.throws( michael@0: function () apiUtils.validateOptions(null, { michael@0: foo: { is: ["object", "number"] } michael@0: }), michael@0: /^The option "foo" must be one of the following types: object, number/, michael@0: "Invalid type should raise exception" michael@0: ); michael@0: }; michael@0: michael@0: exports.testValidateOptionsIsWithExportedValue = function (assert) { michael@0: let { string, number, boolean, object } = apiUtils; michael@0: michael@0: let opts = { michael@0: boolean: true, michael@0: number: 1337, michael@0: object: {}, michael@0: string: "foo" michael@0: }; michael@0: let requirements = { michael@0: string: { is: string }, michael@0: number: { is: number }, michael@0: boolean: { is: boolean }, michael@0: object: { is: object } michael@0: }; michael@0: let val = apiUtils.validateOptions(opts, requirements); michael@0: assert.deepEqual(val, opts); michael@0: michael@0: // Test the types are optional by default michael@0: val = apiUtils.validateOptions({foo: 'bar'}, requirements); michael@0: assert.deepEqual(val, {}); michael@0: }; michael@0: michael@0: exports.testValidateOptionsIsWithEither = function (assert) { michael@0: let { string, number, boolean, either } = apiUtils; michael@0: let text = { is: either(string, number) }; michael@0: michael@0: let requirements = { michael@0: text: text, michael@0: boolOrText: { is: either(text, boolean) } michael@0: }; michael@0: michael@0: let val = apiUtils.validateOptions({text: 12}, requirements); michael@0: assert.deepEqual(val, {text: 12}); michael@0: michael@0: val = apiUtils.validateOptions({text: "12"}, requirements); michael@0: assert.deepEqual(val, {text: "12"}); michael@0: michael@0: val = apiUtils.validateOptions({boolOrText: true}, requirements); michael@0: assert.deepEqual(val, {boolOrText: true}); michael@0: michael@0: val = apiUtils.validateOptions({boolOrText: "true"}, requirements); michael@0: assert.deepEqual(val, {boolOrText: "true"}); michael@0: michael@0: val = apiUtils.validateOptions({boolOrText: 1}, requirements); michael@0: assert.deepEqual(val, {boolOrText: 1}); michael@0: michael@0: assert.throws( michael@0: () => apiUtils.validateOptions({text: true}, requirements), michael@0: /^The option "text" must be one of the following types/, michael@0: "Invalid type should raise exception" michael@0: ); michael@0: michael@0: assert.throws( michael@0: () => apiUtils.validateOptions({boolOrText: []}, requirements), michael@0: /^The option "boolOrText" must be one of the following types/, michael@0: "Invalid type should raise exception" michael@0: ); michael@0: }; michael@0: michael@0: exports.testValidateOptionsWithRequiredAndOptional = function (assert) { michael@0: let { string, number, required, optional } = apiUtils; michael@0: michael@0: let opts = { michael@0: number: 1337, michael@0: string: "foo" michael@0: }; michael@0: michael@0: let requirements = { michael@0: string: required(string), michael@0: number: number michael@0: }; michael@0: michael@0: let val = apiUtils.validateOptions(opts, requirements); michael@0: assert.deepEqual(val, opts); michael@0: michael@0: val = apiUtils.validateOptions({string: "foo"}, requirements); michael@0: assert.deepEqual(val, {string: "foo"}); michael@0: michael@0: assert.throws( michael@0: () => apiUtils.validateOptions({number: 10}, requirements), michael@0: /^The option "string" must be one of the following types/, michael@0: "Invalid type should raise exception" michael@0: ); michael@0: michael@0: // Makes string optional michael@0: requirements.string = optional(requirements.string); michael@0: michael@0: val = apiUtils.validateOptions({number: 10}, requirements), michael@0: assert.deepEqual(val, {number: 10}); michael@0: michael@0: }; michael@0: michael@0: michael@0: michael@0: exports.testValidateOptionsWithExportedValue = function (assert) { michael@0: let { string, number, boolean, object } = apiUtils; michael@0: michael@0: let opts = { michael@0: boolean: true, michael@0: number: 1337, michael@0: object: {}, michael@0: string: "foo" michael@0: }; michael@0: let requirements = { michael@0: string: string, michael@0: number: number, michael@0: boolean: boolean, michael@0: object: object michael@0: }; michael@0: let val = apiUtils.validateOptions(opts, requirements); michael@0: assert.deepEqual(val, opts); michael@0: michael@0: // Test the types are optional by default michael@0: val = apiUtils.validateOptions({foo: 'bar'}, requirements); michael@0: assert.deepEqual(val, {}); michael@0: }; michael@0: michael@0: michael@0: exports.testValidateOptionsMapIsOk = function (assert) { michael@0: let [map, is, ok] = [false, false, false]; michael@0: let val = apiUtils.validateOptions({ foo: 1337 }, { michael@0: foo: { michael@0: map: function (v) v.toString(), michael@0: is: ["string"], michael@0: ok: function (v) v.length > 0 michael@0: } michael@0: }); michael@0: assert.deepEqual(val, { foo: "1337" }); michael@0: michael@0: let requirements = { michael@0: foo: { michael@0: is: ["object"], michael@0: ok: function () assert.fail("is should have caused us to throw by now") michael@0: } michael@0: }; michael@0: assert.throws( michael@0: function () apiUtils.validateOptions(null, requirements), michael@0: /^The option "foo" must be one of the following types: object/, michael@0: "is should be used before ok is called" michael@0: ); michael@0: }; michael@0: michael@0: exports.testValidateOptionsErrorMsg = function (assert) { michael@0: assert.throws( michael@0: function () apiUtils.validateOptions(null, { michael@0: foo: { ok: function (v) v, msg: "foo!" } michael@0: }), michael@0: /^foo!/, michael@0: "ok should raise exception with customized message" michael@0: ); michael@0: }; michael@0: michael@0: exports.testValidateMapWithMissingKey = function (assert) { michael@0: let val = apiUtils.validateOptions({ }, { michael@0: foo: { michael@0: map: function (v) v || "bar" michael@0: } michael@0: }); michael@0: assert.deepEqual(val, { foo: "bar" }); michael@0: michael@0: val = apiUtils.validateOptions({ }, { michael@0: foo: { michael@0: map: function (v) { throw "bar" } michael@0: } michael@0: }); michael@0: assert.deepEqual(val, { }); michael@0: }; michael@0: michael@0: exports.testValidateMapWithMissingKeyAndThrown = function (assert) { michael@0: let val = apiUtils.validateOptions({}, { michael@0: bar: { michael@0: map: function(v) { throw "bar" } michael@0: }, michael@0: baz: { michael@0: map: function(v) "foo" michael@0: } michael@0: }); michael@0: assert.deepEqual(val, { baz: "foo" }); michael@0: }; michael@0: michael@0: exports.testAddIterator = function testAddIterator (assert) { michael@0: let obj = {}; michael@0: let keys = ["foo", "bar", "baz"]; michael@0: let vals = [1, 2, 3]; michael@0: let keysVals = [["foo", 1], ["bar", 2], ["baz", 3]]; michael@0: apiUtils.addIterator( michael@0: obj, michael@0: function keysValsGen() { michael@0: for each (let keyVal in keysVals) michael@0: yield keyVal; michael@0: } michael@0: ); michael@0: michael@0: let keysItr = []; michael@0: for (let key in obj) michael@0: keysItr.push(key); michael@0: michael@0: assert.equal(keysItr.length, keys.length, michael@0: "the keys iterator returns the correct number of items"); michael@0: for (let i = 0; i < keys.length; i++) michael@0: assert.equal(keysItr[i], keys[i], "the key is correct"); michael@0: michael@0: let valsItr = []; michael@0: for each (let val in obj) michael@0: valsItr.push(val); michael@0: assert.equal(valsItr.length, vals.length, michael@0: "the vals iterator returns the correct number of items"); michael@0: for (let i = 0; i < vals.length; i++) michael@0: assert.equal(valsItr[i], vals[i], "the val is correct"); michael@0: michael@0: }; michael@0: michael@0: require('test').run(exports);