Explorar el Código

Tests for ImageUploadEngine.

Szymon Kupś hace 8 años
padre
commit
1c4e78f0ff

+ 1 - 0
packages/ckeditor5-upload/package.json

@@ -10,6 +10,7 @@
 	  "@ckeditor/ckeditor5-utils": "^0.8.0"
   },
   "devDependencies": {
+    "@ckeditor/ckeditor5-clipboard": "^0.5.0",
     "@ckeditor/ckeditor5-dev-lint": "^2.0.2",
     "@ckeditor/ckeditor5-image": "v0.4.0",
   	"@ckeditor/ckeditor5-paragraph": "v0.6.1",

+ 13 - 5
packages/ckeditor5-upload/src/imageuploadengine.js

@@ -48,6 +48,7 @@ export default class ImageUploadEngine extends Plugin {
 			}
 		} );
 
+		// Listen on document changes and start upload process when image with `uploadId` attribute is present.
 		doc.on( 'change', ( evt, type, data, batch ) => {
 			if ( type === 'insert' ) {
 				for ( const value of data.range ) {
@@ -68,6 +69,7 @@ export default class ImageUploadEngine extends Plugin {
 			}
 		} );
 
+		// Model to view converter for image's `uploadId` attribute.
 		editor.editing.modelToView.on( 'addAttribute:uploadId:image', ( evt, data, consumable ) => {
 			if ( !consumable.consume( data.item, eventNameToConsumableType( evt.name ) ) ) {
 				return;
@@ -76,12 +78,20 @@ export default class ImageUploadEngine extends Plugin {
 			const modelImage = data.item;
 			const viewFigure = editor.editing.mapper.toViewElement( modelImage );
 			const viewImg = viewFigure.getChild( 0 );
-			viewImg.setAttribute( 'src', uploadingPlaceholder );
+			const svgData = 'data:image/svg+xml;utf8,' + uploadingPlaceholder;
 
-			// TODO: if there are data -> show data
+			viewImg.setAttribute( 'src', svgData );
 		} );
 	}
 
+	/**
+	 * Performs image loading. Image is read from the disk and temporary data is displayed, after uploading process
+	 * is complete we replace temporary data with target image from the server.
+	 *
+	 * @param {module:upload/filerepository~FileLoader} loader
+	 * @param {module:engine/model/batch~Batch} batch
+	 * @param {module:engine/model/element~Element} imageElement
+	 */
 	load( loader, batch, imageElement ) {
 		const editor = this.editor;
 		const doc = editor.document;
@@ -105,14 +115,12 @@ export default class ImageUploadEngine extends Plugin {
 				clean();
 			} )
 			.catch( msg => {
-				// Might be 'aborted'
+				// Might be 'aborted'.
 				if ( loader.status == 'error' ) {
 					notification.showWarning( msg, { namespace: 'upload' } );
 				}
 
 				clean();
-
-				// TODO: delete image
 			} );
 
 		function clean() {

+ 1 - 1
packages/ckeditor5-upload/tests/_utils/mocks.js

@@ -53,7 +53,7 @@ export class NativeFileReaderMock {
 	mockError( error ) {
 		this.error = error;
 		this.onerror();
-	};
+	}
 
 	mockAbort() {
 		this.onabort();

+ 2 - 2
packages/ckeditor5-upload/tests/imageuploadcommand.js

@@ -3,7 +3,7 @@
  * For licensing, see LICENSE.md.
  */
 
-import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
+import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
 import ImageUploadCommand from '../src/imageuploadcommand';
 import FileRepository from '../src/filerepository';
 import { createNativeFileMock, AdapterMock } from './_utils/mocks';
@@ -15,7 +15,7 @@ describe( 'ImageUploadCommand', () => {
 	let editor, command, adapterMock, document, fileRepository;
 
 	beforeEach( () => {
-		return ClassicTestEditor.create( {
+		return VirtualTestEditor.create( {
 			plugins: [ FileRepository, Image, Paragraph ]
 		} )
 		.then( newEditor => {

+ 113 - 0
packages/ckeditor5-upload/tests/imageuploadengine.js

@@ -0,0 +1,113 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals window */
+
+import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
+import ImageEngine from '@ckeditor/ckeditor5-image/src/image/imageengine';
+import ImageUploadEngine from '../src/imageuploadengine';
+import ImageUploadCommand from '../src/imageuploadcommand';
+import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
+import DataTransfer from '@ckeditor/ckeditor5-clipboard/src/datatransfer';
+import FileRepository from '../src/filerepository';
+import { AdapterMock, createNativeFileMock, NativeFileReaderMock } from './_utils/mocks';
+import { setData as setModelData, getData as getModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
+import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';
+import imagePlaceholder from '../theme/icons/image_placeholder.svg';
+import { eventNameToConsumableType } from '@ckeditor/ckeditor5-engine/src/conversion/model-to-view-converters';
+import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
+
+describe.only( 'ImageUploadEngine', () => {
+	let editor, document, fileRepository, viewDocument, nativeReaderMock, loader, adapterMock;
+	testUtils.createSinonSandbox();
+
+	beforeEach( () => {
+		testUtils.sinon.stub( window, 'FileReader', () => {
+			nativeReaderMock = new NativeFileReaderMock();
+
+			return nativeReaderMock;
+		} );
+
+		return ClassicTestEditor.create( {
+			plugins: [ ImageEngine, ImageUploadEngine, Paragraph ]
+		} )
+		.then( newEditor => {
+			editor = newEditor;
+			document = editor.document;
+			viewDocument = editor.editing.view;
+
+			fileRepository = editor.plugins.get( FileRepository );
+			fileRepository.createAdapter = newLoader => {
+				loader = newLoader;
+				adapterMock = new AdapterMock( loader );
+
+				return adapterMock;
+			};
+		} );
+	} );
+
+	it( 'should register proper schema rules', () => {
+		expect( document.schema.check( { name: 'image', attributes: [ 'uploadId' ], inside: '$root' } ) ).to.be.true;
+	} );
+
+	it( 'should register imageUpload command', () => {
+		expect( editor.commands.get( 'imageUpload' ) ).to.be.instanceOf( ImageUploadCommand );
+	} );
+
+	it( 'should execute imageUpload command when image is pasted', () => {
+		const spy = sinon.spy( editor, 'execute' );
+		const fileMock = createNativeFileMock();
+		const dataTransfer = new DataTransfer( { files: [ fileMock ] } );
+		setModelData( document, '<paragraph>foo bar baz[]</paragraph>' );
+
+		viewDocument.fire( 'input', { dataTransfer } );
+
+		sinon.assert.calledOnce( spy );
+		sinon.assert.calledWith( spy, 'imageUpload' );
+
+		const id = fileRepository.getLoader( fileMock ).id;
+		expect( getModelData( document ) ).to.equal(
+			`<image uploadId="${ id }"></image><paragraph>foo bar baz[]</paragraph>`
+		);
+	} );
+
+	it( 'should not execute imageUpload command when file is not an image', () => {
+		const spy = sinon.spy( editor, 'execute' );
+		const viewDocument = editor.editing.view;
+		const fileMock = {
+			type: 'media/mp3',
+			size: 1024
+		};
+		const dataTransfer = new DataTransfer( { files: [ fileMock ] } );
+		setModelData( document, '<paragraph>foo bar baz[]</paragraph>' );
+
+		viewDocument.fire( 'input', { dataTransfer } );
+
+		sinon.assert.notCalled( spy );
+	} );
+
+	it( 'should convert image\'s uploadId attribute from model to view', () => {
+		setModelData( document, '<image uploadId="1234"></image>' );
+
+		expect( getViewData( viewDocument ) ).to.equal(
+			'[]<figure class="image ck-widget" contenteditable="false">' +
+				`<img src="data:image/svg+xml;utf8,${ imagePlaceholder }"></img>` +
+			'</figure>'
+		);
+	} );
+
+	it( 'should not convert image\'s uploadId attribute if is consumed already', () => {
+		editor.editing.modelToView.on( 'addAttribute:uploadId:image', ( evt, data, consumable ) => {
+			consumable.consume( data.item, eventNameToConsumableType( evt.name ) );
+		}, { priority: 'high' } );
+
+		setModelData( document, '<image uploadId="1234"></image>' );
+
+		expect( getViewData( viewDocument ) ).to.equal(
+			'[]<figure class="image ck-widget" contenteditable="false">' +
+				'<img></img>' +
+			'</figure>' );
+	} );
+} );

+ 8 - 8
packages/ckeditor5-upload/theme/icons/image_placeholder.svg

@@ -1,15 +1,15 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg width="350px" height="169px" viewBox="0 0 350 169" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="800px" height="380px" viewBox="0 0 800 380" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
     <!-- Generator: Sketch 43 (38999) - http://www.bohemiancoding.com/sketch -->
-    <title>image_placeholder</title>
+    <title>image_placeholder_ck5</title>
     <desc>Created with Sketch.</desc>
     <defs></defs>
     <g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
-        <g id="image_placeholder">
-            <rect id="Rectangle-10" fill="#EBF1F7" x="0" y="0" width="350" height="169" rx="4"></rect>
-            <text id="Uploading-image…" font-family="Georgia" font-size="14" font-weight="normal" fill="#A1B0C2">
-                <tspan x="117.100586" y="89">Uploading image…</tspan>
+        <g id="image_placeholder_ck5">
+            <rect id="Rectangle-10" fill="#F7F7F7" x="0" y="0" width="800" height="380" rx="4"></rect>
+            <text id="Uploading-image…" font-family="Roboto-Regular, Roboto" font-size="36" font-weight="normal" fill="#A1B0C2">
+                <tspan x="253.1875" y="200">Uploading image…</tspan>
             </text>
         </g>
     </g>
-</svg>
+</svg>