File: tests.js

package info (click to toggle)
class.js 1.0.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: buster, stretch
  • size: 188 kB
  • sloc: makefile: 114; python: 30
file content (341 lines) | stat: -rw-r--r-- 9,577 bytes parent folder | download | duplicates (2)
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
/**
 * @author		Angelo Dini
 * @version     2.0
 * @copyright	http://www.divio.ch under the BSD Licence
 */

/**
 * TESTS
 */
module("class.js");

test('Core functionality', function() {
	// tests
	equal(typeof(window.Class), 'function', 'class is available within the window object');
	equal(typeof(Class), 'function', 'Class is available to be called');
	equal(objIsEmpty(Class.prototype), true, 'prototype is empty');

	testConstructor(Class);
});

test('Class constructor', function () {
	// setup
	var Animal = new Class();
	var Person = new Class({});
	var Computer = new Class({
		'calc': function () {}
	});

	// tests
	equal(typeof(Animal), 'function', 'class is created');
	equal(objIsEmpty(Animal.prototype), true, 'animal prototype is empty');
	equal(objIsEmpty(Person.prototype), true, 'person prototype is empty');
	equal(objIsEmpty(Computer.prototype), false, 'computer prototype is not empty');

	ok(!(Animal instanceof Class), 'animal is not an instance of class');

	var Correct = new Class({
		'isCorrect': function () {}
	});
	// using strict mode allows it at this point to "forget" the new keyword
	var Wrong = Class({
		'isWrong': function () {}
	});
	equal(typeof(Correct.prototype.isCorrect), 'function', 'invoking class with new keyword works');
	equal(typeof(Wrong.prototype.isWrong), 'function', 'invoking class without the new keyword works');

	equal(typeof(new Correct().isCorrect), 'function', 'invoking instance with new keyword works');
	// you should not be able to call Wrong().isWrong without the new keyword
	equal(typeof(new Wrong().isWrong), 'function', 'invoking instance with new keyword works');

	testConstructor(Animal);
});

test('Class noConflict', function () {
	// setup
	var Original = window.Class;
	var Classy = Class.noConflict();
	var Animal = new Classy();

	// tests
	strictEqual(window.Class, undefined, 'noConflict unsets Class from window');
	deepEqual(Classy, Original, 'noConflict binds the new variable with Class behaviour');

	testConstructor(Animal);

	ok(true, 'For a live example consult libsTest.html');

	window.Class = Original;
});

test('Class method extend', function () {
	// setup
	var Animal = new Class({
		'initialize': function (name, age) {
			this.name = name;
			this.age = age;
		}
	});
	Animal.extend({
		'eat': function () {
			return this.name + ' is eating';
		},
		'die': function () {
			return this.name + ' died at age ' + this.age;
		}
	});
	var name = 'Cat', age = 43, instance = new Animal(name, age);

	// tests
	equal(typeof(Animal.prototype.initialize), 'function', 'initialize has been added');
	equal(typeof(Animal.prototype.eat), 'function', 'eat has been added');
	equal(typeof(Animal.prototype.die), 'function', 'die has been added');

	equal(instance.name, name, 'this.name can be called');
	equal(instance.age, age, 'this.age can be called');

	equal(instance.eat(), name + ' is eating', 'this.eat() can be called');
	equal(instance.die(), name + ' died at age ' + age, 'this.die() can be called');

	ok(instance instanceof Animal, 'correct instance for class is given');
});

test('Class method implement', function () {
	// setup
	var Animal = new Class({
		'initialize': function (name, age) {
			this.name = name;
			this.age = age;
		}
	});
	var essentials = {
		'eat': function () {
			return this.name + ' is eating';
		},
		'die': function () {
			return this.name + ' died at age ' + this.age;
		}
	};
	var advanced = {
		'dance': function () {
			return this.name + ' is dancing';
		},
		'fly': function () {
			return this.name + ' is flying';
		}
	};
	var professional = {
		'invincible': true
	};

	Animal.implement([essentials, advanced]);

	var Cat = new Class({
		'implement': [Animal],
		// initialize is not passed by implement
		'initialize': function (name, age) {
			this.name = name;
			this.age = age;
		},
		'cuteness': function () {
			return this.name + '\'s level is 99';
		}
	});
	Cat.extend({
		'implement': [professional],
		'superpower': true
	});
	var myCat = new Cat('Sora', 2);

	// tests
	equal(typeof(Cat.prototype.initialize), 'function', 'initialize has been added');
	equal(typeof(Cat.prototype.eat), 'function', 'eat has been added');
	equal(typeof(Cat.prototype.die), 'function', 'die has been added');
	equal(typeof(Cat.prototype.dance), 'function', 'dance has been added');
	equal(typeof(Cat.prototype.fly), 'function', 'fly has been added');
	equal(typeof(Cat.prototype.cuteness), 'function', 'cuteness has been added');
	strictEqual(Cat.prototype.invincible, true, 'cuteness has been added');
	strictEqual(Cat.prototype.superpower, true, 'cuteness has been added');
	strictEqual(Cat.prototype.implement, undefined, 'implement has not been passed');
	equal(myCat.cuteness(), 'Sora\'s level is 99', 'appropriate methods can be called');
});

