change-event.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /**
  2. * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. import Model from '../../../src/model/model';
  6. import Document from '../../../src/model/document';
  7. import Element from '../../../src/model/element';
  8. import Text from '../../../src/model/text';
  9. import Position from '../../../src/model/position';
  10. import Range from '../../../src/model/range';
  11. import AttributeOperation from '../../../src/model/operation/attributeoperation';
  12. import InsertOperation from '../../../src/model/operation/insertoperation';
  13. import MoveOperation from '../../../src/model/operation/moveoperation';
  14. import RemoveOperation from '../../../src/model/operation/removeoperation';
  15. import { wrapInDelta } from '../../../tests/model/_utils/utils';
  16. describe( 'Document change event', () => {
  17. let model, doc, root, graveyard, types, changes;
  18. beforeEach( () => {
  19. model = new Model();
  20. doc = new Document( model );
  21. root = doc.createRoot();
  22. graveyard = doc.graveyard;
  23. types = [];
  24. changes = [];
  25. doc.on( 'change', ( evt, type, change ) => {
  26. types.push( type );
  27. changes.push( change );
  28. } );
  29. } );
  30. it( 'should be fired when text is inserted', () => {
  31. model.applyOperation( wrapInDelta( new InsertOperation( new Position( root, [ 0 ] ), 'foo', doc.version ) ) );
  32. expect( changes ).to.have.length( 1 );
  33. expect( types[ 0 ] ).to.equal( 'insert' );
  34. expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, root, 3 ) );
  35. } );
  36. it( 'should be fired when element is inserted', () => {
  37. const element = new Element( 'p' );
  38. model.applyOperation( wrapInDelta( new InsertOperation( new Position( root, [ 0 ] ), element, doc.version ) ) );
  39. expect( changes ).to.have.length( 1 );
  40. expect( types[ 0 ] ).to.equal( 'insert' );
  41. expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, root, 1 ) );
  42. } );
  43. it( 'should be fired when nodes are inserted', () => {
  44. const element = new Element( 'p' );
  45. model.applyOperation( wrapInDelta( new InsertOperation( new Position( root, [ 0 ] ), [ element, 'foo' ], doc.version ) ) );
  46. expect( changes ).to.have.length( 1 );
  47. expect( types[ 0 ] ).to.equal( 'insert' );
  48. expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, root, 4 ) );
  49. } );
  50. it( 'should be fired when nodes are moved', () => {
  51. const p1 = new Element( 'p' );
  52. p1.insertChildren( 0, [ new Element( 'p' ), new Text( 'foo' ) ] );
  53. const p2 = new Element( 'p' );
  54. root.insertChildren( 0, [ p1, p2 ] );
  55. model.applyOperation( wrapInDelta(
  56. new MoveOperation(
  57. new Position( root, [ 0, 0 ] ),
  58. 3,
  59. new Position( root, [ 1, 0 ] ),
  60. doc.version
  61. )
  62. ) );
  63. expect( changes ).to.have.length( 1 );
  64. expect( types[ 0 ] ).to.equal( 'move' );
  65. expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( p2, 0, p2, 3 ) );
  66. expect( changes[ 0 ].sourcePosition ).to.deep.equal( Position.createFromParentAndOffset( p1, 0 ) );
  67. } );
  68. it( 'should be fired when multiple nodes are removed and reinserted', () => {
  69. root.insertChildren( 0, new Text( 'foo' ) );
  70. const removeOperation = new RemoveOperation( new Position( root, [ 0 ] ), 3, new Position( doc.graveyard, [ 0 ] ), doc.version );
  71. model.applyOperation( wrapInDelta( removeOperation ) );
  72. const reinsertOperation = removeOperation.getReversed();
  73. model.applyOperation( wrapInDelta( reinsertOperation ) );
  74. expect( changes ).to.have.length( 2 );
  75. expect( types[ 0 ] ).to.equal( 'remove' );
  76. expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( graveyard, 0, graveyard, 3 ) );
  77. expect( changes[ 0 ].sourcePosition ).to.deep.equal( Position.createFromParentAndOffset( root, 0 ) );
  78. expect( types[ 1 ] ).to.equal( 'reinsert' );
  79. expect( changes[ 1 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, root, 3 ) );
  80. expect( changes[ 1 ].sourcePosition ).to.deep.equal( Position.createFromParentAndOffset( graveyard, 0 ) );
  81. } );
  82. it( 'should be fired when attribute is inserted', () => {
  83. root.insertChildren( 0, new Text( 'foo' ) );
  84. model.applyOperation( wrapInDelta(
  85. new AttributeOperation(
  86. Range.createFromParentsAndOffsets( root, 0, root, 3 ),
  87. 'key',
  88. null,
  89. 'new',
  90. doc.version
  91. )
  92. ) );
  93. expect( changes ).to.have.length( 1 );
  94. expect( types[ 0 ] ).to.equal( 'addAttribute' );
  95. expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, root, 3 ) );
  96. expect( changes[ 0 ].key ).to.equal( 'key' );
  97. expect( changes[ 0 ].oldValue ).to.be.null;
  98. expect( changes[ 0 ].newValue ).to.equal( 'new' );
  99. } );
  100. it( 'should be fired when attribute is removed', () => {
  101. const elem = new Element( 'p', { key: 'old' } );
  102. root.insertChildren( 0, elem );
  103. model.applyOperation( wrapInDelta(
  104. new AttributeOperation(
  105. Range.createFromParentsAndOffsets( root, 0, elem, 0 ),
  106. 'key',
  107. 'old',
  108. null,
  109. doc.version
  110. )
  111. ) );
  112. expect( changes ).to.have.length( 1 );
  113. expect( types[ 0 ] ).to.equal( 'removeAttribute' );
  114. expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, elem, 0 ) );
  115. expect( changes[ 0 ].key ).to.equal( 'key' );
  116. expect( changes[ 0 ].oldValue ).to.equal( 'old' );
  117. expect( changes[ 0 ].newValue ).to.be.null;
  118. } );
  119. it( 'should be fired when attribute changes', () => {
  120. const elem = new Element( 'p', { key: 'old' } );
  121. root.insertChildren( 0, elem );
  122. model.applyOperation( wrapInDelta(
  123. new AttributeOperation(
  124. Range.createFromParentsAndOffsets( root, 0, elem, 0 ),
  125. 'key',
  126. 'old',
  127. 'new',
  128. doc.version
  129. )
  130. ) );
  131. expect( changes ).to.have.length( 1 );
  132. expect( types[ 0 ] ).to.equal( 'changeAttribute' );
  133. expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, elem, 0 ) );
  134. expect( changes[ 0 ].key ).to.equal( 'key' );
  135. expect( changes[ 0 ].oldValue ).to.equal( 'old' );
  136. expect( changes[ 0 ].newValue ).to.equal( 'new' );
  137. } );
  138. } );