uploadadapter.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /**
  2. * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* globals document */
  6. import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
  7. import Image from '@ckeditor/ckeditor5-image/src/image';
  8. import ImageUpload from '@ckeditor/ckeditor5-image/src/imageupload';
  9. import CKFinderUploadAdapter from '../src/uploadadapter';
  10. import FileRepository from '@ckeditor/ckeditor5-upload/src/filerepository';
  11. import { createNativeFileMock } from '@ckeditor/ckeditor5-upload/tests/_utils/mocks';
  12. import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
  13. describe( 'CKFinderUploadAdapter', () => {
  14. let editor, sinonXHR;
  15. testUtils.createSinonSandbox();
  16. beforeEach( () => {
  17. const editorElement = document.createElement( 'div' );
  18. document.body.appendChild( editorElement );
  19. sinonXHR = testUtils.sinon.useFakeServer();
  20. return ClassicTestEditor
  21. .create( editorElement, {
  22. plugins: [ Image, ImageUpload, CKFinderUploadAdapter ],
  23. ckfinder: {
  24. uploadUrl: 'http://example.com'
  25. }
  26. } )
  27. .then( newEditor => {
  28. editor = newEditor;
  29. } );
  30. } );
  31. afterEach( () => {
  32. sinonXHR.restore();
  33. } );
  34. it( 'should be loaded', () => {
  35. expect( editor.plugins.get( CKFinderUploadAdapter ) ).to.be.instanceOf( CKFinderUploadAdapter );
  36. } );
  37. describe( 'UploadAdapter', () => {
  38. let adapter, loaderMock;
  39. beforeEach( () => {
  40. const file = createNativeFileMock();
  41. file.name = 'image.jpeg';
  42. loaderMock = { file };
  43. adapter = editor.plugins.get( FileRepository ).createUploadAdapter( loaderMock );
  44. } );
  45. it( 'crateAdapter method should be registered and have upload and abort methods', () => {
  46. expect( adapter ).to.not.be.undefined;
  47. expect( adapter.upload ).to.be.a( 'function' );
  48. expect( adapter.abort ).to.be.a( 'function' );
  49. } );
  50. it( 'should not set the FileRepository.createUploadAdapter factory if not configured', () => {
  51. const editorElement = document.createElement( 'div' );
  52. document.body.appendChild( editorElement );
  53. return ClassicTestEditor
  54. .create( editorElement, {
  55. plugins: [ Image, ImageUpload, CKFinderUploadAdapter ],
  56. } )
  57. .then( editor => {
  58. const fileRepository = editor.plugins.get( FileRepository );
  59. expect( fileRepository ).to.not.have.property( 'createUploadAdapter' );
  60. editorElement.remove();
  61. return editor.destroy();
  62. } );
  63. } );
  64. describe( 'upload', () => {
  65. it( 'should return promise', () => {
  66. expect( adapter.upload() ).to.be.instanceof( Promise );
  67. } );
  68. it( 'should call url from config', () => {
  69. let request;
  70. const validResponse = {
  71. uploaded: 1
  72. };
  73. const promise = adapter.upload()
  74. .then( () => {
  75. expect( request.url ).to.equal( 'http://example.com' );
  76. } );
  77. request = sinonXHR.requests[ 0 ];
  78. request.respond( 200, { 'Content-Type': 'application/json' }, JSON.stringify( validResponse ) );
  79. return promise;
  80. } );
  81. it( 'should throw an error on generic request error', () => {
  82. const promise = adapter.upload()
  83. .then( () => {
  84. throw new Error( 'Promise should throw.' );
  85. } )
  86. .catch( msg => {
  87. expect( msg ).to.equal( 'Cannot upload file: image.jpeg.' );
  88. } );
  89. const request = sinonXHR.requests[ 0 ];
  90. request.error();
  91. return promise;
  92. } );
  93. it( 'should throw an error on error from server', () => {
  94. const responseError = {
  95. error: {
  96. message: 'Foo bar baz.'
  97. }
  98. };
  99. const promise = adapter.upload()
  100. .then( () => {
  101. throw new Error( 'Promise should throw.' );
  102. } )
  103. .catch( msg => {
  104. expect( msg ).to.equal( 'Foo bar baz.' );
  105. } );
  106. const request = sinonXHR.requests[ 0 ];
  107. request.respond( 200, { 'Content-Type': 'application/json' }, JSON.stringify( responseError ) );
  108. return promise;
  109. } );
  110. it( 'should throw a generic error on error from server without message', () => {
  111. const responseError = {
  112. error: {}
  113. };
  114. const promise = adapter.upload()
  115. .then( () => {
  116. throw new Error( 'Promise should throw.' );
  117. } )
  118. .catch( msg => {
  119. expect( msg ).to.equal( 'Cannot upload file: image.jpeg.' );
  120. } );
  121. const request = sinonXHR.requests[ 0 ];
  122. request.respond( 200, { 'Content-Type': 'application/json' }, JSON.stringify( responseError ) );
  123. return promise;
  124. } );
  125. it( 'should throw an error on abort', () => {
  126. let request;
  127. const promise = adapter.upload()
  128. .then( () => {
  129. throw new Error( 'Promise should throw.' );
  130. } )
  131. .catch( () => {
  132. expect( request.aborted ).to.be.true;
  133. } );
  134. request = sinonXHR.requests[ 0 ];
  135. adapter.abort();
  136. return promise;
  137. } );
  138. it( 'abort should not throw before upload', () => {
  139. expect( () => {
  140. adapter.abort();
  141. } ).to.not.throw();
  142. } );
  143. it( 'should update progress', () => {
  144. adapter.upload();
  145. const request = sinonXHR.requests[ 0 ];
  146. request.uploadProgress( { loaded: 4, total: 10 } );
  147. expect( loaderMock.uploadTotal ).to.equal( 10 );
  148. expect( loaderMock.uploaded ).to.equal( 4 );
  149. } );
  150. } );
  151. } );
  152. } );