Bladeren bron

Added missing tests.

Kamil Piechaczek 7 jaren geleden
bovenliggende
commit
73ead43d65

+ 21 - 2
packages/ckeditor5-enter/src/shiftentercommand.js

@@ -37,6 +37,7 @@ export default class ShiftEnterCommand extends Command {
 // @param {module:engine/model/schema~Schema} schema
 // @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection
 function isEnabled( schema, selection ) {
+	// At this moment is okay with support single range selection but in the future we will need to change that.
 	if ( selection.rangeCount > 1 ) {
 		return false;
 	}
@@ -52,8 +53,8 @@ function isEnabled( schema, selection ) {
 	const startElement = range.start.parent;
 	const endElement = range.end.parent;
 
-	// If the selection contains at least two elements and one of them is the limit element, the soft enter shouldn't be enabled.
-	if ( ( schema.isLimit( startElement ) || schema.isLimit( endElement ) ) && startElement !== endElement ) {
+	// Do not modify the content if selection is cross-limit elements.
+	if ( ( isInsideLimitElement( startElement, schema ) || isInsideLimitElement( endElement, schema ) ) && startElement !== endElement ) {
 		return false;
 	}
 
@@ -98,3 +99,21 @@ function insertBreak( writer, position ) {
 	writer.insert( breakLineElement, position );
 	writer.setSelection( breakLineElement, 'after' );
 }
+
+// Checks whether specified `element` is a children of limit element.
+//
+// Checking whether the `<p>` element is inside a limit element:
+//   - <$root><p>Text.</p></$root> => false
+//   - <$root><limitElement><p>Text</p></limitElement></$root> => true
+//
+// @param {module:engine/model/element~Element} element
+// @param {module:engine/schema~Schema} schema
+// @returns {Boolean}
+function isInsideLimitElement( element, schema ) {
+	// `$root` is a limit element but in this case is an invalid element.
+	if ( element.is( 'rootElement') ) {
+		return false;
+	}
+
+	return schema.isLimit( element ) || isInsideLimitElement( element.parent, schema );
+}

+ 7 - 0
packages/ckeditor5-enter/tests/enter.js

@@ -6,6 +6,7 @@
 import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
 import Enter from '../src/enter';
 import EnterCommand from '../src/entercommand';
+import EnterObserver from '../src/enterobserver';
 import DomEventData from '@ckeditor/ckeditor5-engine/src/view/observer/domeventdata';
 
 describe( 'Enter feature', () => {
@@ -26,6 +27,12 @@ describe( 'Enter feature', () => {
 		expect( editor.commands.get( 'enter' ) ).to.be.instanceof( EnterCommand );
 	} );
 
+	it( 'registers the EnterObserver', () => {
+		const observer = editor.editing.view.getObserver( EnterObserver );
+
+		expect( observer ).to.be.an.instanceOf( EnterObserver );
+	} );
+
 	it( 'listens to the editing view enter event', () => {
 		const spy = editor.execute = sinon.spy();
 		const domEvt = getDomEvent();

+ 13 - 3
packages/ckeditor5-enter/tests/shiftenter-integration.js

@@ -10,12 +10,14 @@ import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor'
 import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
 import ShiftEnter from '../src/shiftenter';
 
-import { getData as getModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
+import { getData as getModelData, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';
 
 describe( 'ShiftEnter integration', () => {
 	let editor, model, div;
 
+	const options = { withoutSelection: true };
+
 	beforeEach( () => {
 		div = document.createElement( 'div' );
 		div.innerHTML = '<p>First line.<br>Second line.</p>';
@@ -32,13 +34,21 @@ describe( 'ShiftEnter integration', () => {
 
 	afterEach( () => {
 		div.remove();
+
 		return editor.destroy();
 	} );
 
 	it( 'loads correct data', () => {
-		const options = { withoutSelection: true };
-
 		expect( getModelData( model, options ) ).to.equal( '<paragraph>First line.<softBreak></softBreak>Second line.</paragraph>' );
 		expect( getViewData( editor.editing.view, options ) ).to.equal( '<p>First line.<br></br>Second line.</p>' );
 	} );
+
+	it( 'BLOCK_FILLER should be inserted after <br> in the paragraph', () => {
+		setModelData( model, '<paragraph>[]</paragraph>' );
+
+		editor.commands.get( 'shiftEnter' ).execute();
+
+		expect( editor.getData() ).to.equal( '<p><br>&nbsp;</p>' );
+		expect( editor.ui.view.editable.element.innerHTML ).to.equal( '<p><br><br data-cke-filler="true"></p>' );
+	} );
 } );

+ 7 - 0
packages/ckeditor5-enter/tests/shiftenter.js

@@ -6,6 +6,7 @@
 import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
 import ShiftEnter from '../src/shiftenter';
 import ShiftEnterCommand from '../src/shiftentercommand';
+import EnterObserver from '../src/enterobserver';
 import DomEventData from '@ckeditor/ckeditor5-engine/src/view/observer/domeventdata';
 
 describe( 'ShiftEnter feature', () => {
@@ -26,6 +27,12 @@ describe( 'ShiftEnter feature', () => {
 		expect( editor.commands.get( 'shiftEnter' ) ).to.be.instanceof( ShiftEnterCommand );
 	} );
 
+	it( 'registers the EnterObserver', () => {
+		const observer = editor.editing.view.getObserver( EnterObserver );
+
+		expect( observer ).to.be.an.instanceOf( EnterObserver );
+	} );
+
 	it( 'listens to the editing view enter event', () => {
 		const spy = editor.execute = sinon.spy();
 		const domEvt = getDomEvent();

+ 90 - 0
packages/ckeditor5-enter/tests/shiftentercommand.js

@@ -215,4 +215,94 @@ describe( 'ShiftEnterCommand', () => {
 			} );
 		}
 	} );
+
+	describe( '#isEnabled', () => {
+		test( 'should be disabled if $text cannot be inserted into element',
+			'<img>[]</img>',
+			false
+		);
+
+		test( 'should be enabled for collapsed selection in $root',
+			'Foo.',
+			true
+		);
+
+		test( 'should be enabled for collapsed selection in paragraph',
+			'<p>Foo.[]</p>',
+			true
+		);
+
+		test( 'should be enabled for collapsed selection in heading',
+			'<h>Foo.[]</h>',
+			true
+		);
+
+		test( 'should be enabled for collapsed selection in inline limit element',
+			'<p><inlineLimit>Foo.[]</inlineLimit></p>',
+			true
+		);
+
+		test( 'should be enabled for non-collapsed selection in inline limit element',
+			'<p><inlineLimit>[Foo.]</inlineLimit></p>',
+			true
+		);
+
+		test( 'should be enabled for collapsed selection in paragraph which is wrapped in the block limit element',
+			'<blockLimit><p>Foo.[]</p></blockLimit>',
+			true
+		);
+
+		test( 'should be enabled for non-collapsed selection in paragraph which is wrapped in the block limit element',
+			'<blockLimit><p>F[oo.]</p></blockLimit>',
+			true
+		);
+
+		test( 'should be enabled for non-collapsed selection in paragraphs',
+			'<p>[Foo.</p><p>Bar.]</p>',
+			true
+		);
+
+		test( 'should be enabled for non-collapsed selection in headings',
+			'<h>[Foo.</h><h>Bar.]</h>',
+			true
+		);
+
+		test( 'should be disabled for non-collapsed selection which starts in the inline limit element',
+			'<p><inlineLimit>F[oo.</inlineLimit>B]ar.</p>',
+			false
+		);
+
+		test( 'should be disabled for non-collapsed selection which end in the inline limit element',
+			'<p>F[oo<inlineLimit>Bar].</inlineLimit></p>',
+			false
+		);
+
+		test( 'should be disabled for non-collapsed selection which starts in element inside the block limit element',
+			'<blockLimit><p>F[oo.</p></blockLimit><p>B]ar.</p>',
+			false
+		);
+
+		test( 'should be disabled for non-collapsed selection which ends in element inside the block limit element',
+			'<p>Fo[o.</p><blockLimit><p>Bar].</p></blockLimit>',
+			false
+		);
+
+		test( 'should be disabled for multi-ranges selection (1)',
+			'<p>[x]</p><p>[foo]</p>',
+			false
+		);
+
+		test( 'should be disabled for multi-ranges selection (2)',
+			'<p>[]x</p><p>[]foo</p>',
+			false
+		);
+
+		function test( title, input, output ) {
+			it( title, () => {
+				setData( model, input );
+
+				expect( command.isEnabled ).to.equal( output );
+			} );
+		}
+	} );
 } );