remove.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* bender-tags: treeview */
  6. 'use strict';
  7. import Writer from '/ckeditor5/core/treeview/writer.js';
  8. import Element from '/ckeditor5/core/treeview/element.js';
  9. import Range from '/ckeditor5/core/treeview/range.js';
  10. import Text from '/ckeditor5/core/treeview/text.js';
  11. import utils from '/tests/core/treeview/writer/_utils/utils.js';
  12. describe( 'Writer', () => {
  13. const create = utils.create;
  14. const test = utils.test;
  15. let writer;
  16. beforeEach( () => {
  17. writer = new Writer();
  18. } );
  19. describe( 'remove', () => {
  20. it( 'should throw when range placed in two containers', () => {
  21. const p1 = new Element( 'p' );
  22. const p2 = new Element( 'p' );
  23. expect( () => {
  24. writer.remove( Range.createFromParentsAndOffsets( p1, 0, p2, 0 ) );
  25. } ).to.throw( 'treeview-writer-invalid-range-container' );
  26. } );
  27. it( 'should return empty array when range is collapsed', () => {
  28. const p = new Element( 'p' );
  29. const range = Range.createFromParentsAndOffsets( p, 0, p, 0 );
  30. const nodes = writer.remove( range );
  31. expect( nodes ).to.be.array;
  32. expect( nodes.length ).to.equal( 0 );
  33. expect( range.isCollapsed ).to.be.true;
  34. } );
  35. it( 'should remove single text node', () => {
  36. // <p>[{foobar}]</p> -> <p>|</p>
  37. const created = create( writer, {
  38. instanceOf: Element,
  39. name: 'p',
  40. rangeStart: 0,
  41. rangeEnd: 1,
  42. children: [
  43. { instanceOf: Text, data: 'foobar' }
  44. ]
  45. } );
  46. const removed = writer.remove( created.range );
  47. test( writer, created.range.start, created.node, {
  48. instanceOf: Element,
  49. name: 'p',
  50. position: 0,
  51. children: []
  52. } );
  53. // Test removed nodes.
  54. test( writer, null, removed, [
  55. { instanceOf: Text, data: 'foobar' }
  56. ] );
  57. } );
  58. it( 'should not leave empty text nodes', () => {
  59. // <p>{[foobar]}</p> -> <p>|</p>
  60. const created = create( writer, {
  61. instanceOf: Element,
  62. name: 'p',
  63. children: [
  64. { instanceOf: Text, data: 'foobar', rangeStart: 0, rangeEnd: 6 }
  65. ]
  66. } );
  67. const removed = writer.remove( created.range );
  68. test( writer, created.range.start, created.node, {
  69. instanceOf: Element,
  70. name: 'p',
  71. position: 0,
  72. children: []
  73. } );
  74. // Test removed nodes.
  75. test( writer, null, removed, [
  76. { instanceOf: Text, data: 'foobar' }
  77. ] );
  78. } );
  79. it( 'should remove part of the text node', () => {
  80. // <p>{f[oob]ar}</p> -> <p>{f|ar}</p>
  81. const created = create( writer, {
  82. instanceOf: Element,
  83. name: 'p',
  84. children: [
  85. { instanceOf: Text, data: 'foobar', rangeStart: 1, rangeEnd: 4 }
  86. ]
  87. } );
  88. const removed = writer.remove( created.range );
  89. test( writer, created.range.start, created.node, {
  90. instanceOf: Element,
  91. name: 'p',
  92. children: [
  93. { instanceOf: Text, data: 'far', position: 1 }
  94. ]
  95. } );
  96. // Test removed nodes.
  97. test( writer, null, removed, [
  98. { instanceOf: Text, data: 'oob' }
  99. ] );
  100. } );
  101. it( 'should remove parts of nodes', () => {
  102. // <p>{f[oo}<b>{ba]r}</b></p> -> <p>{f}|<b>r</b></p>
  103. const created = create( writer, {
  104. instanceOf: Element,
  105. name: 'p',
  106. children: [
  107. { instanceOf: Text, data: 'foo', rangeStart: 1 },
  108. {
  109. instanceOf: Element,
  110. name: 'b',
  111. priority: 1,
  112. children: [
  113. { instanceOf: Text, data: 'bar', rangeEnd: 2 }
  114. ]
  115. }
  116. ]
  117. } );
  118. const removed = writer.remove( created.range );
  119. test( writer, created.range.start, created.node, {
  120. instanceOf: Element,
  121. name: 'p',
  122. position: 1,
  123. children: [
  124. { instanceOf: Text, data: 'f' },
  125. {
  126. instanceOf: Element,
  127. name: 'b',
  128. priority: 1,
  129. children: [
  130. { instanceOf: Text, data: 'r' }
  131. ]
  132. }
  133. ]
  134. } );
  135. // Test removed nodes.
  136. test( writer, null, removed, [
  137. { instanceOf: Text, data: 'oo' },
  138. {
  139. instanceOf: Element,
  140. priority: 1,
  141. name: 'b',
  142. children: [
  143. { instanceOf: Text, data: 'ba' }
  144. ]
  145. }
  146. ] );
  147. } );
  148. it( 'should merge after removing #1', () => {
  149. // <p><b>foo</b>[{bar}]<b>bazqux</b></p> -> <p><b>foo|bazqux</b></p>
  150. const created = create( writer, {
  151. instanceOf: Element,
  152. name: 'p',
  153. rangeStart: 1,
  154. rangeEnd: 2,
  155. children: [
  156. {
  157. instanceOf: Element,
  158. name: 'b',
  159. priority: 1,
  160. children: [
  161. { instanceOf: Text, data: 'foo' }
  162. ]
  163. },
  164. { instanceOf: Text, data: 'bar' },
  165. {
  166. instanceOf: Element,
  167. name: 'b',
  168. priority: 1,
  169. children: [
  170. { instanceOf: Text, data: 'bazqux' }
  171. ]
  172. }
  173. ]
  174. } );
  175. const removed = writer.remove( created.range );
  176. test( writer, created.range.start, created.node, {
  177. instanceOf: Element,
  178. name: 'p',
  179. children: [
  180. {
  181. instanceOf: Element,
  182. name: 'b',
  183. priority: 1,
  184. children: [
  185. { instanceOf: Text, data: 'foobazqux', position: 3 }
  186. ]
  187. }
  188. ]
  189. } );
  190. // Test removed nodes.
  191. test( writer, null, removed, [
  192. { instanceOf: Text, data: 'bar' }
  193. ] );
  194. } );
  195. it( 'should merge after removing #2', () => {
  196. // <p><b>fo[o</b>{bar}<b>ba]zqux</b></p> -> <p><b>fo|zqux</b></p>
  197. const created = create( writer, {
  198. instanceOf: Element,
  199. name: 'p',
  200. children: [
  201. {
  202. instanceOf: Element,
  203. name: 'b',
  204. priority: 1,
  205. children: [
  206. { instanceOf: Text, data: 'foo', rangeStart: 2 }
  207. ]
  208. },
  209. { instanceOf: Text, data: 'bar' },
  210. {
  211. instanceOf: Element,
  212. name: 'b',
  213. priority: 1,
  214. children: [
  215. { instanceOf: Text, data: 'bazqux', rangeEnd: 2 }
  216. ]
  217. }
  218. ]
  219. } );
  220. const removed = writer.remove( created.range );
  221. test( writer, created.range.start, created.node, {
  222. instanceOf: Element,
  223. name: 'p',
  224. children: [
  225. {
  226. instanceOf: Element,
  227. name: 'b',
  228. priority: 1,
  229. children: [
  230. { instanceOf: Text, data: 'fozqux', position: 2 }
  231. ]
  232. }
  233. ]
  234. } );
  235. // Test removed nodes.
  236. test( writer, null, removed, [
  237. {
  238. instanceOf: Element,
  239. priority: 1,
  240. name: 'b',
  241. children: [
  242. { instanceOf: Text, data: 'o' }
  243. ]
  244. },
  245. { instanceOf: Text, data: 'bar' },
  246. {
  247. instanceOf: Element,
  248. priority: 1,
  249. name: 'b',
  250. children: [
  251. { instanceOf: Text, data: 'ba' }
  252. ]
  253. }
  254. ] );
  255. } );
  256. } );
  257. } );