test('Class method getOptions', function () {
	// setup
	var Animal = new Class({
		'options': {
			'name': 'Unnamed',
			'age': 5
		},
		'initialize': function (name, age) {
			this.name = name || this.options.name;
			this.age = age || this.options.age;
		}
	});
	var options = Animal.getOptions();
	var Cat = new Animal('Sora', 2);

	// tests
	equal(options.name, 'Unnamed', 'option name can be read via getOptions');
	equal(options.age, 5, 'option age can be read via getOptions');

	equal(Cat.options.name, 'Unnamed', 'option name can be read via method call');
	equal(Cat.options.age, 5, 'option age can be read via method call');

	equal(Cat.name, 'Sora', 'class name is set correctly');
	equal(Cat.age, 2, 'class age is set correctly');
});

test('Class method setOptions', function () {
	// setup
	var Animal = new Class({
		'options': {
			'name': 'Unnamed',
			'age': 5
		},
		'initialize': function (name, age) {
			this.name = name || this.options.name;
			this.age = age || this.options.age;
		}
	});

	var Cat = new Animal('Sora', 2);
	var Dog = new Animal('Pitschy', 1);

	// tests
	equal(Cat.options.age, 5, 'option age can be read via method call');
	equal(Dog.options.age, 5, 'option age can be read via method call');

	Animal.setOptions({ 'age': 10 });
	equal(Cat.options.age, 10, 'option age can be read via method call');
	equal(Dog.options.age, 10, 'option age can be read via method call');

	Animal.setOptions({ 'age': 15 });
	equal(Cat.options.age, 15, 'option age can be read via method call');
	equal(Dog.options.age, 15, 'option age can be read via method call');

	equal(Cat.age, 2, 'correct age is given');
	equal(Dog.age, 1, 'correct age is given');

	equal(Cat.options.name, 'Unnamed', 'option name can be read via method call');
	equal(Dog.options.name, 'Unnamed', 'option name can be read via method call');

	ok(Cat instanceof Animal, 'correct instance for class is given');
	ok(Dog instanceof Animal, 'correct instance for class is given');
});

test('Class method parent', function () {
	// setup
	var Animal = new Class({
		'initialize': function (name, age) {
			this.name = name;
			this.age = age;
		},
		'eat': function () {
			this.name = 'Pitschy';

			return this.name + ' call FIRST eat';
		},
		'live': function () {
			// the return value will be overwritten
			return this.age + ' call FIRST live';
		}
	});
	Animal.extend({
		'die': function () {}
	});
	Animal.extend({
		'eat': function () {
			this.parent();

			return this.name + ' call SECOND eat';
		},
		'live': function () {
			this.parent();

			return this.age + ' call SECOND live';
		}
	});

	var Cat = new Animal('Sora', 2);

	// tests
	equal(Cat.eat(), 'Pitschy call SECOND eat', 'parent works on first invocation');
	equal(Cat.live(), '2 call SECOND live', 'parent works on second invocation');
	equal(typeof(Cat.die), 'function', 'extending function has been attached');

	ok(Cat.parent(), 'parent is attached to the normal object');
});

test('Class method version', function () {
	// tests
	equal(typeof(Class.version), 'string', 'Class.version() can be called');
});

test('Class demo examples', function () {
	var Dimmer = new Class({
		initialize: function (container) {
			this.container = document.getElementById(container);
		},
		showDim: function () {
			console.log('first');
			return 'show dim';
		},
		hideDim: function () {
			return 'hide dim';
		}
	});

	var Lightbox = new Class({
		implement: [Dimmer],
		initialize: function (container) {
			this.container = document.getElementById(container);
		},
		show: function () {
			this.showDim();
		},
		hide: function () {
			this.hideDim();
		},
		hideDim: function () {
			// this does NOT work, implement overwrites custom methods
			// if you want to create a custom hideDime use extend on Dimmer
			this.parent();
			return 'hide custom dim';
		}
	});

	Lightbox.implement([Dimmer]);

	var lb = new Lightbox();

	// tests
	equal(lb.hideDim(), 'hide dim', 'implement successfully overwrites the instnace method');
});

test('Cleanup check', function () {
	// tests
	equal(typeof(window.Class), 'function', 'class is available within the window object');
	equal(typeof(Class), 'function', 'Class is available to be called');
	equal(objIsEmpty(Class.prototype), true, 'prototype is empty');

	testConstructor(Class);
});

/**
 * HELPERS
 */
// test if an obj is empty or not
function objIsEmpty(obj) {
	for(var prop in obj) {
		if(prop) return false;
	}
	return true;
}
// base constructor tests
function testConstructor(obj) {
	equal(typeof(obj.extend), 'function', 'extend is available');
	equal(typeof(obj.implement), 'function', 'implement is available');
	equal(typeof(obj.setOptions), 'function', 'setOptions is available');
	equal(typeof(obj.getOptions), 'function', 'getOptions is available');
}