position.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /**
  2. * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* bender-tags: treeview */
  6. 'use strict';
  7. import Position from '/ckeditor5/engine/treeview/position.js';
  8. import Node from '/ckeditor5/engine/treeview/node.js';
  9. import Element from '/ckeditor5/engine/treeview/element.js';
  10. import Text from '/ckeditor5/engine/treeview/text.js';
  11. describe( 'Position', () => {
  12. const parentMock = {};
  13. describe( 'constructor', () => {
  14. it( 'should create element without attributes', () => {
  15. const elem = new Position( parentMock, 5 );
  16. expect( elem ).to.have.property( 'parent' ).that.equals( parentMock );
  17. expect( elem ).to.have.property( 'offset' ).that.equals( 5 );
  18. } );
  19. } );
  20. describe( 'nodeBefore', () => {
  21. it( 'should equal to node that is before position', () => {
  22. const b1 = new Element( 'b' );
  23. const el = new Element( 'p', null, [ b1 ] );
  24. const position = new Position( el, 1 );
  25. expect( position.nodeBefore ).to.equal( b1 );
  26. } );
  27. it( 'should equal null if there is no node before', () => {
  28. const b1 = new Element( 'b' );
  29. const el = new Element( 'p', null, [ b1 ] );
  30. const position = new Position( el, 0 );
  31. expect( position.nodeBefore ).to.be.null;
  32. } );
  33. it( 'should equal null if position is located inside text node', () => {
  34. const text = new Text( 'foobar' );
  35. const position = new Position( text, 3 );
  36. expect( position.nodeBefore ).to.be.null;
  37. } );
  38. } );
  39. describe( 'nodeAfter', () => {
  40. it( 'should equal to node that is after position', () => {
  41. const b1 = new Element( 'b' );
  42. const el = new Element( 'p', null, [ b1 ] );
  43. const position = new Position( el, 0 );
  44. expect( position.nodeAfter ).to.equal( b1 );
  45. } );
  46. it( 'should equal null if there is no node before', () => {
  47. const b1 = new Element( 'b' );
  48. const el = new Element( 'p', null, [ b1 ] );
  49. const position = new Position( el, 1 );
  50. expect( position.nodeAfter ).to.be.null;
  51. } );
  52. it( 'should equal null if position is located inside text node', () => {
  53. const text = new Text( 'foobar' );
  54. const position = new Position( text, 3 );
  55. expect( position.nodeAfter ).to.be.null;
  56. } );
  57. } );
  58. describe( 'getShiftedBy', () => {
  59. it( 'returns new instance with shifted offset', () => {
  60. const position = new Position( parentMock, 10 );
  61. const shifted = position.getShiftedBy( 12 );
  62. expect( shifted.offset ).to.equal( 22 );
  63. } );
  64. it( 'accepts negative values', () => {
  65. const position = new Position( parentMock, 10 );
  66. const shifted = position.getShiftedBy( -5 );
  67. expect( shifted.offset ).to.equal( 5 );
  68. } );
  69. it( 'prevents offset to be a negative value', () => {
  70. const position = new Position( parentMock, 10 );
  71. const shifted = position.getShiftedBy( -20 );
  72. expect( shifted.offset ).to.equal( 0 );
  73. } );
  74. } );
  75. describe( 'createFromPosition', () => {
  76. it( 'creates new Position with same parent and offset', () => {
  77. const offset = 50;
  78. const position = new Position( parentMock, offset );
  79. const newPosition = Position.createFromPosition( position );
  80. expect( position ).to.not.equal( newPosition );
  81. expect( position.offset ).to.equal( offset );
  82. expect( position.parent ).to.equal( parentMock );
  83. } );
  84. } );
  85. describe( 'isEqual', () => {
  86. it( 'should return true for same object', () => {
  87. const position = new Position( {}, 12 );
  88. expect( position.isEqual( position ) ).to.be.true;
  89. } );
  90. it( 'should return true for positions with same parent and offset', () => {
  91. const parentMock = {};
  92. const position1 = new Position( parentMock, 12 );
  93. const position2 = new Position( parentMock, 12 );
  94. expect( position1.isEqual( position2 ) ).to.be.true;
  95. } );
  96. it( 'should return false for positions with different parents', () => {
  97. const position1 = new Position( {}, 12 );
  98. const position2 = new Position( {}, 12 );
  99. expect( position1.isEqual( position2 ) ).to.be.false;
  100. } );
  101. it( 'should return false for positions with different positions', () => {
  102. const parentMock = {};
  103. const position1 = new Position( parentMock, 12 );
  104. const position2 = new Position( parentMock, 2 );
  105. expect( position1.isEqual( position2 ) ).to.be.false;
  106. } );
  107. } );
  108. describe( 'isBefore', () => {
  109. it( 'should return false for same positions', () => {
  110. const node = new Node();
  111. const position1 = new Position( node, 10 );
  112. const position2 = new Position( node, 10 );
  113. expect( position1.isBefore( position1 ) ).to.be.false;
  114. expect( position1.isBefore( position2 ) ).to.be.false;
  115. expect( position2.isBefore( position1 ) ).to.be.false;
  116. } );
  117. it( 'should return false if no common ancestor is found', () => {
  118. const t1 = new Text( 'foo' );
  119. const t2 = new Text( 'bar' );
  120. const e1 = new Element( 'p', null, [ t1 ] );
  121. const e2 = new Element( 'p', null, [ t2 ] );
  122. const position1 = new Position( e1, 0 );
  123. const position2 = new Position( e2, 1 );
  124. expect( position1.isBefore( position2 ) );
  125. expect( position2.isBefore( position1 ) );
  126. } );
  127. it( 'should return true if position is before in same node', () => {
  128. const node = new Node();
  129. const p1 = new Position( node, 10 );
  130. const p2 = new Position( node, 5 );
  131. expect( p2.isBefore( p1 ) ).to.be.true;
  132. expect( p1.isBefore( p2 ) ).to.be.false;
  133. } );
  134. it( 'should compare positions that have common parent', () => {
  135. const t1 = new Text( 'foo' );
  136. const t2 = new Text( 'bar' );
  137. const root = new Element( 'p', null, [ t1, t2 ] );
  138. const position1 = new Position( t1, 2 );
  139. const position2 = new Position( t2, 0 );
  140. const position3 = new Position( root, 0 );
  141. const position4 = new Position( root, 2 );
  142. const position5 = new Position( t1, 0 );
  143. const position6 = new Position( root, 1 );
  144. expect( position1.isBefore( position2 ) ).to.be.true;
  145. expect( position2.isBefore( position1 ) ).to.be.false;
  146. expect( position3.isBefore( position1 ) ).to.be.true;
  147. expect( position3.isBefore( position2 ) ).to.be.true;
  148. expect( position1.isBefore( position3 ) ).to.be.false;
  149. expect( position2.isBefore( position3 ) ).to.be.false;
  150. expect( position4.isBefore( position1 ) ).to.be.false;
  151. expect( position4.isBefore( position3 ) ).to.be.false;
  152. expect( position3.isBefore( position4 ) ).to.be.true;
  153. expect( position3.isBefore( position5 ) ).to.be.true;
  154. expect( position6.isBefore( position2 ) ).to.be.true;
  155. expect( position1.isBefore( position6 ) ).to.be.true;
  156. } );
  157. } );
  158. describe( 'isAfter', () => {
  159. it( 'should return false for same positions', () => {
  160. const node = new Node();
  161. const position1 = new Position( node, 10 );
  162. const position2 = new Position( node, 10 );
  163. expect( position1.isAfter( position1 ) ).to.be.false;
  164. expect( position1.isAfter( position2 ) ).to.be.false;
  165. expect( position2.isAfter( position1 ) ).to.be.false;
  166. } );
  167. it( 'should return false if no common ancestor is found', () => {
  168. const t1 = new Text( 'foo' );
  169. const t2 = new Text( 'bar' );
  170. const e1 = new Element( 'p', null, [ t1 ] );
  171. const e2 = new Element( 'p', null, [ t2 ] );
  172. const position1 = new Position( e1, 0 );
  173. const position2 = new Position( e2, 1 );
  174. expect( position1.isAfter( position2 ) );
  175. expect( position2.isAfter( position1 ) );
  176. } );
  177. it( 'should return true if position is after in same node', () => {
  178. const node = new Node();
  179. const p1 = new Position( node, 10 );
  180. const p2 = new Position( node, 5 );
  181. expect( p2.isAfter( p1 ) ).to.be.false;
  182. expect( p1.isAfter( p2 ) ).to.be.true;
  183. } );
  184. it( 'should compare positions that have common parent', () => {
  185. const t1 = new Text( 'foo' );
  186. const t2 = new Text( 'bar' );
  187. const root = new Element( 'p', null, [ t1, t2 ] );
  188. const position1 = new Position( t1, 2 );
  189. const position2 = new Position( t2, 0 );
  190. const position3 = new Position( root, 0 );
  191. const position4 = new Position( root, 2 );
  192. const position5 = new Position( t1, 0 );
  193. const position6 = new Position( root, 1 );
  194. expect( position1.isAfter( position2 ) ).to.be.false;
  195. expect( position2.isAfter( position1 ) ).to.be.true;
  196. expect( position3.isAfter( position1 ) ).to.be.false;
  197. expect( position3.isAfter( position2 ) ).to.be.false;
  198. expect( position1.isAfter( position3 ) ).to.be.true;
  199. expect( position2.isAfter( position3 ) ).to.be.true;
  200. expect( position4.isAfter( position1 ) ).to.be.true;
  201. expect( position4.isAfter( position3 ) ).to.be.true;
  202. expect( position3.isAfter( position4 ) ).to.be.false;
  203. expect( position5.isAfter( position3 ) ).to.be.true;
  204. expect( position2.isAfter( position6 ) ).to.be.true;
  205. } );
  206. } );
  207. describe( 'compareWith', () => {
  208. it( 'should return SAME if positions are same', () => {
  209. const root = new Node();
  210. const position = new Position( root, 0 );
  211. const compared = new Position( root, 0 );
  212. expect( position.compareWith( compared ) ).to.equal( 'SAME' );
  213. } );
  214. it( 'should return BEFORE if the position is before compared one', () => {
  215. const root = new Node();
  216. const position = new Position( root, 0 );
  217. const compared = new Position( root, 1 );
  218. expect( position.compareWith( compared ) ).to.equal( 'BEFORE' );
  219. } );
  220. it( 'should return AFTER if the position is after compared one', () => {
  221. const root = new Node();
  222. const position = new Position( root, 4 );
  223. const compared = new Position( root, 1 );
  224. expect( position.compareWith( compared ) ).to.equal( 'AFTER' );
  225. } );
  226. it( 'should return DIFFERENT if positions are in different roots', () => {
  227. const root1 = new Node();
  228. const root2 = new Node();
  229. const position = new Position( root1, 4 );
  230. const compared = new Position( root2, 1 );
  231. expect( position.compareWith( compared ) ).to.equal( 'DIFFERENT' );
  232. } );
  233. } );
  234. } );