Ver código fonte

Merge pull request #253 from ckeditor/i/6150

Feature: Table cell properties form should handle multi-cell selections. Closes ckeditor/ckeditor5#6150.
Piotrek Koszuliński 5 anos atrás
pai
commit
0f453cfe8c

+ 29 - 7
packages/ckeditor5-table/src/tablecellproperties/commands/tablecellpropertycommand.js

@@ -36,12 +36,11 @@ export default class TableCellPropertyCommand extends Command {
 	 */
 	refresh() {
 		const editor = this.editor;
-		const selection = editor.model.document.selection;
 
-		const tableCell = findAncestor( 'tableCell', selection.getFirstPosition() );
+		const selectedTableCells = getSelectedTableCells( editor.model );
 
-		this.isEnabled = !!tableCell;
-		this.value = this._getAttribute( tableCell );
+		this.isEnabled = !!selectedTableCells.length;
+		this.value = this._getSingleValue( selectedTableCells );
 	}
 
 	/**
@@ -56,12 +55,10 @@ export default class TableCellPropertyCommand extends Command {
 	 */
 	execute( options = {} ) {
 		const model = this.editor.model;
-		const selection = model.document.selection;
 
 		const { value, batch } = options;
 
-		const tableCells = Array.from( selection.getSelectedBlocks() )
-			.map( element => findAncestor( 'tableCell', model.createPositionAt( element, 0 ) ) );
+		const tableCells = getSelectedTableCells( model );
 		const valueToSet = this._getValueToSet( value );
 
 		model.enqueueChange( batch || 'default', writer => {
@@ -98,4 +95,29 @@ export default class TableCellPropertyCommand extends Command {
 	_getValueToSet( value ) {
 		return value;
 	}
+
+	/**
+	 * Returns a single value for all selected table cells. If the value is the same for all cells,
+	 * it will be returned (`undefined` otherwise).
+	 *
+	 * @param {Array.<module:engine/model/element~Element>} tableCell
+	 * @returns {*}
+	 * @private
+	 */
+	_getSingleValue( tableCell ) {
+		const firstCellValue = this._getAttribute( tableCell[ 0 ] );
+
+		const everyCellHasAttribute = tableCell.every( tableCell => this._getAttribute( tableCell ) === firstCellValue );
+
+		return everyCellHasAttribute ? firstCellValue : undefined;
+	}
+}
+
+// Returns all selected table cells.
+function getSelectedTableCells( model ) {
+	const selection = model.document.selection;
+
+	return Array.from( selection.getSelectedBlocks() )
+		.map( element => findAncestor( 'tableCell', model.createPositionAt( element, 0 ) ) )
+		.filter( tableCell => !!tableCell );
 }

+ 11 - 2
packages/ckeditor5-table/src/ui/utils.js

@@ -81,8 +81,7 @@ export function getBalloonTablePositionData( editor ) {
  * @returns {module:utils/dom/position~Options}
  */
 export function getBalloonCellPositionData( editor ) {
-	const firstPosition = editor.model.document.selection.getFirstPosition();
-	const modelTableCell = findAncestor( 'tableCell', firstPosition );
+	const modelTableCell = getTableCellAtPosition( editor.model.document.selection.getFirstPosition() );
 	const viewTableCell = editor.editing.mapper.toViewElement( modelTableCell );
 
 	return {
@@ -468,3 +467,13 @@ function colorConfigToColorGridDefinitions( colorConfig ) {
 		}
 	} ) );
 }
+
+// Returns the first selected table cell from a multi-cell or in-cell selection.
+//
+// @param {module:engine/model/position~Position} position Document position.
+// @returns {module:engine/model/element~Element}
+function getTableCellAtPosition( position ) {
+	const isTableCellSelected = position.nodeAfter && position.nodeAfter.is( 'tableCell' );
+
+	return isTableCellSelected ? position.nodeAfter : findAncestor( 'tableCell', position );
+}

+ 7 - 1
packages/ckeditor5-table/tests/manual/tableselection.html

@@ -52,7 +52,13 @@
 					<td>k</td>
 					<td>l</td>
 					<td><strong>m</strong></td>
-					<td>n</td>
+					<td>
+						<p>n</p>
+						<figure class="image image-style-side">
+							<img src="sample.jpg" />
+							<figcaption>Caption!</figcaption>
+						</figure>
+					</td>
 					<td>o</td>
 				</tr>
 				<tr>

+ 3 - 0
packages/ckeditor5-table/tests/manual/tableselection.js

@@ -31,6 +31,9 @@ function createEditor( target, inspectorName ) {
 				'bulletedList', 'numberedList', 'blockQuote', '|',
 				'undo', 'redo'
 			],
+			image: {
+				toolbar: [ 'imageStyle:full', 'imageStyle:side', '|', 'imageTextAlternative' ]
+			},
 			table: {
 				contentToolbar: [ 'tableColumn', 'tableRow', 'mergeTableCells', 'tableProperties', 'tableCellProperties' ]
 			}

+ 107 - 1
packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellbackgroundcolorcommand.js

@@ -8,9 +8,10 @@ import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
 
 import { setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 
-import { assertTableCellStyle, modelTable } from '../../_utils/utils';
+import { assertTableCellStyle, modelTable, viewTable } from '../../_utils/utils';
 import TableCellPropertiesEditing from '../../../src/tablecellproperties/tablecellpropertiesediting';
 import TableCellBackgroundColorCommand from '../../../src/tablecellproperties/commands/tablecellbackgroundcolorcommand';
+import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
 
 describe( 'table cell properties', () => {
 	describe( 'commands', () => {
@@ -54,6 +55,17 @@ describe( 'table cell properties', () => {
 						expect( command.isEnabled ).to.be.true;
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be true if the selection contains some table cells', () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true }, '01' ],
+							[ '10', { contents: '11', isSelected: true } ]
+						] ) );
+
+						expect( command.isEnabled ).to.be.true;
+					} );
+				} );
 			} );
 
 			describe( 'value', () => {
@@ -84,6 +96,68 @@ describe( 'table cell properties', () => {
 						expect( command.value ).to.equal( 'blue' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be undefined if no table cell have the "backgroundColor" property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if only some table cells have the "backgroundColor" property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, backgroundColor: '#f00' },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, backgroundColor: '#f00' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if one of selected table cells has a different "backgroundColor" property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, backgroundColor: '#f00' },
+								{ contents: '01', isSelected: true, backgroundColor: 'pink' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, backgroundColor: '#f00' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be set if all table cell have the same "backgroundColor" property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, backgroundColor: '#f00' },
+								{ contents: '01', isSelected: true, backgroundColor: '#f00' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, backgroundColor: '#f00' }
+							]
+						] ) );
+
+						expect( command.value ).to.equal( '#f00' );
+					} );
+				} );
 			} );
 
 			describe( 'execute()', () => {
@@ -147,6 +221,38 @@ describe( 'table cell properties', () => {
 						assertTableCellStyle( editor, '' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					beforeEach( () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true }, '01' ],
+							[ '10', { contents: '11', isSelected: true } ]
+						] ) );
+					} );
+
+					it( 'should set the "backgroundColor" attribute value of selected table cells', () => {
+						command.execute( { value: '#f00' } );
+
+						assertEqualMarkup( editor.getData(), viewTable( [
+							[ { contents: '00', style: 'background-color:#f00;' }, '01' ],
+							[ '10', { contents: '11', style: 'background-color:#f00;' } ]
+						] ) );
+					} );
+
+					it( 'should remove "backgroundColor" from a selected table cell if no value is passed', () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true, backgroundColor: '#f00' }, '01' ],
+							[ '10', { contents: '11', isSelected: true, backgroundColor: '#f00' } ]
+						] ) );
+
+						command.execute();
+
+						assertEqualMarkup( editor.getData(), viewTable( [
+							[ '00', '01' ],
+							[ '10', '11' ]
+						] ) );
+					} );
+				} );
 			} );
 		} );
 	} );

