8
0
Oskar Wrobel 9 лет назад
Родитель
Сommit
59575a2816

+ 49 - 47
packages/ckeditor5-core/tests/command/helpers/getschemavalidranges.js

@@ -9,51 +9,53 @@ import Text from '/ckeditor5/engine/model/text.js';
 import Element from '/ckeditor5/engine/model/element.js';
 import Element from '/ckeditor5/engine/model/element.js';
 import getSchemaValidRanges from '/ckeditor5/core/command/helpers/getschemavalidranges.js';
 import getSchemaValidRanges from '/ckeditor5/core/command/helpers/getschemavalidranges.js';
 
 
-const attribute = 'bold';
-let document, root, schema;
-
-beforeEach( () => {
-	document = new Document();
-	schema = document.schema;
-	root = document.createRoot();
-
-	schema.registerItem( 'p', '$block' );
-	schema.registerItem( 'h1', '$block' );
-	schema.registerItem( 'img', '$inline' );
-
-	// Allow bold on p
-	schema.allow( { name: '$text', attributes: 'bold', inside: 'p' } );
-	schema.allow( { name: 'p', attributes: 'bold', inside: '$root' } );
-
-	root.insertChildren( 0, [
-		new Element( 'p', [], [
-			new Text( 'foo' ),
-			new Element( 'img' ),
-			new Element( 'img' ),
-			new Text( 'bar' )
-		] )
-	] );
-} );
-
-it( 'should return unmodified ranges when attribute is allowed on each element', () => {
-	// Allow bold on img
-	schema.allow( { name: 'img', attributes: 'bold', inside: 'p' } );
-
-	const ranges = [ Range.createOn( root.getChild( 0 ) ) ];
-
-	expect( getSchemaValidRanges( attribute, ranges, schema ) ).to.deep.equal( ranges );
-} );
-
-it( 'should split range into two ranges and omit disallowed elements', () => {
-	// Disallow bold on img.
-	document.schema.disallow( { name: 'img', attributes: 'bold', inside: 'p' } );
-
-	const ranges = [ Range.createOn( root.getChild( 0 ) ) ];
-	const result = getSchemaValidRanges( attribute, ranges, schema );
-
-	expect( result ).to.length( 2 );
-	expect( result[ 0 ].start.path ).to.members( [ 0 ] );
-	expect( result[ 0 ].end.path ).to.members( [ 0, 3 ] );
-	expect( result[ 1 ].start.path ) .to.members( [ 0, 5 ] );
-	expect( result[ 1 ].end.path ).to.members( [ 1 ] );
+describe( 'getSchemaValidRanges', () => {
+	const attribute = 'bold';
+	let document, root, schema;
+
+	beforeEach( () => {
+		document = new Document();
+		schema = document.schema;
+		root = document.createRoot();
+
+		schema.registerItem( 'p', '$block' );
+		schema.registerItem( 'h1', '$block' );
+		schema.registerItem( 'img', '$inline' );
+
+		// Allow bold on p
+		schema.allow( { name: '$text', attributes: 'bold', inside: 'p' } );
+		schema.allow( { name: 'p', attributes: 'bold', inside: '$root' } );
+
+		root.insertChildren( 0, [
+			new Element( 'p', [], [
+				new Text( 'foo' ),
+				new Element( 'img' ),
+				new Element( 'img' ),
+				new Text( 'bar' )
+			] )
+		] );
+	} );
+
+	it( 'should return unmodified ranges when attribute is allowed on each element', () => {
+		// Allow bold on img
+		schema.allow( { name: 'img', attributes: 'bold', inside: 'p' } );
+
+		const ranges = [ Range.createOn( root.getChild( 0 ) ) ];
+
+		expect( getSchemaValidRanges( attribute, ranges, schema ) ).to.deep.equal( ranges );
+	} );
+
+	it( 'should split range into two ranges and omit disallowed elements', () => {
+		// Disallow bold on img.
+		document.schema.disallow( { name: 'img', attributes: 'bold', inside: 'p' } );
+
+		const ranges = [ Range.createOn( root.getChild( 0 ) ) ];
+		const result = getSchemaValidRanges( attribute, ranges, schema );
+
+		expect( result ).to.length( 2 );
+		expect( result[ 0 ].start.path ).to.members( [ 0 ] );
+		expect( result[ 0 ].end.path ).to.members( [ 0, 3 ] );
+		expect( result[ 1 ].start.path ).to.members( [ 0, 5 ] );
+		expect( result[ 1 ].end.path ).to.members( [ 1 ] );
+	} );
 } );
 } );

