|
1 "use strict"; |
|
2 |
|
3 var Method = require("../core") |
|
4 |
|
5 function type(value) { |
|
6 return Object.prototype.toString.call(value). |
|
7 split(" "). |
|
8 pop(). |
|
9 split("]"). |
|
10 shift(). |
|
11 toLowerCase() |
|
12 } |
|
13 |
|
14 var values = [ |
|
15 null, // 0 |
|
16 undefined, // 1 |
|
17 Infinity, // 2 |
|
18 NaN, // 3 |
|
19 5, // 4 |
|
20 {}, // 5 |
|
21 Object.create({}), // 6 |
|
22 Object.create(null), // 7 |
|
23 [], // 8 |
|
24 /foo/, // 9 |
|
25 new Date(), // 10 |
|
26 Function, // 11 |
|
27 function() {}, // 12 |
|
28 true, // 13 |
|
29 false, // 14 |
|
30 "string" // 15 |
|
31 ] |
|
32 |
|
33 function True() { return true } |
|
34 function False() { return false } |
|
35 |
|
36 var trues = values.map(True) |
|
37 var falses = values.map(False) |
|
38 |
|
39 exports["test throws if not implemented"] = function(assert) { |
|
40 var method = Method("nope") |
|
41 |
|
42 assert.throws(function() { |
|
43 method({}) |
|
44 }, /not implement/i, "method throws if not implemented") |
|
45 |
|
46 assert.throws(function() { |
|
47 method(null) |
|
48 }, /not implement/i, "method throws on null") |
|
49 } |
|
50 |
|
51 exports["test all types inherit from default"] = function(assert) { |
|
52 var isImplemented = Method("isImplemented") |
|
53 isImplemented.define(function() { return true }) |
|
54 |
|
55 values.forEach(function(value) { |
|
56 assert.ok(isImplemented(value), |
|
57 type(value) + " inherits deafult implementation") |
|
58 }) |
|
59 } |
|
60 |
|
61 exports["test default can be implemented later"] = function(assert) { |
|
62 var isImplemented = Method("isImplemented") |
|
63 isImplemented.define(function() { |
|
64 return true |
|
65 }) |
|
66 |
|
67 values.forEach(function(value) { |
|
68 assert.ok(isImplemented(value), |
|
69 type(value) + " inherits deafult implementation") |
|
70 }) |
|
71 } |
|
72 |
|
73 exports["test dispatch not-implemented"] = function(assert) { |
|
74 var isDefault = Method("isDefault") |
|
75 values.forEach(function(value) { |
|
76 assert.throws(function() { |
|
77 isDefault(value) |
|
78 }, /not implement/, type(value) + " throws if not implemented") |
|
79 }) |
|
80 } |
|
81 |
|
82 exports["test dispatch default"] = function(assert) { |
|
83 var isDefault = Method("isDefault") |
|
84 |
|
85 // Implement default |
|
86 isDefault.define(True) |
|
87 assert.deepEqual(values.map(isDefault), trues, |
|
88 "all implementation inherit from default") |
|
89 |
|
90 } |
|
91 |
|
92 exports["test dispatch null"] = function(assert) { |
|
93 var isNull = Method("isNull") |
|
94 |
|
95 // Implement default |
|
96 isNull.define(False) |
|
97 isNull.define(null, True) |
|
98 assert.deepEqual(values.map(isNull), |
|
99 [ true ]. |
|
100 concat(falses.slice(1)), |
|
101 "only null gets methods defined for null") |
|
102 } |
|
103 |
|
104 exports["test dispatch undefined"] = function(assert) { |
|
105 var isUndefined = Method("isUndefined") |
|
106 |
|
107 // Implement default |
|
108 isUndefined.define(False) |
|
109 isUndefined.define(undefined, True) |
|
110 assert.deepEqual(values.map(isUndefined), |
|
111 [ false, true ]. |
|
112 concat(falses.slice(2)), |
|
113 "only undefined gets methods defined for undefined") |
|
114 } |
|
115 |
|
116 exports["test dispatch object"] = function(assert) { |
|
117 var isObject = Method("isObject") |
|
118 |
|
119 // Implement default |
|
120 isObject.define(False) |
|
121 isObject.define(Object, True) |
|
122 assert.deepEqual(values.map(isObject), |
|
123 [ false, false, false, false, false ]. |
|
124 concat(trues.slice(5, 13)). |
|
125 concat([false, false, false]), |
|
126 "all values except primitives inherit Object methods") |
|
127 |
|
128 } |
|
129 |
|
130 exports["test dispatch number"] = function(assert) { |
|
131 var isNumber = Method("isNumber") |
|
132 isNumber.define(False) |
|
133 isNumber.define(Number, True) |
|
134 |
|
135 assert.deepEqual(values.map(isNumber), |
|
136 falses.slice(0, 2). |
|
137 concat(true, true, true). |
|
138 concat(falses.slice(5)), |
|
139 "all numbers inherit from Number method") |
|
140 } |
|
141 |
|
142 exports["test dispatch string"] = function(assert) { |
|
143 var isString = Method("isString") |
|
144 isString.define(False) |
|
145 isString.define(String, True) |
|
146 |
|
147 assert.deepEqual(values.map(isString), |
|
148 falses.slice(0, 15). |
|
149 concat(true), |
|
150 "all strings inherit from String method") |
|
151 } |
|
152 |
|
153 exports["test dispatch function"] = function(assert) { |
|
154 var isFunction = Method("isFunction") |
|
155 isFunction.define(False) |
|
156 isFunction.define(Function, True) |
|
157 |
|
158 assert.deepEqual(values.map(isFunction), |
|
159 falses.slice(0, 11). |
|
160 concat(true, true). |
|
161 concat(falses.slice(13)), |
|
162 "all functions inherit from Function method") |
|
163 } |
|
164 |
|
165 exports["test dispatch date"] = function(assert) { |
|
166 var isDate = Method("isDate") |
|
167 isDate.define(False) |
|
168 isDate.define(Date, True) |
|
169 |
|
170 assert.deepEqual(values.map(isDate), |
|
171 falses.slice(0, 10). |
|
172 concat(true). |
|
173 concat(falses.slice(11)), |
|
174 "all dates inherit from Date method") |
|
175 } |
|
176 |
|
177 exports["test dispatch RegExp"] = function(assert) { |
|
178 var isRegExp = Method("isRegExp") |
|
179 isRegExp.define(False) |
|
180 isRegExp.define(RegExp, True) |
|
181 |
|
182 assert.deepEqual(values.map(isRegExp), |
|
183 falses.slice(0, 9). |
|
184 concat(true). |
|
185 concat(falses.slice(10)), |
|
186 "all regexps inherit from RegExp method") |
|
187 } |
|
188 |
|
189 exports["test redefine for descendant"] = function(assert) { |
|
190 var isFoo = Method("isFoo") |
|
191 var ancestor = {} |
|
192 isFoo.implement(ancestor, function() { return true }) |
|
193 var descendant = Object.create(ancestor) |
|
194 isFoo.implement(descendant, function() { return false }) |
|
195 |
|
196 assert.ok(isFoo(ancestor), "defined on ancestor") |
|
197 assert.ok(!isFoo(descendant), "overrided for descendant") |
|
198 } |
|
199 |
|
200 exports["test on custom types"] = function(assert) { |
|
201 function Bar() {} |
|
202 var isBar = Method("isBar") |
|
203 |
|
204 isBar.define(function() { return false }) |
|
205 isBar.define(Bar, function() { return true }) |
|
206 |
|
207 assert.ok(!isBar({}), "object is get's default implementation") |
|
208 assert.ok(isBar(new Bar()), "Foo type objects get own implementation") |
|
209 |
|
210 var isObject = Method("isObject") |
|
211 isObject.define(function() { return false }) |
|
212 isObject.define(Object, function() { return true }) |
|
213 |
|
214 assert.ok(isObject(new Bar()), "foo inherits implementation from object") |
|
215 |
|
216 |
|
217 isObject.define(Bar, function() { return false }) |
|
218 |
|
219 assert.ok(!isObject(new Bar()), |
|
220 "implementation inherited form object can be overrided") |
|
221 } |
|
222 |
|
223 |
|
224 exports["test error types"] = function(assert) { |
|
225 var isError = Method("isError") |
|
226 isError.define(function() { return false }) |
|
227 isError.define(Error, function() { return true }) |
|
228 |
|
229 assert.ok(isError(Error("boom")), "error is error") |
|
230 assert.ok(isError(TypeError("boom")), "type error is an error") |
|
231 assert.ok(isError(EvalError("boom")), "eval error is an error") |
|
232 assert.ok(isError(RangeError("boom")), "range error is an error") |
|
233 assert.ok(isError(ReferenceError("boom")), "reference error is an error") |
|
234 assert.ok(isError(SyntaxError("boom")), "syntax error is an error") |
|
235 assert.ok(isError(URIError("boom")), "URI error is an error") |
|
236 } |
|
237 |
|
238 exports["test override define polymorphic method"] = function(assert) { |
|
239 var define = Method.define |
|
240 var implement = Method.implement |
|
241 |
|
242 var fn = Method("fn") |
|
243 var methods = {} |
|
244 implement(define, fn, function(method, label, implementation) { |
|
245 methods[label] = implementation |
|
246 }) |
|
247 |
|
248 function foo() {} |
|
249 |
|
250 define(fn, "foo-case", foo) |
|
251 |
|
252 assert.equal(methods["foo-case"], foo, "define set property") |
|
253 } |
|
254 |
|
255 exports["test override define via method API"] = function(assert) { |
|
256 var define = Method.define |
|
257 var implement = Method.implement |
|
258 |
|
259 var fn = Method("fn") |
|
260 var methods = {} |
|
261 define.implement(fn, function(method, label, implementation) { |
|
262 methods[label] = implementation |
|
263 }) |
|
264 |
|
265 function foo() {} |
|
266 |
|
267 define(fn, "foo-case", foo) |
|
268 |
|
269 assert.equal(methods["foo-case"], foo, "define set property") |
|
270 } |
|
271 |
|
272 require("test").run(exports) |