+ 107 - 1
packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellbordercolorcommand.js

@@ -8,9 +8,10 @@ import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
 
 import { setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 
-import { assertTableCellStyle, modelTable, setTableCellWithObjectAttributes } from '../../_utils/utils';
+import { assertTableCellStyle, modelTable, setTableCellWithObjectAttributes, viewTable } from '../../_utils/utils';
 import TableCellPropertiesEditing from '../../../src/tablecellproperties/tablecellpropertiesediting';
 import TableCellBorderColorCommand from '../../../src/tablecellproperties/commands/tablecellbordercolorcommand';
+import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
 
 describe( 'table cell properties', () => {
 	describe( 'commands', () => {
@@ -54,6 +55,17 @@ describe( 'table cell properties', () => {
 						expect( command.isEnabled ).to.be.true;
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be true if the selection contains some table cells', () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true }, '01' ],
+							[ '10', { contents: '11', isSelected: true } ]
+						] ) );
+
+						expect( command.isEnabled ).to.be.true;
+					} );
+				} );
 			} );
 
 			describe( 'value', () => {
@@ -109,6 +121,68 @@ describe( 'table cell properties', () => {
 						expect( command.value ).to.equal( 'blue' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be undefined if no table cells have the "borderColor" property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if only some table cells have the "borderColor" property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, borderColor: '#f00' },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, borderColor: '#f00' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if one of selected table cells has a different "borderColor" property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, borderColor: '#f00' },
+								{ contents: '01', isSelected: true, borderColor: 'pink' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, borderColor: '#f00' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be set if all table cells have the same "borderColor" property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, borderColor: '#f00' },
+								{ contents: '01', isSelected: true, borderColor: '#f00' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, borderColor: '#f00' }
+							]
+						] ) );
+
+						expect( command.value ).to.equal( '#f00' );
+					} );
+				} );
 			} );
 
 			describe( 'execute()', () => {
@@ -172,6 +246,38 @@ describe( 'table cell properties', () => {
 						assertTableCellStyle( editor, '' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					beforeEach( () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true }, '01' ],
+							[ '10', { contents: '11', isSelected: true } ]
+						] ) );
+					} );
+
+					it( 'should set the "borderColor" attribute value of selected table cells', () => {
+						command.execute( { value: '#f00' } );
+
+						assertEqualMarkup( editor.getData(), viewTable( [
+							[ { contents: '00', style: 'border-bottom:#f00;border-left:#f00;border-right:#f00;border-top:#f00;' }, '01' ],
+							[ '10', { contents: '11', style: 'border-bottom:#f00;border-left:#f00;border-right:#f00;border-top:#f00;' } ]
+						] ) );
+					} );
+
+					it( 'should remove "borderColor" from the selected table cell if no value is passed', () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true, borderColor: '#f00' }, '01' ],
+							[ '10', { contents: '11', isSelected: true, borderColor: '#f00' } ]
+						] ) );
+
+						command.execute();
+
+						assertEqualMarkup( editor.getData(), viewTable( [
+							[ '00', '01' ],
+							[ '10', '11' ]
+						] ) );
+					} );
+				} );
 			} );
 		} );
 	} );

