UNPKG

quixote

Version:

CSS unit and integration testing

124 lines (102 loc) 3.7 kB
// Copyright (c) 2013-2014 Titanium I.T. LLC. All rights reserved. See LICENSE.TXT for details. "use strict"; // Runtime assertions for production code. (Contrast to assert.js, which is for test code.) var shim = require("./shim.js"); var oop = require("./oop.js"); exports.that = function(variable, message) { if (message === undefined) message = "Expected condition to be true"; if (variable === false) throw new EnsureException(exports.that, message); if (variable !== true) throw new EnsureException(exports.that, "Expected condition to be true or false"); }; exports.unreachable = function(message) { if (!message) message = "Unreachable code executed"; throw new EnsureException(exports.unreachable, message); }; exports.signature = function(args, signature) { signature = signature || []; var expectedArgCount = signature.length; var actualArgCount = args.length; if (actualArgCount > expectedArgCount) { throw new EnsureException( exports.signature, "Function called with too many arguments: expected " + expectedArgCount + " but got " + actualArgCount ); } var arg, types, name; for (var i = 0; i < signature.length; i++) { arg = args[i]; types = signature[i]; name = "Argument #" + (i + 1); if (!shim.Array.isArray(types)) types = [ types ]; if (!argMatchesAnyPossibleType(arg, types)) { var message = name + " expected " + explainPossibleTypes(types) + ", but was " + explainArg(arg); throw new EnsureException(exports.signature, message); } } }; function argMatchesAnyPossibleType(arg, type) { for (var i = 0; i < type.length; i++) { if (argMatchesType(arg, type[i])) return true; } return false; function argMatchesType(arg, type) { switch (getArgType(arg)) { case "boolean": return type === Boolean; case "string": return type === String; case "number": return type === Number; case "array": return type === Array; case "function": return type === Function; case "object": return type === Object || arg instanceof type; case "undefined": return type === undefined; case "null": return type === null; case "NaN": return typeof(type) === "number" && isNaN(type); default: exports.unreachable(); } } } function explainPossibleTypes(type) { var joiner = ""; var result = ""; for (var i = 0; i < type.length; i++) { result += joiner + explainOneType(type[i]); joiner = (i === type.length - 2) ? ", or " : ", "; } return result; function explainOneType(type) { switch (type) { case Boolean: return "boolean"; case String: return "string"; case Number: return "number"; case Array: return "array"; case Function: return "function"; case null: return "null"; case undefined: return "undefined"; default: if (typeof type === "number" && isNaN(type)) return "NaN"; else { return oop.className(type) + " instance"; } } } } function explainArg(arg) { var type = getArgType(arg); if (type !== "object") return type; return oop.instanceName(arg) + " instance"; } function getArgType(variable) { var type = typeof variable; if (variable === null) type = "null"; if (shim.Array.isArray(variable)) type = "array"; if (type === "number" && isNaN(variable)) type = "NaN"; return type; } /*****/ var EnsureException = exports.EnsureException = function EnsureException(fnToRemoveFromStackTrace, message) { if (Error.captureStackTrace) Error.captureStackTrace(this, fnToRemoveFromStackTrace); else this.stack = (new Error()).stack; this.message = message; }; EnsureException.prototype = shim.Object.create(Error.prototype); EnsureException.prototype.constructor = EnsureException; EnsureException.prototype.name = "EnsureException";