insert.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  1. /**
  2. * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  4. */
  5. import { Client, syncClients, expectClients, clearBuffer } from './utils.js';
  6. describe( 'transform', () => {
  7. let john, kate;
  8. beforeEach( () => {
  9. return Promise.all( [
  10. Client.get( 'john' ).then( client => ( john = client ) ),
  11. Client.get( 'kate' ).then( client => ( kate = client ) )
  12. ] );
  13. } );
  14. afterEach( () => {
  15. clearBuffer();
  16. return Promise.all( [ john.destroy(), kate.destroy() ] );
  17. } );
  18. describe( 'insert', () => {
  19. describe( 'by insert', () => {
  20. it( 'elements at same position #1', () => {
  21. john.setData( '[]<paragraph>Foo</paragraph>' );
  22. kate.setData( '[]<paragraph>Foo</paragraph>' );
  23. john.insert( '<paragraph>Abc</paragraph>' );
  24. kate.insert( '<paragraph>Xyz</paragraph>' );
  25. syncClients();
  26. expectClients(
  27. '<paragraph>Abc</paragraph>' +
  28. '<paragraph>Xyz</paragraph>' +
  29. '<paragraph>Foo</paragraph>'
  30. );
  31. } );
  32. it( 'elements at same position #2', () => {
  33. john.setData( '[]<paragraph>Foo</paragraph>' );
  34. kate.setData( '[]<paragraph>Foo</paragraph>' );
  35. kate.insert( '<paragraph>Xyz</paragraph>' );
  36. john.insert( '<paragraph>Abc</paragraph>' );
  37. syncClients();
  38. expectClients(
  39. '<paragraph>Abc</paragraph>' +
  40. '<paragraph>Xyz</paragraph>' +
  41. '<paragraph>Foo</paragraph>'
  42. );
  43. } );
  44. it( 'elements in same parent', () => {
  45. john.setData( '[]<paragraph>Foo</paragraph>' );
  46. kate.setData( '<paragraph>Foo</paragraph>[]' );
  47. john.insert( '<paragraph>Abc</paragraph>' );
  48. kate.insert( '<paragraph>Xyz</paragraph>' );
  49. syncClients();
  50. expectClients(
  51. '<paragraph>Abc</paragraph>' +
  52. '<paragraph>Foo</paragraph>' +
  53. '<paragraph>Xyz</paragraph>'
  54. );
  55. } );
  56. it( 'elements in same path', () => {
  57. john.setData( '[]<blockQuote><paragraph>Foo</paragraph></blockQuote>' );
  58. kate.setData( '<blockQuote>[]<paragraph>Foo</paragraph></blockQuote>' );
  59. john.insert( '<paragraph>Abc</paragraph>' );
  60. kate.insert( '<paragraph>Xyz</paragraph>' );
  61. syncClients();
  62. expectClients(
  63. '<paragraph>Abc</paragraph>' +
  64. '<blockQuote>' +
  65. '<paragraph>Xyz</paragraph>' +
  66. '<paragraph>Foo</paragraph>' +
  67. '</blockQuote>'
  68. );
  69. } );
  70. it( 'text at different paths', () => {
  71. john.setData( '<paragraph>Abc[]</paragraph><paragraph>Xyz</paragraph>' );
  72. kate.setData( '<paragraph>Abc</paragraph><paragraph>[]Xyz</paragraph>' );
  73. john.type( 'Foo' );
  74. kate.type( 'Bar' );
  75. syncClients();
  76. expectClients(
  77. '<paragraph>AbcFoo</paragraph>' +
  78. '<paragraph>BarXyz</paragraph>'
  79. );
  80. } );
  81. it( 'text, then wrap and undo', () => {
  82. john.setData( '<paragraph>Foo[]</paragraph>' );
  83. kate.setData( '<paragraph>Foo[]</paragraph>' );
  84. john.type( 'Bar' );
  85. kate.type( 'Abc' );
  86. syncClients();
  87. john.setSelection( [ 0 ], [ 1 ] );
  88. john.wrap( 'blockQuote' );
  89. kate.undo();
  90. syncClients();
  91. expectClients(
  92. '<blockQuote>' +
  93. '<paragraph>FooBar</paragraph>' +
  94. '</blockQuote>'
  95. );
  96. } );
  97. it( 'text, then insert element and merge', () => {
  98. john.setData( '<paragraph>[]</paragraph><paragraph>Abc</paragraph>' );
  99. kate.setData( '<paragraph>[]</paragraph><paragraph>Abc</paragraph>' );
  100. john.type( 'Foo' );
  101. kate.type( ' Bar' );
  102. syncClients();
  103. expectClients(
  104. '<paragraph>Foo Bar</paragraph>' +
  105. '<paragraph>Abc</paragraph>'
  106. );
  107. john.setSelection( [ 1 ] );
  108. kate.setSelection( [ 1 ] );
  109. john.insert( '<paragraph>Xyz</paragraph>' );
  110. kate.merge();
  111. syncClients();
  112. expectClients(
  113. '<paragraph>Foo BarAbc</paragraph>' +
  114. '<paragraph>Xyz</paragraph>'
  115. );
  116. } );
  117. it( 'text, then split and undo', () => {
  118. john.setData( '<paragraph>[]</paragraph>' );
  119. kate.setData( '<paragraph>[]</paragraph>' );
  120. john.type( 'Foo' );
  121. kate.type( ' Bar' );
  122. syncClients();
  123. john.setSelection( [ 0, 1 ] );
  124. kate.setSelection( [ 0, 4 ] );
  125. john.split();
  126. kate.split();
  127. syncClients();
  128. john.undo();
  129. kate.undo();
  130. syncClients();
  131. john.undo();
  132. kate.undo();
  133. syncClients();
  134. expectClients( '<paragraph></paragraph>' );
  135. } );
  136. } );
  137. describe( 'by move', () => {
  138. it( 'element at different paths #1', () => {
  139. john.setData( '[]<paragraph>Foo</paragraph><paragraph>Bar</paragraph>' );
  140. kate.setData( '<paragraph>Foo</paragraph><paragraph>B[ar]</paragraph>' );
  141. john.insert( '<paragraph>Abc</paragraph>' );
  142. kate.move( [ 1, 0 ] );
  143. syncClients();
  144. expectClients(
  145. '<paragraph>Abc</paragraph>' +
  146. '<paragraph>Foo</paragraph>' +
  147. '<paragraph>arB</paragraph>'
  148. );
  149. } );
  150. it( 'element at different paths #2', () => {
  151. john.setData( '<blockQuote><paragraph>Foo</paragraph>[]</blockQuote><paragraph>Bar</paragraph>' );
  152. kate.setData( '<blockQuote><paragraph>Foo</paragraph></blockQuote><paragraph>B[ar]</paragraph>' );
  153. john.insert( '<paragraph>Abc</paragraph>' );
  154. kate.move( [ 0, 0, 0 ] );
  155. syncClients();
  156. expectClients(
  157. '<blockQuote>' +
  158. '<paragraph>arFoo</paragraph>' +
  159. '<paragraph>Abc</paragraph>' +
  160. '</blockQuote>' +
  161. '<paragraph>B</paragraph>'
  162. );
  163. } );
  164. it( 'text at different paths', () => {
  165. john.setData( '<paragraph>[]Foo</paragraph><paragraph>Bar</paragraph>' );
  166. kate.setData( '<paragraph>Foo</paragraph><paragraph>B[ar]</paragraph>' );
  167. john.type( 'Abc' );
  168. kate.move( [ 1, 0 ] );
  169. syncClients();
  170. expectClients(
  171. '<paragraph>AbcFoo</paragraph>' +
  172. '<paragraph>arB</paragraph>'
  173. );
  174. } );
  175. it( 'text at same path', () => {
  176. john.setData( '<paragraph>F[]oo Bar</paragraph>' );
  177. kate.setData( '<paragraph>Foo B[ar]</paragraph>' );
  178. john.type( 'Abc' );
  179. kate.move( [ 0, 0 ] );
  180. syncClients();
  181. expectClients( '<paragraph>arFAbcoo B</paragraph>' );
  182. } );
  183. it( 'text at same position #1', () => {
  184. john.setData( '<paragraph>Foo[] Bar</paragraph>' );
  185. kate.setData( '<paragraph>Foo [Bar]</paragraph>' );
  186. john.type( 'Abc' );
  187. kate.move( [ 0, 3 ] );
  188. syncClients();
  189. expectClients( '<paragraph>FooBarAbc </paragraph>' );
  190. } );
  191. it( 'text at same position #2', () => {
  192. john.setData( '<paragraph>Foo []Bar</paragraph>' );
  193. kate.setData( '<paragraph>Foo [Bar]</paragraph>' );
  194. john.type( 'Abc' );
  195. kate.move( [ 0, 0 ] );
  196. syncClients();
  197. expectClients( '<paragraph>BarFoo Abc</paragraph>' );
  198. } );
  199. } );
  200. describe( 'by wrap', () => {
  201. it( 'element in same path #1', () => {
  202. john.setData( '<paragraph>Foo Bar</paragraph>[]' );
  203. kate.setData( '[<paragraph>Foo Bar</paragraph>]' );
  204. john.insert( '<paragraph>Abc</paragraph>' );
  205. kate.wrap( 'blockQuote' );
  206. syncClients();
  207. expectClients(
  208. '<blockQuote>' +
  209. '<paragraph>Foo Bar</paragraph>' +
  210. '</blockQuote>' +
  211. '<paragraph>Abc</paragraph>'
  212. );
  213. } );
  214. it( 'element in same path #2', () => {
  215. john.setData( '<paragraph>Foo[]</paragraph>' );
  216. kate.setData( '[<paragraph>Foo</paragraph>]' );
  217. john.type( ' Bar' );
  218. kate.wrap( 'blockQuote' );
  219. syncClients();
  220. expectClients(
  221. '<blockQuote>' +
  222. '<paragraph>Foo Bar</paragraph>' +
  223. '</blockQuote>'
  224. );
  225. } );
  226. it( 'element in different paths #1', () => {
  227. john.setData( '<paragraph>Foo</paragraph>[]<paragraph>Bar</paragraph>' );
  228. kate.setData( '<paragraph>Foo</paragraph>[<paragraph>Bar</paragraph>]' );
  229. john.insert( '<paragraph>Abc</paragraph>' );
  230. kate.wrap( 'blockQuote' );
  231. syncClients();
  232. expectClients(
  233. '<paragraph>Foo</paragraph>' +
  234. '<paragraph>Abc</paragraph>' +
  235. '<blockQuote>' +
  236. '<paragraph>Bar</paragraph>' +
  237. '</blockQuote>'
  238. );
  239. } );
  240. it( 'element in different paths #2', () => {
  241. john.setData( '<paragraph>Foo</paragraph><paragraph>Bar[]</paragraph>' );
  242. kate.setData( '[<paragraph>Foo</paragraph>]<paragraph>Bar</paragraph>' );
  243. john.type( 'Abc' );
  244. kate.wrap( 'blockQuote' );
  245. syncClients();
  246. expectClients(
  247. '<blockQuote>' +
  248. '<paragraph>Foo</paragraph>' +
  249. '</blockQuote>' +
  250. '<paragraph>BarAbc</paragraph>'
  251. );
  252. } );
  253. it( 'element, then unwrap and split', () => {
  254. john.setData( '<paragraph>Foo[]</paragraph>' );
  255. kate.setData( '[<paragraph>Foo</paragraph>]' );
  256. john.type( ' Bar' );
  257. kate.wrap( 'blockQuote' );
  258. syncClients();
  259. expectClients( '<blockQuote><paragraph>Foo Bar</paragraph></blockQuote>' );
  260. john.setSelection( [ 0, 0 ] );
  261. kate.setSelection( [ 0, 0, 2 ] );
  262. john.unwrap();
  263. kate.split();
  264. syncClients();
  265. expectClients(
  266. '<paragraph>Fo</paragraph>' +
  267. '<paragraph>o Bar</paragraph>'
  268. );
  269. } );
  270. it( 'element, then add marker and split', () => {
  271. john.setData( '<paragraph>Foo[]</paragraph>' );
  272. kate.setData( '[<paragraph>Foo</paragraph>]' );
  273. john.type( ' Bar' );
  274. kate.wrap( 'blockQuote' );
  275. syncClients();
  276. john.setSelection( [ 0, 0, 0 ], [ 0, 0, 3 ] );
  277. kate.setSelection( [ 0, 0, 2 ] );
  278. john.setMarker( 'm1' );
  279. kate.split();
  280. syncClients();
  281. expectClients(
  282. '<blockQuote>' +
  283. '<paragraph><m1:start></m1:start>Fo</paragraph>' +
  284. '<paragraph>o<m1:end></m1:end> Bar</paragraph>' +
  285. '</blockQuote>'
  286. );
  287. } );
  288. it( 'element, then split at the same position and undo', () => {
  289. john.setData( '<paragraph>Foo[]</paragraph>' );
  290. kate.setData( '[<paragraph>Foo</paragraph>]' );
  291. john.type( ' Bar' );
  292. kate.wrap( 'blockQuote' );
  293. syncClients();
  294. expectClients( '<blockQuote><paragraph>Foo Bar</paragraph></blockQuote>' );
  295. john.setSelection( [ 0, 0, 3 ] );
  296. kate.setSelection( [ 0, 0, 3 ] );
  297. john.split();
  298. kate.split();
  299. syncClients();
  300. expectClients(
  301. '<blockQuote>' +
  302. '<paragraph>Foo</paragraph>' +
  303. '<paragraph> Bar</paragraph>' +
  304. '</blockQuote>'
  305. );
  306. kate.undo();
  307. syncClients();
  308. // Below is not the best result ever but it is acceptable.
  309. expectClients(
  310. '<blockQuote>' +
  311. '<paragraph>Foo Bar</paragraph>' +
  312. '</blockQuote>'
  313. );
  314. } );
  315. } );
  316. describe( 'by unwrap', () => {
  317. it( 'element in different path', () => {
  318. john.setData( '<paragraph>Foo[]</paragraph><blockQuote><paragraph>Bar</paragraph></blockQuote>' );
  319. kate.setData( '<paragraph>Foo</paragraph><blockQuote>[<paragraph>Bar</paragraph>]</blockQuote>' );
  320. john.type( 'Abc' );
  321. kate.unwrap();
  322. syncClients();
  323. expectClients( '<paragraph>FooAbc</paragraph><paragraph>Bar</paragraph>' );
  324. } );
  325. it( 'text in different path', () => {
  326. john.setData( '<paragraph>Foo[]</paragraph><blockQuote><paragraph>Bar</paragraph></blockQuote>' );
  327. kate.setData( '<paragraph>Foo</paragraph><blockQuote><paragraph>[]Bar</paragraph></blockQuote>' );
  328. john.type( 'Abc' );
  329. kate.unwrap();
  330. syncClients();
  331. expectClients( '<paragraph>FooAbc</paragraph><blockQuote>Bar</blockQuote>' );
  332. } );
  333. it( 'element in same path #1', () => {
  334. john.setData( '<blockQuote><paragraph>Foo[]</paragraph></blockQuote>' );
  335. kate.setData( '<blockQuote>[<paragraph>Foo</paragraph>]</blockQuote>' );
  336. john.type( ' Bar' );
  337. kate.unwrap();
  338. syncClients();
  339. expectClients( '<paragraph>Foo Bar</paragraph>' );
  340. } );
  341. it( 'element in same path #2', () => {
  342. john.setData( '<blockQuote><paragraph>Foo</paragraph>[]</blockQuote>' );
  343. kate.setData( '<blockQuote>[<paragraph>Foo</paragraph>]</blockQuote>' );
  344. john.insert( '<paragraph>Bar</paragraph>' );
  345. kate.unwrap();
  346. syncClients();
  347. // Below would be the expected effect with correct wrap transformation.
  348. // expectClients(
  349. // '<paragraph>Foo</paragraph>' +
  350. // '<paragraph>Bar</paragraph>'
  351. // );
  352. expectClients(
  353. '<paragraph>Foo</paragraph>'
  354. );
  355. } );
  356. it( 'element, then wrap and undo on both clients', () => {
  357. john.setData( '<blockQuote><paragraph>Foo</paragraph>[]</blockQuote>' );
  358. kate.setData( '<blockQuote>[<paragraph>Foo</paragraph>]</blockQuote>' );
  359. john.insert( '<paragraph>Bar</paragraph>' );
  360. kate.unwrap();
  361. syncClients();
  362. kate.setSelection( [ 0 ], [ 1 ] );
  363. kate.wrap( 'blockQuote' );
  364. john.undo();
  365. syncClients();
  366. expectClients(
  367. '<blockQuote>' +
  368. '<paragraph>Foo</paragraph>' +
  369. '</blockQuote>'
  370. );
  371. } );
  372. it( 'element, then wrap, unwrap and undo', () => {
  373. john.setData( '<blockQuote><paragraph>Foo[]</paragraph></blockQuote>' );
  374. kate.setData( '<blockQuote>[]<paragraph>Foo</paragraph></blockQuote>' );
  375. john.type( ' Bar' );
  376. kate.unwrap();
  377. syncClients();
  378. expectClients( '<paragraph>Foo Bar</paragraph>' );
  379. john.setSelection( [ 0 ], [ 1 ] );
  380. john.wrap( 'blockQuote' );
  381. syncClients();
  382. expectClients( '<blockQuote><paragraph>Foo Bar</paragraph></blockQuote>' );
  383. john.undo();
  384. kate.setSelection( [ 0, 0 ], [ 0, 1 ] );
  385. kate.unwrap();
  386. syncClients();
  387. expectClients( '<paragraph>Foo Bar</paragraph>' );
  388. } );
  389. } );
  390. describe( 'by split', () => {
  391. it( 'text in same path #1', () => {
  392. john.setData( '<paragraph>Foo</paragraph>[]' );
  393. kate.setData( '<paragraph>F[]oo</paragraph>' );
  394. john.insert( '<paragraph>Bar</paragraph>' );
  395. kate.split();
  396. syncClients();
  397. expectClients(
  398. '<paragraph>F</paragraph>' +
  399. '<paragraph>oo</paragraph>' +
  400. '<paragraph>Bar</paragraph>'
  401. );
  402. } );
  403. it( 'text in same path #2', () => {
  404. john.setData( '<paragraph>Fo[]o</paragraph>' );
  405. kate.setData( '<paragraph>F[]oo</paragraph>' );
  406. john.type( 'Bar' );
  407. kate.split();
  408. syncClients();
  409. expectClients( '<paragraph>F</paragraph><paragraph>oBaro</paragraph>' );
  410. } );
  411. it( 'text in different paths #1', () => {
  412. john.setData( '[]<paragraph>Foo</paragraph><paragraph>Bar</paragraph>' );
  413. kate.setData( '<paragraph>Foo</paragraph><paragraph>B[]ar</paragraph>' );
  414. john.insert( '<paragraph>Abc</paragraph>' );
  415. kate.split();
  416. syncClients();
  417. expectClients(
  418. '<paragraph>Abc</paragraph>' +
  419. '<paragraph>Foo</paragraph>' +
  420. '<paragraph>B</paragraph>' +
  421. '<paragraph>ar</paragraph>'
  422. );
  423. } );
  424. it( 'text in different paths #2', () => {
  425. john.setData( '<paragraph>Foo[]</paragraph><paragraph>Bar</paragraph>' );
  426. kate.setData( '<paragraph>Foo</paragraph><paragraph>B[]ar</paragraph>' );
  427. john.type( 'Abc' );
  428. kate.split();
  429. syncClients();
  430. expectClients(
  431. '<paragraph>FooAbc</paragraph>' +
  432. '<paragraph>B</paragraph>' +
  433. '<paragraph>ar</paragraph>'
  434. );
  435. } );
  436. it( 'text at same position', () => {
  437. john.setData( '<paragraph>F[]oo</paragraph>' );
  438. kate.setData( '<paragraph>F[]oo</paragraph>' );
  439. john.type( 'Bar' );
  440. kate.split();
  441. syncClients();
  442. expectClients( '<paragraph>FBar</paragraph><paragraph>oo</paragraph>' );
  443. } );
  444. it( 'text at same position #2', () => {
  445. john.setData( '<paragraph>Foo[]</paragraph>' );
  446. kate.setData( '<paragraph>Foo[]</paragraph>' );
  447. john.type( 'Bar' );
  448. kate.split();
  449. syncClients();
  450. expectClients( '<paragraph>FooBar</paragraph><paragraph></paragraph>' );
  451. } );
  452. it( 'text, then insert element and split', () => {
  453. john.setData( '<paragraph>[]Foo</paragraph>' );
  454. kate.setData( '<paragraph>F[]oo</paragraph>' );
  455. john.type( 'Bar' );
  456. kate.split();
  457. syncClients();
  458. john.setSelection( [ 1 ] );
  459. kate.setSelection( [ 1, 1 ] );
  460. john.insert( '<paragraph>Abc</paragraph>' );
  461. kate.split();
  462. syncClients();
  463. expectClients(
  464. '<paragraph>BarF</paragraph>' +
  465. '<paragraph>Abc</paragraph>' +
  466. '<paragraph>o</paragraph>' +
  467. '<paragraph>o</paragraph>'
  468. );
  469. } );
  470. } );
  471. describe( 'by remove', () => {
  472. it( 'text in different path', () => {
  473. john.setData( '<paragraph>Foo[]</paragraph><paragraph>Bar</paragraph>' );
  474. kate.setData( '<paragraph>Foo</paragraph><paragraph>[Bar]</paragraph>' );
  475. john.type( 'Abc' );
  476. kate.remove();
  477. syncClients();
  478. expectClients( '<paragraph>FooAbc</paragraph><paragraph></paragraph>' );
  479. } );
  480. it( 'text in same path', () => {
  481. john.setData( '<paragraph>Foo[]</paragraph>' );
  482. kate.setData( '<paragraph>[Foo]</paragraph>' );
  483. john.type( 'Bar' );
  484. kate.remove();
  485. syncClients();
  486. expectClients( '<paragraph>Bar</paragraph>' );
  487. } );
  488. it( 'element in different path', () => {
  489. john.setData( '<paragraph>Foo[]</paragraph><paragraph>Bar</paragraph>' );
  490. kate.setData( '<paragraph>Foo</paragraph>[<paragraph>Bar</paragraph>]' );
  491. john.type( 'Abc' );
  492. kate.remove();
  493. syncClients();
  494. expectClients( '<paragraph>FooAbc</paragraph>' );
  495. } );
  496. it( 'element in same path', () => {
  497. john.setData( '<paragraph>Foo[]</paragraph><paragraph>Bar</paragraph>' );
  498. kate.setData( '[<paragraph>Foo</paragraph>]<paragraph>Bar</paragraph>' );
  499. john.type( 'Abc' );
  500. kate.remove();
  501. syncClients();
  502. expectClients( '<paragraph>Bar</paragraph>' );
  503. } );
  504. it( 'text, then rename, split and undo', () => {
  505. john.setData( '<paragraph>Foo Bar[]</paragraph>' );
  506. kate.setData( '<paragraph>Foo [Bar]</paragraph>' );
  507. john.type( 'Bar' );
  508. kate.remove();
  509. syncClients();
  510. expectClients( '<paragraph>Foo Bar</paragraph>' );
  511. john.setSelection( [ 0, 0 ] );
  512. kate.setSelection( [ 0, 4 ] );
  513. john.rename( 'heading1' );
  514. kate.split();
  515. syncClients();
  516. expectClients( '<heading1>Foo </heading1><heading1>Bar</heading1>' );
  517. kate.undo();
  518. syncClients();
  519. expectClients( '<heading1>Foo Bar</heading1>' );
  520. } );
  521. it( 'element, then add marker, split and undo with type #1', () => {
  522. john.setData( '<paragraph>Foo</paragraph>[]' );
  523. kate.setData( '[<paragraph>Foo</paragraph>]' );
  524. john.insert( '<paragraph>Bar</paragraph>' );
  525. kate.remove();
  526. syncClients();
  527. expectClients( '<paragraph>Bar</paragraph><paragraph></paragraph>' ); // Autoparagraphing.
  528. john.setSelection( [ 0, 0 ], [ 0, 3 ] );
  529. kate.setSelection( [ 0, 2 ] );
  530. john.setMarker( 'm1' );
  531. kate.split();
  532. syncClients();
  533. expectClients(
  534. '<paragraph><m1:start></m1:start>Ba</paragraph>' +
  535. '<paragraph>r<m1:end></m1:end></paragraph>' +
  536. '<paragraph></paragraph>'
  537. );
  538. john.undo();
  539. john.setSelection( [ 1, 1 ] );
  540. john.type( 'Abc' );
  541. kate.undo();
  542. syncClients();
  543. expectClients( '<paragraph>BarAbc</paragraph><paragraph></paragraph>' );
  544. kate.undo();
  545. syncClients();
  546. expectClients( '<paragraph>Foo</paragraph><paragraph>BarAbc</paragraph>' );
  547. } );
  548. it( 'element, then add marker, split and undo with type #2', () => {
  549. john.setData( '<paragraph>Foo</paragraph>[]' );
  550. kate.setData( '[<paragraph>Foo</paragraph>]' );
  551. john.insert( '<paragraph>Bar</paragraph>' );
  552. kate.remove();
  553. syncClients();
  554. expectClients( '<paragraph>Bar</paragraph><paragraph></paragraph>' ); // Autoparagraphing.
  555. john.setSelection( [ 0, 0 ], [ 0, 3 ] );
  556. kate.setSelection( [ 0, 2 ] );
  557. john.setMarker( 'm1' );
  558. kate.split();
  559. syncClients();
  560. expectClients(
  561. '<paragraph><m1:start></m1:start>Ba</paragraph>' +
  562. '<paragraph>r<m1:end></m1:end></paragraph>' +
  563. '<paragraph></paragraph>'
  564. );
  565. john.undo();
  566. john.setSelection( [ 1, 1 ] );
  567. john.type( 'Abc' );
  568. kate.undo();
  569. kate.undo();
  570. syncClients();
  571. expectClients( '<paragraph>Foo</paragraph><paragraph>BarAbc</paragraph>' );
  572. } );
  573. } );
  574. describe( 'by merge', () => {
  575. it( 'element into paragraph', () => {
  576. john.setData( '<paragraph>Foo</paragraph><paragraph>[]</paragraph>' );
  577. kate.setData( '<paragraph>Foo</paragraph>[]<paragraph></paragraph>' );
  578. john.type( ' Bar' );
  579. kate.merge();
  580. syncClients();
  581. expectClients( '<paragraph>Foo Bar</paragraph>' );
  582. } );
  583. } );
  584. describe( 'by marker', () => {
  585. it( 'in different path #1', () => {
  586. john.setData( '[]<paragraph>Foo</paragraph><paragraph>Bar</paragraph>' );
  587. kate.setData( '<paragraph>Foo</paragraph><paragraph>[Bar]</paragraph>' );
  588. john.insert( '<paragraph>Abc</paragraph>' );
  589. kate.setMarker( 'm1' );
  590. syncClients();
  591. expectClients(
  592. '<paragraph>Abc</paragraph>' +
  593. '<paragraph>Foo</paragraph>' +
  594. '<paragraph><m1:start></m1:start>Bar<m1:end></m1:end></paragraph>'
  595. );
  596. } );
  597. it( 'in different path #2', () => {
  598. john.setData( '<paragraph>Foo[]</paragraph><paragraph>Bar</paragraph>' );
  599. kate.setData( '<paragraph>Foo</paragraph><paragraph>[Bar]</paragraph>' );
  600. john.type( 'Abc' );
  601. kate.setMarker( 'm1' );
  602. syncClients();
  603. expectClients(
  604. '<paragraph>FooAbc</paragraph>' +
  605. '<paragraph><m1:start></m1:start>Bar<m1:end></m1:end></paragraph>'
  606. );
  607. } );
  608. it( 'in same path', () => {
  609. john.setData( '<paragraph>[]Foo</paragraph>' );
  610. kate.setData( '<paragraph>Fo[o]</paragraph>' );
  611. john.type( 'Bar' );
  612. kate.setMarker( 'm1' );
  613. syncClients();
  614. expectClients( '<paragraph>BarFo<m1:start></m1:start>o<m1:end></m1:end></paragraph>' );
  615. } );
  616. } );
  617. describe( 'by rename', () => {
  618. it( 'element in different path', () => {
  619. john.setData( '<paragraph>Foo</paragraph><paragraph>Bar</paragraph>[]' );
  620. kate.setData( '<paragraph>F[]oo</paragraph><paragraph>Bar</paragraph>' );
  621. john.insert( '<paragraph>Abc</paragraph>' );
  622. kate.rename( 'heading1' );
  623. syncClients();
  624. expectClients(
  625. '<heading1>Foo</heading1>' +
  626. '<paragraph>Bar</paragraph>' +
  627. '<paragraph>Abc</paragraph>'
  628. );
  629. } );
  630. it( 'element in same path', () => {
  631. john.setData( '<paragraph>Foo</paragraph>[]' );
  632. kate.setData( '<paragraph>F[]oo</paragraph>' );
  633. john.insert( '<paragraph>Bar</paragraph>' );
  634. kate.rename( 'heading1' );
  635. syncClients();
  636. expectClients(
  637. '<heading1>Foo</heading1>' +
  638. '<paragraph>Bar</paragraph>'
  639. );
  640. } );
  641. it( 'text in same path', () => {
  642. john.setData( '<paragraph>Foo[] Bar</paragraph>' );
  643. kate.setData( '<paragraph>F[]oo Bar</paragraph>' );
  644. john.type( 'Abc' );
  645. kate.rename( 'heading1' );
  646. syncClients();
  647. expectClients( '<heading1>FooAbc Bar</heading1>' );
  648. } );
  649. it( 'text in different paths', () => {
  650. john.setData( '<blockQuote><paragraph>Foo</paragraph></blockQuote><paragraph>B[]ar</paragraph>' );
  651. kate.setData( '<blockQuote><paragraph>F[]oo</paragraph></blockQuote><paragraph>Bar</paragraph>' );
  652. john.type( 'Abc' );
  653. kate.rename( 'heading1' );
  654. syncClients();
  655. expectClients(
  656. '<blockQuote>' +
  657. '<heading1>Foo</heading1>' +
  658. '</blockQuote>' +
  659. '<paragraph>BAbcar</paragraph>'
  660. );
  661. } );
  662. } );
  663. } );
  664. } );