Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asynchronous load of emoji list #2049

Merged
merged 17 commits into from
Jun 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion contents.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
body
{
/* Font */
font-family: sans-serif, Arial, Verdana, "Trebuchet MS";
/* Emoji font are added to visualise them nicely in IE */
font-family: sans-serif, Arial, Verdana, "Trebuchet MS", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 12px;

/* Text color */
Expand Down
1 change: 1 addition & 0 deletions plugins/emoji/emoji.json

Large diffs are not rendered by default.

203 changes: 91 additions & 112 deletions plugins/emoji/plugin.js

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions plugins/emoji/samples/emoji.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
.content .sample-data p {
font-size: 1rem;
margin: 0;
line-height: 0;
}

</style>
Expand Down Expand Up @@ -69,7 +68,6 @@ <h1>Emoji plugin</h1>
<div class="grid-container">
<div class="grid-width-100">
<div id="editor">
<p>This is <code>:slightly_smiling_face:</code> :slightly_smiling_face:</p>
<p>Type `:` (colon) to select emoji.</p>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions plugins/emoji/skins/default.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-family: sans-serif, Arial, Verdana, "Trebuchet MS", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}
1 change: 1 addition & 0 deletions tests/plugins/emoji/_assets/emoji.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"id":":star:","symbol":"⭐"}]
27 changes: 27 additions & 0 deletions tests/plugins/emoji/_helpers/tools.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
( function() {
'use strict';
window.emojiTools = {
runAfterInstanceReady: function( editor, bot, testCase ) {
// Emoji are loaded on instance ready, we need to wait for it.
if ( editor.status !== 'ready' ) {
editor.once( 'instanceReady', function() {
resume( function() {
testCase( editor, bot );
} );
}, null, null, 100 );
wait();
} else {
testCase( editor, bot );
}
},
clearAutocompleteModel: function( autocomplete ) {
var model = autocomplete.model;
delete model.data;
delete model.lastRequestId;
delete model.query;
delete model.range;
delete model.selectedItemId;
},
notSupportedEnvironment: CKEDITOR.env.ie && CKEDITOR.env.version < 11
};
} )();
110 changes: 80 additions & 30 deletions tests/plugins/emoji/basic.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/* bender-tags: emoji */
/* bender-ckeditor-plugins: emoji,toolbar,stylescombo,format,clipboard */
/* bender-ckeditor-plugins: emoji,toolbar,stylescombo,format,clipboard,undo */
/* bender-include: _helpers/tools.js */
/* global emojiTools */

( function() {
'use strict';
Expand All @@ -22,61 +24,109 @@
startupData: '<p>foo:grinning_face:bar :not_emoji:</p>',
config: {
extraPlugins: 'divarea',
emoji_blacklistedElements: [ 'section', 'pre', 'code' ]
emoji_minChars: 3
}
}
};

var stub = null;

var singleTests = {
'test for custom emoji characters': function() {
var editor = this.editors.divarea,
bot = this.editorBots.divarea;

emojiTools.runAfterInstanceReady( editor, bot, function( editor, bot ) {
var autocomplete = editor._.emoji.autocomplete;

bot.setHtmlWithSelection( '<p>foo:da^</p>' );
editor.editable().fire( 'keyup', new CKEDITOR.dom.event( {} ) );
assert.isUndefined( autocomplete.model.query );
assert.isUndefined( autocomplete.model.data );

// Handle throttle in autocomplete which by defualt is 20ms;
setTimeout( function() {
resume( function() {
bot.setHtmlWithSelection( '<p>foo:dagg^</p>' );
editor.editable().fire( 'keyup', new CKEDITOR.dom.event( {} ) );
assert.areSame( ':dagg', autocomplete.model.query, 'Model keeps wrong querry.' );
assert.areSame( 1, autocomplete.model.data.length, 'Emoji result contains more than one result.' );
objectAssert.areEqual( { id: ':dagger:', symbol: '🗡' }, autocomplete.model.data[ 0 ], 'Emoji result contains wrong result' );
autocomplete.close();
} );
}, 50 );
wait();
} );
}
};

