test.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. const test = require('tap').test
  2. const fss = require('./')
  3. const clone = require('clone')
  4. const s = JSON.stringify
  5. test('circular reference to root', function (assert) {
  6. const fixture = { name: 'Tywin Lannister' }
  7. fixture.circle = fixture
  8. const expected = s(
  9. { name: 'Tywin Lannister', circle: '[Circular]' }
  10. )
  11. const actual = fss(fixture)
  12. assert.is(actual, expected)
  13. assert.end()
  14. })
  15. test('nested circular reference to root', function (assert) {
  16. const fixture = { name: 'Tywin Lannister' }
  17. fixture.id = { circle: fixture }
  18. const expected = s(
  19. { name: 'Tywin Lannister', id: { circle: '[Circular]' } }
  20. )
  21. const actual = fss(fixture)
  22. assert.is(actual, expected)
  23. assert.end()
  24. })
  25. test('child circular reference', function (assert) {
  26. const fixture = { name: 'Tywin Lannister', child: { name: 'Tyrion Lannister' } }
  27. fixture.child.dinklage = fixture.child
  28. const expected = s({
  29. name: 'Tywin Lannister',
  30. child: {
  31. name: 'Tyrion Lannister', dinklage: '[Circular]'
  32. }
  33. })
  34. const actual = fss(fixture)
  35. assert.is(actual, expected)
  36. assert.end()
  37. })
  38. test('nested child circular reference', function (assert) {
  39. const fixture = { name: 'Tywin Lannister', child: { name: 'Tyrion Lannister' } }
  40. fixture.child.actor = { dinklage: fixture.child }
  41. const expected = s({
  42. name: 'Tywin Lannister',
  43. child: {
  44. name: 'Tyrion Lannister', actor: { dinklage: '[Circular]' }
  45. }
  46. })
  47. const actual = fss(fixture)
  48. assert.is(actual, expected)
  49. assert.end()
  50. })
  51. test('circular objects in an array', function (assert) {
  52. const fixture = { name: 'Tywin Lannister' }
  53. fixture.hand = [fixture, fixture]
  54. const expected = s({
  55. name: 'Tywin Lannister', hand: ['[Circular]', '[Circular]']
  56. })
  57. const actual = fss(fixture)
  58. assert.is(actual, expected)
  59. assert.end()
  60. })
  61. test('nested circular references in an array', function (assert) {
  62. const fixture = {
  63. name: 'Tywin Lannister',
  64. offspring: [{ name: 'Tyrion Lannister' }, { name: 'Cersei Lannister' }]
  65. }
  66. fixture.offspring[0].dinklage = fixture.offspring[0]
  67. fixture.offspring[1].headey = fixture.offspring[1]
  68. const expected = s({
  69. name: 'Tywin Lannister',
  70. offspring: [
  71. { name: 'Tyrion Lannister', dinklage: '[Circular]' },
  72. { name: 'Cersei Lannister', headey: '[Circular]' }
  73. ]
  74. })
  75. const actual = fss(fixture)
  76. assert.is(actual, expected)
  77. assert.end()
  78. })
  79. test('circular arrays', function (assert) {
  80. const fixture = []
  81. fixture.push(fixture, fixture)
  82. const expected = s(['[Circular]', '[Circular]'])
  83. const actual = fss(fixture)
  84. assert.is(actual, expected)
  85. assert.end()
  86. })
  87. test('nested circular arrays', function (assert) {
  88. const fixture = []
  89. fixture.push(
  90. { name: 'Jon Snow', bastards: fixture },
  91. { name: 'Ramsay Bolton', bastards: fixture }
  92. )
  93. const expected = s([
  94. { name: 'Jon Snow', bastards: '[Circular]' },
  95. { name: 'Ramsay Bolton', bastards: '[Circular]' }
  96. ])
  97. const actual = fss(fixture)
  98. assert.is(actual, expected)
  99. assert.end()
  100. })
  101. test('repeated non-circular references in objects', function (assert) {
  102. const daenerys = { name: 'Daenerys Targaryen' }
  103. const fixture = {
  104. motherOfDragons: daenerys,
  105. queenOfMeereen: daenerys
  106. }
  107. const expected = s(fixture)
  108. const actual = fss(fixture)
  109. assert.is(actual, expected)
  110. assert.end()
  111. })
  112. test('repeated non-circular references in arrays', function (assert) {
  113. const daenerys = { name: 'Daenerys Targaryen' }
  114. const fixture = [daenerys, daenerys]
  115. const expected = s(fixture)
  116. const actual = fss(fixture)
  117. assert.is(actual, expected)
  118. assert.end()
  119. })
  120. test('double child circular reference', function (assert) {
  121. // create circular reference
  122. const child = { name: 'Tyrion Lannister' }
  123. child.dinklage = child
  124. // include it twice in the fixture
  125. const fixture = { name: 'Tywin Lannister', childA: child, childB: child }
  126. const cloned = clone(fixture)
  127. const expected = s({
  128. name: 'Tywin Lannister',
  129. childA: {
  130. name: 'Tyrion Lannister', dinklage: '[Circular]'
  131. },
  132. childB: {
  133. name: 'Tyrion Lannister', dinklage: '[Circular]'
  134. }
  135. })
  136. const actual = fss(fixture)
  137. assert.is(actual, expected)
  138. // check if the fixture has not been modified
  139. assert.deepEqual(fixture, cloned)
  140. assert.end()
  141. })
  142. test('child circular reference with toJSON', function (assert) {
  143. // Create a test object that has an overriden `toJSON` property
  144. TestObject.prototype.toJSON = function () { return { special: 'case' } }
  145. function TestObject (content) {}
  146. // Creating a simple circular object structure
  147. const parentObject = {}
  148. parentObject.childObject = new TestObject()
  149. parentObject.childObject.parentObject = parentObject
  150. // Creating a simple circular object structure
  151. const otherParentObject = new TestObject()
  152. otherParentObject.otherChildObject = {}
  153. otherParentObject.otherChildObject.otherParentObject = otherParentObject
  154. // Making sure our original tests work
  155. assert.deepEqual(parentObject.childObject.parentObject, parentObject)
  156. assert.deepEqual(otherParentObject.otherChildObject.otherParentObject, otherParentObject)
  157. // Should both be idempotent
  158. assert.equal(fss(parentObject), '{"childObject":{"special":"case"}}')
  159. assert.equal(fss(otherParentObject), '{"special":"case"}')
  160. // Therefore the following assertion should be `true`
  161. assert.deepEqual(parentObject.childObject.parentObject, parentObject)
  162. assert.deepEqual(otherParentObject.otherChildObject.otherParentObject, otherParentObject)
  163. assert.end()
  164. })
  165. test('null object', function (assert) {
  166. const expected = s(null)
  167. const actual = fss(null)
  168. assert.is(actual, expected)
  169. assert.end()
  170. })
  171. test('null property', function (assert) {
  172. const expected = s({ f: null })
  173. const actual = fss({ f: null })
  174. assert.is(actual, expected)
  175. assert.end()
  176. })
  177. test('nested child circular reference in toJSON', function (assert) {
  178. const circle = { some: 'data' }
  179. circle.circle = circle
  180. const a = {
  181. b: {
  182. toJSON: function () {
  183. a.b = 2
  184. return '[Redacted]'
  185. }
  186. },
  187. baz: {
  188. circle,
  189. toJSON: function () {
  190. a.baz = circle
  191. return '[Redacted]'
  192. }
  193. }
  194. }
  195. const o = {
  196. a,
  197. bar: a
  198. }
  199. const expected = s({
  200. a: {
  201. b: '[Redacted]',
  202. baz: '[Redacted]'
  203. },
  204. bar: {
  205. b: 2,
  206. baz: {
  207. some: 'data',
  208. circle: '[Circular]'
  209. }
  210. }
  211. })
  212. const actual = fss(o)
  213. assert.is(actual, expected)
  214. assert.end()
  215. })