clickoutsidehandler.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /**
  2. * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* global document, Event */
  6. import clickOutsideHandler from '../../src/bindings/clickoutsidehandler';
  7. import DomEmitterMixin from '@ckeditor/ckeditor5-utils/src/dom/emittermixin';
  8. import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
  9. testUtils.createSinonSandbox();
  10. describe( 'clickOutsideHandler', () => {
  11. let activator, actionSpy, contextElement1, contextElement2;
  12. beforeEach( () => {
  13. activator = testUtils.sinon.stub().returns( false );
  14. contextElement1 = document.createElement( 'div' );
  15. contextElement2 = document.createElement( 'div' );
  16. actionSpy = testUtils.sinon.spy();
  17. document.body.appendChild( contextElement1 );
  18. document.body.appendChild( contextElement2 );
  19. clickOutsideHandler( {
  20. emitter: Object.create( DomEmitterMixin ),
  21. activator,
  22. contextElements: [ contextElement1, contextElement2 ],
  23. callback: actionSpy
  24. } );
  25. } );
  26. afterEach( () => {
  27. document.body.removeChild( contextElement1 );
  28. document.body.removeChild( contextElement2 );
  29. } );
  30. it( 'should fired callback after clicking out of context element when listener is active', () => {
  31. activator.returns( true );
  32. document.body.dispatchEvent( new Event( 'mousedown', { bubbles: true } ) );
  33. sinon.assert.calledOnce( actionSpy );
  34. } );
  35. it( 'should not fired callback after clicking out of context element when listener is not active', () => {
  36. activator.returns( false );
  37. document.body.dispatchEvent( new Event( 'mousedown', { bubbles: true } ) );
  38. sinon.assert.notCalled( actionSpy );
  39. } );
  40. it( 'should not fired callback after clicking on context element when listener is active', () => {
  41. activator.returns( true );
  42. contextElement1.dispatchEvent( new Event( 'mouseup', { bubbles: true } ) );
  43. sinon.assert.notCalled( actionSpy );
  44. contextElement2.dispatchEvent( new Event( 'mouseup', { bubbles: true } ) );
  45. sinon.assert.notCalled( actionSpy );
  46. } );
  47. it( 'should not fired callback after clicking on context element when listener is not active', () => {
  48. activator.returns( false );
  49. contextElement1.dispatchEvent( new Event( 'mouseup', { bubbles: true } ) );
  50. sinon.assert.notCalled( actionSpy );
  51. contextElement2.dispatchEvent( new Event( 'mouseup', { bubbles: true } ) );
  52. sinon.assert.notCalled( actionSpy );
  53. } );
  54. it( 'should listen when model initial `ifActive` value was `true`', () => {
  55. const spy = testUtils.sinon.spy();
  56. activator.returns( true );
  57. clickOutsideHandler( {
  58. emitter: Object.create( DomEmitterMixin ),
  59. activator,
  60. contextElements: [ contextElement1 ],
  61. callback: spy
  62. } );
  63. document.body.dispatchEvent( new Event( 'mousedown', { bubbles: true } ) );
  64. sinon.assert.calledOnce( spy );
  65. } );
  66. it( 'should not listen when model initial `ifActive` value was `false`', () => {
  67. const spy = testUtils.sinon.spy();
  68. activator.returns( false );
  69. clickOutsideHandler( {
  70. emitter: Object.create( DomEmitterMixin ),
  71. activator,
  72. contextElements: [ contextElement1 ],
  73. callback: spy
  74. } );
  75. document.body.dispatchEvent( new Event( 'mousedown', { bubbles: true } ) );
  76. sinon.assert.notCalled( spy );
  77. } );
  78. it( 'should react on model `ifActive` property change', () => {
  79. activator.returns( true );
  80. document.body.dispatchEvent( new Event( 'mousedown', { bubbles: true } ) );
  81. sinon.assert.calledOnce( actionSpy );
  82. activator.returns( false );
  83. document.body.dispatchEvent( new Event( 'mousedown', { bubbles: true } ) );
  84. // Still called once, was not called second time.
  85. sinon.assert.calledOnce( actionSpy );
  86. activator.returns( true );
  87. document.body.dispatchEvent( new Event( 'mousedown', { bubbles: true } ) );
  88. // Called one more time.
  89. sinon.assert.calledTwice( actionSpy );
  90. } );
  91. it( 'should not execute the callback if one of #contextElements contains the DOM event target', () => {
  92. const target = document.createElement( 'div' );
  93. activator.returns( true );
  94. contextElement2.appendChild( target );
  95. target.dispatchEvent( new Event( 'mousedown', { bubbles: true } ) );
  96. sinon.assert.notCalled( actionSpy );
  97. } );
  98. } );