highlightstack.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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 HighlightStack from '../src/highlightstack';
  6. describe( 'HighlightStack', () => {
  7. let stack;
  8. beforeEach( () => {
  9. stack = new HighlightStack();
  10. } );
  11. it( 'should fire event when new descriptor is provided to an empty stack', () => {
  12. const spy = sinon.spy();
  13. const descriptor = { priority: 10, classes: 'css-class', id: 'descriptor-id' };
  14. stack.on( 'change:top', spy );
  15. stack.add( descriptor );
  16. sinon.assert.calledOnce( spy );
  17. expect( spy.firstCall.args[ 1 ].newDescriptor ).to.equal( descriptor );
  18. expect( spy.firstCall.args[ 1 ].oldDescriptor ).to.be.undefined;
  19. } );
  20. it( 'should fire event when new top element has changed', () => {
  21. const spy = sinon.spy();
  22. const descriptor = { priority: 10, classes: 'css-class', id: 'descriptor-1' };
  23. const secondDescriptor = { priority: 11, classes: 'css-class', id: 'descriptor-2' };
  24. stack.on( 'change:top', spy );
  25. stack.add( descriptor );
  26. stack.add( secondDescriptor );
  27. sinon.assert.calledTwice( spy );
  28. expect( spy.secondCall.args[ 1 ].newDescriptor ).to.equal( secondDescriptor );
  29. expect( spy.secondCall.args[ 1 ].oldDescriptor ).to.equal( descriptor );
  30. } );
  31. it( 'should fire event when top element has updated', () => {
  32. const spy = sinon.spy();
  33. const descriptor = { priority: 10, classes: 'css-class', id: 'descriptor-1' };
  34. const secondDescriptor = { priority: 11, classes: 'css-class', id: 'descriptor-1' };
  35. stack.on( 'change:top', spy );
  36. stack.add( descriptor );
  37. stack.add( secondDescriptor );
  38. sinon.assert.calledTwice( spy );
  39. expect( spy.firstCall.args[ 1 ].newDescriptor ).to.equal( descriptor );
  40. expect( spy.firstCall.args[ 1 ].oldDescriptor ).to.be.undefined;
  41. expect( spy.secondCall.args[ 1 ].newDescriptor ).to.equal( secondDescriptor );
  42. expect( spy.secondCall.args[ 1 ].oldDescriptor ).to.equal( descriptor );
  43. } );
  44. it( 'should not fire event when element with lower priority was added', () => {
  45. const spy = sinon.spy();
  46. const descriptor = { priority: 10, classes: 'css-class', id: 'descriptor-1' };
  47. const secondDescriptor = { priority: 9, classes: 'css-class', id: 'descriptor-2' };
  48. stack.on( 'change:top', spy );
  49. stack.add( descriptor );
  50. stack.add( secondDescriptor );
  51. sinon.assert.calledOnce( spy );
  52. expect( spy.firstCall.args[ 1 ].newDescriptor ).to.equal( descriptor );
  53. expect( spy.firstCall.args[ 1 ].oldDescriptor ).to.be.undefined;
  54. } );
  55. it( 'should fire event when top element was removed', () => {
  56. const spy = sinon.spy();
  57. const descriptor = { priority: 10, classes: 'css-class', id: 'descriptor-1' };
  58. const secondDescriptor = { priority: 11, classes: 'css-class', id: 'descriptor-2' };
  59. stack.add( descriptor );
  60. stack.add( secondDescriptor );
  61. stack.on( 'change:top', spy );
  62. stack.remove( secondDescriptor.id );
  63. sinon.assert.calledOnce( spy );
  64. expect( spy.firstCall.args[ 1 ].oldDescriptor ).to.equal( secondDescriptor );
  65. expect( spy.firstCall.args[ 1 ].newDescriptor ).to.equal( descriptor );
  66. } );
  67. it( 'should not fire event when other than top element is removed', () => {
  68. const spy = sinon.spy();
  69. const descriptor = { priority: 10, classes: 'css-class', id: 'descriptor-1' };
  70. const secondDescriptor = { priority: 11, classes: 'css-class', id: 'descriptor-2' };
  71. stack.add( descriptor );
  72. stack.add( secondDescriptor );
  73. stack.on( 'change:top', spy );
  74. stack.remove( descriptor );
  75. sinon.assert.notCalled( spy );
  76. } );
  77. it( 'should not fire event when same descriptor is added', () => {
  78. const spy = sinon.spy();
  79. const descriptor = { priority: 10, classes: 'css-class', id: 'descriptor-1' };
  80. const secondDescriptor = { priority: 10, classes: 'css-class', id: 'descriptor-1' };
  81. stack.on( 'change:top', spy );
  82. stack.add( descriptor );
  83. stack.add( secondDescriptor );
  84. sinon.assert.calledOnce( spy );
  85. expect( spy.firstCall.args[ 1 ].newDescriptor ).to.equal( descriptor );
  86. expect( spy.firstCall.args[ 1 ].oldDescriptor ).to.be.undefined;
  87. } );
  88. it( 'should not fire when trying to remove from empty stack', () => {
  89. const spy = sinon.spy();
  90. const descriptor = { priority: 10, classes: 'css-class' };
  91. stack.on( 'change:top', spy );
  92. stack.remove( descriptor );
  93. sinon.assert.notCalled( spy );
  94. } );
  95. it( 'should not fire when trying to remove descriptor which is not present', () => {
  96. const spy = sinon.spy();
  97. const descriptor = { priority: 10, classes: 'css-class', id: 'descriptor-1' };
  98. const secondDescriptor = { priority: 12, classes: 'css-class', id: 'descriptor-2' };
  99. stack.add( descriptor );
  100. stack.on( 'change:top', spy );
  101. stack.remove( secondDescriptor );
  102. sinon.assert.notCalled( spy );
  103. } );
  104. it( 'should fire event when last element from stack was removed', () => {
  105. const spy = sinon.spy();
  106. const descriptor = { priority: 10, classes: 'css-class', id: 'descriptor' };
  107. stack.add( descriptor );
  108. stack.on( 'change:top', spy );
  109. stack.remove( descriptor.id );
  110. sinon.assert.calledOnce( spy );
  111. expect( spy.firstCall.args[ 1 ].newDescriptor ).to.be.undefined;
  112. expect( spy.firstCall.args[ 1 ].oldDescriptor ).to.equal( descriptor );
  113. } );
  114. it( 'should not fire event when new top descriptor is same as previous', () => {
  115. const spy = sinon.spy();
  116. const descriptor = { priority: 10, classes: 'css-class', id: 'descriptor-1' };
  117. const secondDescriptor = { priority: 10, classes: 'css-class', id: 'descriptor-2' };
  118. stack.add( descriptor );
  119. stack.add( secondDescriptor );
  120. stack.on( 'change:top', spy );
  121. stack.remove( secondDescriptor.id );
  122. sinon.assert.notCalled( spy );
  123. } );
  124. it( 'should sort by class when priorities are the same', () => {
  125. const spy = sinon.spy();
  126. const descriptorA = { priority: 10, classes: 'css-a', id: 'descriptor-1' };
  127. const descriptorB = { priority: 10, classes: 'css-b', id: 'descriptor-2' };
  128. const descriptorC = { priority: 10, classes: 'css-c', id: 'descriptor-3' };
  129. stack.on( 'change:top', spy );
  130. stack.add( descriptorB );
  131. stack.add( descriptorA );
  132. stack.add( descriptorC );
  133. sinon.assert.calledTwice( spy );
  134. expect( spy.firstCall.args[ 1 ].newDescriptor ).to.equal( descriptorB );
  135. expect( spy.firstCall.args[ 1 ].oldDescriptor ).to.be.undefined;
  136. expect( spy.secondCall.args[ 1 ].newDescriptor ).to.equal( descriptorC );
  137. expect( spy.secondCall.args[ 1 ].oldDescriptor ).to.equal( descriptorB );
  138. } );
  139. it( 'should sort by class when priorities are the same - array of CSS classes', () => {
  140. const spy = sinon.spy();
  141. const descriptorA = { priority: 10, classes: [ 'css-a', 'css-z' ], id: 'descriptor-1' };
  142. const descriptorB = { priority: 10, classes: [ 'css-a', 'css-y' ], id: 'descriptor-2' };
  143. const descriptorC = { priority: 10, classes: 'css-c', id: 'descriptor-3' };
  144. stack.on( 'change:top', spy );
  145. stack.add( descriptorB );
  146. stack.add( descriptorA );
  147. stack.add( descriptorC );
  148. sinon.assert.calledThrice( spy );
  149. expect( spy.firstCall.args[ 1 ].newDescriptor ).to.equal( descriptorB );
  150. expect( spy.firstCall.args[ 1 ].oldDescriptor ).to.be.undefined;
  151. expect( spy.secondCall.args[ 1 ].newDescriptor ).to.equal( descriptorA );
  152. expect( spy.secondCall.args[ 1 ].oldDescriptor ).to.equal( descriptorB );
  153. expect( spy.thirdCall.args[ 1 ].newDescriptor ).to.equal( descriptorC );
  154. expect( spy.thirdCall.args[ 1 ].oldDescriptor ).to.equal( descriptorA );
  155. } );
  156. } );