test.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. var clone = require('./');
  2. function inspect(obj) {
  3. seen = [];
  4. return JSON.stringify(obj, function (key, val) {
  5. if (val != null && typeof val == "object") {
  6. if (seen.indexOf(val) >= 0) {
  7. return '[cyclic]';
  8. }
  9. seen.push(val);
  10. }
  11. return val;
  12. });
  13. }
  14. // Creates a new VM in node, or an iframe in a browser in order to run the
  15. // script
  16. function apartContext(context, script, callback) {
  17. var vm = require('vm');
  18. if (vm) {
  19. var ctx = vm.createContext({ ctx: context });
  20. callback(vm.runInContext(script, ctx));
  21. } else if (document && document.createElement) {
  22. var iframe = document.createElement('iframe');
  23. iframe.style.display = 'none';
  24. document.body.appendChild(iframe);
  25. var myCtxId = 'tmpCtx' + Math.random();
  26. window[myCtxId] = context;
  27. iframe.src = 'test-apart-ctx.html?' + myCtxId + '&' + encodeURIComponent(script);
  28. iframe.onload = function() {
  29. try {
  30. callback(iframe.contentWindow.results);
  31. } catch (e) {
  32. throw e;
  33. }
  34. };
  35. } else {
  36. console.log('WARNING: cannot create an apart context.');
  37. }
  38. }
  39. exports["clone string"] = function (test) {
  40. test.expect(2); // how many tests?
  41. var a = "foo";
  42. test.strictEqual(clone(a), a);
  43. a = "";
  44. test.strictEqual(clone(a), a);
  45. test.done();
  46. };
  47. exports["clone number"] = function (test) {
  48. test.expect(5); // how many tests?
  49. var a = 0;
  50. test.strictEqual(clone(a), a);
  51. a = 1;
  52. test.strictEqual(clone(a), a);
  53. a = -1000;
  54. test.strictEqual(clone(a), a);
  55. a = 3.1415927;
  56. test.strictEqual(clone(a), a);
  57. a = -3.1415927;
  58. test.strictEqual(clone(a), a);
  59. test.done();
  60. };
  61. exports["clone date"] = function (test) {
  62. test.expect(3); // how many tests?
  63. var a = new Date;
  64. var c = clone(a);
  65. test.ok(!!a.getUTCDate && !!a.toUTCString);
  66. test.ok(!!c.getUTCDate && !!c.toUTCString);
  67. test.equal(a.getTime(), c.getTime());
  68. test.done();
  69. };
  70. exports["clone object"] = function (test) {
  71. test.expect(1); // how many tests?
  72. var a = { foo: { bar: "baz" } };
  73. var b = clone(a);
  74. test.deepEqual(b, a);
  75. test.done();
  76. };
  77. exports["clone array"] = function (test) {
  78. test.expect(2); // how many tests?
  79. var a = [
  80. { foo: "bar" },
  81. "baz"
  82. ];
  83. var b = clone(a);
  84. test.ok(b instanceof Array);
  85. test.deepEqual(b, a);
  86. test.done();
  87. };
  88. exports["clone buffer"] = function (test) {
  89. if (typeof Buffer == 'undefined') {
  90. return test.done();
  91. }
  92. test.expect(1);
  93. var a = new Buffer("this is a test buffer");
  94. var b = clone(a);
  95. // no underscore equal since it has no concept of Buffers
  96. test.deepEqual(b, a);
  97. test.done();
  98. };
  99. exports["clone regexp"] = function (test) {
  100. test.expect(5);
  101. var a = /abc123/gi;
  102. var b = clone(a);
  103. test.deepEqual(b, a);
  104. var c = /a/g;
  105. test.ok(c.lastIndex === 0);
  106. c.exec('123a456a');
  107. test.ok(c.lastIndex === 4);
  108. var d = clone(c);
  109. test.ok(d.global);
  110. test.ok(d.lastIndex === 4);
  111. test.done();
  112. };
  113. exports["clone object containing array"] = function (test) {
  114. test.expect(1); // how many tests?
  115. var a = {
  116. arr1: [ { a: '1234', b: '2345' } ],
  117. arr2: [ { c: '345', d: '456' } ]
  118. };
  119. var b = clone(a);
  120. test.deepEqual(b, a);
  121. test.done();
  122. };
  123. exports["clone object with circular reference"] = function (test) {
  124. test.expect(8); // how many tests?
  125. var c = [1, "foo", {'hello': 'bar'}, function () {}, false, [2]];
  126. var b = [c, 2, 3, 4];
  127. var a = {'b': b, 'c': c};
  128. a.loop = a;
  129. a.loop2 = a;
  130. c.loop = c;
  131. c.aloop = a;
  132. var aCopy = clone(a);
  133. test.ok(a != aCopy);
  134. test.ok(a.c != aCopy.c);
  135. test.ok(aCopy.c == aCopy.b[0]);
  136. test.ok(aCopy.c.loop.loop.aloop == aCopy);
  137. test.ok(aCopy.c[0] == a.c[0]);
  138. test.ok(eq(a, aCopy));
  139. aCopy.c[0] = 2;
  140. test.ok(!eq(a, aCopy));
  141. aCopy.c = "2";
  142. test.ok(!eq(a, aCopy));
  143. function eq(x, y) {
  144. return inspect(x) === inspect(y);
  145. }
  146. test.done();
  147. };
  148. exports['clone prototype'] = function (test) {
  149. test.expect(3); // how many tests?
  150. var a = {
  151. a: "aaa",
  152. x: 123,
  153. y: 45.65
  154. };
  155. var b = clone.clonePrototype(a);
  156. test.strictEqual(b.a, a.a);
  157. test.strictEqual(b.x, a.x);
  158. test.strictEqual(b.y, a.y);
  159. test.done();
  160. };
  161. exports['clone within an apart context'] = function (test) {
  162. var results = apartContext({ clone: clone },
  163. "results = ctx.clone({ a: [1, 2, 3], d: new Date(), r: /^foo$/ig })",
  164. function (results) {
  165. test.ok(results.a.constructor.toString() === Array.toString());
  166. test.ok(results.d.constructor.toString() === Date.toString());
  167. test.ok(results.r.constructor.toString() === RegExp.toString());
  168. test.done();
  169. });
  170. };
  171. exports['clone object with no constructor'] = function (test) {
  172. test.expect(3);
  173. var n = null;
  174. var a = { foo: 'bar' };
  175. a.__proto__ = n;
  176. test.ok(typeof a === 'object');
  177. test.ok(typeof a !== null);
  178. var b = clone(a);
  179. test.ok(a.foo, b.foo);
  180. test.done();
  181. };
  182. exports['clone object with depth argument'] = function (test) {
  183. test.expect(6);
  184. var a = {
  185. foo: {
  186. bar : {
  187. baz : 'qux'
  188. }
  189. }
  190. };
  191. var b = clone(a, false, 1);
  192. test.deepEqual(b, a);
  193. test.notEqual(b, a);
  194. test.strictEqual(b.foo, a.foo);
  195. b = clone(a, true, 2);
  196. test.deepEqual(b, a);
  197. test.notEqual(b.foo, a.foo);
  198. test.strictEqual(b.foo.bar, a.foo.bar);
  199. test.done();
  200. };
  201. exports['maintain prototype chain in clones'] = function (test) {
  202. test.expect(1);
  203. function T() {}
  204. var a = new T();
  205. var b = clone(a);
  206. test.strictEqual(Object.getPrototypeOf(a), Object.getPrototypeOf(b));
  207. test.done();
  208. };
  209. exports['parent prototype is overriden with prototype provided'] = function (test) {
  210. test.expect(1);
  211. function T() {}
  212. var a = new T();
  213. var b = clone(a, true, Infinity, null);
  214. test.strictEqual(b.__defineSetter__, undefined);
  215. test.done();
  216. };
  217. exports['clone object with null children'] = function (test) {
  218. test.expect(1);
  219. var a = {
  220. foo: {
  221. bar: null,
  222. baz: {
  223. qux: false
  224. }
  225. }
  226. };
  227. var b = clone(a);
  228. test.deepEqual(b, a);
  229. test.done();
  230. };
  231. exports['clone instance with getter'] = function (test) {
  232. test.expect(1);
  233. function Ctor() {};
  234. Object.defineProperty(Ctor.prototype, 'prop', {
  235. configurable: true,
  236. enumerable: true,
  237. get: function() {
  238. return 'value';
  239. }
  240. });
  241. var a = new Ctor();
  242. var b = clone(a);
  243. test.strictEqual(b.prop, 'value');
  244. test.done();
  245. };
  246. exports['get RegExp flags'] = function (test) {
  247. test.strictEqual(clone.__getRegExpFlags(/a/), '' );
  248. test.strictEqual(clone.__getRegExpFlags(/a/i), 'i' );
  249. test.strictEqual(clone.__getRegExpFlags(/a/g), 'g' );
  250. test.strictEqual(clone.__getRegExpFlags(/a/gi), 'gi');
  251. test.strictEqual(clone.__getRegExpFlags(/a/m), 'm' );
  252. test.done();
  253. };
  254. exports["recognize Array object"] = function (test) {
  255. var results = apartContext(null, "results = [1, 2, 3]", function(alien) {
  256. var local = [4, 5, 6];
  257. test.ok(clone.__isArray(alien)); // recognize in other context.
  258. test.ok(clone.__isArray(local)); // recognize in local context.
  259. test.ok(!clone.__isDate(alien));
  260. test.ok(!clone.__isDate(local));
  261. test.ok(!clone.__isRegExp(alien));
  262. test.ok(!clone.__isRegExp(local));
  263. test.done();
  264. });
  265. };
  266. exports["recognize Date object"] = function (test) {
  267. var results = apartContext(null, "results = new Date()", function(alien) {
  268. var local = new Date();
  269. test.ok(clone.__isDate(alien)); // recognize in other context.
  270. test.ok(clone.__isDate(local)); // recognize in local context.
  271. test.ok(!clone.__isArray(alien));
  272. test.ok(!clone.__isArray(local));
  273. test.ok(!clone.__isRegExp(alien));
  274. test.ok(!clone.__isRegExp(local));
  275. test.done();
  276. });
  277. };
  278. exports["recognize RegExp object"] = function (test) {
  279. var results = apartContext(null, "results = /foo/", function(alien) {
  280. var local = /bar/;
  281. test.ok(clone.__isRegExp(alien)); // recognize in other context.
  282. test.ok(clone.__isRegExp(local)); // recognize in local context.
  283. test.ok(!clone.__isArray(alien));
  284. test.ok(!clone.__isArray(local));
  285. test.ok(!clone.__isDate(alien));
  286. test.ok(!clone.__isDate(local));
  287. test.done();
  288. });
  289. };