/** * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor'; import { getData as getModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph'; import ImageEditing from '@ckeditor/ckeditor5-image/src/image/imageediting'; import Widget from '@ckeditor/ckeditor5-widget/src/widget'; import { modelTable } from '../_utils/utils'; import TableEditing from '../../src/tableediting'; import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils'; describe( 'upcastTable()', () => { let editor, model; beforeEach( () => { return ClassicTestEditor .create( '', { plugins: [ TableEditing, Paragraph, ImageEditing, Widget ] } ) .then( newEditor => { editor = newEditor; model = editor.model; // Since this part of test tests only view->model conversion editing pipeline is not necessary // so defining model->view converters won't be necessary. editor.editing.destroy(); } ); } ); afterEach( () => { editor.destroy(); } ); function expectModel( data ) { assertEqualMarkup( getModelData( model, { withoutSelection: true } ), data ); } it( 'should convert table figure', () => { editor.setData( '
' + '' + '' + '
1
' + '
' ); expectModel( '' + '1' + '
' ); } ); it( 'should create table model from table without thead', () => { editor.setData( '' + '' + '
1
' ); expectModel( '' + '1' + '
' ); } ); it( 'should not convert empty figure', () => { '
'; expectModel( '' ); } ); it( 'should convert if figure do not have class="table" attribute', () => { editor.setData( '
' + '' + '' + '
1
' + '
' ); expectModel( '' + '1' + '
' ); } ); it( 'should create table model from table with one thead with one row', () => { editor.setData( '' + '' + '
1
' ); expectModel( '' + '1' + '
' ); } ); it( 'should create table model from table with one thead with more then one row', () => { editor.setData( '' + '' + '' + '' + '' + '' + '
1
2
3
' ); expectModel( '' + '1' + '2' + '3' + '
' ); } ); it( 'should create table model from table with two theads with one row', () => { editor.setData( '' + '' + '' + '' + '
1
2
3
' ); expectModel( '' + '1' + '2' + '3' + '
' ); } ); it( 'should create table model from table with thead after the tbody', () => { editor.setData( '' + '' + '' + '
2
1
' ); expectModel( '' + '1' + '2' + '
' ); } ); it( 'should create table model from table with one tfoot with one row', () => { editor.setData( '' + '' + '
1
' ); expectModel( '' + '1' + '
' ); } ); it( 'should create valid table model from empty table', () => { editor.setData( '' + '
' ); expectModel( '
' ); } ); it( 'should create valid table model from all empty rows', () => { editor.setData( '' + '' + '' + '
' ); expectModel( '
' ); } ); it( 'should skip empty table rows', () => { editor.setData( '' + '' + '' + '
bar
' ); expectModel( 'bar
' ); } ); it( 'should skip unknown table children', () => { editor.setData( '' + '' + '' + '
foo
bar
' ); expectModel( 'bar
' ); } ); it( 'should create table model from some broken table', () => { editor.setData( '
foo
' ); expectModel( 'foo
' ); } ); it( 'should fix if inside other blocks', () => { editor.model.schema.register( 'div', { inheritAllFrom: '$block' } ); editor.conversion.for( 'upcast' ).elementToElement( { model: 'div', view: 'div' } ); editor.setData( '
foo' + '' + '' + '' + '
2
1
' + 'bar
' ); expectModel( '
foo
' + '' + '1' + '2' + '
' + '
bar
' ); } ); it( 'should be possible to overwrite table conversion', () => { editor.model.schema.register( 'fooTable', { allowWhere: '$block', allowAttributes: [ 'headingRows' ], isObject: true } ); editor.model.schema.register( 'fooCell', { allowIn: 'fooRow', isObject: true } ); editor.model.schema.register( 'fooRow', { allowIn: 'fooTable', isObject: true } ); editor.conversion.elementToElement( { model: 'fooTable', view: 'table', converterPriority: 'high' } ); editor.conversion.elementToElement( { model: 'fooRow', view: 'tr', converterPriority: 'high' } ); editor.conversion.elementToElement( { model: 'fooCell', view: 'td', converterPriority: 'high' } ); editor.conversion.elementToElement( { model: 'fooCell', view: 'th', converterPriority: 'high' } ); editor.setData( '' + '' + '
foo
' ); expectModel( '' ); } ); it( 'should strip table in table', () => { editor.setData( '' + '' + '' + '' + '
' + '' + '' + '' + '' + '
tableception
' + '
' ); expectModel( '' + '' + '' + 'tableception' + '' + '' + '
' ); } ); describe( 'headingColumns', () => { it( 'should properly calculate heading columns', () => { editor.setData( '' + '' + // This row starts with 1 th (3 total). '' + // This row starts with 2 th (2 total). This one has max number of heading columns: 2. '' + // This row starts with 1 th (1 total). '' + // This row starts with 0 th (3 total). '' + '' + '' + // This row has 4 ths but it is a thead. '' + '' + '
21222324
31323334
41424344
51525354
11121314
' ); expectModel( '' + '' + '11' + '12' + '13' + '14' + '' + '' + '21' + '22' + '23' + '24' + '' + '' + '31' + '32' + '33' + '34' + '' + '' + '41' + '42' + '43' + '44' + '' + '' + '51' + '52' + '53' + '54' + '' + '
' ); } ); it( 'should calculate heading columns of cells with colspan', () => { editor.setData( '' + '' + // This row has colspan of 3 so it should be the whole table should have 3 heading columns. '' + '' + '' + '' + // This row has 4 ths but it is a thead. '' + '' + '
21222324
313334
11121314
' ); expectModel( '' + '' + '11' + '12' + '13' + '14' + '' + '' + '21' + '22' + '23' + '24' + '' + '' + '31' + '33' + '34' + '' + '
' ); } ); } ); describe( 'block contents', () => { it( 'should upcast table with empty table cell to paragraph', () => { editor.setData( '' + '' + '' + '' + '' + '' + '
foo
' ); expectModel( modelTable( [ [ 'foo' ] ] ) ); } ); it( 'should upcast table with

in table cell', () => { editor.setData( '' + '' + '' + '' + '' + '' + '

foo

' ); expectModel( modelTable( [ [ 'foo' ] ] ) ); } ); it( 'should upcast table inline content to single ', () => { editor.model.schema.extend( '$text', { allowAttributes: 'bold' } ); editor.conversion.attributeToElement( { model: 'bold', view: 'strong' } ); editor.setData( '' + '' + '' + '' + '' + '' + '
foo bar
' ); expectModel( modelTable( [ [ 'foo <$text bold="true">bar' ] ] ) ); } ); it( 'should upcast table with multiple

in table cell', () => { editor.setData( '' + '' + '' + '' + '' + '' + '
' + '

foo

' + '

bar

' + '

baz

' + '
' ); expectModel( modelTable( [ [ 'foobarbaz' ] ] ) ); } ); it( 'should upcast table with in table cell', () => { editor.setData( '' + '' + '' + '' + '' + '' + '
' ); expectModel( modelTable( [ [ '' ] ] ) ); } ); } ); describe( 'handling redundant whitespacing between table elements', () => { it( 'table without thead/tbody/tfoot', () => { editor.setData( ' ' + '' + '
1
' ); expectModel( '' + '1' + '
' ); } ); it( 'table with thead only', () => { editor.setData( '' + '' + ' ' + '' + ' ' + '' + '
1
2
3
' ); expectModel( '' + '1' + '2' + '3' + '
' ); } ); it( 'table with thead and tbody', () => { editor.setData( '' + ' ' + '' + '\n\n ' + '' + '' + ' ' + '\n\n ' + ' ' + '' + '
1
2
3
4
5
' ); expectModel( '' + '1' + '2' + '3' + '4' + '5' + '
' ); } ); it( 'table with tbody and tfoot', () => { editor.setData( '' + '' + ' ' + '' + ' ' + '\n\n\n' + '\n\n' + ' ' + '\n\n\n ' + '' + '
1
2
3
4
5
' ); expectModel( '' + '1' + '2' + '3' + '4' + '5' + '
' ); } ); } ); } );