|
|
@@ -3,39 +3,30 @@
|
|
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
|
*/
|
|
|
|
|
|
-/* global document, window */
|
|
|
+/* global document */
|
|
|
|
|
|
// ClassicTestEditor can't be used, as it doesn't handle the focus, which is needed to test resizer visual cues.
|
|
|
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
|
|
|
|
|
|
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
|
|
|
+
|
|
|
import Image from '../../src/image';
|
|
|
import ImageResizeEditing from '../../src/imageresize/imageresizeediting';
|
|
|
import ImageResizeCommand from '../../src/imageresize/imageresizecommand';
|
|
|
import ImageStyle from '../../src/imagestyle';
|
|
|
-import ImageToolbar from '../../src/imagetoolbar';
|
|
|
-import ImageTextAlternative from '../../src/imagetextalternative';
|
|
|
-import Undo from '@ckeditor/ckeditor5-undo/src/undo';
|
|
|
-import Table from '@ckeditor/ckeditor5-table/src/table';
|
|
|
|
|
|
-import Rect from '@ckeditor/ckeditor5-utils/src/dom/rect';
|
|
|
import { setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
|
|
|
|
|
|
import {
|
|
|
- focusEditor,
|
|
|
- resizerMouseSimulator,
|
|
|
- getWidgetDomParts,
|
|
|
- getHandleCenterPoint
|
|
|
+ focusEditor
|
|
|
} from '@ckeditor/ckeditor5-widget/tests/widgetresize/_utils/utils';
|
|
|
|
|
|
-import WidgetResize from '@ckeditor/ckeditor5-widget/src/widgetresize';
|
|
|
-
|
|
|
describe( 'ImageResizeEditing', () => {
|
|
|
// 100x50 black png image
|
|
|
const IMAGE_SRC_FIXTURE = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAyCAQAAAAAPLY1AAAAQklEQVR42u3PQREAAAgDoK1/' +
|
|
|
'aM3g14MGNJMXKiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiJysRFNMgH0RpujAAAAAElFTkSuQmCC';
|
|
|
|
|
|
- let absoluteContainer, widget, editor, view, viewDocument, editorElement;
|
|
|
+ let absoluteContainer, editor, editorElement;
|
|
|
|
|
|
before( () => {
|
|
|
// This container is required to position editor element in a reliable element.
|
|
|
@@ -140,344 +131,8 @@ describe( 'ImageResizeEditing', () => {
|
|
|
it( 'defines the imageResize command', () => {
|
|
|
expect( editor.commands.get( 'imageResize' ) ).to.be.instanceOf( ImageResizeCommand );
|
|
|
} );
|
|
|
-
|
|
|
- it( 'uses the command on commit', async () => {
|
|
|
- const spy = sinon.spy( editor.commands.get( 'imageResize' ), 'execute' );
|
|
|
-
|
|
|
- setData( editor.model, `<paragraph>foo</paragraph>[<image src="${ IMAGE_SRC_FIXTURE }"></image>]` );
|
|
|
- widget = viewDocument.getRoot().getChild( 1 );
|
|
|
- const domParts = getWidgetDomParts( editor, widget, 'bottom-left' );
|
|
|
-
|
|
|
- const finalPointerPosition = getHandleCenterPoint( domParts.widget, 'bottom-left' ).moveBy( 10, -10 );
|
|
|
-
|
|
|
- resizerMouseSimulator.dragTo( editor, domParts.resizeHandle, finalPointerPosition );
|
|
|
-
|
|
|
- expect( spy.calledOnce ).to.be.true;
|
|
|
- expect( spy.args[ 0 ][ 0 ] ).to.deep.equal( { width: '80px' } );
|
|
|
- } );
|
|
|
-
|
|
|
- it( 'disables the resizer if the command is disabled', () => {
|
|
|
- setData( editor.model, `<paragraph>foo</paragraph>[<image src="${ IMAGE_SRC_FIXTURE }"></image>]` );
|
|
|
-
|
|
|
- const resizer = getSelectedImageResizer( editor );
|
|
|
-
|
|
|
- let isEnabled = false;
|
|
|
-
|
|
|
- editor.commands.get( 'imageResize' ).on( 'set:isEnabled', evt => {
|
|
|
- evt.return = isEnabled;
|
|
|
- evt.stop();
|
|
|
- }, { priority: 'highest' } );
|
|
|
-
|
|
|
- editor.commands.get( 'imageResize' ).refresh();
|
|
|
- expect( resizer.isEnabled ).to.be.false;
|
|
|
-
|
|
|
- isEnabled = true;
|
|
|
- editor.commands.get( 'imageResize' ).refresh();
|
|
|
- expect( resizer.isEnabled ).to.be.true;
|
|
|
- } );
|
|
|
-
|
|
|
- it( 'the resizer is disabled from the beginning when the command is disabled when the image is inserted', () => {
|
|
|
- setData( editor.model, '<paragraph>foo[]</paragraph>' );
|
|
|
-
|
|
|
- editor.commands.get( 'imageResize' ).on( 'set:isEnabled', evt => {
|
|
|
- evt.return = false;
|
|
|
- evt.stop();
|
|
|
- }, { priority: 'highest' } );
|
|
|
- editor.commands.get( 'imageResize' ).refresh();
|
|
|
-
|
|
|
- editor.model.change( writer => {
|
|
|
- editor.model.insertContent( writer.createElement( 'image', { src: IMAGE_SRC_FIXTURE } ) );
|
|
|
- } );
|
|
|
-
|
|
|
- const resizer = getSelectedImageResizer( editor );
|
|
|
- const resizerWrapper = editor.ui.getEditableElement().querySelector( '.ck-widget__resizer' );
|
|
|
-
|
|
|
- expect( resizer.isEnabled ).to.be.false;
|
|
|
- expect( resizerWrapper.style.display ).to.equal( 'none' );
|
|
|
- } );
|
|
|
} );
|
|
|
|
|
|
- it( 'uses percents by default', async () => {
|
|
|
- const localEditor = await createEditor( {
|
|
|
- plugins: [ Image, ImageStyle, Paragraph, Undo, Table, ImageResizeEditing ]
|
|
|
- } );
|
|
|
-
|
|
|
- const attachToSpy = sinon.spy( localEditor.plugins.get( WidgetResize ), 'attachTo' );
|
|
|
-
|
|
|
- setData( localEditor.model, `[<image imageStyle="side" src="${ IMAGE_SRC_FIXTURE }"></image>]` );
|
|
|
-
|
|
|
- expect( attachToSpy.args[ 0 ][ 0 ] ).to.have.a.property( 'unit', '%' );
|
|
|
-
|
|
|
- attachToSpy.restore();
|
|
|
- } );
|
|
|
-
|
|
|
- describe( 'side image resizing', () => {
|
|
|
- beforeEach( async () => {
|
|
|
- await createEditor();
|
|
|
-
|
|
|
- setData( editor.model, `<paragraph>foo</paragraph>[<image imageStyle="side" src="${ IMAGE_SRC_FIXTURE }"></image>]` );
|
|
|
-
|
|
|
- widget = viewDocument.getRoot().getChild( 1 );
|
|
|
- } );
|
|
|
-
|
|
|
- it( 'doesn\'t flicker at the beginning of the resize', async () => {
|
|
|
- // (#5189)
|
|
|
- const resizerPosition = 'bottom-left';
|
|
|
- const domParts = getWidgetDomParts( editor, widget, resizerPosition );
|
|
|
- const initialPointerPosition = getHandleCenterPoint( domParts.widget, resizerPosition );
|
|
|
- const resizeWrapperView = widget.getChild( 2 );
|
|
|
-
|
|
|
- resizerMouseSimulator.down( editor, domParts.resizeHandle );
|
|
|
-
|
|
|
- await wait( 40 );
|
|
|
-
|
|
|
- resizerMouseSimulator.move( editor, domParts.resizeHandle, null, initialPointerPosition );
|
|
|
-
|
|
|
- expect( resizeWrapperView.getStyle( 'width' ) ).to.equal( '100px' );
|
|
|
-
|
|
|
- resizerMouseSimulator.up( editor );
|
|
|
- } );
|
|
|
-
|
|
|
- it( 'makes no change when clicking the handle without drag', () => {
|
|
|
- const resizerPosition = 'bottom-left';
|
|
|
- const expectedWidth = 100;
|
|
|
- const domParts = getWidgetDomParts( editor, widget, resizerPosition );
|
|
|
-
|
|
|
- resizerMouseSimulator.down( editor, domParts.resizeHandle );
|
|
|
-
|
|
|
- expect( getDomWidth( domParts.widget ), 'DOM width check' ).to.be.closeTo( expectedWidth, 2 );
|
|
|
-
|
|
|
- resizerMouseSimulator.up( editor );
|
|
|
-
|
|
|
- const modelItem = editor.model.document.getRoot().getChild( 1 );
|
|
|
-
|
|
|
- expect( modelItem.getAttribute( 'width' ), 'model width attribute' ).to.be.undefined;
|
|
|
- } );
|
|
|
- } );
|
|
|
-
|
|
|
- describe( 'undo integration', () => {
|
|
|
- beforeEach( async () => {
|
|
|
- await createEditor();
|
|
|
-
|
|
|
- setData( editor.model, `<paragraph>foo</paragraph>[<image src="${ IMAGE_SRC_FIXTURE }"></image>]` );
|
|
|
-
|
|
|
- widget = viewDocument.getRoot().getChild( 1 );
|
|
|
- } );
|
|
|
-
|
|
|
- it( 'has correct border size after undo', async () => {
|
|
|
- const domParts = getWidgetDomParts( editor, widget, 'bottom-left' );
|
|
|
- const initialPosition = getHandleCenterPoint( domParts.widget, 'bottom-left' );
|
|
|
- const finalPointerPosition = initialPosition.clone().moveBy( 0, 10 );
|
|
|
- const plugin = editor.plugins.get( 'WidgetResize' );
|
|
|
-
|
|
|
- resizerMouseSimulator.dragTo( editor, domParts.resizeHandle, {
|
|
|
- from: initialPosition,
|
|
|
- to: finalPointerPosition
|
|
|
- } );
|
|
|
-
|
|
|
- expect( '120px' ).to.equal( domParts.widget.style.width );
|
|
|
-
|
|
|
- editor.commands.get( 'undo' ).execute();
|
|
|
-
|
|
|
- // Toggle _visibleResizer to force synchronous redraw. Otherwise you'd need to wait ~200ms for
|
|
|
- // throttled redraw to take place, making tests slower.
|
|
|
- const visibleResizer = plugin._visibleResizer;
|
|
|
- plugin._visibleResizer = null;
|
|
|
- plugin._visibleResizer = visibleResizer;
|
|
|
-
|
|
|
- const resizerWrapper = document.querySelector( '.ck-widget__resizer' );
|
|
|
- const shadowBoundingRect = resizerWrapper.getBoundingClientRect();
|
|
|
-
|
|
|
- expect( shadowBoundingRect.width ).to.equal( 100 );
|
|
|
- expect( shadowBoundingRect.height ).to.equal( 50 );
|
|
|
- } );
|
|
|
- } );
|
|
|
-
|
|
|
- describe( 'table integration', () => {
|
|
|
- beforeEach( () => createEditor() );
|
|
|
-
|
|
|
- it( 'works when resizing in a table', () => {
|
|
|
- setData( editor.model,
|
|
|
- '<table>' +
|
|
|
- `<tableRow><tableCell>[<image src="${ IMAGE_SRC_FIXTURE }"></image>]</tableCell></tableRow>` +
|
|
|
- '</table>'
|
|
|
- );
|
|
|
-
|
|
|
- widget = viewDocument.getRoot().getChild( 0 ).getChild( 1 ).getChild( 0 ).getChild( 0 ).getChild( 0 ).getChild( 0 );
|
|
|
- const model = editor.model.document.getRoot().getChild( 0 ).getChild( 0 ).getChild( 0 ).getChild( 0 );
|
|
|
-
|
|
|
- const domParts = getWidgetDomParts( editor, widget, 'bottom-right' );
|
|
|
- const initialPosition = getHandleCenterPoint( domParts.widget, 'bottom-right' );
|
|
|
- const finalPointerPosition = initialPosition.clone().moveBy( -40, -20 );
|
|
|
-
|
|
|
- resizerMouseSimulator.dragTo( editor, domParts.resizeHandle, {
|
|
|
- from: initialPosition,
|
|
|
- to: finalPointerPosition
|
|
|
- } );
|
|
|
-
|
|
|
- expect( model.getAttribute( 'width' ) ).to.equal( '60px' );
|
|
|
- } );
|
|
|
- } );
|
|
|
-
|
|
|
- describe( 'srcset integration', () => {
|
|
|
- // The image is 96x96 pixels.
|
|
|
- const imageBaseUrl = '/assets/sample.png';
|
|
|
- let model;
|
|
|
- let images = [];
|
|
|
-
|
|
|
- before( async () => {
|
|
|
- images = await Promise.all( [
|
|
|
- preloadImage( imageBaseUrl ),
|
|
|
- preloadImage( imageBaseUrl + '?a' ),
|
|
|
- preloadImage( imageBaseUrl + '?b' ),
|
|
|
- preloadImage( imageBaseUrl + '?c' )
|
|
|
- ] );
|
|
|
- } );
|
|
|
-
|
|
|
- after( () => {
|
|
|
- for ( const image of images ) {
|
|
|
- image.remove();
|
|
|
- }
|
|
|
- } );
|
|
|
-
|
|
|
- beforeEach( async () => {
|
|
|
- await createEditor();
|
|
|
-
|
|
|
- editor.setData(
|
|
|
- `<figure class="image">
|
|
|
- <img src="${ imageBaseUrl }"
|
|
|
- srcset="${ imageBaseUrl }?a 110w,
|
|
|
- ${ imageBaseUrl }?b 440w,
|
|
|
- ${ imageBaseUrl }?c 1025w"
|
|
|
- sizes="100vw" width="96">
|
|
|
- </figure>`
|
|
|
- );
|
|
|
-
|
|
|
- widget = viewDocument.getRoot().getChild( 0 );
|
|
|
- model = editor.model.document.getRoot().getChild( 0 );
|
|
|
- } );
|
|
|
-
|
|
|
- it( 'works with images containing srcset', () => {
|
|
|
- const domParts = getWidgetDomParts( editor, widget, 'bottom-right' );
|
|
|
- const initialPosition = getHandleCenterPoint( domParts.widget, 'bottom-right' );
|
|
|
- const finalPointerPosition = initialPosition.clone().moveBy( -20, -20 );
|
|
|
-
|
|
|
- resizerMouseSimulator.dragTo( editor, domParts.resizeHandle, {
|
|
|
- from: initialPosition,
|
|
|
- to: finalPointerPosition
|
|
|
- } );
|
|
|
-
|
|
|
- expect( model.getAttribute( 'width' ) ).to.equal( '76px' );
|
|
|
- } );
|
|
|
-
|
|
|
- it( 'retains width after removing srcset', () => {
|
|
|
- const domParts = getWidgetDomParts( editor, widget, 'bottom-right' );
|
|
|
- const initialPosition = getHandleCenterPoint( domParts.widget, 'bottom-right' );
|
|
|
- const finalPointerPosition = initialPosition.clone().moveBy( -16, -16 );
|
|
|
-
|
|
|
- resizerMouseSimulator.dragTo( editor, domParts.resizeHandle, {
|
|
|
- from: initialPosition,
|
|
|
- to: finalPointerPosition
|
|
|
- } );
|
|
|
-
|
|
|
- editor.model.change( writer => {
|
|
|
- writer.removeAttribute( 'srcset', model );
|
|
|
- } );
|
|
|
-
|
|
|
- const expectedHtml = '<figure class="image image_resized" style="width:80px;"><img src="/assets/sample.png"></figure>';
|
|
|
- expect( editor.getData() ).to.equal( expectedHtml );
|
|
|
- } );
|
|
|
-
|
|
|
- async function preloadImage( imageUrl ) {
|
|
|
- const image = document.createElement( 'img' );
|
|
|
-
|
|
|
- image.src = imageUrl;
|
|
|
-
|
|
|
- return new Promise( ( resolve, reject ) => {
|
|
|
- image.addEventListener( 'load', () => resolve( image ) );
|
|
|
- image.addEventListener( 'error', () => reject( image ) );
|
|
|
- document.body.appendChild( image );
|
|
|
- } );
|
|
|
- }
|
|
|
- } );
|
|
|
-
|
|
|
- describe( 'widget toolbar integration', () => {
|
|
|
- let widgetToolbarRepository;
|
|
|
-
|
|
|
- beforeEach( async () => {
|
|
|
- await createEditor( {
|
|
|
- plugins: [ Image, ImageStyle, Paragraph, Undo, Table, ImageResizeEditing, ImageToolbar, ImageTextAlternative ],
|
|
|
- image: {
|
|
|
- toolbar: [ 'imageTextAlternative' ],
|
|
|
- resizeUnit: 'px'
|
|
|
- }
|
|
|
- } );
|
|
|
-
|
|
|
- setData( editor.model, `<paragraph>foo</paragraph>[<image src="${ IMAGE_SRC_FIXTURE }"></image>]` );
|
|
|
-
|
|
|
- widget = viewDocument.getRoot().getChild( 1 );
|
|
|
-
|
|
|
- widgetToolbarRepository = editor.plugins.get( 'WidgetToolbarRepository' );
|
|
|
- } );
|
|
|
-
|
|
|
- it( 'default toolbar visibility', async () => {
|
|
|
- expect( widgetToolbarRepository.isEnabled ).to.be.true;
|
|
|
- } );
|
|
|
-
|
|
|
- it( 'visibility during the resize', async () => {
|
|
|
- const domResizeHandle = getWidgetDomParts( editor, widget, 'bottom-left' ).resizeHandle;
|
|
|
-
|
|
|
- resizerMouseSimulator.down( editor, domResizeHandle );
|
|
|
-
|
|
|
- expect( widgetToolbarRepository.isEnabled ).to.be.false;
|
|
|
-
|
|
|
- resizerMouseSimulator.up( editor, domResizeHandle );
|
|
|
- } );
|
|
|
-
|
|
|
- it( 'visibility after the resize', async () => {
|
|
|
- const domResizeHandle = getWidgetDomParts( editor, widget, 'bottom-left' ).resizeHandle;
|
|
|
-
|
|
|
- resizerMouseSimulator.down( editor, domResizeHandle );
|
|
|
- resizerMouseSimulator.up( editor, domResizeHandle );
|
|
|
-
|
|
|
- expect( widgetToolbarRepository.isEnabled ).to.be.true;
|
|
|
- } );
|
|
|
-
|
|
|
- it( 'visibility after the resize was canceled', async () => {
|
|
|
- const resizer = getSelectedImageResizer( editor );
|
|
|
- const domResizeHandle = getWidgetDomParts( editor, widget, 'bottom-left' ).resizeHandle;
|
|
|
-
|
|
|
- resizerMouseSimulator.down( editor, domResizeHandle );
|
|
|
-
|
|
|
- resizer.cancel();
|
|
|
- expect( widgetToolbarRepository.isEnabled ).to.be.true;
|
|
|
- } );
|
|
|
-
|
|
|
- it( 'restores toolbar when clicking the handle without drag', () => {
|
|
|
- // (https://github.com/ckeditor/ckeditor5-widget/pull/112#pullrequestreview-337725256).
|
|
|
- const domResizeHandle = getWidgetDomParts( editor, widget, 'bottom-left' ).resizeHandle;
|
|
|
-
|
|
|
- resizerMouseSimulator.down( editor, domResizeHandle );
|
|
|
- resizerMouseSimulator.up( editor, domResizeHandle );
|
|
|
-
|
|
|
- expect( widgetToolbarRepository.isEnabled ).to.be.true;
|
|
|
- } );
|
|
|
- } );
|
|
|
-
|
|
|
- function wait( delay ) {
|
|
|
- return new Promise( resolve => window.setTimeout( () => resolve(), delay ) );
|
|
|
- }
|
|
|
-
|
|
|
- function getDomWidth( domElement ) {
|
|
|
- return new Rect( domElement ).width;
|
|
|
- }
|
|
|
-
|
|
|
- function getSelectedImageResizer( editor ) {
|
|
|
- return editor.plugins.get( 'WidgetResize' )._getResizerByViewElement(
|
|
|
- editor.editing.view.document.selection.getSelectedElement()
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
function createEditor( config ) {
|
|
|
editorElement = document.createElement( 'div' );
|
|
|
|
|
|
@@ -485,16 +140,13 @@ describe( 'ImageResizeEditing', () => {
|
|
|
|
|
|
return ClassicEditor
|
|
|
.create( editorElement, config || {
|
|
|
- plugins: [ Image, ImageStyle, Paragraph, Undo, Table, ImageResizeEditing ],
|
|
|
+ plugins: [ Paragraph, Image, ImageStyle, ImageResizeEditing ],
|
|
|
image: {
|
|
|
resizeUnit: 'px'
|
|
|
}
|
|
|
} )
|
|
|
.then( newEditor => {
|
|
|
editor = newEditor;
|
|
|
- view = editor.editing.view;
|
|
|
- viewDocument = view.document;
|
|
|
- widget = viewDocument.getRoot().getChild( 1 );
|
|
|
|
|
|
focusEditor( editor );
|
|
|
|