+ 113 - 1
packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellborderstylecommand.js

@@ -8,9 +8,10 @@ import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
 
 import { setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 
-import { assertTableCellStyle, modelTable, setTableCellWithObjectAttributes } from '../../_utils/utils';
+import { assertTableCellStyle, modelTable, setTableCellWithObjectAttributes, viewTable } from '../../_utils/utils';
 import TableCellPropertiesEditing from '../../../src/tablecellproperties/tablecellpropertiesediting';
 import TableCellBorderStyleCommand from '../../../src/tablecellproperties/commands/tablecellborderstylecommand';
+import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
 
 describe( 'table cell properties', () => {
 	describe( 'commands', () => {
@@ -54,6 +55,17 @@ describe( 'table cell properties', () => {
 						expect( command.isEnabled ).to.be.true;
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be true if the selection contains some table cells', () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true }, '01' ],
+							[ '10', { contents: '11', isSelected: true } ]
+						] ) );
+
+						expect( command.isEnabled ).to.be.true;
+					} );
+				} );
 			} );
 
 			describe( 'value', () => {
@@ -109,6 +121,68 @@ describe( 'table cell properties', () => {
 						expect( command.value ).to.equal( 'ridge' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be undefined if no table cells have the "borderStyle" property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if only some table cells have the "borderStyle" property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, borderStyle: 'solid' },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, borderStyle: 'solid' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if one of selected table cells has a different "borderStyle" property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, borderStyle: 'solid' },
+								{ contents: '01', isSelected: true, borderStyle: 'ridge' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, borderStyle: 'solid' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be set if all table cells have the same "borderStyle" property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, borderStyle: 'solid' },
+								{ contents: '01', isSelected: true, borderStyle: 'solid' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, borderStyle: 'solid' }
+							]
+						] ) );
+
+						expect( command.value ).to.equal( 'solid' );
+					} );
+				} );
 			} );
 
 			describe( 'execute()', () => {
@@ -172,6 +246,44 @@ describe( 'table cell properties', () => {
 						assertTableCellStyle( editor, '' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					beforeEach( () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true }, '01' ],
+							[ '10', { contents: '11', isSelected: true } ]
+						] ) );
+					} );
+
+					it( 'should set the "borderStyle" attribute value of selected table cells', () => {
+						command.execute( { value: 'solid' } );
+
+						assertEqualMarkup( editor.getData(), viewTable( [
+							[
+								{ contents: '00', style: 'border-bottom:solid;border-left:solid;border-right:solid;border-top:solid;' },
+								'01'
+							],
+							[
+								'10',
+								{ contents: '11', style: 'border-bottom:solid;border-left:solid;border-right:solid;border-top:solid;' }
+							]
+						] ) );
+					} );
+
+					it( 'should remove "borderStyle" from selected table cells if no value is passed', () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true, borderStyle: 'solid' }, '01' ],
+							[ '10', { contents: '11', isSelected: true, borderStyle: 'solid' } ]
+						] ) );
+
+						command.execute();
+
+						assertEqualMarkup( editor.getData(), viewTable( [
+							[ '00', '01' ],
+							[ '10', '11' ]
+						] ) );
+					} );
+				} );
 			} );
 		} );
 	} );

