OSDN Git Service

f8064dc8264676c06853552e09090efef2759981
[sie/sie.git] / tool / Spec / spec / BaseJSSpec.js
1 describe("base.js", function() {\r
2   var gl = (function(){return this;})(); //グローバルオブジェクト\r
3 \r
4   it("cascading inherit", function() {\r
5       /*カスケード継承 (cascading inherit)に関するスペック*/\r
6       base("$parent").mix( function() {\r
7         this.hoge = function() {\r
8           return 12;\r
9         };\r
10         this.up("$child").mix( function() {\r
11           this.hoge = function() {\r
12             return this.$parent.hoge();\r
13           };\r
14         });\r
15       });\r
16       expect(base("$parent")).toEqual(gl.$parent);\r
17       expect(base("$parent").$child).toEqual(gl.$parent.$child);\r
18       expect(base("$parent").$child.hoge()).toEqual(12);\r
19       expect(base("$parent").hoge()).toEqual(12);\r
20       expect(gl.$parent.$child.hoge()).toEqual(12);\r
21       expect(base("$parent").$child.hoge).not.toEqual(base("$parent").hoge());\r
22   });\r
23 \r
24   it("a function base", function() {\r
25     var falsyList = ["", null, 0, undefined],\r
26         i = falsyList.length;\r
27     expect(function(){\r
28       base();\r
29     }).toThrow();\r
30     while(i--) {\r
31       expect(function(){\r
32         base(falsyList[i]);\r
33       }).toThrow();\r
34     }\r
35     expect(typeof base("$wo")).toBe("object");\r
36     expect(base("$w")).toBe(base("$w"));\r
37     expect(base("$w")).toBe(gl.$w);\r
38   });\r
39 \r
40   it("a mix method", function() {\r
41     /*mixメソッドはオブジェクトの合成ができる*/\r
42     expect(typeof base("$a").mix).toBe("function");\r
43     /*メソッドチェーンのチェック*/\r
44     expect(base("$a").mix({})).toBe(base("$a"));\r
45     expect(base("$a").mix(function(){})).toBe(base("$a"));\r
46     expect(base("$a").mix({}).mix({})).toBe(base("$a"));\r
47     expect(base("$a").mix(function(){}).mix({}).mix(function(){})).toBe(base("$a"));\r
48 \r
49     var falsyList = ["", null, 0, undefined],\r
50         i = falsyList.length;\r
51     expect(function(){\r
52       base("$a").mix();\r
53     }).toThrow();\r
54     while(i--) {\r
55       expect(function(){\r
56         base("$a").mix(falsyList[i]);\r
57       }).toThrow();\r
58     }\r
59 \r
60     /*argument to object*/\r
61     base("$a").mix({\r
62       a: 12,\r
63       b: {\r
64         d: 12\r
65       },\r
66       c: function(){\r
67         return (this.a+3);\r
68       }\r
69     });\r
70     expect(base("$a").a).toEqual(12);\r
71     expect(base("$a").b.d).toEqual(12);\r
72     expect(base("$a").c()).toEqual(15);\r
73 \r
74     /*argument to function*/\r
75     base("$b").mix( function() {\r
76       this.a = 12;\r
77       this.b = {\r
78         d: 12\r
79       };\r
80       this.c = function(){\r
81         return (this.a+3);\r
82       };\r
83     });\r
84     expect(base("$b").a).toEqual(12);\r
85     expect(base("$b").b.d).toEqual(12);\r
86     expect(base("$b").c()).toEqual(15);\r
87 \r
88     base("$a").mix({\r
89       a: 0,\r
90       b: {\r
91         d: -12\r
92       },\r
93       c: function(){\r
94         return (this.a+3);\r
95       }\r
96     });\r
97     expect(base("$a").a).toEqual(0);\r
98     expect(base("$a").b.d).toEqual(-12);\r
99     expect(base("$a").c()).toEqual(3);\r
100 \r
101     base("$a").mix(Math);\r
102     expect(base("$a").pi).toEqual(Math.pi);\r
103 \r
104     base("$a").mix({\r
105       a: "hogehoge",\r
106       b: {\r
107         d: 0\r
108       },\r
109       c: function(){\r
110         return (this.a+"hoge");\r
111       }\r
112     });\r
113     expect(base("$a").a).toBe("hogehoge");\r
114     expect(base("$a").b.d).toEqual(0);\r
115     expect(base("$a").c()).toBe("hogehogehoge");\r
116 \r
117     for (var i=0, arr = [];i<500;++i) {\r
118       arr.push(i);\r
119     }\r
120     for (i=0;i<100;++i) {\r
121       base("$a").mix(arr);\r
122     }\r
123     expect(base("$a")[0]).toEqual(0);\r
124     expect(base("$a")[499]).toEqual(499);\r
125   });\r
126 \r
127   it("an up method", function() {\r
128     /*upメソッドは、プロトタイプ継承した新しいオブジェクトを作り、引数で指定された名前のプロパティに格納する*/\r
129     expect(typeof base("$c").up).toEqual("function");\r
130 \r
131     expect(base("$c").up("$a")).not.toBe(base("$a"));\r
132 \r
133     expect(base("$c").up("$c")).not.toBe(base("$c"));\r
134     /*もう一度繰り返す (reapeat)*/\r
135     expect(base("$c").up("$c")).not.toBe(base("$c"));\r
136 \r
137     expect(base("$c").$c).toBe(gl.$c.$c);\r
138     expect(base("$c").$c.up("$c")).not.toBe(base("$c"));\r
139     expect(gl.$c.$c.up("$c")).toBe(base("$c").$c.$c.$c);\r
140 \r
141     /*オブジェクト$cのhogeプロパティの継承*/\r
142     base("$c").hoge = 12;\r
143     expect(base("$c").$c.hoge).toEqual(12);\r
144     expect(base("$c").$c.$c.hoge).toEqual(12);\r
145     expect(base("$c").$c.$c.$c.hoge).toEqual(12);\r
146 \r
147     /*プロトタイプチェーン上のオブジェクトも合成できるようにする*/\r
148     base("$c").mix({\r
149         aa: 12\r
150       }).up("$1").mix({\r
151         bb: 15\r
152       });\r
153     base("$d").mix(base("$c").$1);\r
154     expect(base("$d").aa).toEqual(12);\r
155     expect(base("$d").bb).toEqual(15);\r
156     expect(base("$d").$1).toBe(base("$c").$1);\r
157     base("$d").mix(function() {\r
158       expect(this.$c.aa).toEqual(12);\r
159       expect(this.$1.aa).toEqual(12);\r
160       expect(this.$1.bb).toEqual(15);\r
161     });\r
162 \r
163     for (var i=0;i<5000;++i) {\r
164       base("$c").up("$dd");\r
165     }\r
166     expect(base("$c").$dd.hoge).toEqual(12);\r
167     \r
168     /*引数を省略した場合、引数に文字列"$1"を入れたのと同じ効果が得られる*/\r
169     expect(base("$up").$1).toBeUndefined();\r
170     expect(base("$up").up()).toBe(base("$up").$1);\r
171   });\r
172 \r
173   it("a mix method function", function() {\r
174     /*mixメソッドの引数に指定された関数と、mixメソッドのレシーバオブジェクトについて*/\r
175     base("$mmf").mix(function(_) {\r
176       expect(_).toBe(base("$mmf"));\r
177       expect(this).toBe(_);\r
178     });\r
179   });\r
180 \r
181   it("an on method", function() {\r
182     /*onメソッドは同一名メソッドの合成ができる*/\r
183     base("$a").on("met", function() {return 12;});\r
184     /*メソッドチェーンかどうかのチェック*/\r
185     expect(base("$a").on("met", function(a) {\r
186           this.a = a;\r
187         }))\r
188         .toBe(base("$a"));\r
189     base("$a").met(12);\r
190     expect(base("$a").a).toEqual(12);\r
191 \r
192     base("$a").on("met", function(a) {\r
193         this.b = a;\r
194     }).met(12);\r
195     expect(base("$a").a).toEqual(12);\r
196     expect(base("$a").b).toEqual(12);\r
197 \r
198     /*返り値は、最初に指定しておいたメソッド*/\r
199     expect(base("$a").met()).toEqual(12);\r
200 \r
201     base("$a").mix( function() {\r
202         this.a = 0;\r
203         this.b = 0;\r
204     });\r
205     base("$a").up("$b").on("met", function() {\r
206           this.a = 15;\r
207           this.b = 15;\r
208         }).met();\r
209     expect(base("$a").$b.a).toEqual(15);\r
210     expect(base("$a").$b.b).toEqual(15);\r
211 \r
212     base("$a").on("metmet", function() {\r
213         this.a = 12;\r
214         this.b = 12;\r
215     }).metmet();\r
216     expect(base("$a").a).toEqual(12);\r
217     expect(base("$a").b).toEqual(12);\r
218     /*別のmetメソッドを設定しても、影響を与えないかどうかをチェック*/\r
219     base("$a").on("met", function() {\r
220         this.a = 15;\r
221         this.b = 15;\r
222     }).metmet();\r
223     expect(base("$a").a).toEqual(12);\r
224     expect(base("$a").b).toEqual(12);\r
225 \r
226     expect(base("$a").met()).toEqual(12);\r
227     expect(base("$a").metmet()).toBeUndefined();\r
228 \r
229     /*境界値のチェック*/\r
230     base("$a").on("o", function(){})\r
231                  .o();\r
232     expect(base("$a").on("o", function(){return 12;})\r
233                  .o()).toBeUndefined();\r
234 \r
235     /*通常のメソッドが入っていた場合*/\r
236     base("$a").mix( {aa: function() {\r
237           this.__t = 12;\r
238           return 15;\r
239         }})\r
240         .on("aa", function(){\r
241               this.__n = 12;\r
242             });\r
243     expect(base("$a").aa()).toEqual(15);\r
244     expect(base("$a").__t).toEqual(12);\r
245     expect(base("$a").__n).toEqual(12);\r
246     base("$a").mix({\r
247           aaa: function() {\r
248               this.__t = 18;\r
249               this.__n = 18;\r
250               return 15;\r
251           }\r
252         }).up("$b").on("aaa", function() {\r
253             this.__n = 15;\r
254         });\r
255     expect(base("$a").aaa()).toEqual(15);\r
256     expect(base("$a").$b.__n).toEqual(18);\r
257     expect(base("$a").$b.aaa()).toEqual(15);\r
258     expect(base("$a").$b.__n).toEqual(15);\r
259 \r
260     /*有効同値のチェック*/\r
261     base("$a").mix({\r
262           am: function() {\r
263               this.__t = 18;\r
264               this.__n = 18;\r
265               return 15;\r
266           }\r
267         }).up("$b").up("$c").on("am", function() {\r
268             this.__n = 15;\r
269         });\r
270     expect(base("$a").am()).toEqual(15);\r
271     expect(base("$a").$b.$c.__n).toEqual(18);\r
272     expect(base("$a").$b.$c.am()).toEqual(15);\r
273     expect(base("$a").$b.$c.__n).toEqual(15);\r
274     base("$a").on(\r
275           "am", function(f) {\r
276               this.__t = f;\r
277               return 15;\r
278           }\r
279         ).up("$b").up("$c").on("am", function(f) {\r
280             this.__n = 15;\r
281         });\r
282     expect(base("$a").am(12)).toEqual(15);\r
283     expect(base("$a").__t).toEqual(12);\r
284     expect(base("$a").$b.$c.__n).toEqual(18);\r
285     expect(base("$a").$b.$c.am()).toEqual(15);\r
286     expect(base("$a").$b.$c.__n).toEqual(15);\r
287 \r
288     /*無効同値のチェック*/\r
289     expect(function() {\r
290         base("$a").on("met");\r
291     }).toThrow();\r
292     expect(function() {\r
293         base("$a").on("met", "met");\r
294     }).toThrow();\r
295     expect(function() {\r
296         base("$a").on("met", 12);\r
297     }).toThrow();\r
298     expect(function() {\r
299         base("$a").on("", function(){});\r
300     }).toThrow();\r
301     \r
302     /*up、on、mix、ofメソッドは自己参照の矛盾を引き出すので、例外を投げておく*/\r
303     var message = "Invalid method name error";\r
304     expect(function() {\r
305         base("$a").on("up", function(){});\r
306     }).toThrow(message);\r
307     expect(function() {\r
308         base("$a").on("on", function(){});\r
309     }).toThrow(message);\r
310     expect(function() {\r
311         base("$a").on("mix", function(){});\r
312     }).toThrow(message);\r
313     expect(function() {\r
314         base("$a").on("of", function(){});\r
315     }).toThrow(message);\r
316 \r
317     base("$a").on("upon", function(){}); //これは正常に作動\r
318 \r
319     /*無関係のオブジェクトを返さないようにするためのチェック*/\r
320     this._ddd = {};\r
321     base("_ddd").up("$1");\r
322   });\r
323   \r
324   describe("an 'of' method", function() {\r
325     /*境界条件を調べる*/\r
326     it("limit value analysis", function() {\r
327         expect(typeof base("$fp").of).toBe("function");\r
328         /*メソッドチェーンを作る*/\r
329         expect(base("$fp").of({})).toBe(base("$fp"));\r
330 \r
331         /*同じオブジェクトで再度、ofメソッドを呼び出すことはできない*/\r
332         expect(function() {\r
333           base("$fp").of({});\r
334         }).toThrow("Reset error");\r
335         /*upメソッドで継承したオブジェクトは再度呼び出せる*/\r
336         base("$fp").up().of( {} );\r
337         \r
338         base("$fp").up().of ( {\r
339           a: 0,\r
340           b: 1,\r
341           c: true,\r
342           d: false,\r
343           e: {},\r
344           f: function() {},\r
345           g: [],\r
346           h: null,\r
347           call: function() {}\r
348           \r
349         } );\r
350         base("$fp").$1.mix( function(_) {\r
351           expect(_.a).toEqual(0);\r
352           expect(_.b).toEqual(1);\r
353           expect(_.c).toBeTruthy();\r
354           expect(_.d).toBeFalsy();\r
355           expect(typeof _.e).toBe("object");\r
356           /*callメソッドのあるオブジェクトや関数が指定された時だけ、未定義値\r
357            * ただし、callメソッドは指定されても未定義とならない*/\r
358           expect(_.f).toBeUndefined();\r
359           expect(typeof _.call).toBe("function");\r
360           expect(_.g.length).toEqual(0);\r
361           expect(_.h).toBeNull();\r
362         } );\r
363     });\r
364     /*有効同値を調べる*/\r
365     it("Equivalence partitioning, the following is the valid partion", function() {\r
366       base("$ffp").of({\r
367         a: 10,\r
368         b: 12,\r
369         c: base("$afp"),\r
370         call: function() {\r
371           return this.a + this.b;\r
372         }\r
373       });\r
374       var _ = base("$ffp");\r
375       expect(_.a).toEqual(10);\r
376       expect(_.b).toEqual(12);\r
377       expect(_.c).toBeUndefined();\r
378       expect(_.call()).toEqual(22);\r
379       /*upメソッドを使えば、再び、ofメソッドを再設定できる*/\r
380        _ = base("$ffp").up();\r
381       expect(_.a).toEqual(10);\r
382       expect(_.b).toEqual(12);\r
383       expect(_.c).toBe(base("$afp"));\r
384       expect(_.call()).toEqual(22);\r
385       _.of({\r
386         a: 11,\r
387         b: 13,\r
388         c: "bfp",\r
389         call: function() {\r
390           return this.a + this.b;\r
391         }\r
392       });\r
393       expect(_.a).toEqual(11);\r
394       expect(_.b).toEqual(13);\r
395       expect(_.c).toBe("bfp");\r
396       expect(_.call()).toEqual(24);\r
397       \r
398       /*mixメソッドでも、オブジェクト継承の後であれば上書きが可能*/\r
399       _.up("$p").mix( {\r
400         a: 12,\r
401         b: 13,\r
402         c: base("$afp")\r
403       } );\r
404       expect(_.$p.a).toEqual(12);\r
405       expect(_.$p.b).toEqual(13);\r
406       expect(_.$p.c).toBe(base("$afp"));\r
407       expect(_.$p.call()).toEqual(25);\r
408     });\r
409     \r
410     /*無効同値を調べる*/\r
411     it("Equivalence partitioning, the following is the invalid partion", function() {\r
412       expect( function() {\r
413           base("$ffp").up("$error").of( {\r
414             call: null\r
415           } )\r
416           .of( {} );\r
417       } ).toThrow("Reset error");\r
418       expect( function() {\r
419           base("$ffp").up("$error").of();\r
420       } ).toThrow("No arguments error");\r
421     } );\r
422   });\r
423   \r
424   describe("an 'call' method", function() {\r
425     it("limit value analysis", function() {\r
426       expect(typeof base("$bfp").call).toBe("function");\r
427       expect(base("$bfp").call()).toBe(base("$bfp"));\r
428       expect(base("$bfp").up().call()).toBe(base("$bfp").$1);\r
429       base("$bfp").up().of ( {\r
430         a: 0,\r
431         b: 1,\r
432         c: true,\r
433         d: false,\r
434         e: {},\r
435         f: function() {},\r
436         g: [],\r
437         h: null\r
438       } ).call();\r
439       base("$bfp").$1.mix( function(_) {\r
440         expect(_.a).toEqual(0);\r
441         expect(_.b).toEqual(1);\r
442         expect(_.c).toBeTruthy();\r
443         expect(_.d).toBeFalsy();\r
444         expect(typeof _.e).toBe("object");\r
445         /*callメソッドが設定されていないことに注意*/\r
446         expect(_.f).toBeUndefined();\r
447         expect(typeof _.call).toBe("function");\r
448         expect(_.g.length).toEqual(0);\r
449         expect(_.h).toBeNull();\r
450       } );\r
451     });\r
452     it("Equivalence partitioning, the following is the valid partion", function() {\r
453       base("$bfp").of( {\r
454         a: base("$abfp"),\r
455         call: function() {\r
456           return this.a;\r
457         }\r
458       });\r
459       expect(base("$bfp").a).toBeUndefined();\r
460       base("$abfp").of( {\r
461         call: function() {\r
462           return 12;\r
463         }\r
464       } );\r
465       expect(base("$bfp").call()).toEqual(12);\r
466       /*再度呼び出しても同じ結果となる*/\r
467       expect(base("$bfp").call()).toEqual(12);\r
468       base("$bfp").up("$a").of( {\r
469         a: base("$abfp"),\r
470         b: base("$bbfp")\r
471       } );\r
472       expect(base("$bfp").$a.call()).toEqual(12);\r
473       /*今度は束縛変数としてbプロパティの値を返す*/\r
474       base("$bfp").up("$b").of( {\r
475         b: base("$bbfp"),\r
476         call: function() {\r
477           return this.b;\r
478         }\r
479       } );\r
480       base("$bbfp").of( {\r
481         call: function() {\r
482           return 15;\r
483         }\r
484       } );\r
485       expect(base("$bfp").$b.call()).toEqual(15);\r
486       /*再実行*/\r
487       for (var i=0;i<1000;++i) {\r
488         expect(base("$bfp").$b.call()).toEqual(15);\r
489       }\r
490       /*callメソッドを何も設定していない場合*/\r
491       expect(base("$cfp").of({a:base("$bfp")}).call()).toBe(base("$cfp"));\r
492       expect(base("$cfp").up("$bfp").of({a:base("$bfp")}).call()).toBe(base("$cfp").$bfp);\r
493       \r
494       /*循環参照は防ぐようにする*/\r
495       expect(base("$bfp").$b.up().of( {b: base("$bfp").$b.$1} ).call()).toBe(base("$bfp").$b.$1);\r
496       \r
497       /*ofメソッドで指定されたfuncメソッドなどは、callメソッドで呼び出し時に実行される(thisはcallメソッドのレシーバ)*/\r
498       expect( base("$cfp").up("$a").of( {\r
499         func: function() {\r
500           return this.$a;\r
501         },\r
502         call: function() {\r
503           return this.func;\r
504         }\r
505       } ).call() ).toBe(base("$cfp").$a);\r
506       \r
507       /*遅延評価*/\r
508       base("$bfp").up("$s").of( {\r
509         lazy: {\r
510           a: base("$cfp")\r
511         },\r
512         call: function() {\r
513           return this.lazy.a;\r
514         }\r
515       } );\r
516       expect(base("$bfp").$s.call()).toBe(base("$cfp"));\r
517     });\r
518     \r
519     /*無効同値を調べる*/\r
520     it("Equivalence partitioning, the following is the invalid partion", function() {\r
521       base("$efp").of( {\r
522         a: base("$ee"),\r
523         call: function() {\r
524           return this.a();\r
525         }\r
526       } );\r
527       expect(function() {\r
528         base("$efp").call();\r
529       }).toThrow();\r
530       } );\r
531   });\r
532 \r
533   it("should occur an error, if no arguments", function(){\r
534     var message = "No arguments error";\r
535     expect(function(){\r
536       base();\r
537     }).toThrow(message);\r
538     expect(function(){\r
539       base("$error").mix();\r
540     }).toThrow(message);\r
541     expect(function(){\r
542       base("$error").on();\r
543     }).toThrow(message);\r
544     expect(function(){\r
545       base("$error").of();\r
546     }).toThrow(message);\r
547     message = void 0;\r
548   });\r
549 });\r