+ 68 - 66
packages/ckeditor5-core/tests/command/helpers/isattributeallowedinselection.js

@@ -10,77 +10,79 @@ import Text from '/ckeditor5/engine/model/text.js';
 import Element from '/ckeditor5/engine/model/element.js';
 import Element from '/ckeditor5/engine/model/element.js';
 import isAttributeAllowedInSelection from '/ckeditor5/core/command/helpers/isattributeallowedinselection.js';
 import isAttributeAllowedInSelection from '/ckeditor5/core/command/helpers/isattributeallowedinselection.js';
 
 
-const attribute = 'bold';
-let document, root;
-
-beforeEach( () => {
-	document = new Document();
-	root = document.createRoot();
-
-	document.schema.registerItem( 'p', '$block' );
-	document.schema.registerItem( 'h1', '$block' );
-	document.schema.registerItem( 'img', '$inline' );
-
-	// Bold text is allowed only in P.
-	document.schema.allow( { name: '$text', attributes: 'bold', inside: 'p' } );
-	document.schema.allow( { name: 'p', attributes: 'bold', inside: '$root' } );
-
-	// Disallow bold on image.
-	document.schema.disallow( { name: 'img', attributes: 'bold', inside: '$root' } );
-
-	root.insertChildren( 0, [
-		new Element( 'p', [], [
-			new Text( 'foo' ),
-			new Element( 'img' ),
-			new Element( 'img' ),
-			new Text( 'bar' )
-		] ),
-		new Element( 'h1' ),
-		new Element( 'p' )
-	] );
-} );
-
-describe( 'when selection is collapsed', () => {
-	it( 'should return true if characters with the attribute can be placed at caret position', () => {
-		document.selection.setRanges( [ new Range( new Position( root, [ 0, 1 ] ), new Position( root, [ 0, 1 ] ) ) ] );
-		expect( isAttributeAllowedInSelection( attribute, document.selection, document.schema ) ).to.be.true;
-	} );
-
-	it( 'should return false if characters with the attribute cannot be placed at caret position', () => {
-		document.selection.setRanges( [ new Range( new Position( root, [ 1, 0 ] ), new Position( root, [ 1, 0 ] ) ) ] );
-		expect( isAttributeAllowedInSelection( attribute, document.selection, document.schema ) ).to.be.false;
-
-		document.selection.setRanges( [ new Range( new Position( root, [ 2 ] ), new Position( root, [ 2 ] ) ) ] );
-		expect( isAttributeAllowedInSelection( attribute, document.selection, document.schema ) ).to.be.false;
+describe( 'isAttributeAllowedInSelection', () => {
+	const attribute = 'bold';
+	let document, root;
+
+	beforeEach( () => {
+		document = new Document();
+		root = document.createRoot();
+
+		document.schema.registerItem( 'p', '$block' );
+		document.schema.registerItem( 'h1', '$block' );
+		document.schema.registerItem( 'img', '$inline' );
+
+		// Bold text is allowed only in P.
+		document.schema.allow( { name: '$text', attributes: 'bold', inside: 'p' } );
+		document.schema.allow( { name: 'p', attributes: 'bold', inside: '$root' } );
+
+		// Disallow bold on image.
+		document.schema.disallow( { name: 'img', attributes: 'bold', inside: '$root' } );
+
+		root.insertChildren( 0, [
+			new Element( 'p', [], [
+				new Text( 'foo' ),
+				new Element( 'img' ),
+				new Element( 'img' ),
+				new Text( 'bar' )
+			] ),
+			new Element( 'h1' ),
+			new Element( 'p' )
+		] );
 	} );
 	} );
-} );
 
 
-describe( 'when selection is not collapsed', () => {
-	it( 'should return true if there is at least one node in selection that can have the attribute', () => {
-		// Simple selection on a few characters.
-		document.selection.setRanges( [ new Range( new Position( root, [ 0, 0 ] ), new Position( root, [ 0, 3 ] ) ) ] );
-		expect( isAttributeAllowedInSelection( attribute, document.selection, document.schema ) ).to.be.true;
+	describe( 'when selection is collapsed', () => {
+		it( 'should return true if characters with the attribute can be placed at caret position', () => {
+			document.selection.setRanges( [ new Range( new Position( root, [ 0, 1 ] ), new Position( root, [ 0, 1 ] ) ) ] );
+			expect( isAttributeAllowedInSelection( attribute, document.selection, document.schema ) ).to.be.true;
+		} );
 
 
-		// Selection spans over characters but also include nodes that can't have attribute.
-		document.selection.setRanges( [ new Range( new Position( root, [ 0, 2 ] ), new Position( root, [ 0, 6 ] ) ) ] );
-		expect( isAttributeAllowedInSelection( attribute, document.selection, document.schema ) ).to.be.true;
+		it( 'should return false if characters with the attribute cannot be placed at caret position', () => {
+			document.selection.setRanges( [ new Range( new Position( root, [ 1, 0 ] ), new Position( root, [ 1, 0 ] ) ) ] );
+			expect( isAttributeAllowedInSelection( attribute, document.selection, document.schema ) ).to.be.false;
 
 
-		// Selection on whole root content. Characters in P can have an attribute so it's valid.
-		document.selection.setRanges( [ new Range( new Position( root, [ 0 ] ), new Position( root, [ 3 ] ) ) ] );
-		expect( isAttributeAllowedInSelection( attribute, document.selection, document.schema ) ).to.be.true;
-
-		// Selection on empty P. P can have the attribute.
-		document.selection.setRanges( [ new Range( new Position( root, [ 2 ] ), new Position( root, [ 3 ] ) ) ] );
-		expect( isAttributeAllowedInSelection( attribute, document.selection, document.schema ) ).to.be.true;
+			document.selection.setRanges( [ new Range( new Position( root, [ 2 ] ), new Position( root, [ 2 ] ) ) ] );
+			expect( isAttributeAllowedInSelection( attribute, document.selection, document.schema ) ).to.be.false;
+		} );
 	} );
 	} );
 
 
-	it( 'should return false if there are no nodes in selection that can have the attribute', () => {
-		// Selection on DIV which can't have bold text.
-		document.selection.setRanges( [ new Range( new Position( root, [ 1 ] ), new Position( root, [ 2 ] ) ) ] );
-		expect( isAttributeAllowedInSelection( attribute, document.selection, document.schema ) ).to.be.false;
-
-		// Selection on two images which can't be bold.
-		document.selection.setRanges( [ new Range( new Position( root, [ 0, 3 ] ), new Position( root, [ 0, 5 ] ) ) ] );
-		expect( isAttributeAllowedInSelection( attribute, document.selection, document.schema ) ).to.be.false;
+	describe( 'when selection is not collapsed', () => {
+		it( 'should return true if there is at least one node in selection that can have the attribute', () => {
+			// Simple selection on a few characters.
+			document.selection.setRanges( [ new Range( new Position( root, [ 0, 0 ] ), new Position( root, [ 0, 3 ] ) ) ] );
+			expect( isAttributeAllowedInSelection( attribute, document.selection, document.schema ) ).to.be.true;
+
+			// Selection spans over characters but also include nodes that can't have attribute.
+			document.selection.setRanges( [ new Range( new Position( root, [ 0, 2 ] ), new Position( root, [ 0, 6 ] ) ) ] );
+			expect( isAttributeAllowedInSelection( attribute, document.selection, document.schema ) ).to.be.true;
+
+			// Selection on whole root content. Characters in P can have an attribute so it's valid.
+			document.selection.setRanges( [ new Range( new Position( root, [ 0 ] ), new Position( root, [ 3 ] ) ) ] );
+			expect( isAttributeAllowedInSelection( attribute, document.selection, document.schema ) ).to.be.true;
+
+			// Selection on empty P. P can have the attribute.
+			document.selection.setRanges( [ new Range( new Position( root, [ 2 ] ), new Position( root, [ 3 ] ) ) ] );
+			expect( isAttributeAllowedInSelection( attribute, document.selection, document.schema ) ).to.be.true;
+		} );
+
+		it( 'should return false if there are no nodes in selection that can have the attribute', () => {
+			// Selection on DIV which can't have bold text.
+			document.selection.setRanges( [ new Range( new Position( root, [ 1 ] ), new Position( root, [ 2 ] ) ) ] );
+			expect( isAttributeAllowedInSelection( attribute, document.selection, document.schema ) ).to.be.false;
+
+			// Selection on two images which can't be bold.
+			document.selection.setRanges( [ new Range( new Position( root, [ 0, 3 ] ), new Position( root, [ 0, 5 ] ) ) ] );
+			expect( isAttributeAllowedInSelection( attribute, document.selection, document.schema ) ).to.be.false;
+		} );
 	} );
 	} );
 } );
 } );