+ 113 - 1
packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellborderwidthcommand.js

@@ -8,9 +8,10 @@ import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
 
 import { setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 
-import { assertTableCellStyle, modelTable, setTableCellWithObjectAttributes } from '../../_utils/utils';
+import { assertTableCellStyle, modelTable, setTableCellWithObjectAttributes, viewTable } from '../../_utils/utils';
 import TableCellPropertiesEditing from '../../../src/tablecellproperties/tablecellpropertiesediting';
 import TableCellBorderWidthCommand from '../../../src/tablecellproperties/commands/tablecellborderwidthcommand';
+import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
 
 describe( 'table cell properties', () => {
 	describe( 'commands', () => {
@@ -54,6 +55,17 @@ describe( 'table cell properties', () => {
 						expect( command.isEnabled ).to.be.true;
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be true if the selection contains some table cells', () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true }, '01' ],
+							[ '10', { contents: '11', isSelected: true } ]
+						] ) );
+
+						expect( command.isEnabled ).to.be.true;
+					} );
+				} );
 			} );
 
 			describe( 'value', () => {
@@ -109,6 +121,68 @@ describe( 'table cell properties', () => {
 						expect( command.value ).to.equal( '2em' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be undefined if no table cells have the "borderWidth" property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if only some table cells have the "borderWidth" property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, borderWidth: '1px' },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, borderWidth: '1px' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if one of selected table cells has a different "borderWidth" property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, borderWidth: '1px' },
+								{ contents: '01', isSelected: true, borderWidth: '20px' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, borderWidth: '1px' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be set if all table cells have the same "borderWidth" property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, borderWidth: '1px' },
+								{ contents: '01', isSelected: true, borderWidth: '1px' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, borderWidth: '1px' }
+							]
+						] ) );
+
+						expect( command.value ).to.equal( '1px' );
+					} );
+				} );
 			} );
 
 			describe( 'execute()', () => {
@@ -228,6 +302,44 @@ describe( 'table cell properties', () => {
 						assertTableCellStyle( editor, '' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					beforeEach( () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true }, '01' ],
+							[ '10', { contents: '11', isSelected: true } ]
+						] ) );
+					} );
+
+					it( 'should set the "borderWidth" attribute value of selected table cells', () => {
+						command.execute( { value: '1px' } );
+
+						assertEqualMarkup( editor.getData(), viewTable( [
+							[
+								{ contents: '00', style: 'border-bottom:1px;border-left:1px;border-right:1px;border-top:1px;' },
+								'01'
+							],
+							[
+								'10',
+								{ contents: '11', style: 'border-bottom:1px;border-left:1px;border-right:1px;border-top:1px;' }
+							]
+						] ) );
+					} );
+
+					it( 'should remove "borderWidth" from selected table cells if no value is passed', () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true, borderWidth: '1px' }, '01' ],
+							[ '10', { contents: '11', isSelected: true, borderWidth: '1px' } ]
+						] ) );
+
+						command.execute();
+
+						assertEqualMarkup( editor.getData(), viewTable( [
+							[ '00', '01' ],
+							[ '10', '11' ]
+						] ) );
+					} );
+				} );
 			} );
 		} );
 	} );

