link.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* globals document */
  6. import ClassicTestEditor from '/tests/core/_utils/classictesteditor.js';
  7. import testUtils from '/tests/core/_utils/utils.js';
  8. import { keyCodes } from '/ckeditor5/utils/keyboard.js';
  9. import { setData as setModelData } from '/tests/engine/_utils/model.js';
  10. import Link from '/ckeditor5/link/link.js';
  11. import LinkEngine from '/ckeditor5/link/linkengine.js';
  12. import Button from '/ckeditor5/ui/button/button.js';
  13. import LinkBalloonPanel from '/ckeditor5/link/ui/linkballoonpanel.js';
  14. import ClickObserver from '/ckeditor5/engine/view/observer/clickobserver.js';
  15. testUtils.createSinonSandbox();
  16. describe( 'Link', () => {
  17. let editor, linkFeature, linkButton, unlinkButton, balloonPanel;
  18. beforeEach( () => {
  19. const editorElement = document.createElement( 'div' );
  20. document.body.appendChild( editorElement );
  21. return ClassicTestEditor.create( editorElement, {
  22. features: [ Link ]
  23. } )
  24. .then( newEditor => {
  25. editor = newEditor;
  26. linkFeature = editor.plugins.get( Link );
  27. linkButton = editor.ui.featureComponents.create( 'link' );
  28. unlinkButton = editor.ui.featureComponents.create( 'unlink' );
  29. balloonPanel = linkFeature.balloonPanel;
  30. } );
  31. } );
  32. afterEach( () => {
  33. return editor.destroy();
  34. } );
  35. it( 'should be loaded', () => {
  36. expect( linkFeature ).to.instanceOf( Link );
  37. } );
  38. it( 'should load LinkEngine', () => {
  39. expect( editor.plugins.get( LinkEngine ) ).to.instanceOf( LinkEngine );
  40. } );
  41. it( 'should register click observer', () => {
  42. expect( editor.editing.view.getObserver( ClickObserver ) ).to.instanceOf( ClickObserver );
  43. } );
  44. describe( 'link toolbar button', () => {
  45. it( 'should register link feature component', () => {
  46. expect( linkButton ).to.instanceOf( Button );
  47. } );
  48. it( 'should bind linkButton#model to link command', () => {
  49. const model = linkButton.model;
  50. const command = editor.commands.get( 'link' );
  51. expect( model.isEnabled ).to.be.true;
  52. command.isEnabled = false;
  53. expect( model.isEnabled ).to.be.false;
  54. } );
  55. it( 'should open panel on linkButton#model execute event, when editor is focused', () => {
  56. editor.editing.view.isFocused = true;
  57. linkButton.model.fire( 'execute' );
  58. expect( linkFeature.balloonPanel.view.isVisible ).to.true;
  59. } );
  60. it( 'should not open panel on linkButton#model execute event, when editor is not focused', () => {
  61. linkButton.model.fire( 'execute' );
  62. expect( linkFeature.balloonPanel.view.isVisible ).to.false;
  63. } );
  64. } );
  65. describe( 'unlink toolbar button', () => {
  66. it( 'should register unlink feature component', () => {
  67. expect( unlinkButton ).to.instanceOf( Button );
  68. } );
  69. it( 'should bind unlinkButton#model to unlink command', () => {
  70. const model = unlinkButton.model;
  71. const command = editor.commands.get( 'unlink' );
  72. expect( model.isEnabled ).to.false;
  73. command.hasValue = true;
  74. expect( model.isEnabled ).to.true;
  75. } );
  76. it( 'should execute unlink command on unlinkButton#model execute event', () => {
  77. const executeSpy = testUtils.sinon.spy( editor, 'execute' );
  78. unlinkButton.model.fire( 'execute' );
  79. expect( executeSpy.calledOnce ).to.true;
  80. expect( executeSpy.calledWithExactly( 'unlink' ) ).to.true;
  81. } );
  82. it( 'should hide panel on unlinkButton#model execute event', () => {
  83. balloonPanel.view.model.isVisible = true;
  84. unlinkButton.model.fire( 'execute' );
  85. expect( balloonPanel.view.model.isVisible ).to.false;
  86. } );
  87. } );
  88. describe( 'link panel', () => {
  89. it( 'should create LinkBalloonPanel component', () => {
  90. expect( balloonPanel ).to.instanceOf( LinkBalloonPanel );
  91. } );
  92. it( 'should bind balloonPanel#model to link command', () => {
  93. const model = balloonPanel.model;
  94. const command = editor.commands.get( 'link' );
  95. expect( model.url ).to.undefined;
  96. command.value = 'http://cksource.com';
  97. expect( model.url ).to.equal( 'http://cksource.com' );
  98. } );
  99. it( 'should execute link command on balloonPanel#model execute event', () => {
  100. const executeSpy = testUtils.sinon.spy( editor, 'execute' );
  101. balloonPanel.model.url = 'http://cksource.com';
  102. balloonPanel.model.fire( 'execute' );
  103. expect( executeSpy.calledOnce ).to.true;
  104. expect( executeSpy.calledWithExactly( 'link', 'http://cksource.com' ) ).to.true;
  105. } );
  106. it( 'should append panel element to the body', () => {
  107. expect( document.body.contains( balloonPanel.view.element ) );
  108. } );
  109. it( 'should open panel on `CTRL+L` keystroke', () => {
  110. editor.keystrokes.press( { keyCode: keyCodes.l, ctrlKey: true } );
  111. expect( balloonPanel.view.model.isVisible ).to.true;
  112. } );
  113. it( 'should focus editor on balloonPanel#model hide event', () => {
  114. balloonPanel.model.fire( 'hide' );
  115. expect( editor.editing.view.isFocused ).to.true;
  116. } );
  117. it( 'should hide panel on editor focus event', () => {
  118. balloonPanel.view.model.isVisible = true;
  119. editor.editing.view.focus();
  120. expect( balloonPanel.view.model.isVisible ).to.false;
  121. } );
  122. it( 'should show panel on editor click, when selection is inside link element', () => {
  123. const observer = editor.editing.view.getObserver( ClickObserver );
  124. const linkCommand = editor.commands.get( 'link' );
  125. editor.document.schema.allow( { name: '$text', inside: '$root' } );
  126. setModelData( editor.document, '<$text linkHref="url">some[] url</$text>' );
  127. linkCommand.value = 'url';
  128. observer.fire( 'click', { target: document.body } );
  129. expect( balloonPanel.view.model.isVisible ).to.true;
  130. } );
  131. it( 'should not show panel on editor click, when selection is not inside link element', () => {
  132. const observer = editor.editing.view.getObserver( ClickObserver );
  133. setModelData( editor.document, '[]' );
  134. observer.fire( 'click', { target: document.body } );
  135. expect( balloonPanel.view.model.isVisible ).to.false;
  136. } );
  137. } );
  138. } );