Version 1
[yaffs-website] / node_modules / es5-shim / tests / spec / s-object.js
1 /* global describe, it, xit, expect, beforeEach, jasmine, window */
2
3 var has = Object.prototype.hasOwnProperty;
4 var supportsDescriptors = Object.defineProperty && (function () {
5     try {
6         var obj = {};
7         Object.defineProperty(obj, 'x', { enumerable: false, value: obj });
8         for (var _ in obj) { return false; } // jscs:ignore disallowUnusedVariables
9         return obj.x === obj;
10     } catch (e) { /* this is ES3 */
11         return false;
12     }
13 }());
14 var ifWindowIt = typeof window === 'undefined' ? xit : it;
15 var extensionsPreventible = typeof Object.preventExtensions === 'function' && (function () {
16     var obj = {};
17     Object.preventExtensions(obj);
18     obj.a = 3;
19     return obj.a !== 3;
20 }());
21 var ifExtensionsPreventibleIt = extensionsPreventible ? it : xit;
22 var canSeal = typeof Object.seal === 'function' && (function () {
23     var obj = { a: 3 };
24     Object.seal(obj);
25     delete obj.a;
26     return obj.a === 3;
27 }());
28 var ifCanSealIt = canSeal ? it : xit;
29 var canFreeze = typeof Object.freeze === 'function' && (function () {
30     var obj = {};
31     Object.freeze(obj);
32     obj.a = 3;
33     return obj.a !== 3;
34 }());
35 var ifCanFreezeIt = canFreeze ? it : xit;
36
37 describe('Object', function () {
38     'use strict';
39
40     describe('.keys()', function () {
41         var obj = {
42             str: 'boz',
43             obj: { },
44             arr: [],
45             bool: true,
46             num: 42,
47             'null': null,
48             undefined: undefined
49         };
50
51         var loopedValues = [];
52         for (var key in obj) {
53             loopedValues.push(key);
54         }
55
56         var keys = Object.keys(obj);
57         it('should have correct length', function () {
58             expect(keys.length).toBe(7);
59         });
60
61         describe('arguments objects', function () {
62             it('works with an arguments object', function () {
63                 (function () {
64                     expect(arguments.length).toBe(3);
65                     expect(Object.keys(arguments).length).toBe(arguments.length);
66                     expect(Object.keys(arguments)).toEqual(['0', '1', '2']);
67                 }(1, 2, 3));
68             });
69
70             it('works with a legacy arguments object', function () {
71                 var FakeArguments = function (args) {
72                     args.forEach(function (arg, i) {
73                         this[i] = arg;
74                     }.bind(this));
75                 };
76                 FakeArguments.prototype.length = 3;
77                 FakeArguments.prototype.callee = function () {};
78
79                 var fakeOldArguments = new FakeArguments(['a', 'b', 'c']);
80                 expect(Object.keys(fakeOldArguments)).toEqual(['0', '1', '2']);
81             });
82         });
83
84         it('should return an Array', function () {
85             expect(Array.isArray(keys)).toBe(true);
86         });
87
88         it('should return names which are own properties', function () {
89             keys.forEach(function (name) {
90                 expect(has.call(obj, name)).toBe(true);
91             });
92         });
93
94         it('should return names which are enumerable', function () {
95             keys.forEach(function (name) {
96                 expect(loopedValues.indexOf(name)).toNotBe(-1);
97             });
98         });
99
100         // ES6 Object.keys does not require this throw
101         xit('should throw error for non object', function () {
102             var e = {};
103             expect(function () {
104                 try {
105                     Object.keys(42);
106                 } catch (err) {
107                     throw e;
108                 }
109             }).toThrow(e);
110         });
111
112         describe('enumerating over non-enumerable properties', function () {
113             it('has no enumerable keys on a Function', function () {
114                 var Foo = function () {};
115                 expect(Object.keys(Foo.prototype)).toEqual([]);
116             });
117
118             it('has no enumerable keys on a boolean', function () {
119                 expect(Object.keys(Boolean.prototype)).toEqual([]);
120             });
121
122             it('has no enumerable keys on an object', function () {
123                 expect(Object.keys(Object.prototype)).toEqual([]);
124             });
125         });
126
127         it('works with boxed primitives', function () {
128             expect(Object.keys(Object('hello'))).toEqual(['0', '1', '2', '3', '4']);
129         });
130
131         it('works with boxed primitives with extra properties', function () {
132             var x = Object('x');
133             x.y = 1;
134             var actual = Object.keys(x);
135             var expected = ['0', 'y'];
136             actual.sort();
137             expected.sort();
138             expect(actual).toEqual(expected);
139         });
140
141         ifWindowIt('can serialize all objects on the `window`', function () {
142             var windowItemKeys, exception;
143             var blacklistedKeys = ['window', 'console', 'parent', 'self', 'frame', 'frames', 'frameElement', 'external'];
144             if (supportsDescriptors) {
145                 Object.defineProperty(window, 'thrower', {
146                     configurable: true,
147                     get: function () { throw new RangeError('thrower!'); }
148                 });
149             }
150             for (var k in window) {
151                 windowItemKeys = exception = void 0;
152                 if (blacklistedKeys.indexOf(k) === -1 && has.call(window, k) && window[k] !== null && typeof window[k] === 'object') {
153                     try {
154                         windowItemKeys = Object.keys(window[k]);
155                     } catch (e) {
156                         exception = e;
157                     }
158                     expect(Array.isArray(windowItemKeys)).toBe(true);
159                     expect(exception).toBeUndefined();
160                 }
161             }
162             if (supportsDescriptors) {
163                 delete window.thrower;
164             }
165         });
166     });
167
168     describe('.isExtensible()', function () {
169         var obj = { };
170
171         it('should return true if object is extensible', function () {
172             expect(Object.isExtensible(obj)).toBe(true);
173         });
174
175         ifExtensionsPreventibleIt('should return false if object is not extensible', function () {
176             expect(Object.isExtensible(Object.preventExtensions(obj))).toBe(false);
177         });
178
179         ifCanSealIt('should return false if object is sealed', function () {
180             expect(Object.isExtensible(Object.seal(obj))).toBe(false);
181         });
182
183         ifCanFreezeIt('should return false if object is frozen', function () {
184             expect(Object.isExtensible(Object.freeze(obj))).toBe(false);
185         });
186
187         it('should throw error for non object', function () {
188             try {
189                 // note: in ES6, this is expected to return false.
190                 expect(Object.isExtensible(42)).toBe(false);
191             } catch (err) {
192                 expect(err).toEqual(jasmine.any(TypeError));
193             }
194         });
195     });
196
197     describe('.defineProperty()', function () {
198         var obj;
199
200         beforeEach(function () {
201             obj = {};
202
203             Object.defineProperty(obj, 'name', {
204                 value: 'Testing',
205                 configurable: true,
206                 enumerable: true,
207                 writable: true
208             });
209         });
210
211         it('should return the initial value', function () {
212             expect(has.call(obj, 'name')).toBeTruthy();
213             expect(obj.name).toBe('Testing');
214         });
215
216         it('should be setable', function () {
217             obj.name = 'Other';
218             expect(obj.name).toBe('Other');
219         });
220
221         it('should return the parent initial value', function () {
222             var child = Object.create(obj, {});
223
224             expect(child.name).toBe('Testing');
225             expect(has.call(child, 'name')).toBeFalsy();
226         });
227
228         it('should not override the parent value', function () {
229             var child = Object.create(obj, {});
230
231             Object.defineProperty(child, 'name', {
232                 value: 'Other'
233             });
234
235             expect(obj.name).toBe('Testing');
236             expect(child.name).toBe('Other');
237         });
238
239         it('should throw error for non object', function () {
240             expect(function () {
241                 Object.defineProperty(42, 'name', {});
242             }).toThrow();
243         });
244
245         it('should not throw error for empty descriptor', function () {
246             expect(function () {
247                 Object.defineProperty({}, 'name', {});
248             }).not.toThrow();
249         });
250     });
251
252     describe('.getOwnPropertyDescriptor()', function () {
253         it('should return undefined because the object does not own the property', function () {
254             var descr = Object.getOwnPropertyDescriptor({}, 'name');
255
256             expect(descr).toBeUndefined();
257         });
258
259         it('should return a data descriptor', function () {
260             var descr = Object.getOwnPropertyDescriptor({ name: 'Testing' }, 'name');
261             var expected = {
262                 value: 'Testing',
263                 enumerable: true,
264                 writable: true,
265                 configurable: true
266             };
267
268             expect(descr).toEqual(expected);
269         });
270
271         it('should return undefined because the object does not own the property', function () {
272             var descr = Object.getOwnPropertyDescriptor(Object.create({ name: 'Testing' }, {}), 'name');
273
274             expect(descr).toBeUndefined();
275         });
276
277         it('should return a data descriptor', function () {
278             var expected = {
279                 value: 'Testing',
280                 configurable: true,
281                 enumerable: true,
282                 writable: true
283             };
284             var obj = Object.create({}, { name: expected });
285
286             var descr = Object.getOwnPropertyDescriptor(obj, 'name');
287
288             expect(descr).toEqual(expected);
289         });
290
291         it('should throw error for non object', function () {
292             try {
293                 // note: in ES6, we expect this to return undefined.
294                 expect(Object.getOwnPropertyDescriptor(42, 'name')).toBeUndefined();
295             } catch (err) {
296                 expect(err).toEqual(jasmine.any(TypeError));
297             }
298         });
299     });
300
301     describe('.getPrototypeOf()', function () {
302         it('should return the [[Prototype]] of an object', function () {
303             var Foo = function () {};
304
305             var proto = Object.getPrototypeOf(new Foo());
306
307             expect(proto).toBe(Foo.prototype);
308         });
309
310         it('should shamone to the `Object.prototype` if `object.constructor` is not a function', function () {
311             var Foo = function () {};
312             Foo.prototype.constructor = 1;
313
314             var proto = Object.getPrototypeOf(new Foo()),
315                 fnToString = Function.prototype.toString;
316
317             if (fnToString.call(Object.getPrototypeOf).indexOf('[native code]') < 0) {
318                 expect(proto).toBe(Object.prototype);
319             } else {
320                 expect(proto).toBe(Foo.prototype);
321             }
322         });
323
324         it('should throw error for non object', function () {
325             try {
326                 expect(Object.getPrototypeOf(1)).toBe(Number.prototype); // ES6 behavior
327             } catch (err) {
328                 expect(err).toEqual(jasmine.any(TypeError));
329             }
330         });
331
332         it('should return null on Object.create(null)', function () {
333             var obj = Object.create(null);
334
335             expect(Object.getPrototypeOf(obj) === null).toBe(true);
336         });
337     });
338
339     describe('.defineProperties()', function () {
340         it('should define the constructor property', function () {
341             var target = {};
342             var newProperties = {
343                 constructor: {
344                     value: 'new constructor'
345                 }
346             };
347             Object.defineProperties(target, newProperties);
348             expect(target.constructor).toBe('new constructor');
349         });
350     });
351
352     describe('.create()', function () {
353         it('should create objects with no properties when called as `Object.create(null)`', function () {
354             var obj = Object.create(null);
355
356             expect('hasOwnProperty' in obj).toBe(false);
357             expect('toString' in obj).toBe(false);
358             expect('constructor' in obj).toBe(false);
359
360             var protoIsEnumerable = false;
361             for (var k in obj) {
362                 if (k === '__proto__') {
363                     protoIsEnumerable = true;
364                 }
365             }
366             expect(protoIsEnumerable).toBe(false);
367
368             expect(obj instanceof Object).toBe(false);
369         });
370     });
371 });