+ 107 - 1
packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellheightcommand.js

@@ -8,9 +8,10 @@ import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
 
 import { setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 
-import { assertTableCellStyle, modelTable } from '../../_utils/utils';
+import { assertTableCellStyle, modelTable, viewTable } from '../../_utils/utils';
 import TableCellPropertiesEditing from '../../../src/tablecellproperties/tablecellpropertiesediting';
 import TableCellHeightCommand from '../../../src/tablecellproperties/commands/tablecellheightcommand';
+import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
 
 describe( 'table cell properties', () => {
 	describe( 'commands', () => {
@@ -54,6 +55,17 @@ describe( 'table cell properties', () => {
 						expect( command.isEnabled ).to.be.true;
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be true if the selection contains some table cells', () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true }, '01' ],
+							[ '10', { contents: '11', isSelected: true } ]
+						] ) );
+
+						expect( command.isEnabled ).to.be.true;
+					} );
+				} );
 			} );
 
 			describe( 'value', () => {
@@ -84,6 +96,68 @@ describe( 'table cell properties', () => {
 						expect( command.value ).to.equal( '100px' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be undefined if no table cell have the "height" property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if only some table cells have the "height" property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, height: '100px' },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, height: '100px' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if one of selected table cells has a different "height" property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, height: '100px' },
+								{ contents: '01', isSelected: true, height: '23px' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, height: '100px' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be set if all table cell have the same "height" property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, height: '100px' },
+								{ contents: '01', isSelected: true, height: '100px' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, height: '100px' }
+							]
+						] ) );
+
+						expect( command.value ).to.equal( '100px' );
+					} );
+				} );
 			} );
 
 			describe( 'execute()', () => {
@@ -203,6 +277,38 @@ describe( 'table cell properties', () => {
 						assertTableCellStyle( editor, '' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					beforeEach( () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true }, '01' ],
+							[ '10', { contents: '11', isSelected: true } ]
+						] ) );
+					} );
+
+					it( 'should set the "height" attribute value of selected table cells', () => {
+						command.execute( { value: '100px' } );
+
+						assertEqualMarkup( editor.getData(), viewTable( [
+							[ { contents: '00', style: 'height:100px;' }, '01' ],
+							[ '10', { contents: '11', style: 'height:100px;' } ]
+						] ) );
+					} );
+
+					it( 'should remove "height" from selected table cells if no value is passed', () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true, height: '100px' }, '01' ],
+							[ '10', { contents: '11', isSelected: true, height: '100px' } ]
+						] ) );
+
+						command.execute();
+
+						assertEqualMarkup( editor.getData(), viewTable( [
+							[ '00', '01' ],
+							[ '10', '11' ]
+						] ) );
+					} );
+				} );
 			} );
 		} );
 	} );

+ 107 - 1
packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellhorizontalalignmentcommand.js

@@ -8,9 +8,10 @@ import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
 
 import { setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 
-import { assertTableCellStyle, modelTable } from '../../_utils/utils';
+import { assertTableCellStyle, modelTable, viewTable } from '../../_utils/utils';
 import TableCellPropertiesEditing from '../../../src/tablecellproperties/tablecellpropertiesediting';
 import TableCellHorizontalAlignmentCommand from '../../../src/tablecellproperties/commands/tablecellhorizontalalignmentcommand';
+import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
 
 describe( 'table cell properties', () => {
 	describe( 'commands', () => {
@@ -54,6 +55,17 @@ describe( 'table cell properties', () => {
 						expect( command.isEnabled ).to.be.true;
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be true if the selection contains some table cells', () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true }, '01' ],
+							[ '10', { contents: '11', isSelected: true } ]
+						] ) );
+
+						expect( command.isEnabled ).to.be.true;
+					} );
+				} );
 			} );
 
 			describe( 'value', () => {
@@ -84,6 +96,68 @@ describe( 'table cell properties', () => {
 						expect( command.value ).to.equal( 'center' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be undefined if no table cells have the "horizontalAlignment" property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if only some table cells have the "horizontalAlignment" property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, horizontalAlignment: 'center' },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, horizontalAlignment: 'center' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if one of selected table cells has a different "horizontalAlignment" property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, horizontalAlignment: 'center' },
+								{ contents: '01', isSelected: true, horizontalAlignment: 'right' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, horizontalAlignment: 'center' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be set if all table cells have the same "horizontalAlignment" property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, horizontalAlignment: 'center' },
+								{ contents: '01', isSelected: true, horizontalAlignment: 'center' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, horizontalAlignment: 'center' }
+							]
+						] ) );
+
+						expect( command.value ).to.equal( 'center' );
+					} );
+				} );
 			} );
 
 			describe( 'execute()', () => {
@@ -147,6 +221,38 @@ describe( 'table cell properties', () => {
 						assertTableCellStyle( editor, '' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					beforeEach( () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true }, '01' ],
+							[ '10', { contents: '11', isSelected: true } ]
+						] ) );
+					} );
+
+					it( 'should set the "horizontalAlignment" attribute value of selected table cells', () => {
+						command.execute( { value: 'right' } );
+
+						assertEqualMarkup( editor.getData(), viewTable( [
+							[ { contents: '00', style: 'text-align:right;' }, '01' ],
+							[ '10', { contents: '11', style: 'text-align:right;' } ]
+						] ) );
+					} );
+
+					it( 'should remove the "horizontalAlignment" attribute from selected table cells if no value is passed', () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true, horizontalAlignment: 'right' }, '01' ],
+							[ '10', { contents: '11', isSelected: true, horizontalAlignment: 'right' } ]
+						] ) );
+
+						command.execute();
+
+						assertEqualMarkup( editor.getData(), viewTable( [
+							[ '00', '01' ],
+							[ '10', '11' ]
+						] ) );
+					} );
+				} );
 			} );
 		} );
 	} );

+ 107 - 1
packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellpaddingcommand.js

@@ -8,9 +8,10 @@ import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
 
 import { setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 
-import { assertTableCellStyle, modelTable, setTableCellWithObjectAttributes } from '../../_utils/utils';
+import { assertTableCellStyle, modelTable, setTableCellWithObjectAttributes, viewTable } from '../../_utils/utils';
 import TableCellPropertiesEditing from '../../../src/tablecellproperties/tablecellpropertiesediting';
 import TableCellPaddingCommand from '../../../src/tablecellproperties/commands/tablecellpaddingcommand';
+import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
 
 describe( 'table cell properties', () => {
 	describe( 'commands', () => {
@@ -54,6 +55,17 @@ describe( 'table cell properties', () => {
 						expect( command.isEnabled ).to.be.true;
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be true if the selection contains some table cells', () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true }, '01' ],
+							[ '10', { contents: '11', isSelected: true } ]
+						] ) );
+
+						expect( command.isEnabled ).to.be.true;
+					} );
+				} );
 			} );
 
 			describe( 'value', () => {
@@ -109,6 +121,68 @@ describe( 'table cell properties', () => {
 						expect( command.value ).to.equal( '2em' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be undefined if no table cells have the "padding" property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if only some table cells have the "padding" property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, padding: '2em' },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, padding: '2em' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if one of selected table cells has a different "padding" property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, padding: '2em' },
+								{ contents: '01', isSelected: true, padding: '3em' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, padding: '2em' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be set if all table cells have the same "padding" property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, padding: '2em' },
+								{ contents: '01', isSelected: true, padding: '2em' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, padding: '2em' }
+							]
+						] ) );
+
+						expect( command.value ).to.equal( '2em' );
+					} );
+				} );
 			} );
 
 			describe( 'execute()', () => {
@@ -228,6 +302,38 @@ describe( 'table cell properties', () => {
 						assertTableCellStyle( editor, '' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					beforeEach( () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true }, '01' ],
+							[ '10', { contents: '11', isSelected: true } ]
+						] ) );
+					} );
+
+					it( 'should set the "padding" attribute value of selected table cells', () => {
+						command.execute( { value: '25px' } );
+
+						assertEqualMarkup( editor.getData(), viewTable( [
+							[ { contents: '00', style: 'padding:25px;' }, '01' ],
+							[ '10', { contents: '11', style: 'padding:25px;' } ]
+						] ) );
+					} );
+
+					it( 'should remove "padding" from selected table cells if no value is passed', () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true, padding: '25px' }, '01' ],
+							[ '10', { contents: '11', isSelected: true, padding: '25px' } ]
+						] ) );
+
+						command.execute();
+
+						assertEqualMarkup( editor.getData(), viewTable( [
+							[ '00', '01' ],
+							[ '10', '11' ]
+						] ) );
+					} );
+				} );
 			} );
 		} );
 	} );