+ 178 - 177
packages/ckeditor5-core/tests/command/toggleattributecommand.js

@@ -13,252 +13,253 @@ import Element from '/ckeditor5/engine/model/element.js';
 import writer from '/ckeditor5/engine/model/writer.js';
 import writer from '/ckeditor5/engine/model/writer.js';
 import { itemAt } from '/tests/engine/model/_utils/utils.js';
 import { itemAt } from '/tests/engine/model/_utils/utils.js';
 
 
-let editor, command, modelDoc, root;
+describe( 'ToggleAttributeCommand', () => {
+	const attrKey = 'bold';
+	let editor, command, modelDoc, root;
 
 
-const attrKey = 'bold';
-
-beforeEach( () => {
-	editor = new Editor();
-	editor.document = new Document();
-
-	modelDoc = editor.document;
-	root = modelDoc.createRoot();
-
-	command = new ToggleAttributeCommand( editor, attrKey );
+	beforeEach( () => {
+		editor = new Editor();
+		editor.document = new Document();
 
 
-	modelDoc.schema.registerItem( 'p', '$block' );
-	modelDoc.schema.registerItem( 'h1', '$block' );
-	modelDoc.schema.registerItem( 'img', '$inline' );
+		modelDoc = editor.document;
+		root = modelDoc.createRoot();
 
 
-	// Allow block in "root" (DIV)
-	modelDoc.schema.allow( { name: '$block', inside: '$root' } );
+		command = new ToggleAttributeCommand( editor, attrKey );
 
 
-	// Bold text is allowed only in P.
-	modelDoc.schema.allow( { name: '$text', attributes: 'bold', inside: 'p' } );
-	modelDoc.schema.allow( { name: 'p', attributes: 'bold', inside: '$root' } );
+		modelDoc.schema.registerItem( 'p', '$block' );
+		modelDoc.schema.registerItem( 'h1', '$block' );
+		modelDoc.schema.registerItem( 'img', '$inline' );
 
 
-	// Disallow bold on image.
-	modelDoc.schema.disallow( { name: 'img', attributes: 'bold', inside: '$root' } );
-} );
+		// Allow block in "root" (DIV)
+		modelDoc.schema.allow( { name: '$block', inside: '$root' } );
 
 
-afterEach( () => {
-	command.destroy();
-} );
+		// Bold text is allowed only in P.
+		modelDoc.schema.allow( { name: '$text', attributes: 'bold', inside: 'p' } );
+		modelDoc.schema.allow( { name: 'p', attributes: 'bold', inside: '$root' } );
 
 
-describe( 'value', () => {
-	it( 'should be set to true or false basing on selection attribute', () => {
-		modelDoc.selection.setAttribute( attrKey, true );
-		expect( command.value ).to.be.true;
+		// Disallow bold on image.
+		modelDoc.schema.disallow( { name: 'img', attributes: 'bold', inside: '$root' } );
+	} );
 
 
-		modelDoc.selection.removeAttribute( attrKey );
-		expect( command.value ).to.be.false;
+	afterEach( () => {
+		command.destroy();
 	} );
 	} );
-} );
 
 
-describe( '_doExecute', () => {
-	let p;
+	describe( 'value', () => {
+		it( 'should be set to true or false basing on selection attribute', () => {
+			modelDoc.selection.setAttribute( attrKey, true );
+			expect( command.value ).to.be.true;
 
 
-	beforeEach( () => {
-		let attrs = {};
-		attrs[ attrKey ] = true;
-
-		root.insertChildren( 0, [
-			new Element( 'p', [] , [
-				new Text( 'abc' ),
-				new Text( 'foobar', attrs ),
-				new Text( 'xyz' )
-			] ),
-			new Element( 'p' )
-		] );
-
-		p = root.getChild( 0 );
+			modelDoc.selection.removeAttribute( attrKey );
+			expect( command.value ).to.be.false;
+		} );
 	} );
 	} );
 
 
-	it( 'should add attribute on selected nodes if the command value was false', () => {
-		modelDoc.selection.addRange( new Range( new Position( root, [ 0, 1 ] ), new Position( root, [ 0, 5 ] ) ) );
+	describe( '_doExecute', () => {
+		let p;
 
 
-		expect( command.value ).to.be.false;
+		beforeEach( () => {
+			let attrs = {};
+			attrs[ attrKey ] = true;
 
 
-		command._doExecute();
+			root.insertChildren( 0, [
+				new Element( 'p', [], [
+					new Text( 'abc' ),
+					new Text( 'foobar', attrs ),
+					new Text( 'xyz' )
+				] ),
+				new Element( 'p' )
+			] );
 
 
-		expect( command.value ).to.be.true;
+			p = root.getChild( 0 );
+		} );
 
 
-		expect( p.getChild( 0 ).hasAttribute( attrKey ) ).to.be.false;
-		expect( itemAt( p, 1 ).hasAttribute( attrKey ) ).to.be.true;
-		expect( itemAt( p, 2 ).hasAttribute( attrKey ) ).to.be.true;
-	} );
+		it( 'should add attribute on selected nodes if the command value was false', () => {
+			modelDoc.selection.addRange( new Range( new Position( root, [ 0, 1 ] ), new Position( root, [ 0, 5 ] ) ) );
 
 
-	it( 'should remove attribute from selected nodes if the command value was true', () => {
-		modelDoc.selection.addRange( new Range( new Position( root, [ 0, 3 ] ), new Position( root, [ 0, 6 ] ) ) );
+			expect( command.value ).to.be.false;
 
 
-		expect( command.value ).to.be.true;
+			command._doExecute();
 
 
-		command._doExecute();
+			expect( command.value ).to.be.true;
 
 
-		expect( command.value ).to.be.false;
-		expect( itemAt( p, 3 ).hasAttribute( attrKey ) ).to.be.false;
-		expect( itemAt( p, 4 ).hasAttribute( attrKey ) ).to.be.false;
-		expect( itemAt( p, 5 ).hasAttribute( attrKey ) ).to.be.false;
-	} );
+			expect( p.getChild( 0 ).hasAttribute( attrKey ) ).to.be.false;
+			expect( itemAt( p, 1 ).hasAttribute( attrKey ) ).to.be.true;
+			expect( itemAt( p, 2 ).hasAttribute( attrKey ) ).to.be.true;
+		} );
 
 
-	it( 'should add attribute on selected nodes if execute parameter was set to true', () => {
-		modelDoc.selection.addRange( new Range( new Position( root, [ 0, 7 ] ), new Position( root, [ 0, 10 ] ) ) );
+		it( 'should remove attribute from selected nodes if the command value was true', () => {
+			modelDoc.selection.addRange( new Range( new Position( root, [ 0, 3 ] ), new Position( root, [ 0, 6 ] ) ) );
 
 
-		expect( command.value ).to.be.true;
+			expect( command.value ).to.be.true;
 
 
-		command._doExecute( true );
+			command._doExecute();
 
 
-		expect( command.value ).to.be.true;
-		expect( itemAt( p, 9 ).hasAttribute( attrKey ) ).to.be.true;
-	} );
+			expect( command.value ).to.be.false;
+			expect( itemAt( p, 3 ).hasAttribute( attrKey ) ).to.be.false;
+			expect( itemAt( p, 4 ).hasAttribute( attrKey ) ).to.be.false;
+			expect( itemAt( p, 5 ).hasAttribute( attrKey ) ).to.be.false;
+		} );
 
 
-	it( 'should remove attribute on selected nodes if execute parameter was set to false', () => {
-		modelDoc.selection.addRange( new Range( new Position( root, [ 0, 1 ] ), new Position( root, [ 0, 5 ] ) ) );
+		it( 'should add attribute on selected nodes if execute parameter was set to true', () => {
+			modelDoc.selection.addRange( new Range( new Position( root, [ 0, 7 ] ), new Position( root, [ 0, 10 ] ) ) );
 
 
-		expect( command.value ).to.be.false;
+			expect( command.value ).to.be.true;
 
 
-		command._doExecute( false );
+			command._doExecute( true );
 
 
-		expect( command.value ).to.be.false;
-		expect( itemAt( p, 3 ).hasAttribute( attrKey ) ).to.be.false;
-		expect( itemAt( p, 4 ).hasAttribute( attrKey ) ).to.be.false;
-	} );
+			expect( command.value ).to.be.true;
+			expect( itemAt( p, 9 ).hasAttribute( attrKey ) ).to.be.true;
+		} );
 
 
-	it( 'should change selection attribute if selection is collapsed in non-empty parent', () => {
-		modelDoc.selection.addRange( new Range( new Position( root, [ 0, 1 ] ), new Position( root, [ 0, 1 ] ) ) );
+		it( 'should remove attribute on selected nodes if execute parameter was set to false', () => {
+			modelDoc.selection.addRange( new Range( new Position( root, [ 0, 1 ] ), new Position( root, [ 0, 5 ] ) ) );
 
 
-		expect( command.value ).to.be.false;
+			expect( command.value ).to.be.false;
 
 
-		command._doExecute();
+			command._doExecute( false );
 
 
-		expect( command.value ).to.be.true;
-		expect( modelDoc.selection.hasAttribute( 'bold' ) ).to.be.true;
+			expect( command.value ).to.be.false;
+			expect( itemAt( p, 3 ).hasAttribute( attrKey ) ).to.be.false;
+			expect( itemAt( p, 4 ).hasAttribute( attrKey ) ).to.be.false;
+		} );
 
 
-		command._doExecute();
+		it( 'should change selection attribute if selection is collapsed in non-empty parent', () => {
+			modelDoc.selection.addRange( new Range( new Position( root, [ 0, 1 ] ), new Position( root, [ 0, 1 ] ) ) );
 
 
-		expect( command.value ).to.be.false;
-		expect( modelDoc.selection.hasAttribute( 'bold' ) ).to.be.false;
-	} );
+			expect( command.value ).to.be.false;
 
 
-	it( 'should not store attribute change on selection if selection is collapsed in non-empty parent', () => {
-		modelDoc.selection.addRange( new Range( new Position( root, [ 0, 1 ] ), new Position( root, [ 0, 1 ] ) ) );
-		command._doExecute();
+			command._doExecute();
 
 
-		// It should not save that bold was executed at position ( root, [ 0, 1 ] ).
+			expect( command.value ).to.be.true;
+			expect( modelDoc.selection.hasAttribute( 'bold' ) ).to.be.true;
 
 
-		// Simulate clicking right arrow key by changing selection ranges.
-		modelDoc.selection.setRanges( [ new Range( new Position( root, [ 0, 2 ] ), new Position( root, [ 0, 2 ] ) ) ] );
+			command._doExecute();
 
 
-		// Get back to previous selection.
-		modelDoc.selection.setRanges( [ new Range( new Position( root, [ 0, 1 ] ), new Position( root, [ 0, 1 ] ) ) ] );
+			expect( command.value ).to.be.false;
+			expect( modelDoc.selection.hasAttribute( 'bold' ) ).to.be.false;
+		} );
 
 
-		expect( command.value ).to.be.false;
-	} );
+		it( 'should not store attribute change on selection if selection is collapsed in non-empty parent', () => {
+			modelDoc.selection.addRange( new Range( new Position( root, [ 0, 1 ] ), new Position( root, [ 0, 1 ] ) ) );
+			command._doExecute();
 
 
-	it( 'should change selection attribute and store it if selection is collapsed in empty parent', () => {
-		modelDoc.selection.setRanges( [ new Range( new Position( root, [ 1, 0 ] ), new Position( root, [ 1, 0 ] ) ) ] );
+			// It should not save that bold was executed at position ( root, [ 0, 1 ] ).
 
 
-		expect( command.value ).to.be.false;
+			// Simulate clicking right arrow key by changing selection ranges.
+			modelDoc.selection.setRanges( [ new Range( new Position( root, [ 0, 2 ] ), new Position( root, [ 0, 2 ] ) ) ] );
 
 
-		command._doExecute();
+			// Get back to previous selection.
+			modelDoc.selection.setRanges( [ new Range( new Position( root, [ 0, 1 ] ), new Position( root, [ 0, 1 ] ) ) ] );
 
 
-		expect( command.value ).to.be.true;
-		expect( modelDoc.selection.hasAttribute( 'bold' ) ).to.be.true;
+			expect( command.value ).to.be.false;
+		} );
 
 
-		// Attribute should be stored.
-		// Simulate clicking somewhere else in the editor.
-		modelDoc.selection.setRanges( [ new Range( new Position( root, [ 0, 2 ] ), new Position( root, [ 0, 2 ] ) ) ] );
+		it( 'should change selection attribute and store it if selection is collapsed in empty parent', () => {
+			modelDoc.selection.setRanges( [ new Range( new Position( root, [ 1, 0 ] ), new Position( root, [ 1, 0 ] ) ) ] );
 
 
-		expect( command.value ).to.be.false;
+			expect( command.value ).to.be.false;
 
 
-		// Go back to where attribute was stored.
-		modelDoc.selection.setRanges( [ new Range( new Position( root, [ 1, 0 ] ), new Position( root, [ 1, 0 ] ) ) ] );
+			command._doExecute();
 
 
-		// Attribute should be restored.
-		expect( command.value ).to.be.true;
+			expect( command.value ).to.be.true;
+			expect( modelDoc.selection.hasAttribute( 'bold' ) ).to.be.true;
 
 
-		command._doExecute();
+			// Attribute should be stored.
+			// Simulate clicking somewhere else in the editor.
+			modelDoc.selection.setRanges( [ new Range( new Position( root, [ 0, 2 ] ), new Position( root, [ 0, 2 ] ) ) ] );
 
 
-		expect( command.value ).to.be.false;
-		expect( modelDoc.selection.hasAttribute( 'bold' ) ).to.be.false;
-	} );
+			expect( command.value ).to.be.false;
 
 
-	it( 'should not apply attribute change where it would invalid schema', () => {
-		writer.insert( Position.createFromParentAndOffset( p, 3 ), new Element( 'image' ) );
-		writer.insert( Position.createFromParentAndOffset( p, 12 ), new Element( 'image' ) );
+			// Go back to where attribute was stored.
+			modelDoc.selection.setRanges( [ new Range( new Position( root, [ 1, 0 ] ), new Position( root, [ 1, 0 ] ) ) ] );
 
 
-		modelDoc.selection.setRanges( [ new Range( new Position( root, [ 0, 2 ] ), new Position( root, [ 0, 13 ] ) ) ] );
+			// Attribute should be restored.
+			expect( command.value ).to.be.true;
 
 
-		expect( command.isEnabled ).to.be.true;
+			command._doExecute();
 
 
-		command._doExecute();
+			expect( command.value ).to.be.false;
+			expect( modelDoc.selection.hasAttribute( 'bold' ) ).to.be.false;
+		} );
 
 
-		let expectedHas = [ 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 ];
+		it( 'should not apply attribute change where it would invalid schema', () => {
+			writer.insert( Position.createFromParentAndOffset( p, 3 ), new Element( 'image' ) );
+			writer.insert( Position.createFromParentAndOffset( p, 12 ), new Element( 'image' ) );
 
 
-		let i = 0;
+			modelDoc.selection.setRanges( [ new Range( new Position( root, [ 0, 2 ] ), new Position( root, [ 0, 13 ] ) ) ] );
 
 
-		for ( let node of Range.createIn( p ).getItems( { singleCharacters: true } ) ) {
-			expect( node.hasAttribute( attrKey ) ).to.equal( !!expectedHas[ i++ ] );
-		}
-	} );
-} );
+			expect( command.isEnabled ).to.be.true;
 
 
-describe( '_checkEnabled', () => {
-	beforeEach( () => {
-		root.insertChildren( 0, [
-			new Element( 'p', [], [
-				new Text( 'foo' ),
-				new Element( 'img' ),
-				new Element( 'img' ),
-				new Text( 'bar' )
-			] ),
-			new Element( 'h1' ),
-			new Element( 'p' )
-		] );
-	} );
+			command._doExecute();
 
 
-	describe( 'when selection is collapsed', () => {
-		it( 'should return true if characters with the attribute can be placed at caret position', () => {
-			modelDoc.selection.setRanges( [ new Range( new Position( root, [ 0, 1 ] ), new Position( root, [ 0, 1 ] ) ) ] );
-			expect( command._checkEnabled() ).to.be.true;
-		} );
+			let expectedHas = [ 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 ];
 
 
-		it( 'should return false if characters with the attribute cannot be placed at caret position', () => {
-			modelDoc.selection.setRanges( [ new Range( new Position( root, [ 1, 0 ] ), new Position( root, [ 1, 0 ] ) ) ] );
-			expect( command._checkEnabled() ).to.be.false;
+			let i = 0;
 
 
-			modelDoc.selection.setRanges( [ new Range( new Position( root, [ 2 ] ), new Position( root, [ 2 ] ) ) ] );
-			expect( command._checkEnabled() ).to.be.false;
+			for ( let node of Range.createIn( p ).getItems( { singleCharacters: true } ) ) {
+				expect( node.hasAttribute( attrKey ) ).to.equal( !!expectedHas[ i++ ] );
+			}
 		} );
 		} );
 	} );
 	} );
 
 
-	describe( 'when selection is not collapsed', () => {
-		it( 'should return true if there is at least one node in selection that can have the attribute', () => {
-			// Simple selection on a few characters.
-			modelDoc.selection.setRanges( [ new Range( new Position( root, [ 0, 0 ] ), new Position( root, [ 0, 3 ] ) ) ] );
-			expect( command._checkEnabled() ).to.be.true;
+	describe( '_checkEnabled', () => {
+		beforeEach( () => {
+			root.insertChildren( 0, [
+				new Element( 'p', [], [
+					new Text( 'foo' ),
+					new Element( 'img' ),
+					new Element( 'img' ),
+					new Text( 'bar' )
+				] ),
+				new Element( 'h1' ),
+				new Element( 'p' )
+			] );
+		} );
 
 
-			// Selection spans over characters but also include nodes that can't have attribute.
-			modelDoc.selection.setRanges( [ new Range( new Position( root, [ 0, 2 ] ), new Position( root, [ 0, 6 ] ) ) ] );
-			expect( command._checkEnabled() ).to.be.true;
+		describe( 'when selection is collapsed', () => {
+			it( 'should return true if characters with the attribute can be placed at caret position', () => {
+				modelDoc.selection.setRanges( [ new Range( new Position( root, [ 0, 1 ] ), new Position( root, [ 0, 1 ] ) ) ] );
+				expect( command._checkEnabled() ).to.be.true;
+			} );
 
 
-			// Selection on whole root content. Characters in P can have an attribute so it's valid.
-			modelDoc.selection.setRanges( [ new Range( new Position( root, [ 0 ] ), new Position( root, [ 3 ] ) ) ] );
-			expect( command._checkEnabled() ).to.be.true;
+			it( 'should return false if characters with the attribute cannot be placed at caret position', () => {
+				modelDoc.selection.setRanges( [ new Range( new Position( root, [ 1, 0 ] ), new Position( root, [ 1, 0 ] ) ) ] );
+				expect( command._checkEnabled() ).to.be.false;
 
 
-			// Selection on empty P. P can have the attribute.
-			modelDoc.selection.setRanges( [ new Range( new Position( root, [ 2 ] ), new Position( root, [ 3 ] ) ) ] );
-			expect( command._checkEnabled() ).to.be.true;
+				modelDoc.selection.setRanges( [ new Range( new Position( root, [ 2 ] ), new Position( root, [ 2 ] ) ) ] );
+				expect( command._checkEnabled() ).to.be.false;
+			} );
 		} );
 		} );
 
 
-		it( 'should return false if there are no nodes in selection that can have the attribute', () => {
-			// Selection on DIV which can't have bold text.
-			modelDoc.selection.setRanges( [ new Range( new Position( root, [ 1 ] ), new Position( root, [ 2 ] ) ) ] );
-			expect( command._checkEnabled() ).to.be.false;
-
-			// Selection on two images which can't be bold.
-			modelDoc.selection.setRanges( [ new Range( new Position( root, [ 0, 3 ] ), new Position( root, [ 0, 5 ] ) ) ] );
-			expect( command._checkEnabled() ).to.be.false;
+		describe( 'when selection is not collapsed', () => {
+			it( 'should return true if there is at least one node in selection that can have the attribute', () => {
+				// Simple selection on a few characters.
+				modelDoc.selection.setRanges( [ new Range( new Position( root, [ 0, 0 ] ), new Position( root, [ 0, 3 ] ) ) ] );
+				expect( command._checkEnabled() ).to.be.true;
+
+				// Selection spans over characters but also include nodes that can't have attribute.
+				modelDoc.selection.setRanges( [ new Range( new Position( root, [ 0, 2 ] ), new Position( root, [ 0, 6 ] ) ) ] );
+				expect( command._checkEnabled() ).to.be.true;
+
+				// Selection on whole root content. Characters in P can have an attribute so it's valid.
+				modelDoc.selection.setRanges( [ new Range( new Position( root, [ 0 ] ), new Position( root, [ 3 ] ) ) ] );
+				expect( command._checkEnabled() ).to.be.true;
+
+				// Selection on empty P. P can have the attribute.
+				modelDoc.selection.setRanges( [ new Range( new Position( root, [ 2 ] ), new Position( root, [ 3 ] ) ) ] );
+				expect( command._checkEnabled() ).to.be.true;
+			} );
+
+			it( 'should return false if there are no nodes in selection that can have the attribute', () => {
+				// Selection on DIV which can't have bold text.
+				modelDoc.selection.setRanges( [ new Range( new Position( root, [ 1 ] ), new Position( root, [ 2 ] ) ) ] );
+				expect( command._checkEnabled() ).to.be.false;
+
+				// Selection on two images which can't be bold.
+				modelDoc.selection.setRanges( [ new Range( new Position( root, [ 0, 3 ] ), new Position( root, [ 0, 5 ] ) ) ] );
+				expect( command._checkEnabled() ).to.be.false;
+			} );
 		} );
 		} );
 	} );
 	} );
 } );
 } );