remove.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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( 'remove', () => {
  19. describe( 'by remove', () => {
  20. it( 'text in different path', () => {
  21. john.setData( '<paragraph>F[oo]</paragraph><paragraph>Bar</paragraph>' );
  22. kate.setData( '<paragraph>Foo</paragraph><paragraph>B[ar]</paragraph>' );
  23. john.remove();
  24. kate.remove();
  25. syncClients();
  26. expectClients( '<paragraph>F</paragraph><paragraph>B</paragraph>' );
  27. } );
  28. it( 'text in same path', () => {
  29. john.setData( '<paragraph>F[oo] Bar</paragraph>' );
  30. kate.setData( '<paragraph>Foo B[ar]</paragraph>' );
  31. john.remove();
  32. kate.remove();
  33. syncClients();
  34. expectClients( '<paragraph>F B</paragraph>' );
  35. } );
  36. it( 'text in other user\'s selection #1', () => {
  37. john.setData( '<paragraph>[Foo Bar]</paragraph>' );
  38. kate.setData( '<paragraph>Fo[o B]ar</paragraph>' );
  39. john.remove();
  40. kate.remove();
  41. syncClients();
  42. expectClients( '<paragraph></paragraph>' );
  43. } );
  44. it( 'text in other user\'s selection #2', () => {
  45. john.setData( '<paragraph>[Foo Bar]</paragraph>' );
  46. kate.setData( '<paragraph>[Foo Bar]</paragraph>' );
  47. john.remove();
  48. kate.remove();
  49. syncClients();
  50. expectClients( '<paragraph></paragraph>' );
  51. } );
  52. it( 'element in different path', () => {
  53. john.setData( '<paragraph>[Foo]</paragraph><paragraph>Bar</paragraph>' );
  54. kate.setData( '<paragraph>Foo</paragraph>[<paragraph>Bar</paragraph>]' );
  55. john.remove();
  56. kate.remove();
  57. syncClients();
  58. expectClients( '<paragraph></paragraph>' );
  59. } );
  60. it( 'text in other user\'s selection, then undo', () => {
  61. john.setData( '<paragraph>[Foo Bar]</paragraph>' );
  62. kate.setData( '<paragraph>Fo[o B]ar</paragraph>' );
  63. john.remove();
  64. kate.remove();
  65. syncClients();
  66. john.undo();
  67. kate.undo();
  68. syncClients();
  69. expectClients( '<paragraph>Foo Bar</paragraph>' );
  70. } );
  71. } );
  72. describe( 'by wrap', () => {
  73. it( 'element in different path', () => {
  74. john.setData( '<paragraph>[Foo]</paragraph><paragraph>Bar</paragraph>' );
  75. kate.setData( '<paragraph>Foo</paragraph>[<paragraph>Bar</paragraph>]' );
  76. john.remove();
  77. kate.wrap( 'blockQuote' );
  78. syncClients();
  79. expectClients(
  80. '<paragraph></paragraph>' +
  81. '<blockQuote>' +
  82. '<paragraph>Bar</paragraph>' +
  83. '</blockQuote>'
  84. );
  85. } );
  86. it( 'element in same path', () => {
  87. john.setData( '<paragraph>[Foo]</paragraph>' );
  88. kate.setData( '[<paragraph>Foo</paragraph>]' );
  89. john.remove();
  90. kate.wrap( 'blockQuote' );
  91. syncClients();
  92. expectClients( '<blockQuote><paragraph></paragraph></blockQuote>' );
  93. } );
  94. it( 'element while removing', () => {
  95. john.setData( '<paragraph>Foo</paragraph>[<paragraph>Bar</paragraph>]' );
  96. kate.setData( '<paragraph>Foo</paragraph>[<paragraph>Bar</paragraph>]' );
  97. john.remove();
  98. kate.wrap( 'blockQuote' );
  99. syncClients();
  100. expectClients( '<paragraph>Foo</paragraph>' );
  101. } );
  102. it( 'element while removing, then undo', () => {
  103. john.setData( '<paragraph>Foo</paragraph>[<paragraph>Bar</paragraph>]' );
  104. kate.setData( '<paragraph>Foo</paragraph>[<paragraph>Bar</paragraph>]' );
  105. john.remove();
  106. kate.wrap( 'blockQuote' );
  107. syncClients();
  108. expectClients( '<paragraph>Foo</paragraph>' );
  109. john.undo();
  110. syncClients();
  111. // Below would be the expected effect with correct wrap transformation.
  112. // expectClients(
  113. // '<paragraph>Foo</paragraph>' +
  114. // '<blockQuote>' +
  115. // '<paragraph>Bar</paragraph>' +
  116. // '</blockQuote>'
  117. // );
  118. expectClients( '<paragraph>Foo</paragraph><paragraph>Bar</paragraph>' );
  119. } );
  120. it( 'element while removing, then undo #2', () => {
  121. john.setData( '<paragraph>Foo</paragraph>[<paragraph>Bar</paragraph>]' );
  122. kate.setData( '<paragraph>Foo</paragraph>[<paragraph>Bar</paragraph>]' );
  123. john.remove();
  124. john.undo();
  125. kate.wrap( 'blockQuote' );
  126. syncClients();
  127. // Below would be the expected effect with correct wrap transformation.
  128. // expectClients(
  129. // '<paragraph>Foo</paragraph>' +
  130. // '<blockQuote>' +
  131. // '<paragraph>Bar</paragraph>' +
  132. // '</blockQuote>'
  133. // );
  134. expectClients( '<paragraph>Foo</paragraph><paragraph>Bar</paragraph>' );
  135. } );
  136. } );
  137. describe( 'by unwrap', () => {
  138. it( 'element in different path', () => {
  139. john.setData( '<paragraph>[Foo]</paragraph><blockQuote><paragraph>Bar</paragraph></blockQuote>' );
  140. kate.setData( '<paragraph>Foo</paragraph><blockQuote>[<paragraph>Bar</paragraph>]</blockQuote>' );
  141. john.remove();
  142. kate.unwrap();
  143. syncClients();
  144. expectClients(
  145. '<paragraph></paragraph>' +
  146. '<paragraph>Bar</paragraph>'
  147. );
  148. } );
  149. it( 'text in different path', () => {
  150. john.setData( '<paragraph>[Foo]</paragraph><blockQuote><paragraph>Bar</paragraph></blockQuote>' );
  151. kate.setData( '<paragraph>Foo</paragraph><blockQuote><paragraph>[]Bar</paragraph></blockQuote>' );
  152. john.remove();
  153. kate.unwrap();
  154. syncClients();
  155. expectClients(
  156. '<paragraph></paragraph>' +
  157. '<blockQuote>Bar</blockQuote>'
  158. );
  159. } );
  160. it( 'element in same path', () => {
  161. john.setData( '<blockQuote><paragraph>[Foo]</paragraph></blockQuote>' );
  162. kate.setData( '<blockQuote>[<paragraph>Foo</paragraph>]</blockQuote>' );
  163. john.remove();
  164. kate.unwrap();
  165. syncClients();
  166. expectClients( '<paragraph></paragraph>' );
  167. } );
  168. it( 'element while removing', () => {
  169. john.setData( '<paragraph>Foo</paragraph><blockQuote>[<paragraph>Bar</paragraph>]</blockQuote>' );
  170. kate.setData( '<paragraph>Foo</paragraph><blockQuote>[<paragraph>Bar</paragraph>]</blockQuote>' );
  171. john.remove();
  172. kate.unwrap();
  173. syncClients();
  174. expectClients( '<paragraph>Foo</paragraph>' );
  175. } );
  176. it( 'element while removing, then undo', () => {
  177. john.setData( '<paragraph>Foo</paragraph><blockQuote>[<paragraph>Bar</paragraph>]</blockQuote>' );
  178. kate.setData( '<paragraph>Foo</paragraph><blockQuote>[]<paragraph>Bar</paragraph></blockQuote>' );
  179. john.remove();
  180. kate.unwrap();
  181. syncClients();
  182. expectClients( '<paragraph>Foo</paragraph>' );
  183. john.undo();
  184. syncClients();
  185. // Below would be the expected effect with correct wrap transformation.
  186. // expectClients(
  187. // '<paragraph>Foo</paragraph>' +
  188. // '<paragraph>Bar</paragraph>'
  189. // );
  190. expectClients( '<paragraph>Foo</paragraph><blockQuote><paragraph>Bar</paragraph></blockQuote>' );
  191. } );
  192. } );
  193. describe( 'by split', () => {
  194. it( 'text in different path', () => {
  195. john.setData( '<paragraph>F[oo]</paragraph><paragraph>Bar</paragraph>' );
  196. kate.setData( '<paragraph>Foo</paragraph><paragraph>B[]ar</paragraph>' );
  197. john.remove();
  198. kate.split();
  199. syncClients();
  200. expectClients(
  201. '<paragraph>F</paragraph>' +
  202. '<paragraph>B</paragraph>' +
  203. '<paragraph>ar</paragraph>'
  204. );
  205. } );
  206. it( 'text in same path', () => {
  207. john.setData( '<paragraph>[Foo] Bar</paragraph>' );
  208. kate.setData( '<paragraph>Foo []Bar</paragraph>' );
  209. john.remove();
  210. kate.split();
  211. syncClients();
  212. expectClients(
  213. '<paragraph> </paragraph>' +
  214. '<paragraph>Bar</paragraph>'
  215. );
  216. } );
  217. it( 'text in other user\'s selection #1', () => {
  218. john.setData( '<paragraph>[Foo] Bar</paragraph>' );
  219. kate.setData( '<paragraph>F[]oo Bar</paragraph>' );
  220. john.remove();
  221. kate.split();
  222. syncClients();
  223. expectClients(
  224. '<paragraph></paragraph>' +
  225. '<paragraph> Bar</paragraph>'
  226. );
  227. } );
  228. it( 'text in other user\'s selection #2', () => {
  229. john.setData( '<paragraph>[Foo Bar]</paragraph>' );
  230. kate.setData( '<paragraph>F[]oo Bar</paragraph>' );
  231. john.remove();
  232. kate.split();
  233. syncClients();
  234. expectClients(
  235. '<paragraph></paragraph>' +
  236. '<paragraph></paragraph>'
  237. );
  238. } );
  239. it( 'text, then remove and undo', () => {
  240. john.setData( '<paragraph>[Foo ]Bar</paragraph>' );
  241. kate.setData( '<paragraph>Foo []Bar</paragraph>' );
  242. john.remove();
  243. kate.split();
  244. syncClients();
  245. john.setSelection( [ 1, 0 ], [ 1, 3 ] );
  246. john.remove();
  247. kate.undo();
  248. syncClients();
  249. expectClients( '<paragraph></paragraph>' );
  250. } );
  251. it( 'remove split element', () => {
  252. john.setData( '[<paragraph>Foo</paragraph>]<paragraph>Bar</paragraph>' );
  253. kate.setData( '<paragraph>Fo[]o</paragraph><paragraph>Bar</paragraph>' );
  254. john.remove();
  255. kate.split();
  256. syncClients();
  257. expectClients( '<paragraph>Bar</paragraph>' );
  258. } );
  259. } );
  260. describe( 'by merge', () => {
  261. it( 'element into paragraph #1', () => {
  262. john.setData( '<paragraph>F[oo]</paragraph><paragraph>Bar</paragraph>' );
  263. kate.setData( '<paragraph>Foo</paragraph>[]<paragraph>Bar</paragraph>' );
  264. john.remove();
  265. kate.merge();
  266. syncClients();
  267. expectClients( '<paragraph>FBar</paragraph>' );
  268. } );
  269. it( 'element into paragraph #2', () => {
  270. john.setData( '<paragraph>Foo</paragraph><paragraph>B[ar]</paragraph>' );
  271. kate.setData( '<paragraph>Foo</paragraph>[]<paragraph>Bar</paragraph>' );
  272. john.remove();
  273. kate.merge();
  274. syncClients();
  275. expectClients( '<paragraph>FooB</paragraph>' );
  276. } );
  277. it( 'element into paragraph, then undo', () => {
  278. john.setData( '<paragraph>F[oo]</paragraph><paragraph>Bar</paragraph>' );
  279. kate.setData( '<paragraph>Foo</paragraph>[]<paragraph>Bar</paragraph>' );
  280. john.remove();
  281. kate.merge();
  282. syncClients();
  283. expectClients( '<paragraph>FBar</paragraph>' );
  284. john.undo();
  285. syncClients();
  286. expectClients( '<paragraph>FooBar</paragraph>' );
  287. } );
  288. it( 'wrapped element into wrapped paragraph #1', () => {
  289. john.setData( '<blockQuote><paragraph>F[oo]</paragraph><paragraph>Bar</paragraph></blockQuote>' );
  290. kate.setData( '<blockQuote><paragraph>Foo</paragraph>[]<paragraph>Bar</paragraph></blockQuote>' );
  291. john.remove();
  292. kate.merge();
  293. syncClients();
  294. expectClients( '<blockQuote><paragraph>FBar</paragraph></blockQuote>' );
  295. } );
  296. it( 'wrapped element into wrapped paragraph #2', () => {
  297. john.setData( '<blockQuote><paragraph>Foo</paragraph><paragraph>B[ar]</paragraph></blockQuote>' );
  298. kate.setData( '<blockQuote><paragraph>Foo</paragraph>[]<paragraph>Bar</paragraph></blockQuote>' );
  299. john.remove();
  300. kate.merge();
  301. syncClients();
  302. expectClients( '<blockQuote><paragraph>FooB</paragraph></blockQuote>' );
  303. } );
  304. it( 'removed element, then undo', () => {
  305. john.setData( '<paragraph>Foo</paragraph>[<paragraph>Bar</paragraph>]' );
  306. kate.setData( '<paragraph>Foo</paragraph>[]<paragraph>Bar</paragraph>' );
  307. john.remove();
  308. kate.merge();
  309. syncClients();
  310. expectClients( '<paragraph>Foo</paragraph>' );
  311. john.undo();
  312. syncClients();
  313. expectClients( '<paragraph>Foo</paragraph><paragraph>Bar</paragraph>' );
  314. } );
  315. } );
  316. describe( 'by rename', () => {
  317. it( 'element in different path', () => {
  318. john.setData( '<paragraph>Foo</paragraph><paragraph>[Bar]</paragraph>' );
  319. kate.setData( '<paragraph>F[]oo</paragraph><paragraph>Bar</paragraph>' );
  320. john.remove();
  321. kate.rename( 'heading1' );
  322. syncClients();
  323. expectClients(
  324. '<heading1>Foo</heading1>' +
  325. '<paragraph></paragraph>'
  326. );
  327. } );
  328. it( 'element in same path', () => {
  329. john.setData( '<paragraph>F[o]o</paragraph>' );
  330. kate.setData( '<paragraph>[]Foo</paragraph>' );
  331. john.remove();
  332. kate.rename( 'heading1' );
  333. syncClients();
  334. expectClients( '<heading1>Fo</heading1>' );
  335. } );
  336. it( 'element in other user\'s selection', () => {
  337. kate.setData( '<paragraph>[Foo]</paragraph>' );
  338. john.setData( '<paragraph>[Foo]</paragraph>' );
  339. kate.remove();
  340. john.rename( 'heading1' );
  341. syncClients();
  342. expectClients( '<heading1></heading1>' );
  343. } );
  344. } );
  345. } );
  346. } );