Skip to content

Commit

Permalink
Add tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mati365 committed Oct 25, 2024
1 parent fe20506 commit bd5f48f
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -462,9 +462,8 @@ export default class ImageUploadEditing extends Plugin {
const fileRepository = plugins.get( FileRepository );
const imageUtils = plugins.get( ImageUtils );

// Handle copying and pasting images that are not yet fully uploaded.
// Gather information about uploading image and store it in the view src attribute.
// This way, it'll be possible to paste image to other editor instances and restart the upload there.
// Handle copying images that are not yet fully uploaded.
// Gather information about uploading image and store its as base64 value in the exported img element src attribute.
// See more: https://github.com/ckeditor/ckeditor5/issues/16967
conversion.for( 'dataDowncast' ).add( dispatcher => {
dispatcher.on<DowncastAttributeEvent>( `attribute:uploadId:${ imageType }`, ( evt, data, conversionApi ) => {
Expand All @@ -481,7 +480,8 @@ export default class ImageUploadEditing extends Plugin {
const viewElement = conversionApi.mapper.toViewElement( data.item as Element )!;
const img = imageUtils.findViewImgElement( viewElement );

if ( img && !img.hasAttribute( 'src' ) ) {
// Let's keep src if it's already set. If it's blank or not set, fill it with loader data.
if ( img && !img.getAttribute( 'src' ) ) {
conversionApi.writer.setAttribute( 'src', loader.data, img );
}
} );
Expand Down
69 changes: 69 additions & 0 deletions packages/ckeditor5-image/tests/imageupload/imageuploadediting.js
Original file line number Diff line number Diff line change
Expand Up @@ -1552,6 +1552,75 @@ describe( 'ImageUploadEditing', () => {
} );
} );

describe( 'data downcast conversion of images with uploading state', () => {
it( 'should serialize image in uploading state to base 64', async () => {
setModelData( model, '<paragraph>[]foo</paragraph>' );

const file = createNativeFileMock();
editor.execute( 'uploadImage', { file } );
loader.file.then( () => nativeReaderMock.mockSuccess( base64Sample ) );

await timeout( 50 );

const uploadId = adapterMocks[ 0 ].loader.id;

expect( getModelData( editor.model ) ).to.be.equal(
`<paragraph>[<imageInline uploadId="${ uploadId }" uploadStatus="uploading"></imageInline>]foo</paragraph>`
);

expect( editor.getData() ).to.be.equal(
`<p><img src="${ base64Sample }">foo</p>`
);
} );

it( 'should not crash if uploadId of down casted image is not found in loaders repository', async () => {
setModelData( model, '<paragraph>[]foo</paragraph>' );

const file = createNativeFileMock();
editor.execute( 'uploadImage', { file } );
loader.file.then( () => nativeReaderMock.mockSuccess( base64Sample ) );

await timeout( 50 );

const uploadId = adapterMocks[ 0 ].loader.id;

sinon
.stub( fileRepository.loaders, 'get' )
.withArgs( uploadId )
.returns( null );

expect( getModelData( editor.model ) ).to.be.equal(
`<paragraph>[<imageInline uploadId="${ uploadId }" uploadStatus="uploading"></imageInline>]foo</paragraph>`
);

expect( editor.getData() ).to.be.equal( '<p><img>foo</p>' );
} );

it( 'should not downcast consumed uploadId image attribute', async () => {
editor.conversion.for( 'downcast' ).add( dispatcher =>
dispatcher.on( 'attribute:uploadId:imageInline', ( evt, data, conversionApi ) => {
conversionApi.consumable.consume( data.item, 'attribute:uploadId:imageInline' );
}, { priority: 'high' } )
);

setModelData( model, '<paragraph>[]foo</paragraph>' );

const file = createNativeFileMock();
editor.execute( 'uploadImage', { file } );
loader.file.then( () => nativeReaderMock.mockSuccess( base64Sample ) );

await timeout( 50 );

const uploadId = adapterMocks[ 0 ].loader.id;

expect( getModelData( editor.model ) ).to.be.equal(
`<paragraph>[<imageInline uploadId="${ uploadId }" uploadStatus="uploading"></imageInline>]foo</paragraph>`
);

expect( editor.getData() ).to.be.equal( '<p><img>foo</p>' );
} );
} );

// Helper for validating clipboard and model data as a result of a paste operation. This function checks both clipboard
// data and model data synchronously (`expectedClipboardData`, `expectedModel`) and then the model data after `loader.file`
// promise is resolved (so model state after successful/failed file fetch attempt).
Expand Down

0 comments on commit bd5f48f

Please sign in to comment.