deltareplayer.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /**
  2. * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* global console */
  6. import DeltaReplayer from '../../src/dev-utils/deltareplayer';
  7. import Document from '../../src/model/document';
  8. describe( 'DeltaReplayer', () => {
  9. const sandbox = sinon.sandbox.create();
  10. let stubs;
  11. beforeEach( () => {
  12. stubs = {
  13. consoleWarn: sandbox.stub( console, 'warn' ),
  14. };
  15. } );
  16. afterEach( () => {
  17. sandbox.restore();
  18. } );
  19. describe( 'constructor()', () => {
  20. it( 'should be able to initialize replayer without deltas', () => {
  21. const doc = getDocument();
  22. const stringifiedDeltas = '';
  23. const deltaReplayer = new DeltaReplayer( doc, '---', stringifiedDeltas );
  24. expect( deltaReplayer.getDeltasToReplay() ).to.deep.equal( [] );
  25. } );
  26. it( 'should be able to initialize replayer with deltas', () => {
  27. const doc = getDocument();
  28. const delta = getFirstDelta();
  29. const deltaReplayer = new DeltaReplayer( doc, '---', JSON.stringify( delta ) );
  30. expect( deltaReplayer.getDeltasToReplay() ).to.deep.equal( [ delta ] );
  31. } );
  32. } );
  33. describe( 'applyNextDelta()', () => {
  34. it( 'should remove first delta from stack', () => {
  35. const doc = getDocument();
  36. const delta = getFirstDelta();
  37. const deltaReplayer = new DeltaReplayer( doc, '---', JSON.stringify( delta ) );
  38. return deltaReplayer.applyNextDelta().then( () => {
  39. expect( deltaReplayer.getDeltasToReplay() ).to.deep.equal( [] );
  40. } );
  41. } );
  42. it( 'should apply first delta on the document', () => {
  43. const doc = getDocument();
  44. const delta = getFirstDelta();
  45. const deltaReplayer = new DeltaReplayer( doc, '---', JSON.stringify( delta ) );
  46. return deltaReplayer.applyNextDelta().then( () => {
  47. expect( Array.from( doc.getRoot().getChildren() ).length ).to.equal( 1 );
  48. } );
  49. } );
  50. it( 'should throw an error if 0 deltas are provided', () => {
  51. const doc = getDocument();
  52. const deltaReplayer = new DeltaReplayer( doc, '---', '' );
  53. return deltaReplayer.applyNextDelta().then( () => {
  54. throw new Error( 'This should throw an error' );
  55. }, ( err ) => {
  56. expect( err instanceof Error ).to.equal( true );
  57. expect( err.message ).to.equal( 'No deltas to replay' );
  58. } );
  59. } );
  60. } );
  61. describe( 'applyAllDeltas()', () => {
  62. it( 'should apply all deltas on the document', () => {
  63. const doc = getDocument();
  64. const stringifiedDeltas = [ getFirstDelta(), getSecondDelta() ]
  65. .map( d => JSON.stringify( d ) )
  66. .join( '---' );
  67. const deltaReplayer = new DeltaReplayer( doc, '---', stringifiedDeltas );
  68. return deltaReplayer.applyAllDeltas().then( () => {
  69. expect( Array.from( doc.getRoot().getChildren() ).length ).to.equal( 2 );
  70. expect( deltaReplayer.getDeltasToReplay().length ).to.equal( 0 );
  71. } );
  72. } );
  73. } );
  74. describe( 'applyDeltas()', () => {
  75. it( 'should apply certain number of deltas on the document', () => {
  76. const doc = getDocument();
  77. const stringifiedDeltas = [ getFirstDelta(), getSecondDelta() ]
  78. .map( d => JSON.stringify( d ) )
  79. .join( '---' );
  80. const deltaReplayer = new DeltaReplayer( doc, '---', stringifiedDeltas );
  81. return deltaReplayer.applyDeltas( 1 ).then( () => {
  82. expect( Array.from( doc.getRoot().getChildren() ).length ).to.equal( 1 );
  83. expect( deltaReplayer.getDeltasToReplay().length ).to.equal( 1 );
  84. } );
  85. } );
  86. it( 'should not throw an error if the number of deltas is lower than number of expected deltas to replay', () => {
  87. const doc = getDocument();
  88. const stringifiedDeltas = [ getFirstDelta(), getSecondDelta() ]
  89. .map( d => JSON.stringify( d ) )
  90. .join( '---' );
  91. const deltaReplayer = new DeltaReplayer( doc, '---', stringifiedDeltas );
  92. return deltaReplayer.applyDeltas( 3 ).then( () => {
  93. expect( Array.from( doc.getRoot().getChildren() ).length ).to.equal( 2 );
  94. expect( deltaReplayer.getDeltasToReplay().length ).to.equal( 0 );
  95. sinon.assert.calledWithExactly( stubs.consoleWarn, new Error( 'No deltas to replay' ) );
  96. } );
  97. } );
  98. } );
  99. describe( 'play()', () => {
  100. it( 'should play deltas with time interval', () => {
  101. const doc = getDocument();
  102. const stringifiedDeltas = [ getFirstDelta(), getSecondDelta() ]
  103. .map( d => JSON.stringify( d ) )
  104. .join( '---' );
  105. const deltaReplayer = new DeltaReplayer( doc, '---', stringifiedDeltas );
  106. return deltaReplayer.play( 0 ).then( () => {
  107. expect( deltaReplayer.getDeltasToReplay().length ).to.equal( 0 );
  108. } );
  109. } );
  110. it( 'should work with default time interval', () => {
  111. const doc = getDocument();
  112. const deltaReplayer = new DeltaReplayer( doc, '---', '' );
  113. return deltaReplayer.play();
  114. } );
  115. } );
  116. } );
  117. function getDocument() {
  118. const doc = new Document();
  119. doc.createRoot( 'main' );
  120. return doc;
  121. }
  122. function getFirstDelta() {
  123. return {
  124. operations: [ {
  125. baseVersion: 0,
  126. position: {
  127. root: 'main',
  128. path: [ 0 ]
  129. },
  130. nodes: [ {
  131. name: 'heading1',
  132. children: [ {
  133. data: 'The great world of open Web standards'
  134. } ]
  135. } ],
  136. __className: 'engine.model.operation.InsertOperation'
  137. } ],
  138. __className: 'engine.model.delta.InsertDelta'
  139. };
  140. }
  141. function getSecondDelta() {
  142. return {
  143. operations: [ {
  144. baseVersion: 1,
  145. position: {
  146. root: 'main',
  147. path: [ 1 ]
  148. },
  149. nodes: [ {
  150. name: 'heading2',
  151. children: [ {
  152. data: 'The great world of open Web standards'
  153. } ]
  154. } ],
  155. __className: 'engine.model.operation.InsertOperation'
  156. } ],
  157. __className: 'engine.model.delta.InsertDelta'
  158. };
  159. }