Browse Source

Merge pull request #99 from ckeditor/t/ckeditor5-alignment/16

Other: Update naming of UI components & commands.

BREAKING CHANGE: Renamed the `'headings'` dropdown UI component to `'heading'`.
BREAKING CHANGE: The `'heading1'`, `'heading2'` and `'heading3'` commands are no longer available. They were replaced by the `'heading'` command that accepts heading model element name as a value.
BREAKING CHANGE: The `HeadingCommand#value` is no longer a boolean only. Now it stores a name of the heading model element when selection is inside a heading.
BREAKING CHANGE: The `HeadingCommand` constructor's second parameter is now an array of supported model elements.
Piotrek Koszuliński 7 years ago
parent
commit
0a8e7c0bd1

+ 4 - 4
packages/ckeditor5-heading/docs/features/headings.md

@@ -122,7 +122,7 @@ import Heading from '@ckeditor/ckeditor5-heading/src/heading';
 ClassicEditor
 	.create( document.querySelector( '#editor' ), {
 		plugins: [ Heading, ... ],
-		toolbar: [ 'headings', ... ]
+		toolbar: [ 'heading', ... ]
 	} )
 	.then( ... )
 	.catch( ... );
@@ -132,13 +132,13 @@ ClassicEditor
 
 The {@link module:heading/heading~Heading} plugin registers:
 