+ 107 - 1
packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellverticalalignmentcommand.js

@@ -8,9 +8,10 @@ import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
 
 import { setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 
-import { assertTableCellStyle, modelTable } from '../../_utils/utils';
+import { assertTableCellStyle, modelTable, viewTable } from '../../_utils/utils';
 import TableCellPropertiesEditing from '../../../src/tablecellproperties/tablecellpropertiesediting';
 import TableCellVerticalAlignmentCommand from '../../../src/tablecellproperties/commands/tablecellverticalalignmentcommand';
+import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
 
 describe( 'table cell properties', () => {
 	describe( 'commands', () => {
@@ -54,6 +55,17 @@ describe( 'table cell properties', () => {
 						expect( command.isEnabled ).to.be.true;
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be true if the selection contains some table cells', () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true }, '01' ],
+							[ '10', { contents: '11', isSelected: true } ]
+						] ) );
+
+						expect( command.isEnabled ).to.be.true;
+					} );
+				} );
 			} );
 
 			describe( 'value', () => {
@@ -84,6 +96,68 @@ describe( 'table cell properties', () => {
 						expect( command.value ).to.equal( 'bottom' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be undefined if no table cells have the "verticalAlignment" property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if only some table cells have the "verticalAlignment" property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, verticalAlignment: 'bottom' },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, verticalAlignment: 'bottom' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if one of selected table cells has a different "verticalAlignment" property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, verticalAlignment: 'bottom' },
+								{ contents: '01', isSelected: true, verticalAlignment: 'top' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, verticalAlignment: 'bottom' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be set if all table cells have the same "verticalAlignment" property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, verticalAlignment: 'bottom' },
+								{ contents: '01', isSelected: true, verticalAlignment: 'bottom' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, verticalAlignment: 'bottom' }
+							]
+						] ) );
+
+						expect( command.value ).to.equal( 'bottom' );
+					} );
+				} );
 			} );
 
 			describe( 'execute()', () => {
@@ -147,6 +221,38 @@ describe( 'table cell properties', () => {
 						assertTableCellStyle( editor, '' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					beforeEach( () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true }, '01' ],
+							[ '10', { contents: '11', isSelected: true } ]
+						] ) );
+					} );
+
+					it( 'should set the "verticalAlignment" attribute value of selected table cells', () => {
+						command.execute( { value: 'top' } );
+
+						assertEqualMarkup( editor.getData(), viewTable( [
+							[ { contents: '00', style: 'vertical-align:top;' }, '01' ],
+							[ '10', { contents: '11', style: 'vertical-align:top;' } ]
+						] ) );
+					} );
+
+					it( 'should remove "verticalAlignment" from selected table cells if no value is passed', () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true, verticalAlignment: 'top' }, '01' ],
+							[ '10', { contents: '11', isSelected: true, verticalAlignment: 'top' } ]
+						] ) );
+
+						command.execute();
+
+						assertEqualMarkup( editor.getData(), viewTable( [
+							[ '00', '01' ],
+							[ '10', '11' ]
+						] ) );
+					} );
+				} );
 			} );
 		} );
 	} );

+ 107 - 1
packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellwidthcommand.js

