signet
Version:
Signet type library
1,402 lines (1,304 loc) • 51.3 kB
HTML
<html>
<head>
<title>Signet -- Mochadoc Test Documentation</title>
<link rel="stylesheet" href="../assets/doc-style.css" media="screen">
<link rel="stylesheet" href="../assets/github-gist.css" media="screen">
</head>
<body>
<header>
<a href="../index.html"><span id="library-name">Signet</span>
<span id="subtitle">Mochadoc-Generated Test Documents</span></a>
</header>
<div class="content">
<h1>Signet API</h1>
<div>
<a href="#" class="collapse-all collapse-link">Collapse All</a>
</div>
<ul>
<li class="describe-item">
<h3>isTypeOf</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should verify against an ad-hoc type</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
function is5(value) {
return value === 5;
}
assert.equal(signet.isTypeOf(is5)(5), true);
assert.equal(signet.isTypeOf(is5)(6), false);
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>sign</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should sign a function</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var expectedSignature = 'A < B :: A:number, B:number => number';
var signedAdd = signet.sign(expectedSignature, addBuilder());
var expectedTree = parser.parseSignature(expectedSignature);
assert.equal(JSON.stringify(signedAdd.signatureTree), JSON.stringify(expectedTree));
assert.equal(signedAdd.signature, expectedSignature);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should throw an error if signature contains a bad type</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var fnUnderTest = signet.sign.bind(null, 'number, foo => bar', addBuilder());
var expectedMessage = "Signature contains invalid types: foo, bar";
assert.throws(fnUnderTest, expectedMessage);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should throw an error if signature does not satisfy all declared arguments</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var fnUnderTest = signet.sign.bind(null, 'number => number', addBuilder());
var expectedMessage = 'Signature declaration too short for function with 2 arguments';
assert.throws(fnUnderTest, expectedMessage);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should throw error if signature has no output type</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var fnUnderTest = signet.sign.bind(null, 'number, number', addBuilder());
var expectedMessage = 'Signature must have both input and output types';
assert.throws(fnUnderTest, expectedMessage);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should throw error if signature has multiple output types</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var fnUnderTest = signet.sign.bind(null, 'number, number => number, number', addBuilder());
var expectedMessage = 'Signature can only have a single output type';
assert.throws(fnUnderTest, expectedMessage);
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>enforce</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<li class="describe-item">
<h3>Core Behaviors</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>tuple should produce reliable signatures</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
const expectedSignature = 'tuple<*;*> => *';
const testFn = signet.enforce(expectedSignature, () => null);
assert.equal(testFn.signature, expectedSignature);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should wrap an enforced function with an appropriate enforcer</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var originalAdd = addBuilder();
var add = signet.enforce('number, number => number', originalAdd);
assert.equal(add.toString(), originalAdd.toString());
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should enforce a function with a correct argument count</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var add = signet.enforce('number, number => number', addBuilder());
var expectedMessage = 'Anonymous expected a value of type number but got 6 of type string';
assert.throws(add.bind(null, 5, '6'), expectedMessage);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should enforce a function return value</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var add = signet.enforce('number, number => number', function (a, b) {
(a, b);
return true;
});
var expectedMessage = 'Anonymous expected a return value of type number but got true of type boolean';
assert.throws(add.bind(null, 3, 4), expectedMessage);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should return result from enforced function</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var add = signet.enforce('number, number => number', addBuilder());
assert.equal(add(3, 4), 7);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should not throw on unfulfilled optional int argument in a higher-order function containing a variant type</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
function slice(start, end) { (end) }
var enforcedSlice = signet.enforce('int, [int] => *', slice);
assert.doesNotThrow(function () {
enforcedSlice(5);
});
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should enforce a curried function properly</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
function add(a) {
return function (b) {
(a, b);
return 'bar';
}
}
var curriedAdd = signet.enforce('number => number => number', add);
assert.throws(curriedAdd.bind(null, 'foo'));
assert.throws(curriedAdd(5).bind(null, 'foo'));
assert.throws(curriedAdd(5).bind(null, 6));
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>Custom Errors</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should throw a custom error on bad input</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var add = signet.enforce('number, number => number', function (a, b) {
(a, b);
return true;
}, {
inputErrorBuilder: function (validationResult, args, signatureTree) {
return 'This is a custom input error!' + validationResult.toString() + args.toString() + signatureTree.toString();
}
});
var expectedMessage = 'This is a custom input error!number,no3,no[object Object],[object Object],[object Object]';
assert.throws(add.bind(null, 3, 'no'), expectedMessage);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should throw a default error on bad input with core builder</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var add = signet.enforce('number, number => number', function (a, b) {
(a, b);
return true;
}, {
inputErrorBuilder: function (validationResult, args, signatureTree, functionName) {
return signet.buildInputErrorMessage(validationResult, args, signatureTree, functionName);
}
});
var expectedMessage = 'Anonymous expected a value of type number but got no of type string';
assert.throws(add.bind(null, 3, 'no'), expectedMessage);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should throw a default error on bad output with core builder</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var add = signet.enforce('number, number => number', function (a, b) {
(a, b);
return true;
}, {
outputErrorBuilder: function (validationResult, args, signatureTree, functionName) {
return signet.buildOutputErrorMessage(validationResult, args, signatureTree, functionName);
}
});
var expectedMessage = 'Anonymous expected a return value of type number but got true of type boolean';
assert.throws(add.bind(null, 3, 4), expectedMessage);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should throw a custom error on bad output</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var add = signet.enforce('number, number => number', function (a, b) {
(a, b);
return true;
}, {
outputErrorBuilder: function (validationResult, args, signatureTree) {
return 'This is a custom output error!' + validationResult.toString() + args.toString() + signatureTree.toString();
}
});
var expectedMessage = 'This is a custom output error!number,true3,4[object Object],[object Object],[object Object]';
assert.throws(add.bind(null, 3, 4), expectedMessage);
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>Dependent Type Operator Support</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should properly check symbolic dependent types</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
function orderedProperly(a, b) {
return a > b;
}
var enforcedFn = signet.enforce('A > B :: A:number, B:number => boolean', orderedProperly);
function testWith(a, b) {
return function () {
return enforcedFn(a, b);
};
}
assert.throws(testWith(5, 6), 'orderedProperly expected a value of type A > B but got A = 5 and B = 6 of type string');
assert.equal(testWith(7, 3)(), true);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should properly check symbolic type dependencies</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
function testFnFactory() {
return function (a, b) {
a + b;
return a;
};
}
assert.throws(signet.enforce(
'A <: B :: A:variant<string;number>, B:variant<string;int> => number',
testFnFactory()).bind(null, 2.2, 3),
'Anonymous expected a value of type A <: B but got A = 2.2 and B = 3 of type string');
assert.throws(signet.enforce(
'A < B, B > C :: A:int, B:int, C:int => number',
testFnFactory()).bind(null, 5, 6, 7),
'Anonymous expected a value of type B > C but got B = 6 and C = 7 of type string');
assert.doesNotThrow(signet.enforce(
'A <: B :: A:variant<string;int>, B:variant<string;number> => number',
testFnFactory()).bind(null, 5, 6));
assert.doesNotThrow(signet.enforce(
'A < B, B < C :: A:int, B:int, C:int => number',
testFnFactory()).bind(null, 5, 6, 7));
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>Object and Constructor Support</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should properly enforce constructors</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var testMethodSpy = sinon.spy();
var MyObj = signet.enforce(
'a:int, b:string => undefined',
function (a, b) {
this.testMethod(a, b);
}
);
MyObj.prototype.testMethod = testMethodSpy;
new MyObj(5, 'foo');
var result = JSON.stringify(testMethodSpy.args[0]);
var expectedResult = JSON.stringify([5, 'foo']);
assert.equal(testMethodSpy.callCount, 1);
assert.equal(result, expectedResult);
assert.throws(
function () { return new MyObj('foo', 5); },
'Anonymous expected a value of type a:int but got foo of type string'
);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should properly enforce object methods</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
function MyObj(a) {
this.a = a;
}
MyObj.prototype = {
testMethod: signet.enforce(
'b:int => result:int',
function (b) {
return this.a + b;
}
)
}
var objInstance = new MyObj(6);
assert.equal(objInstance.testMethod(7), 13);
assert.throws(
objInstance.testMethod.bind(objInstance, '7'),
'Anonymous expected a value of type b:int but got 7 of type string'
);
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>Function Properties</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should preserve properties on enforced function</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
function adder(a, b) {
return a + b;
}
adder.myProp = () => 'yay!';
const add = signet.enforce(
'number, number => number',
adder
);
assert.equal(add.myProp(), 'yay!');
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should return a function with the correct arity</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
const add = signet.enforce(
'a:*, b:* => *',
function add(a, b) {
return a + b;
}
);
assert.equal(add.length, 2);
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>Higher-order Function Support</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should support a cross-execution environment table</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
const addIncreasing = signet.enforce(
'a < b, b < sum :: a:int => b:int => sum:int',
a => b => a - b
);
assert.throws(addIncreasing(5).bind(null, 4), 'Anonymous expected a value of type a < b but got a = 5 and b = 4 of type string');
assert.throws(addIncreasing(5).bind(null, 6), 'Anonymous expected a return value of type b < sum but got b = 6 and sum = -1 of type string');
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should enforce passed functions when a signature is provided</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
const testFn = signet.enforce(
'function<* => boolean> => * => boolean',
function (fn) { return () => fn(); });
function badFn() { return 'foo'; }
assert.throws(testFn(badFn), 'badFn expected a return value of type boolean but got foo of type string');
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should should pass options along to sub-enforcement</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
const options = {
outputErrorBuilder: function (validationResult, args, signatureTree) {
return 'This is a custom output error!' + validationResult.toString() + args.toString() + signatureTree.toString();
}
};
const testFn = signet.enforce(
'function<* => boolean> => * => string',
function (fn) { return () => fn(); },
options);
function badFn() { return 'foo'; }
assert.throws(testFn(badFn), 'This is a custom output error!boolean,foo[object Object],[object Object]');
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should not throw when function type is declared with constructor argument</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
function doStuff() { return []; }
signet.enforce('function<*, * => string, boolean => boolean> => array', doStuff);
assert.doesNotThrow(doStuff.bind(null, function () { }));
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
</ul>
</li>
<li class="describe-item">
<h3>extend</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should register a new type</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
signet.extend('foo', function (value) { return value === 'foo'; });
assert.equal(signet.isType('foo'), true);
assert.equal(signet.isTypeOf('foo')('foo'), true);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should handle type arity up front</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
signet.extend('myTestType0', function () { });
signet.extend('myTestType1{1}', function () { });
signet.extend('myTestType1OrMore{1,}', function () { });
signet.extend('myTestType2To5{2, 5}', function () { });
assert.doesNotThrow(signet.isTypeOf.bind(null, 'myTestType0<1, 2, 3>'));
assert.throws(
signet.isTypeOf('myTestType1<1, 2, 3>').bind(null, 'foo'),
'Type myTestType1 accepts, at most, 1 arguments');
assert.throws(
signet.isTypeOf('myTestType1').bind(null, 'foo'),
'Type myTestType1 requires, at least, 1 arguments');
assert.doesNotThrow(signet.isTypeOf('myTestType1OrMore<1, 2, 3>').bind(null, 'foo'));
assert.throws(
signet.isTypeOf('myTestType1OrMore').bind(null, 'foo'),
'Type myTestType1OrMore requires, at least, 1 arguments');
assert.doesNotThrow(signet.isTypeOf('myTestType2To5<1, 2, 3>').bind(null, 'foo'));
assert.throws(
signet.isTypeOf('myTestType2To5').bind(null, 'foo'),
'Type myTestType2To5 requires, at least, 2 arguments');
assert.throws(
signet.isTypeOf('myTestType2To5<1, 2, 3, 4, 5, 6>').bind(null, 'foo'),
'Type myTestType2To5 accepts, at most, 5 arguments');
assert.throws(
signet.extend.bind(null, 'myTestTypeBroken{5, 1}', function () { }),
'Error in myTestTypeBroken arity declaration: min cannot be greater than max');
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>subtype</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should register a subtype</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
signet.subtype('number')('intFoo', function (value) { return Math.floor(value) === value; });
assert.equal(signet.isSubtypeOf('number')('intFoo'), true);
assert.equal(signet.isTypeOf('intFoo')(15), true);
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>alias</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should allow aliasing of types by other names</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
signet.alias('foo', 'string');
assert.equal(signet.isTypeOf('foo')('bar'), true);
assert.equal(signet.isTypeOf('foo')(5), false);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should partially apply a type value</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
signet.alias('testTuple', 'tuple<_; _>');
signet.alias('testPartialTuple', 'testTuple<int; _>');
assert.equal(signet.isTypeOf('testTuple<array; object>')([[], {}]), true);
assert.equal(signet.isTypeOf('testPartialTuple<string>')([5, 'foo']), true);
assert.equal(signet.isTypeOf('testPartialTuple<string>')([5, 6]), false);
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>verify</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should allow function argument verification inside a function body</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
function test(a, b) {
(a, b);
signet.verify(test, arguments);
}
signet.sign('string, number => undefined', test);
assert.throws(test.bind(5, 'five'));
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>typeChain</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should return correct type chains</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
const arrayTypeChain = signet.typeChain('array');
const numberTypeChain = signet.typeChain('number');
assert.equal(arrayTypeChain, '* -> object -> array');
assert.equal(numberTypeChain, '* -> number');
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>duckTypeFactory</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should duck type check an object</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var isMyObj = signet.duckTypeFactory({
foo: 'string',
bar: 'int',
baz: 'array'
});
signet.subtype('object')('myObj', isMyObj);
assert.equal(signet.isTypeOf('myObj')({ foo: 55 }), false);
assert.equal(signet.isTypeOf('myObj')({ foo: 'blah', bar: 55, baz: [] }), true);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should return false if value is not duck-type verifiable</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var isMyObj = signet.duckTypeFactory({
foo: 'string',
bar: 'int',
baz: 'array'
});
assert.equal(isMyObj(null), false);
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>exactDuckTypeFactory</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should check and exact duck type on an object</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var isMyObj = signet.exactDuckTypeFactory({
foo: 'string',
bar: 'int',
baz: 'array'
});
signet.subtype('object')('myExactObj', isMyObj);
assert.equal(signet.isTypeOf('myExactObj')({ foo: 'blah', bar: 55, baz: [], quux: '' }), false);
assert.equal(signet.isTypeOf('myExactObj')({ foo: 'blah', bar: 55, baz: [] }), true);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should check and exact duck type on an object</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var isMyObj = signet.exactDuckTypeFactory({
foo: 'string',
bar: 'int',
baz: 'array'
});
signet.subtype('object')('myExactObj', isMyObj);
assert.equal(signet.isTypeOf('myExactObj')({ foo: 'blah', bar: 55, baz: [], quux: '' }), false);
assert.equal(signet.isTypeOf('myExactObj')({ foo: 'blah', bar: 55, baz: [] }), true);
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>defineDuckType</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should allow duck types to be defined directly</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
signet.defineDuckType('myObj', {
foo: 'string',
bar: 'int',
baz: 'array'
});
assert.equal(signet.isTypeOf('myObj')({ foo: 55 }), false);
assert.equal(signet.isTypeOf('myObj')({ foo: 'blah', bar: 55, baz: [] }), true);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should allow reporting of duck type errors</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
signet.defineDuckType('aTestThingy', {
quux: '!*'
});
signet.defineDuckType('myObj', {
foo: 'string',
bar: 'int',
baz: 'array',
deeperType: 'aTestThingy'
});
var result = signet.reportDuckTypeErrors('myObj')({ foo: 55, bar: 'bad value', baz: null, deeperType: {} });
var expected = '[["foo","string",55],["bar","int","bad value"],["baz","array",null],["deeperType","aTestThingy",[["quux","not<variant<undefined, null>>",null]]]]';
assert.equal(JSON.stringify(result), expected);
assert.equal(signet.isTypeOf('myObj')({ foo: 'blah', bar: 55, baz: [], deeperType: { quux: 'something' } }), true);
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>reportDuckTypeErrors</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should return duck type error on bad object value</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
signet.defineDuckType('duckTest', {});
let checkDuckTest = signet.reportDuckTypeErrors('duckTest');
const nullCheck = checkDuckTest(null);
const intCheck = checkDuckTest(55);
const stringCheck = checkDuckTest('foo');
assert.equal(JSON.stringify(nullCheck), '[["badDuckTypeValue","object",null]]');
assert.equal(JSON.stringify(intCheck), '[["badDuckTypeValue","object",55]]');
assert.equal(JSON.stringify(stringCheck), '[["badDuckTypeValue","object","foo"]]');
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>isRegisteredDuckType</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should allow querying of registered duck types</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
signet.defineDuckType('duckFoo', {});
assert.equal(signet.isRegisteredDuckType('duckFoo'), true);
assert.equal(signet.isRegisteredDuckType('duckBar'), false);
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>whichVariantType</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should get variant type of value</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var getValueType = signet.whichVariantType('variant<string; int>');
assert.equal(getValueType('foo'), 'string');
assert.equal(getValueType(17), 'int');
assert.equal(getValueType(17.5), null);
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>verifyValueType</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should return value when it matches type correctly</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var stringValue = 'foo';
var stringResult = signet.verifyValueType('string')(stringValue);
var boundedIntValue = 5;
var boundedIntResult = signet.verifyValueType('leftBoundedInt<4>')(boundedIntValue);
assert.equal(stringResult, stringValue);
assert.equal(boundedIntResult, boundedIntValue);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should throw an error if the value is of incorrect type</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
var verifyStringValue = signet.verifyValueType('string');
var verifyBoundedIntValue = signet.verifyValueType('leftBoundedInt<4>');
assert.throws(() => verifyStringValue({}));
assert.throws(() => verifyBoundedIntValue(-3));
}
</code>
</pre>
</li>
</ul>
</ul>
</li>
<li class="describe-item">
<h3>iterateOn and recursiveTypeFactory</h3>
<div><a href="#" class="describe-link collapse-link"></a></div>
<ul class="describe-collapsible shown">
<ul>
<li>
<strong>should allow easy creation of a recursive type</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
const isListNode = signet.duckTypeFactory({
value: 'int',
next: 'composite<not<array>, object>'
});
const iterableFactory = signet.iterateOn('next');
const isIntList = signet.recursiveTypeFactory(iterableFactory, isListNode);
const testList = cons(1, cons(2, cons(3, cons(4, cons(5, null)))));
assert.equal(isIntList(testList), true);
assert.equal(isIntList({ value: 1 }), false);
assert.equal(isIntList('blerg'), false);
}
</code>
</pre>
</li>
</ul>
<ul>
<li>
<strong>should properly recurse through a binary tree with left and right values</strong>
</li>
<li>File location: <span class="filename">./test/signet.test.js</span></li>
<li class="code-sample-wrapper">
<div class="code-expand">
<a href="#" class="collapse-link"></a>
</div>
<pre class="code-sample">
<code>
function () {
const isBinaryTreeNode = signet.duckTypeFactory({
value: 'int',
left: 'composite<^array, object>',
right: 'composite<^array, object>',
});
function isOrderedNode(node) {
return isBinaryTreeNode(node)
&& ((node.left === null || node.right === null)
|| (node.value > node.left.value
&& node.value <= node.right.value));
}
signet.subtype('object')('orderedBinaryTreeNode', isOrderedNode);
function iteratorFactory(value) {
var iterable = [];
iterable = value.left !== null ? iterable.concat([value.left]) : iterable;
iterable = value.right !== null ? iterable.concat([value.right]) : iterable;
return signet.iterateOnArray(iterable);
}
signet.defineRecursiveType('orderedBinaryTree', iteratorFactory, 'orderedBinaryTreeNode');
const isOrderedIntTree = signet.isTypeOf('orderedBinaryTree');
const goodBinaryTree = {
value: 0,
left: {
value: -1,
left: null,
right: null
},
right: {
value: 1,