/**
* @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/
/* globals window */
import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import ImageEditing from '../../src/image/imageediting';
import ImageUploadEditing from '../../src/imageupload/imageuploadediting';
import ImageUploadProgress from '../../src/imageupload/imageuploadprogress';
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
import FileRepository from '@ckeditor/ckeditor5-upload/src/filerepository';
import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
import { createNativeFileMock, NativeFileReaderMock, UploadAdapterMock } from '@ckeditor/ckeditor5-upload/tests/_utils/mocks';
import { setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';
import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
import svgPlaceholder from '../../theme/icons/image_placeholder.svg';
describe( 'ImageUploadProgress', () => {
const imagePlaceholder = encodeURIComponent( svgPlaceholder );
// eslint-disable-next-line max-len
const base64Sample = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=';
let editor, model, doc, fileRepository, view, nativeReaderMock, loader, adapterMock;
class UploadAdapterPluginMock extends Plugin {
init() {
fileRepository = this.editor.plugins.get( FileRepository );
fileRepository.createUploadAdapter = newLoader => {
loader = newLoader;
adapterMock = new UploadAdapterMock( loader );
return adapterMock;
};
}
}
testUtils.createSinonSandbox();
beforeEach( () => {
testUtils.sinon.stub( window, 'FileReader' ).callsFake( () => {
nativeReaderMock = new NativeFileReaderMock();
return nativeReaderMock;
} );
return VirtualTestEditor
.create( {
plugins: [ ImageEditing, Paragraph, ImageUploadEditing, ImageUploadProgress, UploadAdapterPluginMock, Clipboard ]
} )
.then( newEditor => {
editor = newEditor;
model = editor.model;
doc = model.document;
view = editor.editing.view;
fileRepository = editor.plugins.get( FileRepository );
fileRepository.createUploadAdapter = newLoader => {
loader = newLoader;
adapterMock = new UploadAdapterMock( loader );
return adapterMock;
};
} );
} );
it( 'should convert image\'s "reading" uploadStatus attribute', () => {
setModelData( model, '` +
'' +
'
foo
' ); } ); it( 'should convert image\'s "uploading" uploadStatus attribute', done => { setModelData( model, 'foo
' ); done(); } catch ( err ) { done( err ); } }, { priority: 'lowest' } ); loader.file.then( () => nativeReaderMock.mockSuccess( base64Sample ) ); } ); // See https://github.com/ckeditor/ckeditor5/issues/1985. // Might be obsolete after changes in table refreshing (now it refreshes siblings of an image and not its parent). it( 'should work if image parent is refreshed by the differ', function( done ) { model.schema.register( 'outerBlock', { allowWhere: '$block', isBlock: true } ); model.schema.register( 'innerBlock', { allowIn: 'outerBlock', isLimit: true } ); model.schema.extend( '$block', { allowIn: 'innerBlock' } ); editor.conversion.elementToElement( { model: 'outerBlock', view: 'outerBlock' } ); editor.conversion.elementToElement( { model: 'innerBlock', view: 'innerBlock' } ); model.document.registerPostFixer( () => { for ( const change of doc.differ.getChanges() ) { // The differ.refreshItem() simulates remove and insert of and image parent thus preventing image from proper work. if ( change.type == 'insert' && change.name == 'image' ) { doc.differ.refreshItem( change.position.parent ); return false; // Refreshing item should not trigger calling post-fixer again. } } } ); setModelData( model, '
' +
'' +
'foo
' ); done(); } catch ( err ) { done( err ); } }, { priority: 'lowest' } ); loader.file.then( () => nativeReaderMock.mockSuccess( base64Sample ) ); } ); it( 'should convert image\'s "complete" uploadStatus attribute and display temporary icon', done => { const clock = testUtils.sinon.useFakeTimers(); setModelData( model, '
' +
'' +
'foo
' ); clock.tick( 3000 ); expect( getViewData( view ) ).to.equal( '[
' +
'foo
' ); done(); } catch ( err ) { done( err ); } }, { priority: 'lowest' } ); loader.file.then( () => adapterMock.mockSuccess( { default: 'image.png' } ) ); } ); loader.file.then( () => nativeReaderMock.mockSuccess( base64Sample ) ); } ); it( 'should allow to customize placeholder image', () => { const uploadProgress = editor.plugins.get( ImageUploadProgress ); uploadProgress.placeholder = base64Sample; setModelData( model, 'foo
' ); } ); it( 'should not process attribute change if it is already consumed', () => { editor.editing.downcastDispatcher.on( 'attribute:uploadStatus:image', ( evt, data, conversionApi ) => { conversionApi.consumable.consume( data.item, evt.name ); }, { priority: 'highest' } ); setModelData( model, 'foo
' ); } ); it( 'should not show progress bar and complete icon if there is no loader with given uploadId', () => { setModelData( model, '