modifyselection.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* bender-tags: model, composer */
  6. 'use strict';
  7. import Document from '/ckeditor5/engine/model/document.js';
  8. import modifySelection from '/ckeditor5/engine/model/composer/modifyselection.js';
  9. import { setData, getData } from '/tests/engine/_utils/model.js';
  10. describe( 'Delete utils', () => {
  11. let document;
  12. beforeEach( () => {
  13. document = new Document();
  14. document.schema.registerItem( 'p', '$block' );
  15. document.createRoot();
  16. } );
  17. describe( 'modifySelection', () => {
  18. describe( 'unit=character', () => {
  19. describe( 'within element', () => {
  20. test(
  21. 'does nothing on empty content',
  22. '<selection />',
  23. '<selection />'
  24. );
  25. test(
  26. 'does nothing on empty content (with empty element)',
  27. '<p><selection /></p>',
  28. '<p><selection /></p>'
  29. );
  30. test(
  31. 'does nothing on empty content (backward)',
  32. '<selection />',
  33. '<selection />',
  34. { direction: 'BACKWARD' }
  35. );
  36. test(
  37. 'does nothing on root boundary',
  38. '<p>foo<selection /></p>',
  39. '<p>foo<selection /></p>'
  40. );
  41. test(
  42. 'does nothing on root boundary (backward)',
  43. '<p><selection />foo</p>',
  44. '<p><selection />foo</p>',
  45. { direction: 'BACKWARD' }
  46. );
  47. test(
  48. 'extends one character forward',
  49. '<p>f<selection />oo</p>',
  50. '<p>f<selection>o</selection>o</p>'
  51. );
  52. test(
  53. 'extends one character backward',
  54. '<p>fo<selection />o</p>',
  55. '<p>f<selection backward>o</selection>o</p>',
  56. { direction: 'BACKWARD' }
  57. );
  58. test(
  59. 'extends one character forward (non-collapsed)',
  60. '<p>f<selection>o</selection>obar</p>',
  61. '<p>f<selection>oo</selection>bar</p>'
  62. );
  63. test(
  64. 'extends one character backward (non-collapsed)',
  65. '<p>foob<selection backward>a</selection>r</p>',
  66. '<p>foo<selection backward>ba</selection>r</p>',
  67. { direction: 'BACKWARD' }
  68. );
  69. test(
  70. 'extends to element boundary',
  71. '<p>fo<selection />o</p>',
  72. '<p>fo<selection>o</selection></p>'
  73. );
  74. test(
  75. 'extends to element boundary (backward)',
  76. '<p>f<selection />oo</p>',
  77. '<p><selection backward>f</selection>oo</p>',
  78. { direction: 'BACKWARD' }
  79. );
  80. test(
  81. 'shrinks forward selection (to collapsed)',
  82. '<p>foo<selection>b</selection>ar</p>',
  83. '<p>foo<selection />bar</p>',
  84. { direction: 'BACKWARD' }
  85. );
  86. test(
  87. 'shrinks backward selection (to collapsed)',
  88. '<p>foo<selection backward>b</selection>ar</p>',
  89. '<p>foob<selection />ar</p>'
  90. );
  91. test(
  92. 'extends one element forward',
  93. '<p>f<selection /><img></img>oo</p>',
  94. '<p>f<selection><img></img></selection>oo</p>'
  95. );
  96. test(
  97. 'extends one non-empty element forward',
  98. '<p>f<selection /><img>x</img>oo</p>',
  99. '<p>f<selection><img>x</img></selection>oo</p>'
  100. );
  101. test(
  102. 'extends one element backward',
  103. '<p>fo<img></img><selection />o</p>',
  104. '<p>fo<selection backward><img></img></selection>o</p>',
  105. { direction: 'BACKWARD' }
  106. );
  107. } );
  108. describe( 'beyond element', () => {
  109. test(
  110. 'extends over boundary of empty elements',
  111. '<p><selection /></p><p></p><p></p>',
  112. '<p><selection></p><p></selection></p><p></p>'
  113. );
  114. test(
  115. 'extends over boundary of empty elements (backward)',
  116. '<p></p><p></p><p><selection /></p>',
  117. '<p></p><p><selection backward></p><p></selection></p>',
  118. { direction: 'BACKWARD' }
  119. );
  120. test(
  121. 'extends over boundary of non-empty elements',
  122. '<p>a<selection /></p><p>bcd</p>',
  123. '<p>a<selection></p><p></selection>bcd</p>'
  124. );
  125. test(
  126. 'extends over boundary of non-empty elements (backward)',
  127. '<p>a</p><p><selection />bcd</p>',
  128. '<p>a<selection backward></p><p></selection>bcd</p>',
  129. { direction: 'BACKWARD' }
  130. );
  131. test(
  132. 'extends over character after boundary',
  133. '<p>a<selection></p><p></selection>bcd</p>',
  134. '<p>a<selection></p><p>b</selection>cd</p>'
  135. );
  136. test(
  137. 'extends over character after boundary (backward)',
  138. '<p>abc<selection backward></p><p></selection>d</p>',
  139. '<p>ab<selection backward>c</p><p></selection>d</p>',
  140. { direction: 'BACKWARD' }
  141. );
  142. test(
  143. 'extends over boundary when next element has nested elements',
  144. '<p>a<selection /></p><p><x>bcd</x></p>',
  145. '<p>a<selection></p><p></selection><x>bcd</x></p>'
  146. );
  147. test(
  148. 'extends over element when next element has nested elements',
  149. '<p>a<selection></p><p></selection><x>bcd</x>ef</p>',
  150. '<p>a<selection></p><p><x>bcd</x></selection>ef</p>'
  151. );
  152. test(
  153. 'extends over element when next node is a text',
  154. '<p>a<selection /></p>bc',
  155. '<p>a<selection></p></selection>bc'
  156. );
  157. test(
  158. 'extends over element when next node is a text (backward)',
  159. 'ab<p><selection />c</p>',
  160. 'ab<selection backward><p></selection>c</p>',
  161. { direction: 'BACKWARD' }
  162. );
  163. test(
  164. 'shrinks over boundary of empty elements',
  165. '<p><selection backward></p><p></selection></p>',
  166. '<p></p><p><selection /></p>'
  167. );
  168. test(
  169. 'shrinks over boundary of empty elements (backward)',
  170. '<p><selection></p><p></selection></p>',
  171. '<p><selection /></p><p></p>',
  172. { direction: 'BACKWARD' }
  173. );
  174. test(
  175. 'shrinks over boundary of non-empty elements',
  176. '<p>a<selection backward></p><p></selection>b</p>',
  177. '<p>a</p><p><selection />b</p>'
  178. );
  179. test(
  180. 'shrinks over boundary of non-empty elements (backward)',
  181. '<p>a<selection></p><p></selection>b</p>',
  182. '<p>a<selection /></p><p>b</p>',
  183. { direction: 'BACKWARD' }
  184. );
  185. } );
  186. } );
  187. test(
  188. 'updates selection attributes',
  189. '<p><$text bold=true>foo</$text><selection>b</selection></p>',
  190. '<p><$text bold=true>foo</$text><selection bold=true />b</p>',
  191. { direction: 'BACKWARD' }
  192. );
  193. } );
  194. function test( title, input, output, options ) {
  195. it( title, () => {
  196. setData( document, input );
  197. modifySelection( document.selection, options );
  198. expect( getData( document ) ).to.equal( output );
  199. } );
  200. }
  201. } );