-
Notifications
You must be signed in to change notification settings - Fork 0
/
test.js
155 lines (128 loc) · 4.61 KB
/
test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
var protocol = require('./index')
, expect = require('expect.js');
describe('protocol implementation', function () {
describe('for basic types', function () {
var Sequence = protocol({
first: [protocol]
, rest: [protocol]
});
Sequence(String, {
first: function (str) { return str.charAt(0); }
, rest: function (str) { return str.slice(1); }
});
Sequence(Array, {
first: function (a) { return a[0]; }
, rest: function (a) { return a.slice(1); }
});
it('should be able to invoke the proper implementation for > 1 type', function () {
expect(Sequence.first('abcd')).to.equal('a');
expect(Sequence.rest('abcd')).to.equal('bcd');
expect(Sequence.first([1, 2, 3, 4])).to.equal(1);
expect(Sequence.rest([1, 2, 3, 4])).to.eql([2, 3, 4]);
});
it('should be able to re-open protocols', function () {
protocol(Sequence, { reverse: [protocol] });
Sequence(String, {
reverse: function (str) {
var rev = '';
for (var i = str.length; i--; ) {
rev += str[i];
}
return rev;
}
});
expect(Sequence.reverse('abc')).to.equal('cba');
});
it('should support multiple arguments', function () {
protocol(Sequence, { slice: [protocol, ('start', Number), ('end', Number)] });
Sequence(String, {
slice: function (string, start, end) {
return string.substring(start, end);
}
});
Sequence(Array, {
slice: function (array, start, end) {
return array.slice(start, end);
}
});
expect(Sequence.slice('abc', 0, 1)).to.equal('a');
expect(Sequence.slice([1, 2, 3], 0, 1)).to.eql([1]);
});
it('should support the type as not necessarily the 1st argument', function () {
protocol(Sequence, { repeat: [Number, protocol] });
Sequence(String, {
repeat: function (times, string) {
var result = '';
while (times--) result += string;
return result;
}
});
Sequence(Array, {
repeat: function (times, array) {
var result = [];
while (times--) result = result.concat(array);
return result;
}
});
expect(Sequence.repeat(3, 'ab')).to.equal('ababab');
expect(Sequence.repeat(2, [1, 2])).to.eql([1, 2, 1, 2]);
});
it('should support more than 1 protocol with overlapping method names', function () {
var Arbitrary = protocol({
first: [protocol]
, rest: [protocol]
});
Arbitrary(String, {
first: function (str) { return 'first'; }
, rest: function (str) { return 'rest'; }
});
Arbitrary(Array, {
first: function (arr) { return 'first'.split(''); }
, rest: function (arr) { return 'rest'.split(''); }
});
expect(Sequence.first('abc')).to.equal('a');
expect(Sequence.rest('abc')).to.equal('bc');
expect(Sequence.first([0])).to.equal(0);
expect(Sequence.rest([0])).to.eql([]);
expect(Arbitrary.first('abc')).to.equal('first');
expect(Arbitrary.rest('abc')).to.equal('rest');
expect(Arbitrary.first([0])).to.eql(['f','i','r','s','t']);
expect(Arbitrary.rest([0])).to.eql(['r','e','s','t']);
});
});
describe('for non-basic types', function () {
function Human () {}
Human.prototype.protocolId = 'human';
function Dog () {}
Dog.prototype.protocolId = 'dog';
var Talker = protocol({
speak: [protocol]
});
Talker(Human, { speak: function (h) { return 'hello'; } });
Talker(Dog, { speak: function (d) { return 'woof'; } });
it('should invoke the proper implementation for > 1 type', function () {
var human = new Human();
expect(Talker.speak(human)).to.equal('hello');
var dog = new Dog();
expect(Talker.speak(dog)).to.equal('woof');
});
});
describe('for inherited types', function () {
function User () {}
User.prototype.protocolId = 'user';
function Guest () {}
Guest.prototype = new User();
function Admin () {}
Admin.prototype = new User();
Admin.prototype.protocolId = 'admin';
var Actor = protocol({ access: [protocol] });
Actor(User, { access: function () { return 'denied'; } });
Actor(Admin, { access: function () { return 'accepted'; } });
it('should invoke the ancestor method if it inherits a protocolId', function () {
expect(Actor.access(new Guest())).to.equal('denied');
});
it('should invoke its own method if it defines its own protocolId', function () {
expect(Actor.access(new Admin())).to.equal('accepted');
});
});
});