-* The `'headings'` dropdown.
-* The `'heading1'`, `'heading2'`, ..., `'headingN'` commands based on the {@link module:heading/heading~HeadingConfig#options `heading.options`} configuration option.
+* The `'heading'` dropdown.
+* The `'heading'` command that accepts value based on the {@link module:heading/heading~HeadingConfig#options `heading.options`} configuration option.
 
 	You can turn the currently selected block(s) to headings by executing one of these commands:
 
 	```js
-	editor.execute( 'heading2' );
+	editor.execute( 'heading', { value: 'heading2' } );
 	```
 
 ## Contribute

+ 2 - 2
packages/ckeditor5-heading/src/heading.js

@@ -95,10 +95,10 @@ export default class Heading extends Plugin {
  * That's assumption is used by features like {@link module:autoformat/autoformat~Autoformat} to know which element
  * they should use when applying the first level heading.
  *
- * The defined headings are also available in {@link module:core/commandcollection~CommandCollection} under their model names.
+ * The defined headings are also available as values passed to `heading` command under their model names.
  * For example, the below code will apply `<heading1>` to the current selection:
  *
- *		editor.execute( 'heading1' );
+ *		editor.execute( 'heading', { value: 'heading1' } );
  *
  * @member {Array.<module:heading/heading~HeadingOption>} module:heading/heading~HeadingConfig#options
  */

+ 23 - 13
packages/ckeditor5-heading/src/headingcommand.js

@@ -20,27 +20,29 @@ export default class HeadingCommand extends Command {
 	 * Creates an instance of the command.
 	 *
 	 * @param {module:core/editor/editor~Editor} editor Editor instance.
-	 * @param {String} modelElement Name of the element which this command will apply in the model.
+	 * @param {Array.<String>} modelElements Names of the element which this command can apply in the model.
 	 */
-	constructor( editor, modelElement ) {
+	constructor( editor, modelElements ) {
 		super( editor );
 
 		/**
-		 * Whether the selection starts in a heading of {@link #modelElement this level}.
+		 * If the selection starts in a heading (which {@link #modelElements is supported by this command})
+		 * the value is set to the name of that heading model element.
+		 * It is  set to `false` otherwise.
 		 *
 		 * @observable
 		 * @readonly
-		 * @member {Boolean} #value
+		 * @member {Boolean|String} #value
 		 */
 
 		/**
-		 * Unique identifier of the command, also element's name in the model.
+		 * Set of defined model's elements names that this command support.
 		 * See {@link module:heading/heading~HeadingOption}.
 		 *
 		 * @readonly
-		 * @member {String}
+		 * @member {Array.<String>}
 		 */
-		this.modelElement = modelElement;
+		this.modelElements = modelElements;
 	}
 
 	/**
@@ -49,29 +51,37 @@ export default class HeadingCommand extends Command {
 	refresh() {
 		const block = first( this.editor.model.document.selection.getSelectedBlocks() );
 
-		this.value = !!block && block.is( this.modelElement );
-		this.isEnabled = !!block && checkCanBecomeHeading( block, this.modelElement, this.editor.model.schema );
+		this.value = !!block && this.modelElements.includes( block.name ) && block.name;
+		this.isEnabled = !!block && this.modelElements.some( heading => checkCanBecomeHeading( block, heading, this.editor.model.schema ) );
 	}
 
 	/**
 	 * Executes the command. Applies the heading to the selected blocks or, if the first selected
 	 * block is a heading already, turns selected headings (of this level only) to paragraphs.
 	 *
+	 * @param {Object} options
+	 * @param {String} options.value Name of the element which this command will apply in the model.
 	 * @fires execute
 	 */
-	execute() {
+	execute( options = {} ) {
 		const model = this.editor.model;
 		const document = model.document;
 
+		const modelElement = options.value;
+
+		if ( !this.modelElements.includes( modelElement ) ) {
+			return;
+		}
+
 		model.change( writer => {
 			const blocks = Array.from( document.selection.getSelectedBlocks() )
 				.filter( block => {
-					return checkCanBecomeHeading( block, this.modelElement, model.schema );
+					return checkCanBecomeHeading( block, modelElement, model.schema );
 				} );
 
 			for ( const block of blocks ) {
-				if ( !block.is( this.modelElement ) ) {
-					writer.rename( block, this.modelElement );
+				if ( !block.is( modelElement ) ) {
+					writer.rename( block, modelElement );
 				}
 			}
 		} );

+ 6 - 2
packages/ckeditor5-heading/src/headingediting.js

@@ -51,6 +51,8 @@ export default class HeadingEditing extends Plugin {
 		const editor = this.editor;
 		const options = editor.config.get( 'heading.options' );
 
+		const modelElements = [];
+
 		for ( const option of options ) {
 			// Skip paragraph - it is defined in required Paragraph feature.
 			if ( option.model !== defaultModelElement ) {
@@ -61,10 +63,12 @@ export default class HeadingEditing extends Plugin {
 
 				editor.conversion.elementToElement( option );
 
-				// Register the heading command for this option.
-				editor.commands.add( option.model, new HeadingCommand( editor, option.model ) );
+				modelElements.push( option.model );
 			}
 		}
+
+		// Register the heading command for this option.
+		editor.commands.add( 'heading', new HeadingCommand( editor, modelElements ) );
 	}
 
 	/**

+ 23 - 11
packages/ckeditor5-heading/src/headingui.js

@@ -33,24 +33,37 @@ export default class HeadingUI extends Plugin {
 		const dropdownTooltip = t( 'Heading' );
 
 		// Register UI component.
-		editor.ui.componentFactory.add( 'headings', locale => {
-			const commands = [];
+		editor.ui.componentFactory.add( 'heading', locale => {
+			const titles = {};
 			const dropdownItems = new Collection();
 
+			const headingCommand = editor.commands.get( 'heading' );
+			const paragraphCommand = editor.commands.get( 'paragraph' );
+
+			const commands = [ headingCommand ];
+
 			for ( const option of options ) {
-				const command = editor.commands.get( option.model );
 				const itemModel = new Model( {
-					commandName: option.model,
 					label: option.title,
 					class: option.class
 				} );
 
-				itemModel.bind( 'isActive' ).to( command, 'value' );
+				if ( option.model === 'paragraph' ) {
+					itemModel.bind( 'isActive' ).to( paragraphCommand, 'value' );
+					itemModel.set( 'commandName', 'paragraph' );
+					commands.push( paragraphCommand );
+				} else {
+					itemModel.bind( 'isActive' ).to( headingCommand, 'value', value => value === option.model );
+					itemModel.set( {
+						commandName: 'heading',
+						commandValue: option.model
+					} );
+				}
 
 				// Add the option to the collection.
 				dropdownItems.add( itemModel );
 
-				commands.push( command );
+				titles[ option.model ] = option.title;
 			}
 
 			const dropdownView = createDropdown( locale );
@@ -74,16 +87,15 @@ export default class HeadingUI extends Plugin {
 				return areEnabled.some( isEnabled => isEnabled );
 			} );
 
-			dropdownView.buttonView.bind( 'label' ).toMany( commands, 'value', ( ...areActive ) => {
-				const index = areActive.findIndex( value => value );
-
+			dropdownView.buttonView.bind( 'label' ).to( headingCommand, 'value', paragraphCommand, 'value', ( value, para ) => {
+				const whichModel = value || para && 'paragraph';
 				// If none of the commands is active, display default title.
-				return options[ index ] ? options[ index ].title : defaultTitle;
+				return titles[ whichModel ] ? titles[ whichModel ] : defaultTitle;
 			} );
 
 			// Execute command when an item from the dropdown is selected.
 			this.listenTo( dropdownView, 'execute', evt => {
-				editor.execute( evt.source.commandName );
+				editor.execute( evt.source.commandName, evt.source.commandValue ? { value: evt.source.commandValue } : undefined );
 				editor.editing.view.focus();
 			} );
 

+ 42 - 38
packages/ckeditor5-heading/tests/headingcommand.js

@@ -16,24 +16,29 @@ const options = [
 ];
 
 describe( 'HeadingCommand', () => {
-	let editor, model, document, commands, root, schema;
+	let editor, model, document, command, root, schema;
 
 	beforeEach( () => {
 		return ModelTestEditor.create().then( newEditor => {
 			editor = newEditor;
 			model = editor.model;
 			document = model.document;
-			commands = {};
 			schema = model.schema;
 
 			editor.commands.add( 'paragraph', new ParagraphCommand( editor ) );
 			schema.register( 'paragraph', { inheritAllFrom: '$block' } );
 
+			const modelElements = [];
+
 			for ( const option of options ) {
-				commands[ option.model ] = new HeadingCommand( editor, option.model );
+				modelElements.push( option.model );
 				schema.register( option.model, { inheritAllFrom: '$block' } );
 			}
 
+			command = new HeadingCommand( editor, modelElements );
+			editor.commands.add( 'heading', command );
+			schema.register( 'heading', { inheritAllFrom: '$block' } );
+
 			schema.register( 'notBlock' );
 			schema.extend( 'notBlock', { allowIn: '$root' } );
 			schema.extend( '$text', { allowIn: 'notBlock' } );
@@ -42,15 +47,9 @@ describe( 'HeadingCommand', () => {
 		} );
 	} );
 
-	afterEach( () => {
-		for ( const modelElement in commands ) {
-			commands[ modelElement ].destroy();
-		}
-	} );
-
-	describe( 'modelElement', () => {
+	describe( 'modelElements', () => {
 		it( 'is set', () => {
-			expect( commands.heading1.modelElement ).to.equal( 'heading1' );
+			expect( command.modelElements ).to.deep.equal( [ 'heading1', 'heading2', 'heading3' ] );
 		} );
 	} );
 
@@ -70,13 +69,13 @@ describe( 'HeadingCommand', () => {
 					];
 					writer.setSelection( ranges );
 				} );
-				expect( commands[ modelElement ].value ).to.be.true;
+				expect( command.value ).to.equal( modelElement );
 			} );
 
 			it( 'equals false if inside to non-block element', () => {
 				setData( model, '<notBlock>[foo]</notBlock>' );
 
-				expect( commands[ modelElement ].value ).to.be.false;
+				expect( command.value ).to.be.false;
 			} );
 
 			it( `equals false if moved from ${ modelElement } to non-block element`, () => {
@@ -87,18 +86,17 @@ describe( 'HeadingCommand', () => {
 					writer.setSelection( Range.createIn( element ) );
 				} );
 
-				expect( commands[ modelElement ].value ).to.be.false;
+				expect( command.value ).to.be.false;
 			} );
 
 			it( 'should be refreshed after calling refresh()', () => {
-				const command = commands[ modelElement ];
 				setData( model, `<${ modelElement }>[foo]</${ modelElement }><notBlock>foo</notBlock>` );
 				const element = document.getRoot().getChild( 1 );
 
 				model.change( writer => {
 					writer.setSelection( Range.createIn( element ) );
 
-					expect( command.value ).to.be.true;
+					expect( command.value ).to.equal( modelElement );
 					command.refresh();
 					expect( command.value ).to.be.false;
 				} );
@@ -108,13 +106,11 @@ describe( 'HeadingCommand', () => {
 
 	describe( 'execute()', () => {
 		it( 'should update value after execution', () => {
-			const command = commands.heading1;
-
 			setData( model, '<paragraph>[]</paragraph>' );
-			command.execute();
+			command.execute( { value: 'heading1' } );
 
 			expect( getData( model ) ).to.equal( '<heading1>[]</heading1>' );
-			expect( command.value ).to.be.true;
+			expect( command.value ).to.equal( 'heading1' );
 		} );
 
 		// https://github.com/ckeditor/ckeditor5-heading/issues/73
@@ -134,7 +130,7 @@ describe( 'HeadingCommand', () => {
 				'<fooBlock>de]f</fooBlock>'
 			);
 
-			commands.heading1.execute();
+			command.execute( { value: 'heading1' } );
 
 			expect( getData( model ) ).to.equal(
 				'<heading1>a[bc</heading1>' +
@@ -157,7 +153,7 @@ describe( 'HeadingCommand', () => {
 				'<paragraph>de]f</paragraph>'
 			);
 
-			commands.heading1.execute();
+			command.execute( { value: 'heading1' } );
 
 			expect( getData( model ) ).to.equal(
 				'<heading1>a[bc</heading1>' +
@@ -167,19 +163,33 @@ describe( 'HeadingCommand', () => {
 		} );
 
 		it( 'should use parent batch', () => {
-			const command = commands.heading1;
-
 			setData( model, '<paragraph>foo[]bar</paragraph>' );
 
 			model.change( writer => {
 				expect( writer.batch.deltas.length ).to.equal( 0 );
 
-				command.execute();
+				command.execute( { value: 'heading1' } );
 
 				expect( writer.batch.deltas.length ).to.be.above( 0 );
 			} );
 		} );
 
+		it( 'should do nothing on non-registered model elements', () => {
+			setData( model, '<heading1>[]</heading1>' );
+			command.execute( { value: 'paragraph' } );
+
+			expect( getData( model ) ).to.equal( '<heading1>[]</heading1>' );
+			expect( command.value ).to.equal( 'heading1' );
+		} );
+
+		it( 'should do nothing when empty value is passed', () => {
+			setData( model, '<heading1>[]</heading1>' );
+			command.execute();
+
+			expect( getData( model ) ).to.equal( '<heading1>[]</heading1>' );
+			expect( command.value ).to.equal( 'heading1' );
+		} );
+
 		describe( 'collapsed selection', () => {
 			let convertTo = options[ options.length - 1 ];
 
@@ -191,7 +201,7 @@ describe( 'HeadingCommand', () => {
 			it( 'does nothing when executed with already applied option', () => {
 				setData( model, '<heading1>foo[]bar</heading1>' );
 
-				commands.heading1.execute();
+				command.execute( { value: 'heading1' } );
 				expect( getData( model ) ).to.equal( '<heading1>foo[]bar</heading1>' );
 			} );
 
@@ -200,7 +210,7 @@ describe( 'HeadingCommand', () => {
 				schema.extend( '$text', { allowIn: 'inlineImage' } );
 
 				setData( model, '<paragraph><inlineImage>foo[]</inlineImage>bar</paragraph>' );
-				commands.heading1.execute();
+				command.execute( { value: 'heading1' } );
 
 				expect( getData( model ) ).to.equal( '<heading1><inlineImage>foo[]</inlineImage>bar</heading1>' );
 			} );
@@ -208,7 +218,7 @@ describe( 'HeadingCommand', () => {
 			function test( from, to ) {
 				it( `converts ${ from.model } to ${ to.model } on collapsed selection`, () => {
 					setData( model, `<${ from.model }>foo[]bar</${ from.model }>` );
-					commands[ to.model ].execute();
+					command.execute( { value: to.model } );
 
 					expect( getData( model ) ).to.equal( `<${ to.model }>foo[]bar</${ to.model }>` );
 				} );
@@ -226,7 +236,7 @@ describe( 'HeadingCommand', () => {
 			it( 'converts all elements where selection is applied', () => {
 				setData( model, '<heading1>foo[</heading1><heading2>bar</heading2><heading3>baz]</heading3>' );
 
-				commands.heading3.execute();
+				command.execute( { value: 'heading3' } );
 
 				expect( getData( model ) ).to.equal(
 					'<heading3>foo[</heading3><heading3>bar</heading3><heading3>baz]</heading3>'
@@ -235,7 +245,7 @@ describe( 'HeadingCommand', () => {
 
 			it( 'does nothing to the elements with same option (#1)', () => {
 				setData( model, '<heading1>[foo</heading1><heading1>bar]</heading1>' );
-				commands.heading1.execute();
+				command.execute( { value: 'heading1' } );
 
 				expect( getData( model ) ).to.equal(
 					'<heading1>[foo</heading1><heading1>bar]</heading1>'
@@ -244,7 +254,7 @@ describe( 'HeadingCommand', () => {
 
 			it( 'does nothing to the elements with same option (#2)', () => {
 				setData( model, '<heading1>[foo</heading1><heading1>bar</heading1><heading2>baz]</heading2>' );
-				commands.heading1.execute();
+				command.execute( { value: 'heading1' } );
 
 				expect( getData( model ) ).to.equal(
 					'<heading1>[foo</heading1><heading1>bar</heading1><heading1>baz]</heading1>'
@@ -258,7 +268,7 @@ describe( 'HeadingCommand', () => {
 						`<${ fromElement }>foo[bar</${ fromElement }><${ fromElement }>baz]qux</${ fromElement }>`
 					);
 
-					commands[ toElement ].execute();
+					command.execute( { value: toElement } );
 
 					expect( getData( model ) ).to.equal(
 						`<${ toElement }>foo[bar</${ toElement }><${ toElement }>baz]qux</${ toElement }>`
@@ -274,12 +284,6 @@ describe( 'HeadingCommand', () => {
 		}
 
 		function test( modelElement ) {
-			let command;
-
-			beforeEach( () => {
-				command = commands[ modelElement ];
-			} );
-
 			describe( `${ modelElement } command`, () => {
 				it( 'should be enabled when inside another block', () => {
 					setData( model, '<paragraph>f{}oo</paragraph>' );

+ 1 - 6
packages/ckeditor5-heading/tests/headingediting.js

@@ -49,9 +49,7 @@ describe( 'HeadingEditing', () => {
 
 	it( 'should register #commands', () => {
 		expect( editor.commands.get( 'paragraph' ) ).to.be.instanceOf( ParagraphCommand );
-		expect( editor.commands.get( 'heading1' ) ).to.be.instanceOf( HeadingCommand );
-		expect( editor.commands.get( 'heading2' ) ).to.be.instanceOf( HeadingCommand );
-		expect( editor.commands.get( 'heading3' ) ).to.be.instanceOf( HeadingCommand );
+		expect( editor.commands.get( 'heading' ) ).to.be.instanceOf( HeadingCommand );
 	} );
 
 	it( 'should convert heading1', () => {
@@ -154,9 +152,6 @@ describe( 'HeadingEditing', () => {
 					.then( editor => {
 						model = editor.model;
 
-						expect( editor.commands.get( 'h4' ) ).to.be.instanceOf( HeadingCommand );
-						expect( editor.commands.get( 'paragraph' ) ).to.be.instanceOf( ParagraphCommand );
-
 						expect( model.schema.isRegistered( 'paragraph' ) ).to.be.true;
 						expect( model.schema.isRegistered( 'h4' ) ).to.be.true;
 

+ 46 - 32
packages/ckeditor5-heading/tests/headingui.js

@@ -52,7 +52,7 @@ describe( 'HeadingUI', () => {
 			} )
 			.then( newEditor => {
 				editor = newEditor;
-				dropdown = editor.ui.componentFactory.create( 'headings' );
+				dropdown = editor.ui.componentFactory.create( 'heading' );
 
 				// Set data so the commands will be enabled.
 				setData( editor.model, '<paragraph>f{}oo</paragraph>' );
@@ -67,7 +67,7 @@ describe( 'HeadingUI', () => {
 
 	describe( 'init()', () => {
 		it( 'should register options feature component', () => {
-			const dropdown = editor.ui.componentFactory.create( 'headings' );
+			const dropdown = editor.ui.componentFactory.create( 'heading' );
 
 			expect( dropdown ).to.be.instanceOf( DropdownView );
 			expect( dropdown.buttonView.isEnabled ).to.be.true;
@@ -76,20 +76,32 @@ describe( 'HeadingUI', () => {
 			expect( dropdown.buttonView.tooltip ).to.equal( 'Heading' );
 		} );
 
-		it( 'should execute format command on model execute event', () => {
+		it( 'should execute format command on model execute event for paragraph', () => {
 			const executeSpy = testUtils.sinon.spy( editor, 'execute' );
-			const dropdown = editor.ui.componentFactory.create( 'headings' );
+			const dropdown = editor.ui.componentFactory.create( 'heading' );
 
 			dropdown.commandName = 'paragraph';
 			dropdown.fire( 'execute' );
 
 			sinon.assert.calledOnce( executeSpy );
-			sinon.assert.calledWithExactly( executeSpy, 'paragraph' );
+			sinon.assert.calledWithExactly( executeSpy, 'paragraph', undefined );
+		} );
+
+		it( 'should execute format command on model execute event for heading', () => {
+			const executeSpy = testUtils.sinon.spy( editor, 'execute' );
+			const dropdown = editor.ui.componentFactory.create( 'heading' );
+
+			dropdown.commandName = 'heading';
+			dropdown.commandValue = 'heading1';
+			dropdown.fire( 'execute' );
+
+			sinon.assert.calledOnce( executeSpy );
+			sinon.assert.calledWithExactly( executeSpy, 'heading', { value: 'heading1' } );
 		} );
 
 		it( 'should focus view after command execution', () => {
 			const focusSpy = testUtils.sinon.spy( editor.editing.view, 'focus' );
-			const dropdown = editor.ui.componentFactory.create( 'headings' );
+			const dropdown = editor.ui.componentFactory.create( 'heading' );
 
 			dropdown.commandName = 'paragraph';
 			dropdown.fire( 'execute' );
@@ -98,7 +110,7 @@ describe( 'HeadingUI', () => {
 		} );
 
 		it( 'should add custom CSS class to dropdown', () => {
-			const dropdown = editor.ui.componentFactory.create( 'headings' );
+			const dropdown = editor.ui.componentFactory.create( 'heading' );
 
 			dropdown.render();
 
@@ -106,41 +118,46 @@ describe( 'HeadingUI', () => {
 		} );
 
 		describe( 'model to command binding', () => {
-			let commands;
+			let command, paragraphCommand;
 
 			beforeEach( () => {
-				commands = {};
-
-				editor.config.get( 'heading.options' ).forEach( ( { model } ) => {
-					commands[ model ] = editor.commands.get( model );
-				} );
+				command = editor.commands.get( 'heading' );
+				paragraphCommand = editor.commands.get( 'paragraph' );
 			} );
 
 			it( 'isEnabled', () => {
-				for ( const name in commands ) {
-					commands[ name ].isEnabled = false;
-				}
+				command.isEnabled = false;
+				paragraphCommand.isEnabled = false;
 
 				expect( dropdown.buttonView.isEnabled ).to.be.false;
 
-				commands.heading2.isEnabled = true;
+				command.isEnabled = true;
+				expect( dropdown.buttonView.isEnabled ).to.be.true;
+
+				command.isEnabled = false;
+				expect( dropdown.buttonView.isEnabled ).to.be.false;
+
+				paragraphCommand.isEnabled = true;
 				expect( dropdown.buttonView.isEnabled ).to.be.true;
 			} );
 
 			it( 'label', () => {
-				for ( const name in commands ) {
-					commands[ name ].value = false;
-				}
+				command.value = false;
+				paragraphCommand.value = false;
 
 				expect( dropdown.buttonView.label ).to.equal( 'Choose heading' );
 
-				commands.heading2.value = true;
+				command.value = 'heading2';
 				expect( dropdown.buttonView.label ).to.equal( 'Heading 2' );
+				command.value = false;
+
+				paragraphCommand.value = true;
+				expect( dropdown.buttonView.label ).to.equal( 'Paragraph' );
 			} );
 		} );
 
 		describe( 'localization', () => {
-			let commands, editor, dropdown;
+			let command, paragraphCommand, editor, dropdown;
 
 			beforeEach( () => {
 				return localizedEditor( [
@@ -163,15 +180,15 @@ describe( 'HeadingUI', () => {
 
 				// Setting manually paragraph.value to `false` because there might be some content in editor
 				// after initialisation (for example empty <p></p> inserted when editor is empty).
-				commands.paragraph.value = false;
+				paragraphCommand.value = false;
 				expect( buttonView.label ).to.equal( 'Wybierz nagłówek' );
 				expect( buttonView.tooltip ).to.equal( 'Nagłówek' );
 
-				commands.paragraph.value = true;
+				paragraphCommand.value = true;
 				expect( buttonView.label ).to.equal( 'Akapit' );
 
-				commands.paragraph.value = false;
-				commands.heading1.value = true;
+				paragraphCommand.value = false;
+				command.value = 'heading1';
 				expect( buttonView.label ).to.equal( 'Nagłówek 1' );
 			} );
 
@@ -226,12 +243,9 @@ describe( 'HeadingUI', () => {
 					} )
 					.then( newEditor => {
 						editor = newEditor;
-						dropdown = editor.ui.componentFactory.create( 'headings' );
-						commands = {};
-
-						editor.config.get( 'heading.options' ).forEach( ( { model } ) => {
-							commands[ model ] = editor.commands.get( model );
-						} );
+						dropdown = editor.ui.componentFactory.create( 'heading' );
+						command = editor.commands.get( 'heading' );
+						paragraphCommand = editor.commands.get( 'paragraph' );
 
 						editorElement.remove();
 

+ 3 - 3
packages/ckeditor5-heading/tests/integration.js

@@ -78,7 +78,7 @@ describe( 'Heading integration', () => {
 				'<paragraph>b]ar</paragraph>'
 			);
 
-			editor.execute( 'heading1' );
+			editor.execute( 'heading', { value: 'heading1' } );
 
 			expect( getModelData( model ) ).to.equal(
 				'<heading1>fo[o</heading1>' +
@@ -94,7 +94,7 @@ describe( 'Heading integration', () => {
 		it( 'does not create undo steps when applied to an existing heading (collapsed selection)', () => {
 			setModelData( model, '<heading1>foo[]bar</heading1>' );
 
-			editor.execute( 'heading1' );
+			editor.execute( 'heading', { value: 'heading1' } );
 			expect( getModelData( model ) ).to.equal( '<heading1>foo[]bar</heading1>' );
 
 			expect( editor.commands.get( 'undo' ).isEnabled ).to.be.false;
@@ -103,7 +103,7 @@ describe( 'Heading integration', () => {
 		it( 'does not create undo steps when applied to an existing heading (non–collapsed selection)', () => {
 			setModelData( model, '<heading1>[foo</heading1><heading1>bar]</heading1>' );
 
-			editor.execute( 'heading1' );
+			editor.execute( 'heading', { value: 'heading1' } );
 			expect( getModelData( model ) ).to.equal( '<heading1>[foo</heading1><heading1>bar]</heading1>' );
 
 			expect( editor.commands.get( 'undo' ).isEnabled ).to.be.false;

+ 1 - 1
packages/ckeditor5-heading/tests/manual/heading.js

@@ -15,7 +15,7 @@ import Undo from '@ckeditor/ckeditor5-undo/src/undo';
 ClassicEditor
 	.create( document.querySelector( '#editor' ), {
 		plugins: [ Enter, Typing, Undo, Heading, Paragraph ],
-		toolbar: [ 'headings', '|', 'undo', 'redo' ]
+		toolbar: [ 'heading', '|', 'undo', 'redo' ]
 	} )
 	.then( editor => {
 		window.editor = editor;