8
0

splitdelta.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* bender-tags: model, operation */
  6. import transformations from 'ckeditor5/engine/model/delta/basic-transformations.js';
  7. /*jshint unused: false*/
  8. import transform from 'ckeditor5/engine/model/delta/transform.js';
  9. import Element from 'ckeditor5/engine/model/element.js';
  10. import Position from 'ckeditor5/engine/model/position.js';
  11. import Range from 'ckeditor5/engine/model/range.js';
  12. import Delta from 'ckeditor5/engine/model/delta/delta.js';
  13. import SplitDelta from 'ckeditor5/engine/model/delta/splitdelta.js';
  14. import AttributeDelta from 'ckeditor5/engine/model/delta/attributedelta.js';
  15. import RenameDelta from 'ckeditor5/engine/model/delta/renamedelta.js';
  16. import InsertOperation from 'ckeditor5/engine/model/operation/insertoperation.js';
  17. import AttributeOperation from 'ckeditor5/engine/model/operation/attributeoperation.js';
  18. import ReinsertOperation from 'ckeditor5/engine/model/operation/reinsertoperation.js';
  19. import MoveOperation from 'ckeditor5/engine/model/operation/moveoperation.js';
  20. import NoOperation from 'ckeditor5/engine/model/operation/nooperation.js';
  21. import RenameOperation from 'ckeditor5/engine/model/operation/renameoperation.js';
  22. import { getNodesAndText, jsonParseStringify } from 'tests/engine/model/_utils/utils.js';
  23. import {
  24. applyDelta,
  25. expectDelta,
  26. getFilledDocument,
  27. getSplitDelta,
  28. getWrapDelta,
  29. getUnwrapDelta
  30. } from 'tests/engine/model/delta/transform/_utils/utils.js';
  31. describe( 'transform', () => {
  32. let doc, root, gy, baseVersion;
  33. beforeEach( () => {
  34. doc = getFilledDocument();
  35. root = doc.getRoot();
  36. gy = doc.graveyard;
  37. baseVersion = doc.version;
  38. } );
  39. describe( 'SplitDelta by', () => {
  40. let splitDelta, splitPosition;
  41. beforeEach( () => {
  42. splitPosition = new Position( root, [ 3, 3, 3, 3 ] );
  43. splitDelta = getSplitDelta( splitPosition, new Element( 'p' ), 9, baseVersion );
  44. } );
  45. describe( 'SplitDelta', () => {
  46. it( 'split in same parent and offset', () => {
  47. let splitDeltaB = getSplitDelta( splitPosition, new Element( 'p' ), 9, baseVersion );
  48. let transformed = transform( splitDelta, splitDeltaB );
  49. baseVersion = splitDeltaB.operations.length;
  50. expect( transformed.length ).to.equal( 1 );
  51. expectDelta( transformed[ 0 ], {
  52. type: Delta,
  53. operations: [
  54. {
  55. type: NoOperation,
  56. baseVersion: baseVersion
  57. }
  58. ]
  59. } );
  60. // Test if deltas do what they should after applying transformed delta.
  61. applyDelta( splitDeltaB, doc );
  62. applyDelta( transformed[ 0 ], doc );
  63. let nodesAndText = getNodesAndText( Range.createFromPositionAndShift( new Position( root, [ 3, 3, 0 ] ), 5 ) );
  64. // Incoming split delta is discarded. Only one new element is created after applying both split deltas.
  65. // There are no empty P elements.
  66. expect( nodesAndText ).to.equal( 'XXXXXabcdXPabcPPfoobarxyzP' );
  67. } );
  68. it( 'split in same parent, incoming delta splits closer', () => {
  69. let splitDeltaB = getSplitDelta( new Position( root, [ 3, 3, 3, 5 ] ), new Element( 'p' ), 7, baseVersion );
  70. let transformed = transform( splitDelta, splitDeltaB );
  71. baseVersion = splitDeltaB.operations.length;
  72. expect( transformed.length ).to.equal( 1 );
  73. expectDelta( transformed[ 0 ], {
  74. type: SplitDelta,
  75. operations: [
  76. {
  77. type: InsertOperation,
  78. position: new Position( root, [ 3, 3, 4 ] ),
  79. baseVersion: baseVersion
  80. },
  81. {
  82. type: MoveOperation,
  83. sourcePosition: new Position( root, [ 3, 3, 3, 3 ] ),
  84. howMany: 2,
  85. targetPosition: new Position( root, [ 3, 3, 4, 0 ] ),
  86. baseVersion: baseVersion + 1
  87. }
  88. ]
  89. } );
  90. // Test if deltas do what they should after applying transformed delta.
  91. applyDelta( splitDeltaB, doc );
  92. applyDelta( transformed[ 0 ], doc );
  93. let nodesAndText = getNodesAndText( Range.createFromPositionAndShift( new Position( root, [ 3, 3, 0 ] ), 6 ) );
  94. // P element is correctly split, there are three P elements, letters in P elements are in correct order.
  95. expect( nodesAndText ).to.equal( 'XXXXXabcdXPabcPPfoPPobarxyzP' );
  96. } );
  97. it( 'split in same parent, incoming delta splits closer, split deltas have reinsert operations', () => {
  98. let reOp = new ReinsertOperation(
  99. new Position( gy, [ 1 ] ),
  100. 1,
  101. Position.createFromPosition( splitDelta.operations[ 0 ].position ),
  102. splitDelta.operations[ 0 ].baseVersion
  103. );
  104. splitDelta.operations[ 0 ] = reOp;
  105. let splitDeltaB = getSplitDelta( new Position( root, [ 3, 3, 3, 5 ] ), new Element( 'p' ), 7, baseVersion );
  106. reOp = new ReinsertOperation(
  107. new Position( gy, [ 0 ] ),
  108. 1,
  109. Position.createFromPosition( splitDeltaB.operations[ 0 ].position ),
  110. splitDeltaB.operations[ 0 ].baseVersion
  111. );
  112. splitDeltaB.operations[ 0 ] = reOp;
  113. let transformed = transform( splitDelta, splitDeltaB );
  114. baseVersion = splitDeltaB.operations.length;
  115. expect( transformed.length ).to.equal( 1 );
  116. expectDelta( transformed[ 0 ], {
  117. type: SplitDelta,
  118. operations: [
  119. {
  120. type: ReinsertOperation,
  121. sourcePosition: new Position( gy, [ 0 ] ),
  122. howMany: 1,
  123. targetPosition: new Position( root, [ 3, 3, 4 ] ),
  124. baseVersion: baseVersion
  125. },
  126. {
  127. type: MoveOperation,
  128. sourcePosition: new Position( root, [ 3, 3, 3, 3 ] ),
  129. howMany: 2,
  130. targetPosition: new Position( root, [ 3, 3, 4, 0 ] ),
  131. baseVersion: baseVersion + 1
  132. }
  133. ]
  134. } );
  135. } );
  136. it( 'split in same parent, incoming delta splits further', () => {
  137. let splitDeltaB = getSplitDelta( new Position( root, [ 3, 3, 3, 1 ] ), new Element( 'p' ), 11, baseVersion );
  138. let transformed = transform( splitDelta, splitDeltaB );
  139. baseVersion = splitDeltaB.operations.length;
  140. expect( transformed.length ).to.equal( 1 );
  141. expectDelta( transformed[ 0 ], {
  142. type: SplitDelta,
  143. operations: [
  144. {
  145. type: InsertOperation,
  146. position: new Position( root, [ 3, 3, 5 ] ),
  147. baseVersion: baseVersion
  148. },
  149. {
  150. type: MoveOperation,
  151. sourcePosition: new Position( root, [ 3, 3, 4, 2 ] ),
  152. howMany: 9,
  153. targetPosition: new Position( root, [ 3, 3, 5, 0 ] ),
  154. baseVersion: baseVersion + 1
  155. }
  156. ]
  157. } );
  158. // Test if deltas do what they should after applying transformed delta.
  159. applyDelta( splitDeltaB, doc );
  160. applyDelta( transformed[ 0 ], doc );
  161. let nodesAndText = getNodesAndText( Range.createFromPositionAndShift( new Position( root, [ 3, 3, 0 ] ), 6 ) );
  162. // P element is correctly split, there are three P elements, letters in P elements are in correct order.
  163. expect( nodesAndText ).to.equal( 'XXXXXabcdXPaPPbcPPfoobarxyzP' );
  164. } );
  165. it( 'split in same parent, incoming delta splits further, split deltas have reinsert operations', () => {
  166. let reOp = new ReinsertOperation(
  167. new Position( gy, [ 1 ] ),
  168. 1,
  169. Position.createFromPosition( splitDelta.operations[ 0 ].position ),
  170. splitDelta.operations[ 0 ].baseVersion
  171. );
  172. splitDelta.operations[ 0 ] = reOp;
  173. let splitDeltaB = getSplitDelta( new Position( root, [ 3, 3, 3, 1 ] ), new Element( 'p' ), 11, baseVersion );
  174. reOp = new ReinsertOperation(
  175. new Position( gy, [ 0 ] ),
  176. 1,
  177. Position.createFromPosition( splitDeltaB.operations[ 0 ].position ),
  178. splitDeltaB.operations[ 0 ].baseVersion
  179. );
  180. splitDeltaB.operations[ 0 ] = reOp;
  181. let transformed = transform( splitDelta, splitDeltaB );
  182. baseVersion = splitDeltaB.operations.length;
  183. expect( transformed.length ).to.equal( 1 );
  184. expectDelta( transformed[ 0 ], {
  185. type: SplitDelta,
  186. operations: [
  187. {
  188. type: ReinsertOperation,
  189. sourcePosition: new Position( gy, [ 0 ] ),
  190. howMany: 1,
  191. targetPosition: new Position( root, [ 3, 3, 5 ] ),
  192. baseVersion: baseVersion
  193. },
  194. {
  195. type: MoveOperation,
  196. sourcePosition: new Position( root, [ 3, 3, 4, 2 ] ),
  197. howMany: 9,
  198. targetPosition: new Position( root, [ 3, 3, 5, 0 ] ),
  199. baseVersion: baseVersion + 1
  200. }
  201. ]
  202. } );
  203. } );
  204. it( 'split in split parent', () => {
  205. let splitDeltaB = getSplitDelta( new Position( root, [ 3, 3, 3 ] ), new Element( 'div' ), 1, baseVersion );
  206. let transformed = transform( splitDelta, splitDeltaB );
  207. baseVersion = splitDeltaB.operations.length;
  208. expect( transformed.length ).to.equal( 1 );
  209. expectDelta( transformed[ 0 ], {
  210. type: SplitDelta,
  211. operations: [
  212. {
  213. type: InsertOperation,
  214. position: new Position( root, [ 3, 4, 1 ] ),
  215. baseVersion: baseVersion
  216. },
  217. {
  218. type: MoveOperation,
  219. sourcePosition: new Position( root, [ 3, 4, 0, 3 ] ),
  220. howMany: 9,
  221. targetPosition: new Position( root, [ 3, 4, 1, 0 ] ),
  222. baseVersion: baseVersion + 1
  223. }
  224. ]
  225. } );
  226. // Test if deltas do what they should after applying transformed delta.
  227. applyDelta( splitDeltaB, doc );
  228. applyDelta( transformed[ 0 ], doc );
  229. let nodesAndText = getNodesAndText( Range.createFromPositionAndShift( new Position( root, [ 3, 3 ] ), 2 ) );
  230. // DIV and P elements are correctly split.
  231. expect( nodesAndText ).to.equal( 'DIVXXXXXabcdXDIVDIVPabcPPfoobarxyzPDIV' );
  232. } );
  233. } );
  234. describe( 'UnwrapDelta', () => {
  235. it( 'split position directly in unwrapped node', () => {
  236. let unwrapDelta = getUnwrapDelta( new Position( root, [ 3, 3, 3 ] ), 12, baseVersion );
  237. let transformed = transform( splitDelta, unwrapDelta );
  238. baseVersion = unwrapDelta.operations.length;
  239. expect( transformed.length ).to.equal( 1 );
  240. expectDelta( transformed[ 0 ], {
  241. type: Delta,
  242. operations: [
  243. {
  244. type: NoOperation,
  245. baseVersion: baseVersion
  246. }
  247. ]
  248. } );
  249. // Test if deltas do what they should after applying transformed delta.
  250. applyDelta( unwrapDelta, doc );
  251. applyDelta( transformed[ 0 ], doc );
  252. let nodesAndText = getNodesAndText( Range.createFromPositionAndShift( new Position( root, [ 3, 3 ] ), 1 ) );
  253. // UnwrapDelta is applied. SplitDelta is discarded.
  254. expect( nodesAndText ).to.equal( 'DIVXXXXXabcdXabcfoobarxyzDIV' );
  255. } );
  256. it( 'split position indirectly in unwrapped node', () => {
  257. let unwrapDelta = getUnwrapDelta( new Position( root, [ 3, 3 ] ), 4, baseVersion );
  258. let transformed = transform( splitDelta, unwrapDelta );
  259. expect( transformed.length ).to.equal( 1 );
  260. baseVersion = unwrapDelta.operations.length;
  261. expectDelta( transformed[ 0 ], {
  262. type: SplitDelta,
  263. operations: [
  264. {
  265. type: InsertOperation,
  266. position: new Position( root, [ 3, 7 ] ),
  267. baseVersion: baseVersion
  268. },
  269. {
  270. type: MoveOperation,
  271. sourcePosition: new Position( root, [ 3, 6, 3 ] ),
  272. howMany: 9,
  273. targetPosition: new Position( root, [ 3, 7, 0 ] ),
  274. baseVersion: baseVersion + 1
  275. }
  276. ]
  277. } );
  278. // Test if deltas do what they should after applying transformed delta.
  279. applyDelta( unwrapDelta, doc );
  280. applyDelta( transformed[ 0 ], doc );
  281. let nodesAndText = getNodesAndText( Range.createFromPositionAndShift( new Position( root, [ 3 ] ), 1 ) );
  282. // UnwrapDelta and SplitDelta are correctly applied.
  283. expect( nodesAndText ).to.equal( 'DIVXXXXXaXXXXXXabcdXPabcPPfoobarxyzPDIV' );
  284. } );
  285. } );
  286. describe( 'WrapDelta', () => {
  287. it( 'split position is between wrapped nodes', () => {
  288. let wrapRange = new Range( new Position( root, [ 3, 3, 3, 1 ] ), new Position( root, [ 3, 3, 3, 5 ] ) );
  289. let wrapElement = new Element( 'E' );
  290. let wrapDelta = getWrapDelta( wrapRange, wrapElement, baseVersion );
  291. let transformed = transform( splitDelta, wrapDelta );
  292. baseVersion = wrapDelta.operations.length;
  293. expect( transformed.length ).to.equal( 1 );
  294. expectDelta( transformed[ 0 ], {
  295. type: Delta,
  296. operations: [
  297. {
  298. type: NoOperation,
  299. baseVersion: baseVersion
  300. }
  301. ]
  302. } );
  303. // Test if deltas do what they should after applying transformed delta.
  304. applyDelta( wrapDelta, doc );
  305. applyDelta( transformed[ 0 ], doc );
  306. let nodesAndText = getNodesAndText( Range.createFromPositionAndShift( new Position( root, [ 3, 3, 3 ] ), 1 ) );
  307. // WrapDelta is applied. SplitDelta is discarded.
  308. expect( nodesAndText ).to.equal( 'PaEbcfoEobarxyzP' );
  309. } );
  310. it( 'split position is before wrapped nodes', () => {
  311. let wrapRange = new Range( new Position( root, [ 3, 3, 3, 5 ] ), new Position( root, [ 3, 3, 3, 7 ] ) );
  312. let wrapElement = new Element( 'E' );
  313. let wrapDelta = getWrapDelta( wrapRange, wrapElement, baseVersion );
  314. let transformed = transform( splitDelta, wrapDelta );
  315. expect( transformed.length ).to.equal( 1 );
  316. baseVersion = wrapDelta.operations.length;
  317. expectDelta( transformed[ 0 ], {
  318. type: SplitDelta,
  319. operations: [
  320. {
  321. type: InsertOperation,
  322. position: new Position( root, [ 3, 3, 4 ] ),
  323. baseVersion: baseVersion
  324. },
  325. {
  326. type: MoveOperation,
  327. sourcePosition: new Position( root, [ 3, 3, 3, 3 ] ),
  328. howMany: 8,
  329. targetPosition: new Position( root, [ 3, 3, 4, 0 ] ),
  330. baseVersion: baseVersion + 1
  331. }
  332. ]
  333. } );
  334. // Test if deltas do what they should after applying transformed delta.
  335. applyDelta( wrapDelta, doc );
  336. applyDelta( transformed[ 0 ], doc );
  337. let nodesAndText = getNodesAndText( Range.createFromPositionAndShift( new Position( root, [ 3, 3, 3 ] ), 2 ) );
  338. // WrapDelta and SplitDelta are correctly applied.
  339. expect( nodesAndText ).to.equal( 'PabcPPfoEobEarxyzP' );
  340. } );
  341. it( 'split position is inside wrapped node', () => {
  342. let wrapRange = new Range( new Position( root, [ 3, 3, 2 ] ), new Position( root, [ 3, 3, 4 ] ) );
  343. let wrapElement = new Element( 'E' );
  344. let wrapDelta = getWrapDelta( wrapRange, wrapElement, baseVersion );
  345. let transformed = transform( splitDelta, wrapDelta );
  346. expect( transformed.length ).to.equal( 1 );
  347. baseVersion = wrapDelta.operations.length;
  348. expectDelta( transformed[ 0 ], {
  349. type: SplitDelta,
  350. operations: [
  351. {
  352. type: InsertOperation,
  353. position: new Position( root, [ 3, 3, 2, 2 ] ),
  354. baseVersion: baseVersion
  355. },
  356. {
  357. type: MoveOperation,
  358. sourcePosition: new Position( root, [ 3, 3, 2, 1, 3 ] ),
  359. howMany: 9,
  360. targetPosition: new Position( root, [ 3, 3, 2, 2, 0 ] ),
  361. baseVersion: baseVersion + 1
  362. }
  363. ]
  364. } );
  365. // Test if deltas do what they should after applying transformed delta.
  366. applyDelta( wrapDelta, doc );
  367. applyDelta( transformed[ 0 ], doc );
  368. let nodesAndText = getNodesAndText( Range.createFromPositionAndShift( new Position( root, [ 3, 3, 2 ] ), 1 ) );
  369. // WrapDelta and SplitDelta are correctly applied.
  370. expect( nodesAndText ).to.equal( 'EXabcdXPabcPPfoobarxyzPE' );
  371. } );
  372. } );
  373. describe( 'AttributeDelta', () => {
  374. it( 'attribute changed on split element', () => {
  375. let attributeDelta = new AttributeDelta();
  376. attributeDelta.addOperation( new AttributeOperation(
  377. Range.createFromParentsAndOffsets( root, 0, root, 2 ), 'key', 'oldValue', 'newValue', baseVersion
  378. ) );
  379. attributeDelta.addOperation( new AttributeOperation(
  380. Range.createFromPositionAndShift( new Position( root, [ 3, 3, 2 ] ), 3 ), 'key', null, 'newValue', baseVersion + 1
  381. ) );
  382. let transformed = transform( splitDelta, attributeDelta );
  383. baseVersion = attributeDelta.operations.length;
  384. expect( transformed.length ).to.equal( 1 );
  385. expectDelta( transformed[ 0 ], {
  386. type: SplitDelta,
  387. operations: [
  388. {
  389. type: InsertOperation,
  390. position: new Position( root, [ 3, 3, 4 ] ),
  391. baseVersion: baseVersion
  392. },
  393. {
  394. type: MoveOperation,
  395. sourcePosition: new Position( root, [ 3, 3, 3, 3 ] ),
  396. howMany: 9,
  397. targetPosition: new Position( root, [ 3, 3, 4, 0 ] ),
  398. baseVersion: baseVersion + 1
  399. }
  400. ]
  401. } );
  402. expect( transformed[ 0 ].operations[ 0 ].nodes.getNode( 0 ).getAttribute( 'key' ) ).to.equal( 'newValue' );
  403. } );
  404. it( 'attribute removed from split element', () => {
  405. splitDelta.operations[ 0 ].nodes.getNode( 0 ).setAttribute( 'key', 'oldValue' );
  406. let attributeDelta = new AttributeDelta();
  407. attributeDelta.addOperation( new AttributeOperation(
  408. Range.createFromParentsAndOffsets( root, 0, root, 2 ), 'key', 'otherValue', null, baseVersion
  409. ) );
  410. attributeDelta.addOperation( new AttributeOperation(
  411. Range.createFromPositionAndShift( new Position( root, [ 3, 3, 2 ] ), 3 ), 'key', 'oldValue', null, baseVersion + 1
  412. ) );
  413. let transformed = transform( splitDelta, attributeDelta );
  414. baseVersion = attributeDelta.operations.length;
  415. expect( transformed.length ).to.equal( 1 );
  416. expectDelta( transformed[ 0 ], {
  417. type: SplitDelta,
  418. operations: [
  419. {
  420. type: InsertOperation,
  421. position: new Position( root, [ 3, 3, 4 ] ),
  422. baseVersion: baseVersion
  423. },
  424. {
  425. type: MoveOperation,
  426. sourcePosition: new Position( root, [ 3, 3, 3, 3 ] ),
  427. howMany: 9,
  428. targetPosition: new Position( root, [ 3, 3, 4, 0 ] ),
  429. baseVersion: baseVersion + 1
  430. }
  431. ]
  432. } );
  433. expect( transformed[ 0 ].operations[ 0 ].nodes.getNode( 0 ).hasAttribute( 'key' ) ).to.be.false;
  434. } );
  435. it( 'attribute changed on split element that is reinserted from graveyard', () => {
  436. splitDelta.operations[ 0 ] = new ReinsertOperation(
  437. new Position( gy, [ 1 ] ),
  438. 1,
  439. new Position( root, [ 3, 3, 4 ] ),
  440. baseVersion
  441. );
  442. let attributeDelta = new AttributeDelta();
  443. attributeDelta.addOperation( new AttributeOperation(
  444. Range.createFromParentsAndOffsets( root, 0, root, 4 ), 'key', 'oldValue', 'newValue', baseVersion
  445. ) );
  446. let transformed = transform( splitDelta, attributeDelta );
  447. baseVersion = attributeDelta.operations.length;
  448. expect( transformed.length ).to.equal( 1 );
  449. expectDelta( transformed[ 0 ], {
  450. type: SplitDelta,
  451. operations: [
  452. {
  453. type: ReinsertOperation,
  454. sourcePosition: new Position( gy, [ 1 ] ),
  455. howMany: 1,
  456. targetPosition: new Position( root, [ 3, 3, 4 ] ),
  457. baseVersion: baseVersion
  458. },
  459. {
  460. type: MoveOperation,
  461. sourcePosition: new Position( root, [ 3, 3, 3, 3 ] ),
  462. howMany: 9,
  463. targetPosition: new Position( root, [ 3, 3, 4, 0 ] ),
  464. baseVersion: baseVersion + 1
  465. }
  466. ]
  467. } );
  468. } );
  469. } );
  470. describe( 'RenameDelta', () => {
  471. it( 'renamed split element', () => {
  472. const renameDelta = new RenameDelta();
  473. renameDelta.addOperation( new RenameOperation(
  474. new Position( root, [ 3, 3, 3 ] ), 'p', 'li', baseVersion
  475. ) );
  476. let transformed = transform( splitDelta, renameDelta );
  477. baseVersion = renameDelta.operations.length;
  478. expect( transformed.length ).to.equal( 1 );
  479. expectDelta( transformed[ 0 ], {
  480. type: SplitDelta,
  481. operations: [
  482. {
  483. type: InsertOperation,
  484. position: new Position( root, [ 3, 3, 4 ] ),
  485. baseVersion: baseVersion
  486. },
  487. {
  488. type: MoveOperation,
  489. sourcePosition: new Position( root, [ 3, 3, 3, 3 ] ),
  490. howMany: 9,
  491. targetPosition: new Position( root, [ 3, 3, 4, 0 ] ),
  492. baseVersion: baseVersion + 1
  493. }
  494. ]
  495. } );
  496. expect( transformed[ 0 ].operations[ 0 ].nodes.getNode( 0 ).name ).to.equal( 'li' );
  497. } );
  498. it( 'split element is different than renamed element', () => {
  499. const renameDelta = new RenameDelta();
  500. renameDelta.addOperation( new RenameOperation(
  501. new Position( root, [ 4 ] ), 'p', 'li', baseVersion
  502. ) );
  503. let transformed = transform( splitDelta, renameDelta );
  504. baseVersion = renameDelta.operations.length;
  505. expect( transformed.length ).to.equal( 1 );
  506. expectDelta( transformed[ 0 ], {
  507. type: SplitDelta,
  508. operations: [
  509. {
  510. type: InsertOperation,
  511. position: new Position( root, [ 3, 3, 4 ] ),
  512. baseVersion: baseVersion
  513. },
  514. {
  515. type: MoveOperation,
  516. sourcePosition: new Position( root, [ 3, 3, 3, 3 ] ),
  517. howMany: 9,
  518. targetPosition: new Position( root, [ 3, 3, 4, 0 ] ),
  519. baseVersion: baseVersion + 1
  520. }
  521. ]
  522. } );
  523. } );
  524. it( 'renamed split element that is reinserted from graveyard', () => {
  525. splitDelta.operations[ 0 ] = new ReinsertOperation(
  526. new Position( gy, [ 1 ] ),
  527. 1,
  528. new Position( root, [ 3, 3, 4 ] ),
  529. baseVersion
  530. );
  531. const renameDelta = new RenameDelta();
  532. renameDelta.addOperation( new RenameOperation(
  533. new Position( root, [ 3, 3, 3 ] ), 'p', 'li', baseVersion
  534. ) );
  535. let transformed = transform( splitDelta, renameDelta );
  536. baseVersion = renameDelta.operations.length;
  537. expect( transformed.length ).to.equal( 1 );
  538. expectDelta( transformed[ 0 ], {
  539. type: SplitDelta,
  540. operations: [
  541. {
  542. type: ReinsertOperation,
  543. sourcePosition: new Position( gy, [ 1 ] ),
  544. howMany: 1,
  545. targetPosition: new Position( root, [ 3, 3, 4 ] ),
  546. baseVersion: baseVersion
  547. },
  548. {
  549. type: MoveOperation,
  550. sourcePosition: new Position( root, [ 3, 3, 3, 3 ] ),
  551. howMany: 9,
  552. targetPosition: new Position( root, [ 3, 3, 4, 0 ] ),
  553. baseVersion: baseVersion + 1
  554. }
  555. ]
  556. } );
  557. } );
  558. } );
  559. } );
  560. } );