1 | 'use strict';
|
2 |
|
3 | var isValidStructure = require('../src/structure'),
|
4 | assert = require('chai').assert;
|
5 |
|
6 | describe('structure', function() {
|
7 | var STRUCTURE = {
|
8 | key0: function(value) { return typeof value === 'string'; },
|
9 | key1: function(value) { return typeof value === 'number'; },
|
10 | key2: function(value) { return typeof value === 'function'; }
|
11 | },
|
12 | VALID_VALUE = {
|
13 | key0: 'test',
|
14 | key1: 100,
|
15 | key2: function() {
|
16 | return 'test';
|
17 | }
|
18 | };
|
19 |
|
20 | it('returns function if only one argument provided', function() {
|
21 | assert.ok(isValidStructure(STRUCTURE) instanceof Function);
|
22 | });
|
23 |
|
24 | it('throws TypeError if structure is not an object', function() {
|
25 | var notObject = 'definitely not an object';
|
26 | assert.throws(function() {
|
27 | isValidStructure(notObject);
|
28 | }, TypeError, /must be an object/);
|
29 |
|
30 | assert.throws(function() {
|
31 | isValidStructure(notObject)(VALID_VALUE);
|
32 | }, TypeError, /must be an object/);
|
33 | });
|
34 |
|
35 | it('throws Error if structure object is empty', function() {
|
36 | assert.throws(function() {
|
37 | isValidStructure({});
|
38 | }, Error, /object cannot be empty/);
|
39 |
|
40 | assert.throws(function() {
|
41 | isValidStructure({})(VALID_VALUE);
|
42 | }, Error, /object cannot be empty/);
|
43 | });
|
44 |
|
45 | it('throws TypeError if not every property of structure is a function', function() {
|
46 | var invalidStructure = {
|
47 | key0: function() { return true; },
|
48 | key1: 'value'
|
49 | };
|
50 |
|
51 | assert.throws(function() {
|
52 | isValidStructure(invalidStructure);
|
53 | }, TypeError, /must consist of predicates/);
|
54 |
|
55 | assert.throws(function() {
|
56 | isValidStructure(invalidStructure)(VALID_VALUE);
|
57 | }, TypeError, /must consist of predicates/);
|
58 | });
|
59 |
|
60 | it('checks whether an object satisfies the structure', function() {
|
61 | var almostValidObject = {
|
62 | key0: 'string',
|
63 | key1: 100,
|
64 | key2: 'nope'
|
65 | };
|
66 |
|
67 | assert.ok(isValidStructure(STRUCTURE, VALID_VALUE));
|
68 | assert.ok(isValidStructure(STRUCTURE)(VALID_VALUE));
|
69 |
|
70 | assert.ok(isValidStructure(STRUCTURE, {}) === false);
|
71 | assert.ok(isValidStructure(STRUCTURE)({}) === false);
|
72 |
|
73 | assert.ok(isValidStructure(STRUCTURE, almostValidObject) === false);
|
74 | assert.ok(isValidStructure(STRUCTURE)(almostValidObject) === false);
|
75 | });
|
76 |
|
77 | it('stops performing further tests if one of predicates earlier has not been satisfied', function() {
|
78 | var structure = {
|
79 | key0: function(value) { return typeof value === 'string'; },
|
80 | key1: function() { return false; },
|
81 | key2: function() { throw new Error('This predicate should not be called'); }
|
82 | };
|
83 |
|
84 | assert.ok(isValidStructure(structure)({
|
85 | key0: 'string',
|
86 | key1: 1,
|
87 | key2: 2
|
88 | }) === false);
|
89 | });
|
90 |
|
91 | it('predicates are called with the same context and proper arguments', function() {
|
92 | var exampleContext = {some: 'context'},
|
93 | structure = {
|
94 | key0: function() {
|
95 | assert.strictEqual(exampleContext, this);
|
96 | assert.strictEqual(arguments[0], 1);
|
97 | assert.strictEqual(arguments[1], 2);
|
98 | assert.strictEqual(arguments[2], 3);
|
99 | assert.strictEqual(arguments[3], undefined);
|
100 | return true;
|
101 | },
|
102 | key1: function() {
|
103 | assert.strictEqual(exampleContext, this);
|
104 | assert.strictEqual(arguments[0], 'string');
|
105 | assert.strictEqual(arguments[1], 2);
|
106 | assert.strictEqual(arguments[2], 3);
|
107 | assert.strictEqual(arguments[3], undefined);
|
108 | return true;
|
109 | }
|
110 | },
|
111 | exampleObject = {
|
112 | key0: 1,
|
113 | key1: 'string'
|
114 | };
|
115 |
|
116 | isValidStructure.call(exampleContext, structure, exampleObject, 2, 3);
|
117 | isValidStructure(structure).call(exampleContext, exampleObject, 2, 3);
|
118 | });
|
119 | });
|