object_test.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. // Copyright 2006 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. goog.provide('goog.objectTest');
  15. goog.setTestOnly('goog.objectTest');
  16. goog.require('goog.array');
  17. goog.require('goog.functions');
  18. goog.require('goog.object');
  19. goog.require('goog.testing.jsunit');
  20. goog.require('goog.testing.recordFunction');
  21. function stringifyObject(m) {
  22. var keys = goog.object.getKeys(m);
  23. var s = '';
  24. for (var i = 0; i < keys.length; i++) {
  25. s += keys[i] + goog.object.get(m, keys[i]);
  26. }
  27. return s;
  28. }
  29. function getObject() {
  30. return {a: 0, b: 1, c: 2, d: 3};
  31. }
  32. function testKeys() {
  33. var m = getObject();
  34. assertEquals(
  35. 'getKeys, The keys should be a,b,c', 'a,b,c,d',
  36. goog.object.getKeys(m).join(','));
  37. }
  38. function testValues() {
  39. var m = getObject();
  40. assertEquals(
  41. 'getValues, The values should be 0,1,2', '0,1,2,3',
  42. goog.object.getValues(m).join(','));
  43. }
  44. function testGetAnyKey() {
  45. var m = getObject();
  46. assertTrue(
  47. 'getAnyKey, The key should be a,b,c or d', goog.object.getAnyKey(m) in m);
  48. assertUndefined(
  49. 'getAnyKey, The key should be undefined', goog.object.getAnyKey({}));
  50. }
  51. function testGetAnyValue() {
  52. var m = getObject();
  53. assertTrue(
  54. 'getAnyValue, The value should be 0,1,2 or 3',
  55. goog.object.containsValue(m, goog.object.getAnyValue(m)));
  56. assertUndefined(
  57. 'getAnyValue, The value should be undefined',
  58. goog.object.getAnyValue({}));
  59. }
  60. function testContainsKey() {
  61. var m = getObject();
  62. assertTrue(
  63. "containsKey, Should contain the 'a' key",
  64. goog.object.containsKey(m, 'a'));
  65. assertFalse(
  66. "containsKey, Should not contain the 'e' key",
  67. goog.object.containsKey(m, 'e'));
  68. }
  69. function testContainsValue() {
  70. var m = getObject();
  71. assertTrue(
  72. 'containsValue, Should contain the value 0',
  73. goog.object.containsValue(m, 0));
  74. assertFalse(
  75. 'containsValue, Should not contain the value 4',
  76. goog.object.containsValue(m, 4));
  77. assertTrue('isEmpty, The map should not be empty', !goog.object.isEmpty(m));
  78. }
  79. function testFindKey() {
  80. var dict = {'a': 1, 'b': 2, 'c': 3, 'd': 4};
  81. var key = goog.object.findKey(dict, function(v, k, d) {
  82. assertEquals('valid 3rd argument', dict, d);
  83. assertTrue('valid 1st argument', goog.object.containsValue(d, v));
  84. assertTrue('valid 2nd argument', k in d);
  85. return v % 3 == 0;
  86. });
  87. assertEquals('key "c" found', 'c', key);
  88. var pred = function(value) { return value > 5; };
  89. assertUndefined('no match', goog.object.findKey(dict, pred));
  90. }
  91. function testFindValue() {
  92. var dict = {'a': 1, 'b': 2, 'c': 3, 'd': 4};
  93. var value = goog.object.findValue(dict, function(v, k, d) {
  94. assertEquals('valid 3rd argument', dict, d);
  95. assertTrue('valid 1st argument', goog.object.containsValue(d, v));
  96. assertTrue('valid 2nd argument', k in d);
  97. return k.toUpperCase() == 'C';
  98. });
  99. assertEquals('value 3 found', 3, value);
  100. var pred = function(value, key) { return key > 'd'; };
  101. assertUndefined('no match', goog.object.findValue(dict, pred));
  102. }
  103. function testClear() {
  104. var m = getObject();
  105. goog.object.clear(m);
  106. assertTrue('cleared so it should be empty', goog.object.isEmpty(m));
  107. assertFalse(
  108. "cleared so it should not contain 'a' key",
  109. goog.object.containsKey(m, 'a'));
  110. }
  111. function testClone() {
  112. var m = getObject();
  113. var m2 = goog.object.clone(m);
  114. assertFalse('clone so it should not be empty', goog.object.isEmpty(m2));
  115. assertTrue(
  116. "clone so it should contain 'c' key", goog.object.containsKey(m2, 'c'));
  117. }
  118. function testUnsafeClonePrimitive() {
  119. assertEquals(
  120. 'cloning a primitive should return an equal primitive', 5,
  121. goog.object.unsafeClone(5));
  122. }
  123. function testUnsafeCloneObjectThatHasACloneMethod() {
  124. var original = {
  125. name: 'original',
  126. clone: goog.functions.constant({name: 'clone'})
  127. };
  128. var clone = goog.object.unsafeClone(original);
  129. assertEquals('original', original.name);
  130. assertEquals('clone', clone.name);
  131. }
  132. function testUnsafeCloneObjectThatHasACloneNonMethod() {
  133. var originalIndex = {red: [0, 4], clone: [1, 3, 5, 7], yellow: [2, 6]};
  134. var clone = goog.object.unsafeClone(originalIndex);
  135. assertArrayEquals([1, 3, 5, 7], originalIndex.clone);
  136. assertArrayEquals([1, 3, 5, 7], clone.clone);
  137. }
  138. function testUnsafeCloneFlatObject() {
  139. var original = {a: 1, b: 2, c: 3};
  140. var clone = goog.object.unsafeClone(original);
  141. assertNotEquals(original, clone);
  142. assertObjectEquals(original, clone);
  143. }
  144. function testUnsafeCloneDeepObject() {
  145. var original = {a: 1, b: {c: 2, d: 3}, e: {f: {g: 4, h: 5}}};
  146. var clone = goog.object.unsafeClone(original);
  147. assertNotEquals(original, clone);
  148. assertNotEquals(original.b, clone.b);
  149. assertNotEquals(original.e, clone.e);
  150. assertEquals(1, clone.a);
  151. assertEquals(2, clone.b.c);
  152. assertEquals(3, clone.b.d);
  153. assertEquals(4, clone.e.f.g);
  154. assertEquals(5, clone.e.f.h);
  155. }
  156. function testUnsafeCloneFunctions() {
  157. var original = {f: goog.functions.constant('hi')};
  158. var clone = goog.object.unsafeClone(original);
  159. assertNotEquals(original, clone);
  160. assertEquals('hi', clone.f());
  161. assertEquals(original.f, clone.f);
  162. }
  163. function testForEach() {
  164. var m = getObject();
  165. var s = '';
  166. goog.object.forEach(m, function(val, key, m2) {
  167. assertNotUndefined(key);
  168. assertEquals(m, m2);
  169. s += key + val;
  170. });
  171. assertEquals(s, 'a0b1c2d3');
  172. }
  173. function testFilter() {
  174. var m = getObject();
  175. var m2 = goog.object.filter(m, function(val, key, m3) {
  176. assertNotUndefined(key);
  177. assertEquals(m, m3);
  178. return val > 1;
  179. });
  180. assertEquals(stringifyObject(m2), 'c2d3');
  181. }
  182. function testMap() {
  183. var m = getObject();
  184. var m2 = goog.object.map(m, function(val, key, m3) {
  185. assertNotUndefined(key);
  186. assertEquals(m, m3);
  187. return val * val;
  188. });
  189. assertEquals(stringifyObject(m2), 'a0b1c4d9');
  190. }
  191. function testSome() {
  192. var m = getObject();
  193. var b = goog.object.some(m, function(val, key, m2) {
  194. assertNotUndefined(key);
  195. assertEquals(m, m2);
  196. return val > 1;
  197. });
  198. assertTrue(b);
  199. var b = goog.object.some(m, function(val, key, m2) {
  200. assertNotUndefined(key);
  201. assertEquals(m, m2);
  202. return val > 100;
  203. });
  204. assertFalse(b);
  205. }
  206. function testEvery() {
  207. var m = getObject();
  208. var b = goog.object.every(m, function(val, key, m2) {
  209. assertNotUndefined(key);
  210. assertEquals(m, m2);
  211. return val >= 0;
  212. });
  213. assertTrue(b);
  214. b = goog.object.every(m, function(val, key, m2) {
  215. assertNotUndefined(key);
  216. assertEquals(m, m2);
  217. return val > 1;
  218. });
  219. assertFalse(b);
  220. }
  221. function testContains() {
  222. var m = getObject();
  223. assertTrue(goog.object.contains(m, 3));
  224. assertFalse(goog.object.contains(m, 4));
  225. }
  226. function testObjectProperties() {
  227. var m = {};
  228. goog.object.set(m, 'toString', 'once');
  229. goog.object.set(m, 'valueOf', 'upon');
  230. goog.object.set(m, 'eval', 'a');
  231. goog.object.set(m, 'toSource', 'midnight');
  232. goog.object.set(m, 'prototype', 'dreary');
  233. goog.object.set(m, 'hasOwnProperty', 'dark');
  234. assertEquals(goog.object.get(m, 'toString'), 'once');
  235. assertEquals(goog.object.get(m, 'valueOf'), 'upon');
  236. assertEquals(goog.object.get(m, 'eval'), 'a');
  237. assertEquals(goog.object.get(m, 'toSource'), 'midnight');
  238. assertEquals(goog.object.get(m, 'prototype'), 'dreary');
  239. assertEquals(goog.object.get(m, 'hasOwnProperty'), 'dark');
  240. }
  241. function testSetDefault() {
  242. var dict = {};
  243. assertEquals(1, goog.object.setIfUndefined(dict, 'a', 1));
  244. assertEquals(1, dict['a']);
  245. assertEquals(1, goog.object.setIfUndefined(dict, 'a', 2));
  246. assertEquals(1, dict['a']);
  247. }
  248. function createRecordedGetFoo() {
  249. return goog.testing.recordFunction(goog.functions.constant('foo'));
  250. }
  251. function testSetWithReturnValueNotSet_KeyIsSet() {
  252. var f = createRecordedGetFoo();
  253. var obj = {};
  254. obj['key'] = 'bar';
  255. assertEquals('bar', goog.object.setWithReturnValueIfNotSet(obj, 'key', f));
  256. f.assertCallCount(0);
  257. }
  258. function testSetWithReturnValueNotSet_KeyIsNotSet() {
  259. var f = createRecordedGetFoo();
  260. var obj = {};
  261. assertEquals('foo', goog.object.setWithReturnValueIfNotSet(obj, 'key', f));
  262. f.assertCallCount(1);
  263. }
  264. function testSetWithReturnValueNotSet_KeySetValueIsUndefined() {
  265. var f = createRecordedGetFoo();
  266. var obj = {};
  267. obj['key'] = undefined;
  268. assertEquals(
  269. undefined, goog.object.setWithReturnValueIfNotSet(obj, 'key', f));
  270. f.assertCallCount(0);
  271. }
  272. function testTranspose() {
  273. var m = getObject();
  274. var b = goog.object.transpose(m);
  275. assertEquals('a', b[0]);
  276. assertEquals('b', b[1]);
  277. assertEquals('c', b[2]);
  278. assertEquals('d', b[3]);
  279. }
  280. function testExtend() {
  281. var o = {};
  282. var o2 = {a: 0, b: 1};
  283. goog.object.extend(o, o2);
  284. assertEquals(0, o.a);
  285. assertEquals(1, o.b);
  286. assertTrue('a' in o);
  287. assertTrue('b' in o);
  288. o2 = {c: 2};
  289. goog.object.extend(o, o2);
  290. assertEquals(2, o.c);
  291. assertTrue('c' in o);
  292. o2 = {c: 3};
  293. goog.object.extend(o, o2);
  294. assertEquals(3, o.c);
  295. assertTrue('c' in o);
  296. o = {};
  297. o2 = {c: 2};
  298. var o3 = {c: 3};
  299. goog.object.extend(o, o2, o3);
  300. assertEquals(3, o.c);
  301. assertTrue('c' in o);
  302. o = {};
  303. o2 = {a: 0, b: 1};
  304. o3 = {c: 2, d: 3};
  305. goog.object.extend(o, o2, o3);
  306. assertEquals(0, o.a);
  307. assertEquals(1, o.b);
  308. assertEquals(2, o.c);
  309. assertEquals(3, o.d);
  310. assertTrue('a' in o);
  311. assertTrue('b' in o);
  312. assertTrue('c' in o);
  313. assertTrue('d' in o);
  314. o = {};
  315. o2 = {
  316. 'constructor': 0,
  317. 'hasOwnProperty': 1,
  318. 'isPrototypeOf': 2,
  319. 'propertyIsEnumerable': 3,
  320. 'toLocaleString': 4,
  321. 'toString': 5,
  322. 'valueOf': 6
  323. };
  324. goog.object.extend(o, o2);
  325. assertEquals(0, o['constructor']);
  326. assertEquals(1, o['hasOwnProperty']);
  327. assertEquals(2, o['isPrototypeOf']);
  328. assertEquals(3, o['propertyIsEnumerable']);
  329. assertEquals(4, o['toLocaleString']);
  330. assertEquals(5, o['toString']);
  331. assertEquals(6, o['valueOf']);
  332. assertTrue('constructor' in o);
  333. assertTrue('hasOwnProperty' in o);
  334. assertTrue('isPrototypeOf' in o);
  335. assertTrue('propertyIsEnumerable' in o);
  336. assertTrue('toLocaleString' in o);
  337. assertTrue('toString' in o);
  338. assertTrue('valueOf' in o);
  339. }
  340. function testCreate() {
  341. assertObjectEquals(
  342. 'With multiple arguments', {a: 0, b: 1},
  343. goog.object.create('a', 0, 'b', 1));
  344. assertObjectEquals(
  345. 'With an array argument', {a: 0, b: 1},
  346. goog.object.create(['a', 0, 'b', 1]));
  347. assertObjectEquals('With no arguments', {}, goog.object.create());
  348. assertObjectEquals(
  349. 'With an ampty array argument', {}, goog.object.create([]));
  350. assertThrows('Should throw due to uneven arguments', function() {
  351. goog.object.create('a');
  352. });
  353. assertThrows('Should throw due to uneven arguments', function() {
  354. goog.object.create('a', 0, 'b');
  355. });
  356. assertThrows('Should throw due to uneven length array', function() {
  357. goog.object.create(['a']);
  358. });
  359. assertThrows('Should throw due to uneven length array', function() {
  360. goog.object.create(['a', 0, 'b']);
  361. });
  362. }
  363. function testCreateSet() {
  364. assertObjectEquals(
  365. 'With multiple arguments', {a: true, b: true},
  366. goog.object.createSet('a', 'b'));
  367. assertObjectEquals(
  368. 'With an array argument', {a: true, b: true},
  369. goog.object.createSet(['a', 'b']));
  370. assertObjectEquals('With no arguments', {}, goog.object.createSet());
  371. assertObjectEquals(
  372. 'With an ampty array argument', {}, goog.object.createSet([]));
  373. }
  374. function createTestDeepObject() {
  375. var obj = {};
  376. obj.a = {};
  377. obj.a.b = {};
  378. obj.a.b.c = {};
  379. obj.a.b.c.fooArr = [5, 6, 7, 8];
  380. obj.a.b.c.knownNull = null;
  381. return obj;
  382. }
  383. function testGetValueByKeys() {
  384. var obj = createTestDeepObject();
  385. assertEquals(obj, goog.object.getValueByKeys(obj));
  386. assertEquals(obj.a, goog.object.getValueByKeys(obj, 'a'));
  387. assertEquals(obj.a.b, goog.object.getValueByKeys(obj, 'a', 'b'));
  388. assertEquals(obj.a.b.c, goog.object.getValueByKeys(obj, 'a', 'b', 'c'));
  389. assertEquals(
  390. obj.a.b.c.d, goog.object.getValueByKeys(obj, 'a', 'b', 'c', 'd'));
  391. assertEquals(8, goog.object.getValueByKeys(obj, 'a', 'b', 'c', 'fooArr', 3));
  392. assertNull(goog.object.getValueByKeys(obj, 'a', 'b', 'c', 'knownNull'));
  393. assertUndefined(goog.object.getValueByKeys(obj, 'e', 'f', 'g'));
  394. }
  395. function testGetValueByKeysArraySyntax() {
  396. var obj = createTestDeepObject();
  397. assertEquals(obj, goog.object.getValueByKeys(obj, []));
  398. assertEquals(obj.a, goog.object.getValueByKeys(obj, ['a']));
  399. assertEquals(obj.a.b, goog.object.getValueByKeys(obj, ['a', 'b']));
  400. assertEquals(obj.a.b.c, goog.object.getValueByKeys(obj, ['a', 'b', 'c']));
  401. assertEquals(
  402. obj.a.b.c.d, goog.object.getValueByKeys(obj, ['a', 'b', 'c', 'd']));
  403. assertEquals(
  404. 8, goog.object.getValueByKeys(obj, ['a', 'b', 'c', 'fooArr', 3]));
  405. assertNull(goog.object.getValueByKeys(obj, ['a', 'b', 'c', 'knownNull']));
  406. assertUndefined(goog.object.getValueByKeys(obj, 'e', 'f', 'g'));
  407. }
  408. function testImmutableView() {
  409. if (!Object.isFrozen) {
  410. return;
  411. }
  412. var x = {propA: 3};
  413. var y = goog.object.createImmutableView(x);
  414. x.propA = 4;
  415. x.propB = 6;
  416. y.propA = 5;
  417. y.propB = 7;
  418. assertEquals(4, x.propA);
  419. assertEquals(6, x.propB);
  420. assertFalse(goog.object.isImmutableView(x));
  421. assertEquals(4, y.propA);
  422. assertEquals(6, y.propB);
  423. assertTrue(goog.object.isImmutableView(y));
  424. assertFalse('x and y should be different references', x == y);
  425. assertTrue(
  426. 'createImmutableView should not create a new view of an immutable object',
  427. y == goog.object.createImmutableView(y));
  428. }
  429. function testImmutableViewStrict() {
  430. 'use strict';
  431. // IE9 supports isFrozen, but does not support strict mode. Exit early if we
  432. // are not actually running in strict mode.
  433. var isStrict = (function() { return !this; })();
  434. if (!Object.isFrozen || !isStrict) {
  435. return;
  436. }
  437. var x = {propA: 3};
  438. var y = goog.object.createImmutableView(x);
  439. assertThrows(function() { y.propA = 4; });
  440. assertThrows(function() { y.propB = 4; });
  441. }
  442. function testEmptyObjectsAreEqual() {
  443. assertTrue(goog.object.equals({}, {}));
  444. }
  445. function testObjectsWithDifferentKeysAreUnequal() {
  446. assertFalse(goog.object.equals({'a': 1}, {'b': 1}));
  447. }
  448. function testObjectsWithDifferentValuesAreUnequal() {
  449. assertFalse(goog.object.equals({'a': 1}, {'a': 2}));
  450. }
  451. function testObjectsWithSameKeysAndValuesAreEqual() {
  452. assertTrue(goog.object.equals({'a': 1}, {'a': 1}));
  453. }
  454. function testObjectsWithSameKeysInDifferentOrderAreEqual() {
  455. assertTrue(goog.object.equals({'a': 1, 'b': 2}, {'b': 2, 'a': 1}));
  456. }
  457. function testIs() {
  458. var object = {};
  459. assertTrue(goog.object.is(object, object));
  460. assertFalse(goog.object.is(object, {}));
  461. assertTrue(goog.object.is(NaN, NaN));
  462. assertTrue(goog.object.is(0, 0));
  463. assertTrue(goog.object.is(1, 1));
  464. assertTrue(goog.object.is(-1, -1));
  465. assertTrue(goog.object.is(123, 123));
  466. assertFalse(goog.object.is(0, -0));
  467. assertFalse(goog.object.is(-0, 0));
  468. assertFalse(goog.object.is(0, 1));
  469. assertTrue(goog.object.is(true, true));
  470. assertTrue(goog.object.is(false, false));
  471. assertFalse(goog.object.is(true, false));
  472. assertFalse(goog.object.is(false, true));
  473. assertTrue(goog.object.is('', ''));
  474. assertTrue(goog.object.is('a', 'a'));
  475. assertFalse(goog.object.is('', 'a'));
  476. assertFalse(goog.object.is('a', ''));
  477. assertFalse(goog.object.is('a', 'b'));
  478. assertFalse(goog.object.is(true, 'true'));
  479. assertFalse(goog.object.is('true', true));
  480. assertFalse(goog.object.is(false, 'false'));
  481. assertFalse(goog.object.is('false', false));
  482. assertFalse(goog.object.is(0, '0'));
  483. assertFalse(goog.object.is('0', 0));
  484. }
  485. function testGetAllPropertyNames_enumerableProperties() {
  486. var obj = {a: function() {}, b: 'b', c: function(x) {}};
  487. assertSameElements(['a', 'b', 'c'], goog.object.getAllPropertyNames(obj));
  488. }
  489. function testGetAllPropertyNames_nonEnumerableProperties() {
  490. var obj = {};
  491. try {
  492. Object.defineProperty(obj, 'foo', {value: 'bar', enumerable: false});
  493. } catch (ex) {
  494. // IE8 doesn't allow Object.defineProperty on non-DOM elements.
  495. if (ex.message == 'Object doesn\'t support this action') {
  496. return;
  497. }
  498. }
  499. var expected = goog.isDef(Object.getOwnPropertyNames) ? ['foo'] : [];
  500. assertSameElements(expected, goog.object.getAllPropertyNames(obj));
  501. }
  502. function testGetAllPropertyNames_inheritedProperties() {
  503. var parent = function() {};
  504. parent.prototype.a = null;
  505. var child = function() {};
  506. goog.inherits(child, parent);
  507. child.prototype.b = null;
  508. var expected = ['a', 'b'];
  509. if (goog.isDef(Object.getOwnPropertyNames)) {
  510. expected.push('constructor');
  511. }
  512. assertSameElements(
  513. expected, goog.object.getAllPropertyNames(child.prototype));
  514. }
  515. function testGetAllPropertyNames_es6ClassProperties() {
  516. // Create an ES6 class via eval so we can bail out if it's a syntax error in
  517. // browsers that don't support ES6 classes.
  518. try {
  519. eval(
  520. 'var Foo = class {' +
  521. ' a() {}' +
  522. '};' +
  523. 'Foo.prototype.b = null;' +
  524. 'var Bar = class extends Foo {' +
  525. ' c() {}' +
  526. ' static d() {}' +
  527. '};');
  528. } catch (e) {
  529. if (e instanceof SyntaxError) {
  530. return;
  531. }
  532. }
  533. assertSameElements(
  534. ['a', 'b', 'constructor'],
  535. goog.object.getAllPropertyNames(Foo.prototype));
  536. assertSameElements(
  537. ['a', 'b', 'c', 'constructor'],
  538. goog.object.getAllPropertyNames(Bar.prototype));
  539. var expectedBarProperties = ['d', 'prototype', 'length', 'name'];
  540. // Some versions of Firefox don't find the name property via
  541. // getOwnPropertyNames.
  542. if (!goog.array.contains(Object.getOwnPropertyNames(Bar), 'name')) {
  543. goog.array.remove(expectedBarProperties, 'name');
  544. }
  545. assertSameElements(
  546. expectedBarProperties, goog.object.getAllPropertyNames(Bar));
  547. }
  548. function testGetAllPropertyNames_includeObjectPrototype() {
  549. var obj = {a: function() {}, b: 'b', c: function(x) {}};
  550. // There's slightly different behavior depending on what APIs the browser
  551. // under test supports.
  552. var additionalProps = !!Object.getOwnPropertyNames ?
  553. Object.getOwnPropertyNames(Object.prototype) :
  554. [];
  555. // __proto__ is a bit special and should be excluded from the result set.
  556. goog.array.remove(additionalProps, '__proto__');
  557. assertSameElements(
  558. ['a', 'b', 'c'].concat(additionalProps),
  559. goog.object.getAllPropertyNames(obj, true));
  560. }
  561. function testGetAllPropertyNames_includeFunctionPrototype() {
  562. var obj = function() {};
  563. obj.a = function() {};
  564. // There's slightly different behavior depending on what APIs the browser
  565. // under test supports.
  566. var additionalProps = !!Object.getOwnPropertyNames ?
  567. Object.getOwnPropertyNames(Function.prototype).concat(['prototype']) :
  568. [];
  569. var expectedElements = ['a'].concat(additionalProps);
  570. goog.array.removeDuplicates(expectedElements);
  571. assertSameElements(
  572. expectedElements, goog.object.getAllPropertyNames(obj, false, true));
  573. }