var tests = {
setUp: function() {
if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) {
if ( emojiTools.notSupportedEnvironment ) {
assert.ignore();
}
},

'test emoji is converted during editor creation': function( editor ) {
assert.areSame( '<p>foo😀bar :not_emoji:</p>', editor.getData() );
},
// Fallback in case where ajax couldn't load before tests.
var data = JSON.stringify( [
{ id: ':bug:', symbol: '🐛' },
{ id: ':dagger:', symbol: '🗡' }
] );

'test emoji is converted during setData': function( editor, bot ) {
bot.setData( '<p>bar:slightly_smiling_face:baz :not_emoji:</p>', function() {
assert.areSame( '<p>bar🙂baz :not_emoji:</p>', editor.getData() );
stub = sinon.stub( CKEDITOR.ajax, 'load', function( url, callback ) {
if ( url.indexOf( 'emoji/_assets/emoji.json' ) !== -1 ) {
callback( data );
}
} );
},

'test emoji is converted durign insertText': function( editor, bot ) {
bot.setHtmlWithSelection( '<p>hello^world</p>' );
editor.insertText( ':face_with_tears_of_joy:' );
assert.areSame( '<p>hello😂world</p>', editor.getData() );
tearDown: function() {
stub.restore();
},

'test emoji is not converted durign insertText': function( editor, bot ) {
bot.setHtmlWithSelection( '<p>hello^world</p>' );
editor.insertText( ':this_should_not_be_converted:' );
assert.areSame( '<p>hello:this_should_not_be_converted:world</p>', editor.getData() );
'test emoji objects are added to editor': function( editor ) {
emojiTools.runAfterInstanceReady( editor, null, function( editor ) {
assert.isObject( editor._.emoji, 'Emoji variable doesn\' exists.' );
objectAssert.ownsKeys( [ 'list', 'autocomplete' ], editor._.emoji, 'Emoji variable is missing some keys.' );
} );
},

'test emoji is not converted in pre and code tags': function( editor, bot ) {
bot.setData( '<p>foo:grinning_face:bar</p><pre>foo:grinning_face:bar</pre><p><code>foo:grinning_face:bar</code></p>', function() {
assert.areSame( '<p>foo😀bar</p><pre>foo:grinning_face:bar</pre><p><code>foo:grinning_face:bar</code></p>', editor.getData() );
'test emoji suggestion box has proper values': function( editor, bot ) {
emojiTools.runAfterInstanceReady( editor, bot, function( editor, bot ) {
var autocomplete = editor._.emoji.autocomplete;

bot.setHtmlWithSelection( '<p>foo:bug^</p>' );
editor.editable().fire( 'keyup', new CKEDITOR.dom.event( {} ) );
assert.areSame( ':bug', autocomplete.model.query, 'Model keeps wrong querry.' );
assert.areSame( 1, autocomplete.model.data.length, 'Emoji result contains more than one result.' );
objectAssert.areEqual( { id: ':bug:', symbol: '🐛' }, autocomplete.model.data[ 0 ], 'Emoji result contains wrong result' );

emojiTools.clearAutocompleteModel( autocomplete );
autocomplete.close();
} );
},

'test emoji with paste event': function( editor, bot ) {
bot.setHtmlWithSelection( '<p>111^222</p>' );
'test emoji are not actived when too few letters are written': function( editor, bot ) {
emojiTools.runAfterInstanceReady( editor, bot, function( editor, bot ) {
var autocomplete = editor._.emoji.autocomplete;
bot.setHtmlWithSelection( '<p>foo:b^</p>' );
editor.editable().fire( 'keyup', new CKEDITOR.dom.event( {} ) );

editor.once( 'afterPaste', function() {
resume( function() {
assert.areSame( '<p>111🦄222</p>', editor.getData() );
} );
} );
assert.isUndefined( autocomplete.model.query );
assert.isUndefined( autocomplete.model.data );

bender.tools.emulatePaste( editor, ':unicorn_face:' );
emojiTools.clearAutocompleteModel( autocomplete );
autocomplete.close();

wait();
} );
}

};

tests = bender.tools.createTestsForEditors( CKEDITOR.tools.objectKeys( bender.editors ), tests );
CKEDITOR.tools.array.forEach( CKEDITOR.tools.objectKeys( singleTests ), function( key ) {
if ( tests[ key ] === undefined ) {
tests[ key ] = singleTests[ key ];
}
} );
bender.test( tests );
} )();
72 changes: 72 additions & 0 deletions tests/plugins/emoji/customemojilist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/* bender-tags: emoji */
/* bender-ckeditor-plugins: emoji,toolbar,stylescombo,format,clipboard */
/* bender-include: _helpers/tools.js */
/* global emojiTools */

( function() {
'use strict';

bender.editors = {
classic: {
name: 'classic',
config: {
emoji_emojiListUrl: '%BASE_PATH%/plugins/emoji/_assets/emoji.json'
},
startupData: '<p>foo :grinning_face: bar :not_emoji: this is converted emoji :star:</p>'
},
classic2: {
name: 'classic2',
config: {
emoji_emojiListUrl: 'fake.url'
},
startupData: '<p>foo :grinning_face: bar :not_emoji: this is not converted emoji :star:</p>'
}
};

bender.test( {
setUp: function() {
if ( emojiTools.notSupportedEnvironment ) {
assert.ignore();
}
},

// (#2036)
'test custom emoji list is load': function() {
var editor = this.editors.classic;
emojiTools.runAfterInstanceReady( editor, null, function( editor ) {
assert.areSame( 1, editor._.emoji.list.length );
objectAssert.areEqual( { id: ':star:', symbol: '⭐' }, editor._.emoji.list[ 0 ] );
} );
},

'test invalid emoji list': function() {
var editor = this.editors.classic2;
emojiTools.runAfterInstanceReady( editor, null, function( editor ) {
assert.isUndefined( editor._.emoji, 'editor._.emoji should not be initialised when invalid emoji file is loaded.' );
} );
},

'test long ajax loading': function() {
var server = sinon.fakeServer.create();

server.respondWith( 'GET', 'http://random.url', [ 200, { 'Content-Type': 'application/json' }, '[{"id":":bug:","symbol":"🐛"}]' ] );

bender.editorBot.create( {
name: 'created1',
config: {
emoji_emojiListUrl: 'http://random.url'
},
startupData: '<p>foo :grinning_face: bar :not_emoji: this :star: is converted emoji :bug:</p>'
}, function( bot ) {
emojiTools.runAfterInstanceReady( bot.editor, null, function( editor ) {
assert.isUndefined( editor._.emoji, 'Emoji is loaded on this stage, what should not happen here.' );
server.respond();
assert.areSame( 1, editor._.emoji.list.length );
objectAssert.areEqual( { id: ':bug:', symbol: '🐛' }, editor._.emoji.list[ 0 ] );
server.restore();
} );
} );
}
} );

} )();
37 changes: 0 additions & 37 deletions tests/plugins/emoji/manual/blockedelements.html

This file was deleted.

21 changes: 0 additions & 21 deletions tests/plugins/emoji/manual/blockedelements.md

This file was deleted.

24 changes: 24 additions & 0 deletions tests/plugins/emoji/manual/customemojilist.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<h1>Classic editor</h1>

<textarea id="editor1" cols="10" rows="10">
<p>Hello world.</p>
</textarea>

<h1>Divarea editor</h1>

<div id="editor2" cols="10" rows="10">
<p>Hello world.</p>
</div>

<script>
if ( emojiTools.notSupportedEnvironment) {
bender.ignore();
}
CKEDITOR.replace( 'editor1', {
emoji_emojiListUrl: '%BASE_PATH%/plugins/emoji/_assets/emoji.json'
} );
CKEDITOR.replace( 'editor2', {
extraPlugins: 'divarea',
emoji_emojiListUrl: '%BASE_PATH%/plugins/emoji/_assets/emoji.json'
} );
</script>
19 changes: 19 additions & 0 deletions tests/plugins/emoji/manual/customemojilist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@bender-tags: 4.10.0, feature, emoji, 2036
@bender-ckeditor-plugins: wysiwygarea, toolbar, elementspath, sourcearea, emoji, clipboard, undo
@bender-ui: collapsed
@bender-include: ../_helpers/tools.js

1. Insert new emoji by typing its name in editor. There should be only one emoji available (`:star:`). _You need to type at least 2 characters from emoji name to see suggestion box with emoji._

## Expected:
**Only** `:star:` emoji is available to insert in editor. Other emojis are not converted.

## Example emoji to use in tests:

| name | symbol |
| ---: | --- |
| :bug: | 🐛 |
| :winking_face: | 😉 |
| :collision: | 💥 |
| :unicorn_face: | 🦄 |

3 changes: 3 additions & 0 deletions tests/plugins/emoji/manual/emoji.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ <h6>This is header H6</h6>
</div>

<script>
if ( emojiTools.notSupportedEnvironment) {
bender.ignore();
}
CKEDITOR.replace( 'editor1' );
CKEDITOR.replace( 'editor2', {
extraPlugins: 'divarea'
Expand Down
Loading