8
0

liveposition.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. /**
  2. * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* bender-tags: treemodel */
  6. 'use strict';
  7. const modules = bender.amd.require(
  8. 'treemodel/document',
  9. 'treemodel/element',
  10. 'treemodel/position',
  11. 'treemodel/liveposition',
  12. 'treemodel/range',
  13. 'emittermixin'
  14. );
  15. describe( 'LivePosition', () => {
  16. let Document, Element, Position, LivePosition, Range, EmitterMixin;
  17. let doc, root, ul, p, li1, li2;
  18. before( () => {
  19. Document = modules[ 'treemodel/document' ];
  20. Element = modules[ 'treemodel/element' ];
  21. Position = modules[ 'treemodel/position' ];
  22. LivePosition = modules[ 'treemodel/liveposition' ];
  23. Range = modules[ 'treemodel/range' ];
  24. EmitterMixin = modules.emittermixin;
  25. doc = new Document();
  26. root = doc.createRoot( 'root' );
  27. li1 = new Element( 'li', [], 'abcdef' );
  28. li2 = new Element( 'li', [], 'foobar' );
  29. ul = new Element( 'ul', [], [ li1, li2 ] );
  30. p = new Element( 'p', [], 'qwerty' );
  31. root.insertChildren( 0, [ p, ul ] );
  32. } );
  33. it( 'should be an instance of Position', () => {
  34. let live = new LivePosition( root, [ 0 ] );
  35. live.detach();
  36. expect( live ).to.be.instanceof( Position );
  37. } );
  38. it( 'should listen to a change event of the document that owns this position root', () => {
  39. sinon.spy( LivePosition.prototype, 'listenTo' );
  40. let live = new LivePosition( root, [ 0 ] );
  41. live.detach();
  42. expect( live.listenTo.calledWith( doc, 'change' ) ).to.be.true;
  43. LivePosition.prototype.listenTo.restore();
  44. } );
  45. it( 'should stop listening when detached', () => {
  46. sinon.spy( LivePosition.prototype, 'stopListening' );
  47. let live = new LivePosition( root, [ 0 ] );
  48. live.detach();
  49. expect( live.stopListening.called ).to.be.true;
  50. LivePosition.prototype.stopListening.restore();
  51. } );
  52. it( 'createFromPosition should return LivePosition', () => {
  53. let position = LivePosition.createFromPosition( new Position( root, [ 0 ] ) );
  54. expect( position ).to.be.instanceof( LivePosition );
  55. position.detach();
  56. } );
  57. it( 'createFromParentAndOffset should return LivePosition', () => {
  58. let position = LivePosition.createFromParentAndOffset( ul, 0 );
  59. expect( position ).to.be.instanceof( LivePosition );
  60. position.detach();
  61. } );
  62. it( 'createBefore should return LivePosition', () => {
  63. let position = LivePosition.createBefore( ul );
  64. expect( position ).to.be.instanceof( LivePosition );
  65. position.detach();
  66. } );
  67. it( 'createAfter should return LivePosition', () => {
  68. let position = LivePosition.createAfter( ul );
  69. expect( position ).to.be.instanceof( LivePosition );
  70. position.detach();
  71. } );
  72. describe( 'should get transformed if', () => {
  73. let live;
  74. beforeEach( () => {
  75. live = new LivePosition( root, [ 1, 4, 6 ] );
  76. } );
  77. afterEach( () => {
  78. live.detach();
  79. } );
  80. describe( 'insertion', () => {
  81. it( 'is in the same parent and closer offset', () => {
  82. let insertRange = new Range( new Position( root, [ 1, 4, 0 ] ), new Position( root, [ 1, 4, 3 ] ) );
  83. doc.fire( 'change', 'insert', { range: insertRange }, null );
  84. expect( live.path ).to.deep.equal( [ 1, 4, 9 ] );
  85. } );
  86. it( 'is at the same position and live position is sticking to right side', () => {
  87. let insertRange = new Range( new Position( root, [ 1, 4, 6 ] ), new Position( root, [ 1, 4, 9 ] ) );
  88. doc.fire( 'change', 'insert', { range: insertRange }, null );
  89. expect( live.path ).to.deep.equal( [ 1, 4, 9 ] );
  90. } );
  91. it( 'is before a node from the live position path', () => {
  92. let insertRange = new Range( new Position( root, [ 1, 0 ] ), new Position( root, [ 1, 2 ] ) );
  93. doc.fire( 'change', 'insert', { range: insertRange }, null );
  94. expect( live.path ).to.deep.equal( [ 1, 6, 6 ] );
  95. } );
  96. } );
  97. describe( 'range move', () => {
  98. it( 'is at the same parent and closer offset', () => {
  99. let moveSource = new Position( root, [ 2 ] );
  100. let moveRange = new Range( new Position( root, [ 1, 4, 0 ] ), new Position( root, [ 1, 4, 3 ] ) );
  101. let changes = {
  102. range: moveRange,
  103. sourcePosition: moveSource
  104. };
  105. doc.fire( 'change', 'move', changes, null );
  106. expect( live.path ).to.deep.equal( [ 1, 4, 9 ] );
  107. } );
  108. it( 'is at the same position and live position is sticking to right side', () => {
  109. let moveSource = new Position( root, [ 2 ] );
  110. let moveRange = new Range( new Position( root, [ 1, 4, 6 ] ), new Position( root, [ 1, 4, 9 ] ) );
  111. let changes = {
  112. range: moveRange,
  113. sourcePosition: moveSource
  114. };
  115. doc.fire( 'change', 'move', changes, null );
  116. expect( live.path ).to.deep.equal( [ 1, 4, 9 ] );
  117. } );
  118. it( 'is at a position before a node from the live position path', () => {
  119. let moveSource = new Position( root, [ 2 ] );
  120. let moveRange = new Range( new Position( root, [ 1, 0 ] ), new Position( root, [ 1, 2 ] ) );
  121. let changes = {
  122. range: moveRange,
  123. sourcePosition: moveSource
  124. };
  125. doc.fire( 'change', 'move', changes, null );
  126. expect( live.path ).to.deep.equal( [ 1, 6, 6 ] );
  127. } );
  128. it( 'is from the same parent and closer offset', () => {
  129. let moveSource = new Position( root, [ 1, 4, 0 ] );
  130. let moveRange = new Range( new Position( root, [ 2, 0 ] ), new Position( root, [ 2, 4 ] ) );
  131. let changes = {
  132. range: moveRange,
  133. sourcePosition: moveSource
  134. };
  135. doc.fire( 'change', 'move', changes, null );
  136. expect( live.path ).to.deep.equal( [ 1, 4, 2 ] );
  137. } );
  138. it( 'is from a position before a node from the live position path', () => {
  139. let moveSource = new Position( root, [ 1, 0 ] );
  140. let moveRange = new Range( new Position( root, [ 2, 0 ] ), new Position( root, [ 2, 4 ] ) );
  141. let changes = {
  142. range: moveRange,
  143. sourcePosition: moveSource
  144. };
  145. doc.fire( 'change', 'move', changes, null );
  146. expect( live.path ).to.deep.equal( [ 1, 0, 6 ] );
  147. } );
  148. it( 'contains live position (same level)', () => {
  149. let moveSource = new Position( root, [ 1, 4, 4 ] );
  150. let moveRange = new Range( new Position( root, [ 2, 0 ] ), new Position( root, [ 2, 4 ] ) );
  151. let changes = {
  152. range: moveRange,
  153. sourcePosition: moveSource
  154. };
  155. doc.fire( 'change', 'move', changes, null );
  156. expect( live.path ).to.deep.equal( [ 2, 2 ] );
  157. } );
  158. it( 'contains live position (deep)', () => {
  159. let moveSource = new Position( root, [ 1, 3 ] );
  160. let moveRange = new Range( new Position( root, [ 2, 0 ] ), new Position( root, [ 2, 4 ] ) );
  161. let changes = {
  162. range: moveRange,
  163. sourcePosition: moveSource
  164. };
  165. doc.fire( 'change', 'move', changes, null );
  166. expect( live.path ).to.deep.equal( [ 2, 1, 6 ] );
  167. } );
  168. } );
  169. } );
  170. describe( 'should not get transformed if', () => {
  171. let path, otherRoot;
  172. before( () => {
  173. path = [ 1, 4, 6 ];
  174. otherRoot = doc.createRoot( 'otherRoot' );
  175. } );
  176. let live;
  177. beforeEach( () => {
  178. live = new LivePosition( root, path );
  179. } );
  180. afterEach( () => {
  181. live.detach();
  182. } );
  183. describe( 'insertion', () => {
  184. it( 'is in the same parent and further offset', () => {
  185. let insertRange = new Range( new Position( root, [ 1, 4, 7 ] ), new Position( root, [ 1, 4, 9 ] ) );
  186. doc.fire( 'change', 'insert', { range: insertRange }, null );
  187. expect( live.path ).to.deep.equal( path );
  188. } );
  189. it( 'is at the same position and live position is sticking to left side', () => {
  190. let live = new LivePosition( root, path, LivePosition.STICKS_TO_PREVIOUS );
  191. let insertRange = new Range( new Position( root, [ 1, 4, 6 ] ), new Position( root, [ 1, 4, 9 ] ) );
  192. doc.fire( 'change', 'insert', { range: insertRange }, null );
  193. expect( live.path ).to.deep.equal( path );
  194. live.detach();
  195. } );
  196. it( 'is after a node from the position path', () => {
  197. let insertRange = new Range( new Position( root, [ 1, 5 ] ), new Position( root, [ 1, 7 ] ) );
  198. doc.fire( 'change', 'insert', { range: insertRange }, null );
  199. expect( live.path ).to.deep.equal( path );
  200. } );
  201. it( 'is in different root', () => {
  202. let insertRange = new Range( new Position( otherRoot, [ 1, 4, 0 ] ), new Position( otherRoot, [ 1, 4, 4 ] ) );
  203. doc.fire( 'change', 'insert', { range: insertRange }, null );
  204. expect( live.path ).to.deep.equal( path );
  205. } );
  206. } );
  207. describe( 'range move', () => {
  208. it( 'is at the same parent and further offset', () => {
  209. let moveSource = new Position( root, [ 2 ] );
  210. let moveRange = new Range( new Position( root, [ 1, 4, 7 ] ), new Position( root, [ 1, 4, 9 ] ) );
  211. let changes = {
  212. range: moveRange,
  213. sourcePosition: moveSource
  214. };
  215. doc.fire( 'change', 'move', changes, null );
  216. expect( live.path ).to.deep.equal( path );
  217. } );
  218. it( 'is at the same position and live position is sticking to left side', () => {
  219. let live = new LivePosition( root, path, LivePosition.STICKS_TO_PREVIOUS );
  220. let moveSource = new Position( root, [ 2 ] );
  221. let moveRange = new Range( new Position( root, [ 1, 4, 6 ] ), new Position( root, [ 1, 4, 9 ] ) );
  222. let changes = {
  223. range: moveRange,
  224. sourcePosition: moveSource
  225. };
  226. doc.fire( 'change', 'move', changes, null );
  227. expect( live.path ).to.deep.equal( path );
  228. live.detach();
  229. } );
  230. it( 'is at a position after a node from the live position path', () => {
  231. let moveSource = new Position( root, [ 2 ] );
  232. let moveRange = new Range( new Position( root, [ 1, 5 ] ), new Position( root, [ 1, 7 ] ) );
  233. let changes = {
  234. range: moveRange,
  235. sourcePosition: moveSource
  236. };
  237. doc.fire( 'change', 'move', changes, null );
  238. expect( live.path ).to.deep.equal( path );
  239. } );
  240. it( 'is from the same parent and further offset', () => {
  241. let moveSource = new Position( root, [ 1, 4, 7 ] );
  242. let moveRange = new Range( new Position( root, [ 2, 0 ] ), new Position( root, [ 2, 4 ] ) );
  243. let changes = {
  244. range: moveRange,
  245. sourcePosition: moveSource
  246. };
  247. doc.fire( 'change', 'move', changes, null );
  248. expect( live.path ).to.deep.equal( path );
  249. } );
  250. it( 'is from a position after a node from the live position path', () => {
  251. let moveSource = new Position( root, [ 1, 5 ] );
  252. let moveRange = new Range( new Position( root, [ 2, 0 ] ), new Position( root, [ 2, 4 ] ) );
  253. let changes = {
  254. range: moveRange,
  255. sourcePosition: moveSource
  256. };
  257. doc.fire( 'change', 'move', changes, null );
  258. expect( live.path ).to.deep.equal( path );
  259. } );
  260. it( 'is to different root', () => {
  261. let moveSource = new Position( root, [ 2, 0 ] );
  262. let moveRange = new Range( new Position( otherRoot, [ 1, 0 ] ), new Position( otherRoot, [ 1, 4 ] ) );
  263. let changes = {
  264. range: moveRange,
  265. sourcePosition: moveSource
  266. };
  267. doc.fire( 'change', 'move', changes, null );
  268. expect( live.path ).to.deep.equal( path );
  269. } );
  270. it( 'is from different root', () => {
  271. let moveSource = new Position( otherRoot, [ 1, 0 ] );
  272. let moveRange = new Range( new Position( root, [ 2, 0 ] ), new Position( root, [ 2, 4 ] ) );
  273. let changes = {
  274. range: moveRange,
  275. sourcePosition: moveSource
  276. };
  277. doc.fire( 'change', 'move', changes, null );
  278. expect( live.path ).to.deep.equal( path );
  279. } );
  280. } );
  281. } );
  282. } );