8
0
Просмотр исходного кода

Added tests for upload adapter.

Szymon Kupś 8 лет назад
Родитель
Сommit
6b2938d3f8

+ 2 - 1
packages/ckeditor5-adapter-ckfinder/package.json

@@ -5,7 +5,8 @@
   "keywords": [],
   "dependencies": {
 	  "@ckeditor/ckeditor5-core": "^0.8.0",
-	  "@ckeditor/ckeditor5-upload": "^0.0.1"
+	  "@ckeditor/ckeditor5-upload": "^0.0.1",
+	  "@ckeditor/ckeditor5-utils": "^0.9.0"
   },
   "devDependencies": {
     "@ckeditor/ckeditor5-basic-styles": "^0.8.0",

+ 17 - 1
packages/ckeditor5-adapter-ckfinder/src/uploadadapter.js

@@ -12,6 +12,7 @@
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 import FileRepository from '@ckeditor/ckeditor5-upload/src/filerepository';
 import { getCsrfToken } from './utils';
+import log from '@ckeditor/ckeditor5-utils/src/log';
 
 /**
  * Plugin that enables CKFinder uploads in CKEditor 5.
@@ -38,7 +39,16 @@ export default class CKFinderUploadAdapter extends Plugin {
 	 * @inheritDoc
 	 */
 	init() {
-		const url = this.editor.config.get( 'ckfinder.uploadUrl' ) || '';
+		const url = this.editor.config.get( 'ckfinder.uploadUrl' );
+
+		if ( !url ) {
+			/**
+			 * Please provide `ckfinder.uploadUrl` config option.
+			 *
+			 * @error ckfinder-upload-adapter-no-config
+			 */
+			log.warn( 'ckfinder-upload-adapter-no-config: Please provide "ckfinder.uploadUrl" config option.' );
+		}
 
 		// Register CKFinderAdapter
 		this.editor.plugins.get( FileRepository ).createAdapter = loader => new Adapter( loader, url, this.editor.t );
@@ -74,6 +84,11 @@ class Adapter {
 		 */
 		this.url = url;
 
+		/**
+		 * Locale translation method.
+		 *
+		 * @member {module:utils/locale~Locale#t} #t
+		 */
 		this.t = t;
 	}
 
@@ -143,6 +158,7 @@ class Adapter {
 		} );
 
 		// Upload progress when it's supported.
+		/* istanbul ignore else */
 		if ( xhr.upload ) {
 			xhr.upload.addEventListener( 'progress', ( evt ) => {
 				if ( evt.lengthComputable ) {

+ 194 - 0
packages/ckeditor5-adapter-ckfinder/tests/uploadadapter.js

@@ -0,0 +1,194 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals document */
+import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
+import Image from '@ckeditor/ckeditor5-image/src/image';
+import ImageUpload from '@ckeditor/ckeditor5-upload/src/imageupload';
+import CKFinderUploadAdapter from '../src/uploadadapter';
+import FileRepository from '@ckeditor/ckeditor5-upload/src/filerepository';
+import { createNativeFileMock } from '@ckeditor/ckeditor5-upload/tests/_utils/mocks';
+import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
+import log from '@ckeditor/ckeditor5-utils/src/log';
+
+describe( 'CKFinderUploadAdapter', () => {
+	let editor, sinonXHR;
+	testUtils.createSinonSandbox();
+
+	beforeEach( () => {
+		const editorElement = document.createElement( 'div' );
+		document.body.appendChild( editorElement );
+
+		sinonXHR = testUtils.sinon.useFakeXMLHttpRequest();
+
+		return ClassicTestEditor.create( editorElement, {
+			plugins: [ Image, ImageUpload, CKFinderUploadAdapter ],
+			ckfinder: {
+				uploadUrl: 'http://example.com'
+			}
+		} )
+		.then( newEditor => {
+			editor = newEditor;
+		} );
+	} );
+
+	afterEach( () => {
+		sinonXHR.restore();
+	} );
+
+	it( 'should be loaded', () => {
+		expect( editor.plugins.get( CKFinderUploadAdapter ) ).to.be.instanceOf( CKFinderUploadAdapter );
+	} );
+
+	describe( 'Adapter', () => {
+		let adapter, loaderMock;
+
+		beforeEach( () => {
+			const file = createNativeFileMock();
+			file.name = 'image.jpeg';
+			loaderMock = { file	};
+
+			adapter = editor.plugins.get( FileRepository ).createAdapter( loaderMock );
+		} );
+
+		it( 'crateAdapter method should be registered and have upload and abort methods', () => {
+			expect( adapter ).to.be.defined;
+			expect( adapter.upload ).to.be.function;
+			expect( adapter.abort ).to.be.function;
+		} );
+
+		it( 'should log warning when there is no configuration', () => {
+			const editorElement = document.createElement( 'div' );
+			document.body.appendChild( editorElement );
+			const warnSub = testUtils.sinon.stub( log, 'warn' );
+
+			return ClassicTestEditor.create( editorElement, {
+				plugins: [ Image, ImageUpload, CKFinderUploadAdapter ],
+			} )
+			.then( () => {
+				sinon.assert.calledOnce( warnSub );
+				sinon.assert.calledWithExactly(
+					warnSub,
+					'ckfinder-upload-adapter-no-config: Please provide "ckfinder.uploadUrl" config option.'
+				);
+			} );
+		} );
+
+		describe( 'upload', () => {
+			it( 'should return promise', () => {
+				expect( adapter.upload() ).to.be.instanceof( Promise );
+			} );
+
+			it( 'should call url from config', () => {
+				let request;
+				const validResponse = {
+					uploaded: 1
+				};
+
+				const promise = adapter.upload()
+					.then( () => {
+						expect( request.url ).to.equal( 'http://example.com' );
+					} );
+
+				request = sinonXHR.requests[ 0 ];
+				request.respond( 200, { 'Content-Type': 'application/json' }, JSON.stringify( validResponse ) );
+
+				return promise;
+			} );
+
+			it( 'should throw an error on generic request error', () => {
+				let request;
+
+				const promise = adapter.upload()
+					.then( () => {
+						throw new Error( 'Promise should throw.' );
+					} )
+					.catch( ( msg ) => {
+						expect( msg ).to.equal( 'Cannot upload file: image.jpeg.' );
+					} );
+
+				request = sinonXHR.requests[ 0 ];
+				request.error();
+
+				return promise;
+			} );
+
+			it( 'should throw an error on error from server', () => {
+				let request;
+				const responseError = {
+					error: {
+						message: 'Foo bar baz.'
+					}
+				};
+
+				const promise = adapter.upload()
+					.then( () => {
+						throw new Error( 'Promise should throw.' );
+					} )
+					.catch( ( msg ) => {
+						expect( msg ).to.equal( 'Foo bar baz.' );
+					} );
+
+				request = sinonXHR.requests[ 0 ];
+				request.respond( 200, { 'Content-Type': 'application/json' }, JSON.stringify( responseError ) );
+
+				return promise;
+			} );
+
+			it( 'should throw a generic error on error from server without message', () => {
+				let request;
+				const responseError = {
+					error: {}
+				};
+
+				const promise = adapter.upload()
+					.then( () => {
+						throw new Error( 'Promise should throw.' );
+					} )
+					.catch( ( msg ) => {
+						expect( msg ).to.equal( 'Cannot upload file: image.jpeg.' );
+					} );
+
+				request = sinonXHR.requests[ 0 ];
+				request.respond( 200, { 'Content-Type': 'application/json' }, JSON.stringify( responseError ) );
+
+				return promise;
+			} );
+
+			it( 'should throw an error on abort', () => {
+				let request;
+
+				const promise = adapter.upload()
+					.then( () => {
+						throw new Error( 'Promise should throw.' );
+					} )
+					.catch( () => {
+						expect( request.aborted ).to.be.true;
+					} );
+
+				request = sinonXHR.requests[ 0 ];
+				adapter.abort();
+
+				return promise;
+			} );
+
+			it( 'abort should not throw before upload', () => {
+				expect( () => {
+					adapter.abort();
+				} ).to.not.throw();
+			} );
+
+			it( 'should update progress', () => {
+				adapter.upload();
+
+				const request = sinonXHR.requests[ 0 ];
+				request.uploadProgress( { loaded: 4, total: 10 } );
+
+				expect( loaderMock.uploadTotal ).to.equal( 10 );
+				expect( loaderMock.uploaded ).to.equal( 4 );
+			} );
+		} );
+	} );
+} );