Skip to content

Commit

Permalink
Added tests and applied fixes after review.
Browse files Browse the repository at this point in the history
  • Loading branch information
niegowski committed Oct 16, 2023
1 parent 9abe34d commit 5707d9b
Show file tree
Hide file tree
Showing 7 changed files with 220 additions and 17 deletions.
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ The following libraries are included in CKEditor under the [MIT license](https:/
* turndown - turndown is copyright © Dom Christie and released under the MIT license.
* turndown-plugin-gfm - turndown-plugin-gfm is copyright © Dom Christie and released under the MIT license.
* vanilla-colorful - Copyright (c) 2020 Serhii Kulykov <[email protected]> (MIT license).
* blurhash - ... TODO
* blurhash - Copyright (c) 2018 Wolt Enterprises (MIT license).

Trademarks
----------
Expand Down
2 changes: 1 addition & 1 deletion packages/ckeditor5-ckbox/LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Where not otherwise indicated, all CKEditor content is authored by CKSource engi

The following libraries are included in CKEditor under the [MIT license](https://opensource.org/licenses/MIT):

* blurhash - ... TODO
* blurhash - Copyright (c) 2018 Wolt Enterprises (MIT license).

Trademarks
----------
Expand Down
4 changes: 2 additions & 2 deletions packages/ckeditor5-ckbox/src/ckboxcommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import type {
CKBoxRawAssetDefinition
} from './ckboxconfig';

import { base64FromBlurHash, getImageUrls } from './utils';
import { blurHashToDataUrl, getImageUrls } from './utils';

declare global {
// eslint-disable-next-line no-var
Expand Down Expand Up @@ -379,7 +379,7 @@ function prepareAssets(
function prepareImageAssetAttributes( asset: CKBoxRawAssetDefinition ): CKBoxAssetImageAttributesDefinition {
const { imageFallbackUrl, imageSources } = getImageUrls( asset.data.imageUrls! );
const { description, width, height, blurHash } = asset.data.metadata!;
const imagePlaceholder = base64FromBlurHash( blurHash );
const imagePlaceholder = blurHashToDataUrl( blurHash );

return {
imageFallbackUrl,
Expand Down
4 changes: 2 additions & 2 deletions packages/ckeditor5-ckbox/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ export function getWorkspaceId( token: InitializedToken, defaultWorkspaceId?: st
const BLUR_RESOLUTION = 32;

/**
* Generates base64-encoded image from its `blurhash` representation.
* Generates an image data URL from its `blurhash` representation.
*/
export function base64FromBlurHash( hash?: string ): string | undefined {
export function blurHashToDataUrl( hash?: string ): string | undefined {
if ( !hash ) {
return;
}
Expand Down
6 changes: 3 additions & 3 deletions packages/ckeditor5-ckbox/tests/ckboxcommand.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import TokenMock from '@ckeditor/ckeditor5-cloud-services/tests/_utils/tokenmock

import CKBoxEditing from '../src/ckboxediting';
import CKBoxCommand from '../src/ckboxcommand';
import { base64FromBlurHash } from '../src/utils';
import { blurHashToDataUrl } from '../src/utils';

describe( 'CKBoxCommand', () => {
let editor, model, command, originalCKBox;
Expand Down Expand Up @@ -599,7 +599,7 @@ describe( 'CKBoxCommand', () => {

it( 'should insert an image inline (with blurhash placeholder)', () => {
const spy = sinon.spy( editor, 'execute' );
const placeholder = base64FromBlurHash( assets.imagesWithBlurHash[ 0 ].data.metadata.blurHash );
const placeholder = blurHashToDataUrl( assets.imagesWithBlurHash[ 0 ].data.metadata.blurHash );

onChoose( [ assets.imagesWithBlurHash[ 0 ] ] );

Expand Down Expand Up @@ -681,7 +681,7 @@ describe( 'CKBoxCommand', () => {

it( 'should insert an image block (with blurhash placeholder)', () => {
const spy = sinon.spy( editor, 'execute' );
const placeholder = base64FromBlurHash( assets.imagesWithBlurHash[ 0 ].data.metadata.blurHash );
const placeholder = blurHashToDataUrl( assets.imagesWithBlurHash[ 0 ].data.metadata.blurHash );

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

Expand Down
12 changes: 6 additions & 6 deletions packages/ckeditor5-ckbox/tests/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import TokenMock from '@ckeditor/ckeditor5-cloud-services/tests/_utils/tokenmock';
import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
import { getWorkspaceId, getImageUrls, base64FromBlurHash } from '../src/utils';
import { getWorkspaceId, getImageUrls, blurHashToDataUrl } from '../src/utils';

describe( 'utils', () => {
testUtils.createSinonSandbox();
Expand Down Expand Up @@ -171,17 +171,17 @@ describe( 'utils', () => {

describe( 'base64FromBlurHash()', () => {
it( 'should return undefined if no blurHash', () => {
expect( base64FromBlurHash( undefined ) ).to.be.undefined;
expect( base64FromBlurHash( null ) ).to.be.undefined;
expect( base64FromBlurHash( '' ) ).to.be.undefined;
expect( blurHashToDataUrl( undefined ) ).to.be.undefined;
expect( blurHashToDataUrl( null ) ).to.be.undefined;
expect( blurHashToDataUrl( '' ) ).to.be.undefined;
} );

it( 'should return undefined if invalid blurHash', () => {
expect( base64FromBlurHash( '123' ) ).to.be.undefined;
expect( blurHashToDataUrl( '123' ) ).to.be.undefined;
} );

it( 'should generate image data url', () => {
const result = base64FromBlurHash( 'KTF55N=ZR4PXSirp5ZOZW9' );
const result = blurHashToDataUrl( 'KTF55N=ZR4PXSirp5ZOZW9' );
const prefix = 'data:image/png;base64,';
const binary = atob( result.substring( prefix.length ) );

Expand Down
207 changes: 205 additions & 2 deletions packages/ckeditor5-image/tests/image/imageplaceholder.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
import { setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
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 '../../src/image/imageplaceholder';
Expand Down Expand Up @@ -92,6 +92,72 @@ describe( 'ImagePlaceholder', () => {
);
} );

it( 'should remove placeholder when the image is loaded', () => {
setModelData( model, '<imageBlock src="/assets/sample.png" placeholder="#blurImage"></imageBlock>' );

const modelElement = doc.getRoot().getChild( 0 );
const viewElement = editor.editing.mapper.toViewElement( modelElement ).getChild( 0 );
const domElement = editor.editing.view.domConverter.mapViewToDom( viewElement );

expect( domElement.tagName ).to.equal( 'IMG' );

expect( getViewData( view, { withoutSelection: true } ) ).to.equal(
'<figure class="ck-widget ck-widget_selected image" contenteditable="false">' +
'<img class="image_placeholder" src="/assets/sample.png" style="background-image:url(#blurImage)"></img>' +
'<div class="ck ck-reset_all ck-widget__type-around"></div>' +
'</figure>'
);

expect( editor.getData() ).to.equal(
'<figure class="image"><img src="/assets/sample.png"></figure>'
);

view.document.fire( 'imageLoaded', {
target: domElement
} );

expect( getModelData( model, { withoutSelection: true } ) ).to.equal(
'<imageBlock src="/assets/sample.png"></imageBlock>'
);

expect( getViewData( view, { withoutSelection: true } ) ).to.equal(
'<figure class="ck-widget ck-widget_selected image" contenteditable="false">' +
'<img src="/assets/sample.png"></img>' +
'<div class="ck ck-reset_all ck-widget__type-around"></div>' +
'</figure>'
);
} );

it( 'should not remove placeholder when some other image is loaded', () => {
setModelData( model, '<imageBlock src="/assets/sample.png" placeholder="#blurImage"></imageBlock>' );

expect( getViewData( view, { withoutSelection: true } ) ).to.equal(
'<figure class="ck-widget ck-widget_selected image" contenteditable="false">' +
'<img class="image_placeholder" src="/assets/sample.png" style="background-image:url(#blurImage)"></img>' +
'<div class="ck ck-reset_all ck-widget__type-around"></div>' +
'</figure>'
);

expect( editor.getData() ).to.equal(
'<figure class="image"><img src="/assets/sample.png"></figure>'
);

view.document.fire( 'imageLoaded', {
target: document.createElement( 'img' )
} );

expect( getModelData( model, { withoutSelection: true } ) ).to.equal(
'<imageBlock placeholder="#blurImage" src="/assets/sample.png"></imageBlock>'
);

expect( getViewData( view, { withoutSelection: true } ) ).to.equal(
'<figure class="ck-widget ck-widget_selected image" contenteditable="false">' +
'<img class="image_placeholder" src="/assets/sample.png" style="background-image:url(#blurImage)"></img>' +
'<div class="ck ck-reset_all ck-widget__type-around"></div>' +
'</figure>'
);
} );

it( 'should not apply placeholder to other elements than image', () => {
model.schema.register( 'test', { inheritAllFrom: '$blockObject', allowAttributes: [ 'src', 'placeholder' ] } );
editor.conversion.elementToElement( { model: 'test', view: 'div' } );
Expand Down Expand Up @@ -158,6 +224,143 @@ describe( 'ImagePlaceholder', () => {
expect( model.schema.checkAttribute( 'imageBlock', 'placeholder' ) ).to.be.false;
} );

// TODO
it( 'should apply placeholder to the img in the editing view (only)', () => {
setModelData( model, '<paragraph><imageInline src="/assets/sample.png" placeholder="#blurImage"></imageInline></paragraph>' );

expect( getViewData( view, { withoutSelection: true } ) ).to.equal(
'<p>' +
'<span class="ck-widget image-inline" contenteditable="false">' +
'<img class="image_placeholder" src="/assets/sample.png" style="background-image:url(#blurImage)"></img>' +
'</span>' +
'</p>'
);

expect( editor.getData() ).to.equal(
'<p><img src="/assets/sample.png"></p>'
);
} );

it( 'should remove placeholder from the img in the editing view (only)', () => {
setModelData( model, '<paragraph><imageInline src="/assets/sample.png" placeholder="#blurImage"></imageInline></paragraph>' );

model.change( writer => writer.removeAttribute( 'placeholder', doc.getRoot().getChild( 0 ).getChild( 0 ) ) );

expect( getViewData( view, { withoutSelection: true } ) ).to.equal(
'<p>' +
'<span class="ck-widget image-inline" contenteditable="false">' +
'<img src="/assets/sample.png"></img>' +
'</span>' +
'</p>'
);

expect( editor.getData() ).to.equal(
'<p><img src="/assets/sample.png"></p>'
);
} );

it( 'should remove placeholder when the image is loaded', () => {
setModelData( model, '<paragraph><imageInline src="/assets/sample.png" placeholder="#blurImage"></imageInline></paragraph>' );

const modelElement = doc.getRoot().getChild( 0 ).getChild( 0 );
const viewElement = editor.editing.mapper.toViewElement( modelElement ).getChild( 0 );
const domElement = editor.editing.view.domConverter.mapViewToDom( viewElement );

expect( domElement.tagName ).to.equal( 'IMG' );

expect( getViewData( view, { withoutSelection: true } ) ).to.equal(
'<p>' +
'<span class="ck-widget image-inline" contenteditable="false">' +
'<img class="image_placeholder" src="/assets/sample.png" style="background-image:url(#blurImage)"></img>' +
'</span>' +
'</p>'
);

expect( editor.getData() ).to.equal(
'<p><img src="/assets/sample.png"></p>'
);

view.document.fire( 'imageLoaded', {
target: domElement
} );

expect( getModelData( model, { withoutSelection: true } ) ).to.equal(
'<paragraph><imageInline src="/assets/sample.png"></imageInline></paragraph>'
);

expect( getViewData( view, { withoutSelection: true } ) ).to.equal(
'<p>' +
'<span class="ck-widget image-inline" contenteditable="false">' +
'<img src="/assets/sample.png"></img>' +
'</span>' +
'</p>'
);
} );

it( 'should not remove placeholder when some other image is loaded', () => {
setModelData( model, '<paragraph><imageInline src="/assets/sample.png" placeholder="#blurImage"></imageInline></paragraph>' );

expect( getViewData( view, { withoutSelection: true } ) ).to.equal(
'<p>' +
'<span class="ck-widget image-inline" contenteditable="false">' +
'<img class="image_placeholder" src="/assets/sample.png" style="background-image:url(#blurImage)"></img>' +
'</span>' +
'</p>'
);

expect( editor.getData() ).to.equal(
'<p><img src="/assets/sample.png"></p>'
);

view.document.fire( 'imageLoaded', {
target: document.createElement( 'img' )
} );

expect( getModelData( model, { withoutSelection: true } ) ).to.equal(
'<paragraph><imageInline placeholder="#blurImage" src="/assets/sample.png"></imageInline></paragraph>'
);

expect( getViewData( view, { withoutSelection: true } ) ).to.equal(
'<p>' +
'<span class="ck-widget image-inline" contenteditable="false">' +
'<img class="image_placeholder" src="/assets/sample.png" style="background-image:url(#blurImage)"></img>' +
'</span>' +
'</p>'
);
} );

it( 'should not apply placeholder to other elements than image', () => {
model.schema.register( 'test', { inheritAllFrom: '$inlineObject', allowAttributes: [ 'src', 'placeholder' ] } );
editor.conversion.elementToElement( { model: 'test', view: 'span' } );
editor.conversion.attributeToAttribute( { model: 'src', view: 'data-src' } );
editor.conversion.attributeToAttribute( { model: 'placeholder', view: 'data-placeholder' } );

setModelData( model, '<paragraph><test src="/assets/sample.png" placeholder="#blurImage"></test></paragraph>' );

expect( getViewData( view, { withoutSelection: true } ) ).to.equal(
'<p><span data-placeholder="#blurImage" data-src="/assets/sample.png"></span></p>'
);

expect( editor.getData() ).to.equal(
'<p><span data-src="/assets/sample.png" data-placeholder="#blurImage">&nbsp;</span></p>'
);
} );

it( 'should not apply placeholder consumed by other converter', () => {
editor.conversion.attributeToAttribute( { model: 'placeholder', view: 'data-placeholder', converterPriority: 'high' } );

setModelData( model, '<paragraph><imageInline src="/assets/sample.png" placeholder="#blurImage"></imageInline></paragraph>' );

expect( getViewData( view, { withoutSelection: true } ) ).to.equal(
'<p>' +
'<span class="ck-widget image-inline" contenteditable="false" data-placeholder="#blurImage">' +
'<img src="/assets/sample.png"></img>' +
'</span>' +
'</p>'
);

expect( editor.getData() ).to.equal(
'<p><img src="/assets/sample.png" data-placeholder="#blurImage"></p>'
);
} );
} );
} );

0 comments on commit 5707d9b

Please sign in to comment.