/**
* @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/
import Model from '../../../src/model/model';
import DocumentFragment from '../../../src/model/documentfragment';
import getSelectedContent from '../../../src/model/utils/getselectedcontent';
import { setData, stringify } from '../../../src/dev-utils/model';
describe( 'DataController utils', () => {
let model, doc;
describe( 'getSelectedContent', () => {
it( 'should use parent batch', () => {
model = new Model();
doc = model.document;
doc.createRoot();
model.schema.extend( '$text', { allowIn: '$root' } );
setData( model, 'x[abc]x' );
model.change( writer => {
getSelectedContent( model, doc.selection );
expect( writer.batch.operations ).to.length( 1 );
} );
} );
describe( 'in simple scenarios', () => {
beforeEach( () => {
model = new Model();
doc = model.document;
doc.createRoot();
const schema = model.schema;
schema.register( 'image', { allowWhere: '$text', allowIn: '$root' } );
schema.extend( '$text', {
allowIn: '$root',
allowAttributes: [ 'bold', 'italic' ]
} );
} );
it( 'returns empty fragment for no selection', () => {
setData( model, 'abc' );
const frag = getSelectedContent( model, doc.selection );
expect( frag ).instanceOf( DocumentFragment );
expect( frag.isEmpty ).to.be.true;
} );
it( 'returns empty fragment for empty selection', () => {
setData( model, 'a[]bc' );
const frag = getSelectedContent( model, doc.selection );
expect( frag ).instanceOf( DocumentFragment );
expect( frag.isEmpty ).to.be.true;
} );
it( 'gets one character', () => {
setData( model, 'a[b]c' );
const frag = getSelectedContent( model, doc.selection );
const content = stringify( frag );
expect( frag ).instanceOf( DocumentFragment );
expect( content ).to.equal( 'b' );
} );
it( 'gets full text', () => {
setData( model, '[abc]' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'abc' );
} );
it( 'gets text with an attribute', () => {
setData( model, 'xxx<$text bold="true">a[b]c$text>' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( '<$text bold="true">b$text>' );
} );
it( 'gets text with attributes', () => {
setData( model, 'x<$text bold="true">a[b$text><$text italic="true">c]d$text>x' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( '<$text bold="true">b$text><$text italic="true">c$text>' );
} );
it( 'gets text with and without attribute', () => {
setData( model, '<$text bold="true">a[b$text>c]d' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( '<$text bold="true">b$text>c' );
} );
it( 'gets text and element', () => {
setData( model, '[abc]' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'abc' );
} );
it( 'gets one element', () => {
setData( model, 'a[]b' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( '' );
} );
it( 'gets multiple elements', () => {
setData( model, '[]' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( '' );
} );
} );
describe( 'in blocks', () => {
beforeEach( () => {
model = new Model();
doc = model.document;
doc.createRoot();
const schema = model.schema;
schema.register( 'paragraph', { inheritAllFrom: '$block' } );
schema.register( 'heading1', { inheritAllFrom: '$block' } );
schema.register( 'blockImage', { isObject: true } );
schema.register( 'caption' );
schema.register( 'image', { allowWhere: '$text' } );
schema.extend( 'blockImage', { allowIn: '$root' } );
schema.extend( 'caption', { allowIn: 'blockImage' } );
schema.extend( '$text', {
allowIn: 'caption',
allowAttributes: 'bold'
} );
} );
it( 'gets one character', () => {
setData( model, 'a[b]c' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'b' );
} );
it( 'gets entire paragraph content', () => {
setData( model, '[ab]' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'ab' );
} );
it( 'gets two blocks - partial, partial', () => {
setData( model, 'a[bcde]f' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'bcde' );
} );
it( 'gets two blocks - full, partial', () => {
setData( model, '[abcde]f' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'abcde' );
} );
it( 'gets two blocks - full, partial 2', () => {
setData( model, '[abcde]f' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'abcde' );
} );
it( 'gets two blocks - full, partial 3', () => {
setData( model, 'x[abcde]f' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'abcde' );
} );
it( 'gets two blocks - full, partial 4', () => {
setData( model, '[abcde]f' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'abcde' );
} );
it( 'gets two blocks - partial, full', () => {
setData( model, 'a[bcdef]' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'bcdef' );
} );
it( 'gets two blocks - partial, full 2', () => {
setData( model, 'a[bcdef]' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'bcdef' );
} );
// See https://github.com/ckeditor/ckeditor5-engine/issues/652#issuecomment-261358484
it( 'gets two blocks - empty, full', () => {
setData( model, 'abc[def]' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'def' );
} );
// See https://github.com/ckeditor/ckeditor5-engine/issues/652#issuecomment-261358484
it( 'gets two blocks - partial, empty', () => {
setData( model, 'a[bc]def' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'bc' );
} );
it( 'gets three blocks', () => {
setData( model, 'a[bcxde]f' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'bcxde' );
} );
it( 'gets block image', () => {
setData( model, 'a[Foo]b' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'Foo' );
} );
it( 'gets two blocks', () => {
setData( model, 'a[]b' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( '' );
} );
// Purely related to the current implementation.
it( 'gets content when multiple text items needs to be removed from the right excess', () => {
setData( model, 'a[bc]d<$text bold="true">e$text>f' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content )
.to.equal( 'bc' );
} );
// Purely related to the current implementation.
it( 'gets content when multiple text items needs to be removed from the left excess', () => {
setData( model, 'a<$text bold="true">b$text>c[de]f' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content )
.to.equal( 'de' );
} );
} );
describe( 'in blocks (deeply nested)', () => {
beforeEach( () => {
model = new Model();
doc = model.document;
doc.createRoot();
const schema = model.schema;
schema.register( 'paragraph', { inheritAllFrom: '$block' } );
schema.register( 'heading1', { inheritAllFrom: '$block' } );
schema.register( 'quote' );
schema.extend( '$block', { allowIn: 'quote' } );
schema.extend( 'quote', { allowIn: '$root' } );
} );
it( 'gets content when ends are equally deeply nested', () => {
setData( model, 'xa[bcde]f
' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'bcde' );
} );
it( 'gets content when left end nested deeper', () => {
setData( model, 'a[bc
de]f' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'bc
de' );
} );
it( 'gets content when left end nested deeper 2', () => {
setData( model, 'a[bcx
de]f' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'bcx
de' );
} );
it( 'gets content when left end nested deeper 3', () => {
setData( model, 'xa[bc
de]f' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'bc
de' );
} );
// See https://github.com/ckeditor/ckeditor5-engine/issues/652#issuecomment-261358484
it( 'gets content when left end nested deeper 4', () => {
setData( model, 'x[abc
de]f' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'abc
de' );
} );
it( 'gets content when right end nested deeper', () => {
setData( model, 'a[bcde]f
' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content ).to.equal( 'bcde
' );
} );
it( 'gets content when both ends nested deeper than the middle element', () => {
setData( model, 'a[bc
xde]f
' );
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content )
.to.equal( 'bc
xde
' );
} );
// See: https://github.com/ckeditor/ckeditor5-engine/pull/1043#issuecomment-318012286
it( 'ensures that elements are retrieved by indexes instead of offsets', () => {
model.schema.extend( '$text', { allowIn: '$root' } );
model.schema.extend( '$text', { allowIn: 'quote' } );
setData( model,
'foo' +
'' +
'' +
'b[ar' +
'' +
'bo]m' +
'
'
);
const content = stringify( getSelectedContent( model, doc.selection ) );
expect( content )
.to.equal( 'arbo' );
} );
} );
} );
} );