UNPKG

13 kBJavaScriptView Raw
1describe('Object', function () {
2 var ifShimIt = (typeof process !== 'undefined' && process.env.NO_ES6_SHIM) ? it.skip : it;
3
4 ifShimIt('is on the exported object', function () {
5 var exported = require('../');
6 expect(exported.Object).to.equal(Object);
7 });
8
9 var functionsHaveNames = (function foo() {}).name === 'foo';
10 var ifFunctionsHaveNamesIt = functionsHaveNames ? it : xit;
11 var ifExtensionsPreventable = Object.preventExtensions ? it : xit;
12
13 var hasSymbols = typeof Symbol === 'function' && typeof Symbol() === 'symbol';
14 var ifSymbolsIt = hasSymbols ? it : xit;
15 var ifBrowserIt = typeof window === 'object' && typeof document === 'object' ? it : xit;
16 var ifObjectGetPrototypeOfIt = typeof Object.getPrototypeOf === 'function' ? it : xit;
17
18 if (Object.getOwnPropertyNames) {
19 describe('.getOwnPropertyNames()', function () {
20 it('throws on null or undefined', function () {
21 expect(function () { Object.getOwnPropertyNames(); }).to['throw'](TypeError);
22 expect(function () { Object.getOwnPropertyNames(undefined); }).to['throw'](TypeError);
23 expect(function () { Object.getOwnPropertyNames(null); }).to['throw'](TypeError);
24 });
25
26 it('works on primitives', function () {
27 [true, false, NaN, 42, /a/g, 'foo'].forEach(function (item) {
28 expect(Object.getOwnPropertyNames(item)).to.eql(Object.getOwnPropertyNames(Object(item)));
29 });
30 });
31
32 ifBrowserIt('does not break when an iframe is added', function () {
33 var div = document.createElement('div');
34 div.innerHTML = '<iframe src="http://xkcd.com"></iframe>';
35 document.body.appendChild(div);
36 setTimeout(function () {
37 document.body.removeChild(div);
38 }, 0);
39 expect(Array.isArray(Object.getOwnPropertyNames(window))).to.eql(true);
40 });
41 });
42 }
43
44 if (Object.getOwnPropertyDescriptor) {
45 describe('.getOwnPropertyDescriptor()', function () {
46 it('throws on null or undefined', function () {
47 expect(function () { Object.getOwnPropertyDescriptor(); }).to['throw'](TypeError);
48 expect(function () { Object.getOwnPropertyDescriptor(undefined); }).to['throw'](TypeError);
49 expect(function () { Object.getOwnPropertyDescriptor(null); }).to['throw'](TypeError);
50 });
51
52 it('works on primitives', function () {
53 [true, false, NaN, 42, /a/g, 'foo'].forEach(function (item) {
54 expect(Object.getOwnPropertyDescriptor(item, 'foo')).to.eql(Object.getOwnPropertyDescriptor(Object(item), 'foo'));
55 });
56 });
57 });
58 }
59
60 if (Object.seal) {
61 describe('.seal()', function () {
62 it('works on primitives', function () {
63 [null, undefined, true, false, NaN, 42, 'foo'].forEach(function (item) {
64 expect(Object.seal(item)).to.eql(item);
65 });
66 });
67 });
68 }
69
70 if (Object.isSealed) {
71 describe('.isSealed()', function () {
72 it('works on primitives', function () {
73 [null, undefined, true, false, NaN, 42, 'foo'].forEach(function (item) {
74 expect(Object.isSealed(item)).to.equal(true);
75 });
76 });
77 });
78 }
79
80 if (Object.freeze) {
81 describe('.freeze()', function () {
82 it('works on primitives', function () {
83 [null, undefined, true, false, NaN, 42, 'foo'].forEach(function (item) {
84 expect(Object.freeze(item)).to.eql(item);
85 });
86 });
87 });
88 }
89
90 if (Object.isFrozen) {
91 describe('.isFrozen()', function () {
92 it('works on primitives', function () {
93 [null, undefined, true, false, NaN, 42, 'foo'].forEach(function (item) {
94 expect(Object.isFrozen(item)).to.equal(true);
95 });
96 });
97 });
98 }
99
100 if (Object.preventExtensions) {
101 describe('.preventExtensions()', function () {
102 it('works on primitives', function () {
103 [null, undefined, true, false, NaN, 42, 'foo'].forEach(function (item) {
104 expect(Object.preventExtensions(item)).to.eql(item);
105 });
106 });
107 });
108 }
109
110 if (Object.isExtensible) {
111 describe('.isExtensible()', function () {
112 it('works on primitives', function () {
113 [null, undefined, true, false, NaN, 42, 'foo'].forEach(function (item) {
114 expect(Object.isExtensible(item)).to.equal(false);
115 });
116 });
117 });
118 }
119
120 describe('.keys()', function () {
121 it('works on strings', function () {
122 expect(Object.keys('foo')).to.eql(['0', '1', '2']);
123 });
124
125 it('throws on null or undefined', function () {
126 expect(function () { Object.keys(); }).to['throw'](TypeError);
127 expect(function () { Object.keys(undefined); }).to['throw'](TypeError);
128 expect(function () { Object.keys(null); }).to['throw'](TypeError);
129 });
130
131 it('works on other primitives', function () {
132 [true, false, NaN, 42, /a/g].forEach(function (item) {
133 expect(Object.keys(item)).to.eql([]);
134 });
135 });
136 });
137
138 describe('.is()', function () {
139 if (!Object.prototype.hasOwnProperty.call(Object, 'is')) {
140 return it('exists', function () {
141 expect(Object).to.have.property('is');
142 });
143 }
144
145 ifFunctionsHaveNamesIt('has the right name', function () {
146 expect(Object.is).to.have.property('name', 'is');
147 });
148
149 it('should have the right arity', function () {
150 expect(Object.is).to.have.property('length', 2);
151 });
152
153 it('should compare regular objects correctly', function () {
154 [null, undefined, [0], 5, 'str', { a: null }].map(function (item) {
155 return Object.is(item, item);
156 }).forEach(function (result) {
157 expect(result).to.equal(true);
158 });
159 });
160
161 it('should compare 0 and -0 correctly', function () {
162 expect(Object.is(0, -0)).to.equal(false);
163 });
164
165 it('should compare NaNs correctly', function () {
166 expect(Object.is(NaN, NaN)).to.equal(true);
167 });
168 });
169
170 describe('.assign()', function () {
171 if (!Object.prototype.hasOwnProperty.call(Object, 'assign')) {
172 return it('exists', function () {
173 expect(Object).to.have.property('assign');
174 });
175 }
176
177 it('has the correct length', function () {
178 expect(Object.assign.length).to.eql(2);
179 });
180
181 it('returns the modified target object', function () {
182 var target = {};
183 var returned = Object.assign(target, { a: 1 });
184 expect(returned).to.equal(target);
185 });
186
187 it('should merge two objects', function () {
188 var target = { a: 1 };
189 var returned = Object.assign(target, { b: 2 });
190 expect(returned).to.eql({ a: 1, b: 2 });
191 });
192
193 it('should merge three objects', function () {
194 var target = { a: 1 };
195 var source1 = { b: 2 };
196 var source2 = { c: 3 };
197 var returned = Object.assign(target, source1, source2);
198 expect(returned).to.eql({ a: 1, b: 2, c: 3 });
199 });
200
201 it('only iterates over own keys', function () {
202 var Foo = function () {};
203 Foo.prototype.bar = true;
204 var foo = new Foo();
205 foo.baz = true;
206 var target = { a: 1 };
207 var returned = Object.assign(target, foo);
208 expect(returned).to.equal(target);
209 expect(target).to.eql({ baz: true, a: 1 });
210 });
211
212 it('throws when target is null or undefined', function () {
213 expect(function () { Object.assign(null); }).to['throw'](TypeError);
214 expect(function () { Object.assign(undefined); }).to['throw'](TypeError);
215 });
216
217 it('coerces lone target to an object', function () {
218 var result = {
219 bool: Object.assign(true),
220 number: Object.assign(1),
221 string: Object.assign('1')
222 };
223
224 expect(typeof result.bool).to.equal('object');
225 expect(Boolean.prototype.valueOf.call(result.bool)).to.equal(true);
226
227 expect(typeof result.number).to.equal('object');
228 expect(Number.prototype.valueOf.call(result.number)).to.equal(1);
229
230 expect(typeof result.string).to.equal('object');
231 expect(String.prototype.valueOf.call(result.string)).to.equal('1');
232 });
233
234 it('coerces target to an object, assigns from sources', function () {
235 var sourceA = { a: 1 };
236 var sourceB = { b: 1 };
237
238 var result = {
239 bool: Object.assign(true, sourceA, sourceB),
240 number: Object.assign(1, sourceA, sourceB),
241 string: Object.assign('1', sourceA, sourceB)
242 };
243
244 expect(typeof result.bool).to.equal('object');
245 expect(Boolean.prototype.valueOf.call(result.bool)).to.equal(true);
246 expect(result.bool).to.eql({ a: 1, b: 1 });
247
248 expect(typeof result.number).to.equal('object');
249 expect(Number.prototype.valueOf.call(result.number)).to.equal(1);
250
251 expect(typeof result.string).to.equal('object');
252 expect(String.prototype.valueOf.call(result.string)).to.equal('1');
253 expect(result.string).to.eql({ 0: '1', a: 1, b: 1 });
254 });
255
256 it('ignores non-object sources', function () {
257 expect(Object.assign({ a: 1 }, null, { b: 2 })).to.eql({ a: 1, b: 2 });
258 expect(Object.assign({ a: 1 }, undefined, { b: 2 })).to.eql({ a: 1, b: 2 });
259 expect(Object.assign({ a: 1 }, { b: 2 }, null)).to.eql({ a: 1, b: 2 });
260 });
261
262 ifExtensionsPreventable('does not have pending exceptions', function () {
263 'use strict';
264
265 // Firefox 37 still has "pending exception" logic in its Object.assign implementation,
266 // which is 72% slower than our shim, and Firefox 40's native implementation.
267 var thrower = { 1: 2, 2: 3, 3: 4 };
268 Object.defineProperty(thrower, 2, {
269 get: function () { return 3; },
270 set: function (v) { throw new RangeError('IE 9 does not throw on preventExtensions: ' + v); }
271 });
272 Object.preventExtensions(thrower);
273 expect(thrower).to.have.property(2, 3);
274 var error;
275 try {
276 Object.assign(thrower, 'wxyz');
277 } catch (e) {
278 error = e;
279 }
280 expect(thrower).not.to.have.property(0);
281 if (thrower[1] === 'x') {
282 // IE 9 doesn't throw in strict mode with preventExtensions
283 expect(error).to.be.an.instanceOf(RangeError);
284 } else {
285 expect(error).to.be.an.instanceOf(TypeError);
286 expect(thrower).to.have.property(1, 2);
287 }
288 expect(thrower).to.have.property(2, 3);
289 expect(thrower).to.have.property(3, 4);
290 });
291
292 ifSymbolsIt('includes enumerable symbols, after keys', function () {
293 /* eslint max-statements-per-line: 1 */
294 var visited = [];
295 var obj = {};
296 Object.defineProperty(obj, 'a', { get: function () { visited.push('a'); return 42; }, enumerable: true });
297 var symbol = Symbol('enumerable');
298 Object.defineProperty(obj, symbol, {
299 get: function () { visited.push(symbol); return Infinity; },
300 enumerable: true
301 });
302 var nonEnumSymbol = Symbol('non-enumerable');
303 Object.defineProperty(obj, nonEnumSymbol, {
304 get: function () { visited.push(nonEnumSymbol); return -Infinity; },
305 enumerable: false
306 });
307 var target = Object.assign({}, obj);
308 expect(visited).to.eql(['a', symbol]);
309 expect(target.a).to.equal(42);
310 expect(target[symbol]).to.equal(Infinity);
311 expect(target[nonEnumSymbol]).not.to.equal(-Infinity);
312 });
313 });
314
315 describe('Object.setPrototypeOf()', function () {
316 if (!Object.setPrototypeOf) {
317 return; // IE < 11
318 }
319
320 describe('argument checking', function () {
321 it('should throw TypeError if first arg is not object', function () {
322 var nonObjects = [null, undefined, true, false, 1, 3, 'foo'];
323 nonObjects.forEach(function (value) {
324 expect(function () { Object.setPrototypeOf(value); }).to['throw'](TypeError);
325 });
326 });
327
328 it('should throw TypeError if second arg is not object or null', function () {
329 expect(function () { Object.setPrototypeOf({}, null); }).not.to['throw'](TypeError);
330 var invalidPrototypes = [true, false, 1, 3, 'foo'];
331 invalidPrototypes.forEach(function (proto) {
332 expect(function () { Object.setPrototypeOf({}, proto); }).to['throw'](TypeError);
333 });
334 });
335 });
336
337 describe('set prototype', function () {
338 it('should work', function () {
339 var Foo = function () {};
340 var Bar = {};
341 var foo = new Foo();
342 expect(Object.getPrototypeOf(foo)).to.equal(Foo.prototype);
343
344 var fooBar = Object.setPrototypeOf(foo, Bar);
345 expect(fooBar).to.equal(foo);
346 expect(Object.getPrototypeOf(foo)).to.equal(Bar);
347 });
348 it('should be able to set to null', function () {
349 var Foo = function () {};
350 var foo = new Foo();
351
352 var fooNull = Object.setPrototypeOf(foo, null);
353 expect(fooNull).to.equal(foo);
354 expect(Object.getPrototypeOf(foo)).to.equal(null);
355 });
356 });
357 });
358
359 describe('.getPrototypeOf()', function () {
360 ifObjectGetPrototypeOfIt('does not throw for a primitive', function () {
361 expect(Object.getPrototypeOf(3)).to.equal(Number.prototype);
362 });
363 });
364});