1 | describe('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 |
|
266 |
|
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 |
|
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 |
|
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;
|
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 | });
|