@@ -8,9 +8,10 @@ import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
 
 import { setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 
-import { assertTableCellStyle, modelTable } from '../../_utils/utils';
+import { assertTableCellStyle, modelTable, viewTable } from '../../_utils/utils';
 import TableCellPropertiesEditing from '../../../src/tablecellproperties/tablecellpropertiesediting';
 import TableCellWidthCommand from '../../../src/tablecellproperties/commands/tablecellwidthcommand';
+import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
 
 describe( 'table cell properties', () => {
 	describe( 'commands', () => {
@@ -54,6 +55,17 @@ describe( 'table cell properties', () => {
 						expect( command.isEnabled ).to.be.true;
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be true if the selection contains some table cells', () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true }, '01' ],
+							[ '10', { contents: '11', isSelected: true } ]
+						] ) );
+
+						expect( command.isEnabled ).to.be.true;
+					} );
+				} );
 			} );
 
 			describe( 'value', () => {
@@ -84,6 +96,68 @@ describe( 'table cell properties', () => {
 						expect( command.value ).to.equal( '100px' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be undefined if no table cells have the "width" property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if only some table cells have the "width" property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, width: '100px' },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, width: '100px' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if one of selected table cells has a different "width" property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, width: '100px' },
+								{ contents: '01', isSelected: true, width: '25px' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, width: '100px' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be set if all table cells have the same "width" property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, width: '100px' },
+								{ contents: '01', isSelected: true, width: '100px' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, width: '100px' }
+							]
+						] ) );
+
+						expect( command.value ).to.equal( '100px' );
+					} );
+				} );
 			} );
 
 			describe( 'execute()', () => {
@@ -203,6 +277,38 @@ describe( 'table cell properties', () => {
 						assertTableCellStyle( editor, '' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					beforeEach( () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true }, '01' ],
+							[ '10', { contents: '11', isSelected: true } ]
+						] ) );
+					} );
+
+					it( 'should set the "width" attribute value of selected table cells', () => {
+						command.execute( { value: '25px' } );
+
+						assertEqualMarkup( editor.getData(), viewTable( [
+							[ { contents: '00', style: 'width:25px;' }, '01' ],
+							[ '10', { contents: '11', style: 'width:25px;' } ]
+						] ) );
+					} );
+
+					it( 'should remove "width" from selected table cells if no value is passed', () => {
+						setData( model, modelTable( [
+							[ { contents: '00', isSelected: true, width: '25px' }, '01' ],
+							[ '10', { contents: '11', isSelected: true, width: '25px' } ]
+						] ) );
+
+						command.execute();
+
+						assertEqualMarkup( editor.getData(), viewTable( [
+							[ '00', '01' ],
+							[ '10', '11' ]
+						] ) );
+					} );
+				} );
 			} );
 		} );
 	} );

+ 15 - 1
packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesui.js

@@ -8,7 +8,7 @@
 import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
 import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
 import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';
-import { getData as getModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
+import { getData as getModelData, setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 
 import Undo from '@ckeditor/ckeditor5-undo/src/undo';
 import Batch from '@ckeditor/ckeditor5-engine/src/model/batch';
@@ -21,6 +21,7 @@ import TableCellPropertiesEditing from '../../src/tablecellproperties/tablecellp
 import TableCellPropertiesUI from '../../src/tablecellproperties/tablecellpropertiesui';
 import TableCellPropertiesUIView from '../../src/tablecellproperties/ui/tablecellpropertiesview';
 import { defaultColors } from '../../src/ui/utils';
+import { modelTable } from '../_utils/utils';
 
 describe( 'table cell properties', () => {
 	describe( 'TableCellPropertiesUI', () => {
@@ -529,6 +530,19 @@ describe( 'table cell properties', () => {
 				expect( firstBatch ).to.not.equal( secondBatch );
 			} );
 
+			it( 'should show the ui for multi-cell selection', () => {
+				setData( editor.model, modelTable( [ [ '01', '02' ] ] ) );
+				editor.model.change( writer => {
+					writer.setSelection( [
+						writer.createRangeOn( editor.model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ) ),
+						writer.createRangeOn( editor.model.document.getRoot().getNodeByPath( [ 0, 0, 1 ] ) )
+					], 0 );
+				} );
+
+				tableCellPropertiesButton.fire( 'execute' );
+				expect( contextualBalloon.visibleView ).to.equal( tableCellPropertiesView );
+			} );
+
 			describe( 'initial data', () => {
 				it( 'should be set from the command values', () => {
 					editor.commands.get( 'tableCellBorderStyle' ).value = 'a';