/** * @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 ModelTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/modeltesteditor'; import EnterCommand from '../src/entercommand'; import { getData, setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; describe( 'EnterCommand', () => { let editor, model, doc, schema, command; beforeEach( () => { return ModelTestEditor.create() .then( newEditor => { editor = newEditor; model = editor.model; doc = model.document; command = new EnterCommand( editor ); editor.commands.add( 'enter', command ); schema = model.schema; // Note: We could use real names like 'paragraph', but that would make test patterns too long. // Plus, this is actually a good test that the algorithm can be used for any model. schema.register( 'img', { allowWhere: '$block' } ); schema.register( 'p', { inheritAllFrom: '$block', allowIn: 'blockLimit' } ); schema.register( 'h', { inheritAllFrom: '$block' } ); schema.register( 'inlineLimit', { allowIn: 'p', isLimit: true } ); schema.register( 'blockLimit', { allowIn: '$root', isLimit: true } ); schema.extend( '$text', { allowIn: [ 'inlineLimit', '$root' ] } ); } ); } ); describe( 'EnterCommand', () => { it( 'splits a block using parent batch', () => { setData( model, '

foo[]

' ); model.change( writer => { expect( writer.batch.operations ).to.length( 0 ); editor.execute( 'enter' ); expect( writer.batch.operations ).to.length.above( 0 ); } ); } ); } ); describe( 'execute()', () => { describe( 'collapsed selection', () => { test( 'does nothing in the root', 'foo[]bar', 'foo[]bar' ); test( 'splits block', '

x

foo[]bar

y

', '

x

foo

[]bar

y

' ); test( 'splits block at the end', '

x

foo[]

y

', '

x

foo

[]

y

' ); test( 'splits block at the beginning', '

x

[]foo

y

', '

x

[]foo

y

' ); test( 'inserts new block after empty one', '

x

[]

y

', '

x

[]

y

' ); describe( 'copyOnEnter', () => { beforeEach( () => { schema.extend( '$text', { allowAttributes: [ 'foo', 'bar' ] } ); schema.setAttributeProperties( 'foo', { copyOnEnter: true } ); } ); test( 'allowed attributes are copied', '

<$text foo="true">test[]

', '

<$text foo="true">test

<$text foo="true">[]

' ); test( 'unknown attributes are not copied', '

<$text bar="true">test[]

', '

<$text bar="true">test

[]

' ); test( 'only allowed attributes are copied from mix set', '

<$text bar="true" foo="true">test[]

', '

<$text bar="true" foo="true">test

<$text foo="true">[]

' ); } ); } ); describe( 'non-collapsed selection', () => { test( 'only deletes the content when directly in the root', 'fo[ob]ar', 'fo[]ar' ); test( 'deletes text and splits', '

ab[cd]ef

ghi

', '

ab

[]ef

ghi

' ); test( 'places selection in the 2nd element', 'ab[c

d]ef

ghi

', 'ab

[]ef

ghi

' ); test( 'leaves one empty element after one was fully selected', '

x

[abcdef]

y

', '

x

[]

y

' ); test( 'leaves one empty element after two were fully selected', '

[abc

def]

', '

[]

' ); test( 'should not break inline limit elements - collapsed', '

foo[]bar

', '

foo[]bar

' ); test( 'should not break inline limit elements', '

foo[bar]baz

', '

foo[]baz

' ); it( 'should not break inline limit elements - selection partially inside', () => { // Wrap all changes in one block to avoid post-fixing the selection (which is incorret) in the meantime. model.change( () => { setData( model, '

ba[r

f]oo

' ); command.execute(); expect( getData( model ) ).to.equal( '

ba[r

f]oo

' ); } ); } ); test( 'should break paragraph in blockLimit', '

foo[]bar

', '

foo

[]bar

' ); it( 'leaves one empty element after two were fully selected (backward)', () => { setData( model, '

[abc

def]

' ); // @TODO: Add option for setting selection direction to model utils. doc.selection._lastRangeBackward = true; command.execute(); expect( getData( model ) ).to.equal( '

[]

' ); } ); it( 'uses DataController.deleteContent', () => { const spy = sinon.spy(); editor.model.on( 'deleteContent', spy ); setData( model, '

[x]

' ); command.execute(); expect( spy.calledOnce ).to.be.true; } ); } ); function test( title, input, output ) { it( title, () => { setData( model, input ); command.execute(); expect( getData( model ) ).to.equal( output ); } ); } } ); } );