dc07ccb4f29f9949024025308b9b7578c77114e4
[pwl6.git] / yT.js
1 var JS = this.JS || require('jstest');
2 var yT = this.yT || require('yuu/yT');
3
4 JS.Test.describe('yT', function() { with (this) {
5
6 it("makes Object subclasses", function () { with (this) {
7 var A = yT(Object, {});
8 assertKindOf(Object, new A());
9 }});
10 it("makes Object subclasses from a prototype", function () { with (this) {
11 var A = yT(Object.prototype, {});
12 assertKindOf(Object, new A());
13 }});
14 it("makes a non-Object subclass", function () { with (this) {
15 var A = yT(null, {});
16 var a = new A();
17 assertKindOf("object", a);
18 assertNot(a instanceof Object);
19 }});
20 it("makes Object subclasses by default", function () { with (this) {
21 var A = yT({});
22 assertKindOf(Object, new A());
23 }});
24 it("makes nested subclasses", function () { with (this) {
25 var A = yT({});
26 var B = yT(A, {});
27 assertKindOf(Object, new B());
28 assertKindOf(A, new B());
29 assertKindOf(B, new B());
30 }});
31 it("makes nested subclasses from a prototype", function () { with (this) {
32 var A = yT({});
33 var B = yT(A.prototype, {});
34 assertKindOf(Object, new B());
35 assertKindOf(A, new B());
36 assertKindOf(B, new B());
37 }});
38
39 it("sets constructors", function () { with (this) {
40 function ctor () {};
41 var A = yT({ constructor: ctor });
42 var a = new A();
43 assertSame(A, a.constructor);
44 assertSame(ctor, a.constructor);
45 }});
46 it("auto-creates root constructors", function () { with (this) {
47 var A = yT({});
48 var a = new A();
49 assertSame(A, a.constructor);
50 }});
51 it("auto-creates parent-calling constructors", function () { with (this) {
52 var A = yT({ constructor: function (x, y) { this.i = x + y; } });
53 var B = yT(A, {});
54 var b = new B(1, 2);
55 assertEqual(3, b.i);
56 assertSame(B, b.constructor);
57 assertNotSame(A, b.constructor);
58 }});
59
60 it("creates data descriptors", function () { with (this) {
61 var A = yT({ X: { value: 1 } });
62 var a = new A();
63 assertEqual(1, a.X);
64 a.X = 2;
65 assertEqual(1, a.X, "X should not be writable");
66 }});
67 it("creates writable data descriptors", function () { with (this) {
68 var A = yT({ x: { value: 1, writable: true } });
69 var a = new A();
70 assertEqual(1, a.x);
71 a.x = 2;
72 assertEqual(2, a.x);
73 }});
74 it("creates bare value descriptors", function () { with (this) {
75 var A = yT({ X: 1 });
76 var a = new A();
77 assertEqual(1, a.X);
78 a.X = 2;
79 assertEqual(1, a.X, "X should not be writable");
80 }});
81 it("creates read-only aliases", function () { with (this) {
82 var A = yT({ a: { alias: "b", readonly: true } });
83 var a = new A();
84 a.b = "hello";
85 assertEqual("hello", a.a);
86 a.b = "world";
87 assertEqual("world", a.a);
88 a.a = "goodbye";
89 assertEqual("world", a.a);
90 assertEqual("world", a.b);
91 }});
92 it("creates read-write aliases", function () { with (this) {
93 var A = yT({ a: { alias: "b", readonly: false } });
94 var a = new A();
95 a.b = "hello";
96 assertEqual("hello", a.a);
97 a.b = "world";
98 assertEqual("world", a.a);
99 a.a = "goodbye";
100 assertEqual("goodbye", a.a);
101 assertEqual("goodbye", a.b);
102 }});
103 it("creates read-write aliases by default", function () { with (this) {
104 var A = yT({ a: { alias: "b" } });
105 var a = new A();
106 a.b = "hello";
107 assertEqual("hello", a.a);
108 a.b = "world";
109 assertEqual("world", a.a);
110 a.a = "goodbye";
111 assertEqual("goodbye", a.a);
112 assertEqual("goodbye", a.b);
113 }});
114 }});
115
116 JS.Test.describe('an example Point type', function() { with (this) {
117 var Point = yT({
118 constructor: function (x, y) {
119 this.x = x || 0;
120 this.y = y || 0;
121 },
122
123 x: { value: 0, chainable: true },
124 y: { value: 0, chainable: true },
125 0: { alias: "x" },
126 1: { alias: "y" },
127 xy: { swizzle: "xy" },
128 yx: { swizzle: "yx" },
129
130 angle: {
131 chainable: true,
132 get: function () {
133 return Math.atan2(this.y, this.x);
134 },
135 set: function (angle) {
136 var magnitude = this.magnitude;
137 this.x = Math.cos(angle) * magnitude;
138 this.y = Math.sin(angle) * magnitude;
139 }
140 },
141
142 magnitude: {
143 chainable: true,
144 get: function () {
145 return Math.sqrt(this.x * this.x + this.y * this.y);
146 },
147 set: function (magnitude) {
148 var angle = this.angle;
149 this.x = Math.cos(angle) * magnitude;
150 this.y = Math.sin(angle) * magnitude;
151 }
152 },
153
154 length: 2
155 });
156
157 it("constructs 0, 0 by default", function () { with (this) {
158 var p = new Point();
159 assertEqual(0, p.x);
160 assertEqual(0, p.y);
161 assertEqual(2, p.length);
162 }});
163
164
165 it("has chainable setters", function () { with (this) {
166 var p = new Point().setX(1).setY(2);
167 assertEqual(1, p.x);
168 assertEqual(2, p.y);
169 }});
170
171 it("x is also 0", function () { with (this) {
172 var p = new Point();
173 assertEqual(0, p.x);
174 assertEqual(0, p[0]);
175 p.x = 1;
176 assertEqual(1, p.x);
177 assertEqual(1, p[0]);
178 p[0] = 2;
179 assertEqual(2, p.x);
180 assertEqual(2, p[0]);
181 }});
182 it("y is also 1", function () { with (this) {
183 var p = new Point();
184 assertEqual(0, p.y);
185 assertEqual(0, p[1]);
186 p.y = 1;
187 assertEqual(1, p.y);
188 assertEqual(1, p[1]);
189 p[1] = 2;
190 assertEqual(2, p.y);
191 assertEqual(2, p[1]);
192 }});
193
194 it("x and y have swizzling", function () { with (this) {
195 var p = new Point();
196 assertEqual([0, 0], p.xy);
197 assertEqual([0, 0], p.yx);
198 p.xy = [1, 0];
199 assertEqual([1, 0], p.xy);
200 assertEqual([0, 1], p.yx);
201 p.xy = p.yx;
202 assertEqual([0, 1], p.xy);
203 assertEqual([1, 0], p.yx);
204 }});
205
206 it("can change magnitude", function () { with (this) {
207 var p = new Point(1, 0);
208 assertEqual(1, p.magnitude);
209 p.magnitude = 10;
210 assertEqual([10, 0], p.xy);
211 }});
212 it("can change angle", function () { with (this) {
213 var delta = 1e-13;
214 var p = new Point(1, 0);
215 assertEqual(0, p.angle);
216 p.angle = Math.PI / 2;
217 assertInDelta(Math.PI / 2, p.angle, delta);
218 assertInDelta(0, p.x, delta);
219 assertInDelta(1, p.y, delta);
220 p.angle = Math.PI / 4;
221 assertInDelta(Math.PI / 4, p.angle, delta);
222 assertInDelta(Math.sqrt(2) / 2, p.x, delta);
223 assertInDelta(Math.sqrt(2) / 2, p.y, delta);
224 assertInDelta(p.x, p.y, delta);
225 }});
226 }});
227