highlightcommand.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /**
  2. * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. import HighlightCommand from './../src/highlightcommand';
  6. import Command from '@ckeditor/ckeditor5-core/src/command';
  7. import ModelTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/modeltesteditor';
  8. import { getData, setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
  9. import Position from '../../ckeditor5-engine/src/model/position';
  10. import Range from '../../ckeditor5-engine/src/model/range';
  11. describe( 'HighlightCommand', () => {
  12. let editor, model, doc, root, command;
  13. beforeEach( () => {
  14. return ModelTestEditor.create()
  15. .then( newEditor => {
  16. editor = newEditor;
  17. model = editor.model;
  18. doc = model.document;
  19. root = doc.getRoot();
  20. command = new HighlightCommand( newEditor );
  21. editor.commands.add( 'highlight', command );
  22. model.schema.register( 'paragraph', { inheritAllFrom: '$block' } );
  23. model.schema.extend( '$text', { allowAttributes: 'highlight' } );
  24. } );
  25. } );
  26. afterEach( () => {
  27. editor.destroy();
  28. } );
  29. it( 'is a command', () => {
  30. expect( HighlightCommand.prototype ).to.be.instanceOf( Command );
  31. expect( command ).to.be.instanceOf( Command );
  32. } );
  33. describe( 'value', () => {
  34. it( 'is set to highlight attribute value when selection is in text with highlight attribute', () => {
  35. setData( model, '<paragraph><$text highlight="marker">fo[o]</$text></paragraph>' );
  36. expect( command ).to.have.property( 'value', 'marker' );
  37. } );
  38. it( 'is undefined when selection is not in text with highlight attribute', () => {
  39. setData( model, '<paragraph>fo[]o</paragraph>' );
  40. expect( command ).to.have.property( 'value', undefined );
  41. } );
  42. } );
  43. describe( 'isEnabled', () => {
  44. it( 'is true when selection is on text which can have highlight added', () => {
  45. setData( model, '<paragraph>fo[]o</paragraph>' );
  46. expect( command ).to.have.property( 'isEnabled', true );
  47. } );
  48. } );
  49. describe( 'execute()', () => {
  50. describe( 'with option.value set', () => {
  51. describe( 'on collapsed range', () => {
  52. it( 'should change entire highlight when inside highlighted text', () => {
  53. setData( model, '<paragraph>abc<$text highlight="marker">foo[]bar</$text>xyz</paragraph>' );
  54. expect( command.value ).to.equal( 'marker' );
  55. command.execute( { value: 'greenMarker' } );
  56. expect( getData( model ) ).to.equal( '<paragraph>abc[<$text highlight="greenMarker">foobar</$text>]xyz</paragraph>' );
  57. expect( command.value ).to.equal( 'greenMarker' );
  58. } );
  59. it( 'should remove entire highlight when inside highlighted text of the same value', () => {
  60. setData( model, '<paragraph>abc<$text highlight="marker">foo[]bar</$text>xyz</paragraph>' );
  61. expect( command.value ).to.equal( 'marker' );
  62. command.execute( { value: 'marker' } );
  63. expect( getData( model ) ).to.equal( '<paragraph>abcfoo[]barxyz</paragraph>' );
  64. expect( command.value ).to.be.undefined;
  65. } );
  66. it( 'should change selection attribute in non-empty parent', () => {
  67. setData( model, '<paragraph>a[]bc<$text highlight="marker">foobar</$text>xyz</paragraph>' );
  68. expect( command.value ).to.be.undefined;
  69. command.execute( { value: 'foo' } );
  70. expect( command.value ).to.equal( 'foo' );
  71. expect( doc.selection.hasAttribute( 'highlight' ) ).to.be.true;
  72. command.execute();
  73. expect( command.value ).to.be.undefined;
  74. expect( doc.selection.hasAttribute( 'highlight' ) ).to.be.false;
  75. } );
  76. it( 'should not store attribute change on selection if selection is collapsed in non-empty parent', () => {
  77. setData( model, '<paragraph>a[]bc<$text highlight="marker">foobar</$text>xyz</paragraph>' );
  78. command.execute( { value: 'foo' } );
  79. // It should not save that bold was executed at position ( root, [ 0, 1 ] ).
  80. model.change( () => {
  81. // Simulate clicking right arrow key by changing selection ranges.
  82. doc.selection.setRanges( [ new Range( new Position( root, [ 0, 2 ] ), new Position( root, [ 0, 2 ] ) ) ] );
  83. // Get back to previous selection.
  84. doc.selection.setRanges( [ new Range( new Position( root, [ 0, 1 ] ), new Position( root, [ 0, 1 ] ) ) ] );
  85. } );
  86. expect( command.value ).to.be.undefined;
  87. } );
  88. it( 'should change selection attribute and store it if selection is collapsed in empty parent', () => {
  89. setData( model, '<paragraph>abc<$text highlight="marker">foobar</$text>xyz</paragraph><paragraph>[]</paragraph>' );
  90. expect( command.value ).to.be.undefined;
  91. command.execute( { value: 'foo' } );
  92. expect( command.value ).to.equal( 'foo' );
  93. expect( doc.selection.hasAttribute( 'highlight' ) ).to.be.true;
  94. // Attribute should be stored.
  95. // Simulate clicking somewhere else in the editor.
  96. model.change( () => {
  97. doc.selection.setRanges( [ new Range( new Position( root, [ 0, 2 ] ), new Position( root, [ 0, 2 ] ) ) ] );
  98. } );
  99. expect( command.value ).to.be.undefined;
  100. // Go back to where attribute was stored.
  101. model.change( () => {
  102. doc.selection.setRanges( [ new Range( new Position( root, [ 1, 0 ] ), new Position( root, [ 1, 0 ] ) ) ] );
  103. } );
  104. // Attribute should be restored.
  105. expect( command.value ).to.equal( 'foo' );
  106. command.execute();
  107. expect( command.value ).to.be.undefined;
  108. expect( doc.selection.hasAttribute( 'highlight' ) ).to.be.false;
  109. } );
  110. it( 'should change entire highlight when inside highlighted text', () => {
  111. setData( model, '<paragraph>abc<$text highlight="marker">foo[]bar</$text>xyz</paragraph>' );
  112. expect( command.value ).to.equal( 'marker' );
  113. command.execute( { value: 'greenMarker' } );
  114. expect( getData( model ) ).to.equal( '<paragraph>abc[<$text highlight="greenMarker">foobar</$text>]xyz</paragraph>' );
  115. expect( command.value ).to.equal( 'greenMarker' );
  116. } );
  117. } );
  118. describe( 'on not collapsed range', () => {
  119. it( 'should set highlight attribute on selected node when passed as parameter', () => {
  120. setData( model, '<paragraph>a[bc<$text highlight="marker">fo]obar</$text>xyz</paragraph>' );
  121. expect( command.value ).to.be.undefined;
  122. command.execute( { value: 'marker' } );
  123. expect( command.value ).to.equal( 'marker' );
  124. expect( getData( model ) ).to.equal( '<paragraph>a[<$text highlight="marker">bcfo]obar</$text>xyz</paragraph>' );
  125. } );
  126. it( 'should set highlight attribute on selected node when passed as parameter (multiple nodes)', () => {
  127. setData(
  128. model,
  129. '<paragraph>abcabc[abc</paragraph>' +
  130. '<paragraph>foofoofoo</paragraph>' +
  131. '<paragraph>barbar]bar</paragraph>'
  132. );
  133. command.execute( { value: 'marker' } );
  134. expect( command.value ).to.equal( 'marker' );
  135. expect( getData( model ) ).to.equal(
  136. '<paragraph>abcabc[<$text highlight="marker">abc</$text></paragraph>' +
  137. '<paragraph><$text highlight="marker">foofoofoo</$text></paragraph>' +
  138. '<paragraph><$text highlight="marker">barbar</$text>]bar</paragraph>'
  139. );
  140. } );
  141. it( 'should set highlight attribute on selected nodes when passed as parameter only on selected characters', () => {
  142. setData( model, '<paragraph>abc[<$text highlight="marker">foo]bar</$text>xyz</paragraph>' );
  143. expect( command.value ).to.equal( 'marker' );
  144. command.execute( { value: 'foo' } );
  145. expect( getData( model ) ).to.equal(
  146. '<paragraph>abc[<$text highlight="foo">foo</$text>]<$text highlight="marker">bar</$text>xyz</paragraph>'
  147. );
  148. expect( command.value ).to.equal( 'foo' );
  149. } );
  150. } );
  151. } );
  152. describe( 'with undefined option.value', () => {
  153. describe( 'on collapsed range', () => {
  154. it( 'should remove entire highlight when inside highlighted text', () => {
  155. setData( model, '<paragraph>abc<$text highlight="marker">foo[]bar</$text>xyz</paragraph>' );
  156. expect( command.value ).to.equal( 'marker' );
  157. command.execute();
  158. expect( getData( model ) ).to.equal( '<paragraph>abcfoo[]barxyz</paragraph>' );
  159. expect( command.value ).to.be.undefined;
  160. } );
  161. } );
  162. describe( 'on not collapsed range', () => {
  163. it( 'should remove highlight attribute on selected node when undefined passed as parameter', () => {
  164. setData( model, '<paragraph>abc[<$text highlight="marker">foo]bar</$text>xyz</paragraph>' );
  165. expect( command.value ).to.equal( 'marker' );
  166. command.execute();
  167. expect( getData( model ) ).to.equal( '<paragraph>abc[foo]<$text highlight="marker">bar</$text>xyz</paragraph>' );
  168. expect( command.value ).to.be.undefined;
  169. } );
  170. } );
  171. } );
  172. } );
  173. } );