index.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. 'use strict'
  2. const { test } = require('tap')
  3. const rfdc = require('..')
  4. const clone = rfdc()
  5. const cloneProto = rfdc({proto: true})
  6. const cloneCircles = rfdc({circles: true})
  7. const cloneCirclesProto = rfdc({circles: true, proto: true})
  8. types(clone, 'default')
  9. types(cloneProto, 'proto option')
  10. types(cloneCircles, 'circles option')
  11. types(cloneCirclesProto, 'circles and proto option')
  12. test('default – does not copy proto properties', async ({is}) => {
  13. is(clone(Object.create({a: 1})).a, undefined, 'value not copied')
  14. })
  15. test('proto option – copies enumerable proto properties', async ({is}) => {
  16. is(cloneProto(Object.create({a: 1})).a, 1, 'value copied')
  17. })
  18. test('circles option - circular object', async ({same, is, isNot}) => {
  19. const o = {nest: {a: 1, b: 2}}
  20. o.circular = o
  21. same(cloneCircles(o), o, 'same values')
  22. isNot(cloneCircles(o), o, 'different objects')
  23. isNot(cloneCircles(o).nest, o.nest, 'different nested objects')
  24. const c = cloneCircles(o)
  25. is(c.circular, c, 'circular references point to copied parent')
  26. isNot(c.circular, o, 'circular references do not point to original parent')
  27. })
  28. test('circles option – deep circular object', async ({same, is, isNot}) => {
  29. const o = {nest: {a: 1, b: 2}}
  30. o.nest.circular = o
  31. same(cloneCircles(o), o, 'same values')
  32. isNot(cloneCircles(o), o, 'different objects')
  33. isNot(cloneCircles(o).nest, o.nest, 'different nested objects')
  34. const c = cloneCircles(o)
  35. is(c.nest.circular, c, 'circular references point to copied parent')
  36. isNot(c.nest.circular, o, 'circular references do not point to original parent')
  37. })
  38. test('circles option alone – does not copy proto properties', async ({is}) => {
  39. is(cloneCircles(Object.create({a: 1})).a, undefined, 'value not copied')
  40. })
  41. test('circles and proto option – copies enumerable proto properties', async ({is}) => {
  42. is(cloneCirclesProto(Object.create({a: 1})).a, 1, 'value copied')
  43. })
  44. test('circles and proto option - circular object', async ({same, is, isNot}) => {
  45. const o = {nest: {a: 1, b: 2}}
  46. o.circular = o
  47. same(cloneCirclesProto(o), o, 'same values')
  48. isNot(cloneCirclesProto(o), o, 'different objects')
  49. isNot(cloneCirclesProto(o).nest, o.nest, 'different nested objects')
  50. const c = cloneCirclesProto(o)
  51. is(c.circular, c, 'circular references point to copied parent')
  52. isNot(c.circular, o, 'circular references do not point to original parent')
  53. })
  54. test('circles and proto option – deep circular object', async ({same, is, isNot}) => {
  55. const o = {nest: {a: 1, b: 2}}
  56. o.nest.circular = o
  57. same(cloneCirclesProto(o), o, 'same values')
  58. isNot(cloneCirclesProto(o), o, 'different objects')
  59. isNot(cloneCirclesProto(o).nest, o.nest, 'different nested objects')
  60. const c = cloneCirclesProto(o)
  61. is(c.nest.circular, c, 'circular references point to copied parent')
  62. isNot(c.nest.circular, o, 'circular references do not point to original parent')
  63. })
  64. function types(clone, label) {
  65. test(label + ' – number', async ({is}) => {
  66. is(clone(42), 42, 'same value')
  67. })
  68. test(label + ' – string', async ({is}) => {
  69. is(clone('str'), 'str', 'same value')
  70. })
  71. test(label + ' – boolean', async ({is}) => {
  72. is(clone(true), true, 'same value')
  73. })
  74. test(label + ' – function', async ({is}) => {
  75. const fn = () => {}
  76. is(clone(fn), fn, 'same function')
  77. })
  78. test(label + ' – async function', async ({is}) => {
  79. const fn = async () => {}
  80. is(clone(fn), fn, 'same function')
  81. })
  82. test(label + ' – generator function', async ({is}) => {
  83. const fn = function * () {}
  84. is(clone(fn), fn, 'same function')
  85. })
  86. test(label + ' – date', async ({is, isNot}) => {
  87. const date = new Date()
  88. is(+clone(date), +date, 'same value')
  89. isNot(clone(date), date, 'different object')
  90. })
  91. test(label + ' – null', async ({is}) => {
  92. is(clone(null), null, 'same value')
  93. })
  94. test(label + ' – shallow object', async ({same, isNot}) => {
  95. const o = {a: 1, b: 2}
  96. same(clone(o), o, 'same values')
  97. isNot(clone(o), o, 'different object')
  98. })
  99. test(label + ' – shallow array', async ({same, isNot}) => {
  100. const o = [1, 2]
  101. same(clone(o), o, 'same values')
  102. isNot(clone(o), o, 'different arrays')
  103. })
  104. test(label + ' – deep object', async ({same, isNot}) => {
  105. const o = {nest: {a: 1, b: 2}}
  106. same(clone(o), o, 'same values')
  107. isNot(clone(o), o, 'different objects')
  108. isNot(clone(o).nest, o.nest, 'different nested objects')
  109. })
  110. test(label + ' – deep array', async ({same, isNot}) => {
  111. const o = [ {a: 1, b: 2}, [3] ]
  112. same(clone(o), o, 'same values')
  113. isNot(clone(o), o, 'different arrays')
  114. isNot(clone(o)[0], o[0], 'different array elements')
  115. isNot(clone(o)[1], o[1], 'different array elements')
  116. })
  117. test(label + ' – nested number', async ({is}) => {
  118. is(clone({a: 1}).a, 1, 'same value')
  119. })
  120. test(label + ' – nested string', async ({is}) => {
  121. is(clone({s: 'str'}).s, 'str', 'same value')
  122. })
  123. test(label + ' – nested boolean', async ({is}) => {
  124. is(clone({b: true}).b, true, 'same value')
  125. })
  126. test(label + ' – nested function', async ({is}) => {
  127. const fn = () => {}
  128. is(clone({fn}).fn, fn, 'same function')
  129. })
  130. test(label + ' – nested async function', async ({is}) => {
  131. const fn = async () => {}
  132. is(clone({fn}).fn, fn, 'same function')
  133. })
  134. test(label + ' – nested generator function', async ({is}) => {
  135. const fn = function * () {}
  136. is(clone({fn}).fn, fn, 'same function')
  137. })
  138. test(label + ' – nested date', async ({is, isNot}) => {
  139. const date = new Date()
  140. is(+clone({d: date}).d, +date, 'same value')
  141. isNot(clone({d: date}).d, date, 'different object')
  142. })
  143. test(label + ' – nested null', async ({is}) => {
  144. is(clone({n: null}).n, null, 'same value')
  145. })
  146. test(label + ' – arguments', async ({isNot, same}) => {
  147. function fn (...args) {
  148. same(clone(arguments), args, 'same values')
  149. isNot(clone(arguments), arguments, 'different object')
  150. }
  151. fn(1, 2, 3)
  152. })
  153. }