How to use listItem method in Cypress

Best JavaScript code snippet using cypress

listediting.js

Source:listediting.js Github

copy

Full Screen

1/**2 * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.3 * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license4 */5import ListEditing from '../src/listediting';6import ListCommand from '../src/listcommand';7import IndentCommand from '../src/indentcommand';8import ModelRange from '@ckeditor/ckeditor5-engine/src/model/range';9import BoldEditing from '@ckeditor/ckeditor5-basic-styles/src/bold/boldediting';10import UndoEditing from '@ckeditor/ckeditor5-undo/src/undoediting';11import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';12import BlockQuoteEditing from '@ckeditor/ckeditor5-block-quote/src/blockquoteediting';13import HeadingEditing from '@ckeditor/ckeditor5-heading/src/headingediting';14import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';15import { getData as getModelData, parse as parseModel, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';16import { getData as getViewData, parse as parseView } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';17import IndentEditing from '@ckeditor/ckeditor5-indent/src/indentediting';18import { getCode } from '@ckeditor/ckeditor5-utils/src/keyboard';19import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';20import TableEditing from '@ckeditor/ckeditor5-table/src/tableediting';21describe( 'ListEditing', () => {22	let editor, model, modelDoc, modelRoot, view, viewDoc, viewRoot;23	beforeEach( () => {24		return VirtualTestEditor25			.create( {26				plugins: [ Clipboard, BoldEditing, ListEditing, UndoEditing, BlockQuoteEditing, TableEditing ]27			} )28			.then( newEditor => {29				editor = newEditor;30				model = editor.model;31				modelDoc = model.document;32				modelRoot = modelDoc.getRoot();33				view = editor.editing.view;34				viewDoc = view.document;35				viewRoot = viewDoc.getRoot();36				model.schema.register( 'foo', {37					allowWhere: '$block',38					allowAttributes: [ 'listIndent', 'listType' ],39					isBlock: true,40					isObject: true41				} );42			} );43	} );44	afterEach( () => {45		return editor.destroy();46	} );47	it( 'should have pluginName', () => {48		expect( ListEditing.pluginName ).to.equal( 'ListEditing' );49	} );50	it( 'should be loaded', () => {51		expect( editor.plugins.get( ListEditing ) ).to.be.instanceOf( ListEditing );52	} );53	it( 'should set proper schema rules', () => {54		expect( model.schema.isRegistered( 'listItem' ) );55		expect( model.schema.isBlock( 'listItem' ) );56		expect( model.schema.checkChild( [ '$root' ], 'listItem' ) ).to.be.true;57		expect( model.schema.checkChild( [ '$root', 'listItem' ], '$text' ) ).to.be.true;58		expect( model.schema.checkChild( [ '$root', 'listItem' ], 'listItem' ) ).to.be.false;59		expect( model.schema.checkChild( [ '$root', 'listItem' ], '$block' ) ).to.be.false;60		expect( model.schema.checkAttribute( [ '$root', 'listItem' ], 'listIndent' ) ).to.be.true;61		expect( model.schema.checkAttribute( [ '$root', 'listItem' ], 'listType' ) ).to.be.true;62	} );63	describe( 'commands', () => {64		it( 'should register bulleted list command', () => {65			const command = editor.commands.get( 'bulletedList' );66			expect( command ).to.be.instanceOf( ListCommand );67			expect( command ).to.have.property( 'type', 'bulleted' );68		} );69		it( 'should register numbered list command', () => {70			const command = editor.commands.get( 'numberedList' );71			expect( command ).to.be.instanceOf( ListCommand );72			expect( command ).to.have.property( 'type', 'numbered' );73		} );74		it( 'should register indent list command', () => {75			const command = editor.commands.get( 'indentList' );76			expect( command ).to.be.instanceOf( IndentCommand );77		} );78		it( 'should register outdent list command', () => {79			const command = editor.commands.get( 'outdentList' );80			expect( command ).to.be.instanceOf( IndentCommand );81		} );82		it( 'should add indent list command to indent command', () => {83			return VirtualTestEditor84				.create( {85					plugins: [ ListEditing, IndentEditing ]86				} )87				.then( newEditor => {88					editor = newEditor;89				} )90				.then( () => {91					const indentListCommand = editor.commands.get( 'indentList' );92					const indentCommand = editor.commands.get( 'indent' );93					const spy = sinon.spy( indentListCommand, 'execute' );94					indentListCommand.isEnabled = true;95					indentCommand.execute();96					sinon.assert.calledOnce( spy );97				} );98		} );99		it( 'should add outdent list command to outdent command', () => {100			return VirtualTestEditor101				.create( {102					plugins: [ ListEditing, IndentEditing ]103				} )104				.then( newEditor => {105					editor = newEditor;106				} )107				.then( () => {108					const outdentListCommand = editor.commands.get( 'outdentList' );109					const outdentCommand = editor.commands.get( 'outdent' );110					const spy = sinon.spy( outdentListCommand, 'execute' );111					outdentListCommand.isEnabled = true;112					outdentCommand.execute();113					sinon.assert.calledOnce( spy );114				} );115		} );116	} );117	describe( 'enter key handling callback', () => {118		it( 'should execute outdentList command on enter key in empty list', () => {119			const domEvtDataStub = { preventDefault() {} };120			sinon.spy( editor, 'execute' );121			setModelData( model, '<listItem listType="bulleted" listIndent="0">[]</listItem>' );122			editor.editing.view.document.fire( 'enter', domEvtDataStub );123			sinon.assert.calledOnce( editor.execute );124			sinon.assert.calledWithExactly( editor.execute, 'outdentList' );125		} );126		it( 'should not execute outdentList command on enter key in non-empty list', () => {127			const domEvtDataStub = { preventDefault() {} };128			sinon.spy( editor, 'execute' );129			setModelData( model, '<listItem listType="bulleted" listIndent="0">foo[]</listItem>' );130			editor.editing.view.document.fire( 'enter', domEvtDataStub );131			sinon.assert.notCalled( editor.execute );132		} );133	} );134	describe( 'delete key handling callback', () => {135		it( 'should execute outdentList command on backspace key in first item of list (first node in root)', () => {136			const domEvtDataStub = { preventDefault() {}, direction: 'backward' };137			sinon.spy( editor, 'execute' );138			setModelData( model, '<listItem listType="bulleted" listIndent="0">[]foo</listItem>' );139			editor.editing.view.document.fire( 'delete', domEvtDataStub );140			sinon.assert.calledWithExactly( editor.execute, 'outdentList' );141		} );142		it( 'should execute outdentList command on backspace key in first item of list (after a paragraph)', () => {143			const domEvtDataStub = { preventDefault() {}, direction: 'backward' };144			sinon.spy( editor, 'execute' );145			setModelData( model, '<paragraph>foo</paragraph><listItem listType="bulleted" listIndent="0">[]foo</listItem>' );146			editor.editing.view.document.fire( 'delete', domEvtDataStub );147			sinon.assert.calledWithExactly( editor.execute, 'outdentList' );148		} );149		it( 'should not execute outdentList command on delete key in first item of list', () => {150			const domEvtDataStub = { preventDefault() {}, direction: 'forward' };151			sinon.spy( editor, 'execute' );152			setModelData( model, '<listItem listType="bulleted" listIndent="0">[]foo</listItem>' );153			editor.editing.view.document.fire( 'delete', domEvtDataStub );154			sinon.assert.notCalled( editor.execute );155		} );156		it( 'should not execute outdentList command when selection is not collapsed', () => {157			const domEvtDataStub = { preventDefault() {}, direction: 'backward' };158			sinon.spy( editor, 'execute' );159			setModelData( model, '<listItem listType="bulleted" listIndent="0">[fo]o</listItem>' );160			editor.editing.view.document.fire( 'delete', domEvtDataStub );161			sinon.assert.notCalled( editor.execute );162		} );163		it( 'should not execute outdentList command if not in list item', () => {164			const domEvtDataStub = { preventDefault() {}, direction: 'backward' };165			sinon.spy( editor, 'execute' );166			setModelData( model, '<paragraph>[]foo</paragraph>' );167			editor.editing.view.document.fire( 'delete', domEvtDataStub );168			sinon.assert.notCalled( editor.execute );169		} );170		it( 'should not execute outdentList command if not in first list item', () => {171			const domEvtDataStub = { preventDefault() {}, direction: 'backward' };172			sinon.spy( editor, 'execute' );173			setModelData(174				model,175				'<listItem listType="bulleted" listIndent="0">foo</listItem><listItem listType="bulleted" listIndent="0">[]foo</listItem>'176			);177			editor.editing.view.document.fire( 'delete', domEvtDataStub );178			sinon.assert.notCalled( editor.execute );179		} );180		it( 'should not execute outdentList command when selection is not on first position', () => {181			const domEvtDataStub = { preventDefault() {}, direction: 'backward' };182			sinon.spy( editor, 'execute' );183			setModelData( model, '<listItem listType="bulleted" listIndent="0">fo[]o</listItem>' );184			editor.editing.view.document.fire( 'delete', domEvtDataStub );185			sinon.assert.notCalled( editor.execute );186		} );187		it( 'should outdent list when previous element is nested in block quote', () => {188			const domEvtDataStub = { preventDefault() {}, direction: 'backward' };189			sinon.spy( editor, 'execute' );190			setModelData(191				model,192				'<blockQuote><paragraph>x</paragraph></blockQuote><listItem listType="bulleted" listIndent="0">[]foo</listItem>'193			);194			editor.editing.view.document.fire( 'delete', domEvtDataStub );195			sinon.assert.calledWithExactly( editor.execute, 'outdentList' );196		} );197		it( 'should outdent list when list is nested in block quote', () => {198			const domEvtDataStub = { preventDefault() {}, direction: 'backward' };199			sinon.spy( editor, 'execute' );200			setModelData(201				model,202				'<paragraph>x</paragraph><blockQuote><listItem listType="bulleted" listIndent="0">[]foo</listItem></blockQuote>'203			);204			editor.editing.view.document.fire( 'delete', domEvtDataStub );205			sinon.assert.calledWithExactly( editor.execute, 'outdentList' );206		} );207	} );208	describe( 'tab key handling callback', () => {209		let domEvtDataStub;210		beforeEach( () => {211			domEvtDataStub = {212				keyCode: getCode( 'Tab' ),213				preventDefault: sinon.spy(),214				stopPropagation: sinon.spy()215			};216			sinon.spy( editor, 'execute' );217		} );218		afterEach( () => {219			editor.execute.restore();220		} );221		it( 'should execute indentList command on tab key', () => {222			setModelData(223				model,224				'<listItem listType="bulleted" listIndent="0">foo</listItem>' +225				'<listItem listType="bulleted" listIndent="0">[]bar</listItem>'226			);227			editor.editing.view.document.fire( 'keydown', domEvtDataStub );228			sinon.assert.calledOnce( editor.execute );229			sinon.assert.calledWithExactly( editor.execute, 'indentList' );230			sinon.assert.calledOnce( domEvtDataStub.preventDefault );231			sinon.assert.calledOnce( domEvtDataStub.stopPropagation );232		} );233		it( 'should execute outdentList command on Shift+Tab keystroke', () => {234			domEvtDataStub.keyCode += getCode( 'Shift' );235			setModelData(236				model,237				'<listItem listType="bulleted" listIndent="0">foo</listItem>' +238				'<listItem listType="bulleted" listIndent="1">[]bar</listItem>'239			);240			editor.editing.view.document.fire( 'keydown', domEvtDataStub );241			sinon.assert.calledOnce( editor.execute );242			sinon.assert.calledWithExactly( editor.execute, 'outdentList' );243			sinon.assert.calledOnce( domEvtDataStub.preventDefault );244			sinon.assert.calledOnce( domEvtDataStub.stopPropagation );245		} );246		it( 'should not indent if command is disabled', () => {247			setModelData( model, '<listItem listType="bulleted" listIndent="0">[]foo</listItem>' );248			editor.editing.view.document.fire( 'keydown', domEvtDataStub );249			expect( editor.execute.called ).to.be.false;250			sinon.assert.notCalled( domEvtDataStub.preventDefault );251			sinon.assert.notCalled( domEvtDataStub.stopPropagation );252		} );253		it( 'should not indent or outdent if alt+tab is pressed', () => {254			domEvtDataStub.keyCode += getCode( 'alt' );255			setModelData(256				model,257				'<listItem listType="bulleted" listIndent="0">foo</listItem>' +258				'<listItem listType="bulleted" listIndent="0">[]bar</listItem>'259			);260			editor.editing.view.document.fire( 'keydown', domEvtDataStub );261			expect( editor.execute.called ).to.be.false;262			sinon.assert.notCalled( domEvtDataStub.preventDefault );263			sinon.assert.notCalled( domEvtDataStub.stopPropagation );264		} );265	} );266	describe( 'flat lists', () => {267		describe( 'setting data', () => {268			function testList( testName, string, expectedString = null ) {269				it( testName, () => {270					editor.setData( string );271					expect( editor.getData() ).to.equal( expectedString || string );272				} );273			}274			testList( 'single item', '<ul><li>x</li></ul>' );275			testList( 'multiple items', '<ul><li>a</li><li>b</li><li>c</li></ul>' );276			testList( 'items and text', '<p>xxx</p><ul><li>a</li><li>b</li></ul><p>yyy</p><ul><li>c</li><li>d</li></ul>' );277			testList( 'numbered list', '<ol><li>a</li><li>b</li></ol>' );278			testList( 'mixed list and content #1', '<p>xxx</p><ul><li>a</li><li>b</li></ul><ol><li>c</li><li>d</li></ol><p>yyy</p>' );279			testList( 'mixed list and content #2',280				'<ol><li>a</li></ol><p>xxx</p><ul><li>b</li><li>c</li></ul><p>yyy</p><ul><li>d</li></ul>' );281			testList(282				'clears incorrect elements',283				'<ul>x<li>a</li><li>b</li><p>xxx</p>x</ul><p>c</p>', '<ul><li>a</li><li>b</li></ul><p>c</p>'284			);285			testList(286				'clears whitespaces',287				'<p>foo</p>' +288				'<ul>' +289				'	<li>xxx</li>' +290				'	<li>yyy</li>' +291				'</ul>',292				'<p>foo</p><ul><li>xxx</li><li>yyy</li></ul>'293			);294			// #ckeditor5/1399295			testList( 'single item with `font-weight` style',296				'<ol><li style="font-weight: bold">foo</li></ol>', '<ol><li><strong>foo</strong></li></ol>' );297			it( 'model test for mixed content', () => {298				editor.setData( '<ol><li>a</li></ol><p>xxx</p><ul><li>b</li><li>c</li></ul><p>yyy</p><ul><li>d</li></ul>' );299				const expectedModelData =300					'<listItem listIndent="0" listType="numbered">a</listItem>' +301					'<paragraph>xxx</paragraph>' +302					'<listItem listIndent="0" listType="bulleted">b</listItem>' +303					'<listItem listIndent="0" listType="bulleted">c</listItem>' +304					'<paragraph>yyy</paragraph>' +305					'<listItem listIndent="0" listType="bulleted">d</listItem>';306				expect( getModelData( model, { withoutSelection: true } ) ).to.equal( expectedModelData );307			} );308			describe( 'block elements inside list items', () => {309				describe( 'single block', () => {310					testList(311						'single item',312						'<ul><li><p>Foo</p></li></ul>',313						'<p>Foo</p>'314					);315					testList(316						'multiple items',317						'<ul><li><p>Foo</p></li><li><p>Bar</p></li></ul>',318						'<p>Foo</p><p>Bar</p>'319					);320					testList(321						'nested items',322						'<ul><li><p>Foo</p><ol><li><p>Bar</p></li></ol></li></ul>',323						'<p>Foo</p><p>Bar</p>'324					);325				} );326				describe( 'multiple blocks', () => {327					testList(328						'single item',329						'<ul><li><h2>Foo</h2><p>Bar</p></li></ul>',330						'<p>Foo</p><p>Bar</p>'331					);332					testList(333						'multiple items',334						'<ol><li><p>123</p></li></ol><ul><li><h2>Foo</h2><p>Bar</p></li></ul>',335						'<p>123</p><p>Foo</p><p>Bar</p>'336					);337					testList(338						'nested items #2',339						'<ol><li><p>123</p><p>456</p><ul><li><h2>Foo</h2><p>Bar</p></li></ul></li></ol>',340						'<p>123</p><p>456</p><p>Foo</p><p>Bar</p>'341					);342				} );343				describe.skip( 'multiple blocks', () => { // Skip due to #112 issue.344					testList(345						'nested items #1',346						'<ol><li><p>123</p><ul><li><h2>Foo</h2><p>Bar</p></li></ul><p>456</p></li></ol>',347						'<p>123</p><p>Foo</p><p>Bar</p><p>456</p>'348					);349				} );350				describe( 'inline + block', () => {351					testList(352						'single item',353						'<ul><li>Foo<p>Bar</p></li></ul>',354						'<ul><li>Foo</li></ul><p>Bar</p>'355					);356					testList(357						'multiple items',358						'<ul><li>Foo<p>Bar</p></li><li>Foz<p>Baz</p></li></ul>',359						'<ul><li>Foo</li></ul><p>Bar</p><ul><li>Foz</li></ul><p>Baz</p>'360					);361					testList(362						'split by list items',363						'<ul><li>Foo</li><li><p>Bar</p></li></ul>',364						'<ul><li>Foo</li></ul><p>Bar</p>'365					);366					testList(367						'nested split by list items',368						'<ul><li>Foo<ol><li><p>Bar</p></li></ol></li></ul>',369						'<ul><li>Foo</li></ul><p>Bar</p>'370					);371					testList(372						'nested items #1',373						'<ol><li>Foo<p>Bar</p><ul><li>123<h2>456</h2></li></ul></li></ol>',374						'<ol><li>Foo</li></ol><p>Bar</p><ul><li>123</li></ul><p>456</p>'375					);376					testList(377						'nested items #2',378						'<ol><li>Foo<p>Bar</p><ul><li>123<h2>456</h2></li></ul></li><li>abc<h2>def</h2></li></ol>',379						'<ol><li>Foo</li></ol><p>Bar</p><ul><li>123</li></ul><p>456</p><ol><li>abc</li></ol><p>def</p>'380					);381				} );382				describe( 'block + inline', () => {383					testList(384						'single item',385						'<ul><li><p>Foo</p>Bar</li></ul>',386						'<p>Foo</p><ul><li>Bar</li></ul>'387					);388					testList(389						'multiple items',390						'<ul><li><p>Foo</p>Bar</li><li><p>Foz</p>Baz</li></ul>',391						'<p>Foo</p><ul><li>Bar</li></ul><p>Foz</p><ul><li>Baz</li></ul>'392					);393					testList(394						'split by list items',395						'<ul><li><p>Bar</p><li>Foo</li></li></ul>',396						'<p>Bar</p><ul><li>Foo</li></ul>'397					);398					testList(399						'nested split by list items',400						'<ul><li><p>Bar</p><ol><li>Foo</li></ol></li></ul>',401						'<p>Bar</p><ol><li>Foo</li></ol>'402					);403					testList(404						'nested items #1',405						'<ol><li><p>Foo</p>Bar<ul><li><h2>123</h2>456</li></ul></li></ol>',406						'<p>Foo</p><ol><li>Bar</li></ol><p>123</p><ul><li>456</li></ul>'407					);408					testList(409						'nested items #2',410						'<ol><li><p>Foo</p>Bar<ul><li><h2>123</h2>456</li></ul></li><li><h2>abc</h2>def</li></ol>',411						'<p>Foo</p><ol><li>Bar</li></ol><p>123</p><ul><li>456</li></ul><p>abc</p><ol><li>def</li></ol>'412					);413				} );414				describe( 'complex', () => {415					testList(416						'single item with inline block inline',417						'<ul><li>Foo<p>Bar</p>Baz</li></ul>',418						'<ul><li>Foo</li></ul><p>Bar</p><ul><li>Baz</li></ul>'419					);420					testList(421						'single item with inline block block',422						'<ul><li>Text<p>Foo</p><p>Bar</p></li></ul>',423						'<ul><li>Text</li></ul><p>Foo</p><p>Bar</p>'424					);425					testList(426						'single item with block block inline',427						'<ul><li><p>Foo</p><p>Bar</p>Text</li></ul>',428						'<p>Foo</p><p>Bar</p><ul><li>Text</li></ul>'429					);430					testList(431						'single item with block block block',432						'<ul><li><p>Foo</p><p>Bar</p><p>Baz</p></li></ul>',433						'<p>Foo</p><p>Bar</p><p>Baz</p>'434					);435					testList(436						'item inline + item block and inline',437						'<ul><li>Foo</li><li><p>Bar</p>Baz</li></ul>',438						'<ul><li>Foo</li></ul><p>Bar</p><ul><li>Baz</li></ul>'439					);440					testList(441						'item inline and block + item inline',442						'<ul><li>Foo<p>Bar</p></li><li>Baz</li></ul>',443						'<ul><li>Foo</li></ul><p>Bar</p><ul><li>Baz</li></ul>'444					);445					testList(446						'multiple items inline/block mix',447						'<ul><li>Text<p>Foo</p></li><li>Bar<p>Baz</p>123</li></ul>',448						'<ul><li>Text</li></ul><p>Foo</p><ul><li>Bar</li></ul><p>Baz</p><ul><li>123</li></ul>'449					);450					testList(451						'nested items',452						'<ul><li>Foo<p>Bar</p></li><li>Baz<p>123</p>456<ol><li>ABC<p>DEF</p></li><li>GHI</li></ol></li></ul>',453						'<ul><li>Foo</li></ul><p>Bar</p><ul><li>Baz</li></ul><p>123</p><ul><li>456<ol><li>ABC</li></ol></li></ul>' +454							'<p>DEF</p><ol><li>GHI</li></ol>'455					);456					testList(457						'list with empty inline element',458						'<ul><li><span></span>Foo<p>Bar</p></li></ul>',459						'<ul><li>Foo</li></ul><p>Bar</p>'460					);461				} );462			} );463		} );464		describe( 'position mapping', () => {465			let mapper;466			beforeEach( () => {467				mapper = editor.editing.mapper;468				editor.setData(469					'<p>a</p>' +470					'<ul>' +471						'<li>b</li>' +472						'<li>c</li>' +473						'<li>d</li>' +474					'</ul>' +475					'<p>e</p>' +476					'<ol>' +477						'<li>f</li>' +478					'</ol>' +479					'<p>g</p>'480				);481			} );482			/*483				<paragraph>a</paragraph>484				<listItem listIndent=0 listType="bulleted">b</listItem>485				<listItem listIndent=0 listType="bulleted">c</listItem>486				<listItem listIndent=0 listType="bulleted">d</listItem>487				<paragraph>e</paragraph>488				<listItem listIndent=0 listType="numbered">f</listItem>489				<paragraph>g</paragraph>490			 */491			describe( 'view to model', () => {492				function testList( testName, viewPath, modelPath ) {493					it( testName, () => {494						const viewPos = getViewPosition( viewRoot, viewPath, view );495						const modelPos = mapper.toModelPosition( viewPos );496						expect( modelPos.root ).to.equal( modelRoot );497						expect( modelPos.path ).to.deep.equal( modelPath );498					} );499				}500				testList( 'before ul',			[ 1 ],			[ 1 ] );	// --> before first `listItem`501				testList( 'before first li',	[ 1, 0 ],		[ 1 ] );	// --> before first `listItem`502				testList( 'beginning of li',	[ 1, 0, 0 ],	[ 1, 0 ] );	// --> beginning of first `listItem`503				testList( 'end of li',			[ 1, 0, 1 ],	[ 1, 1 ] );	// --> end of first `listItem`504				testList( 'before middle li',	[ 1, 1 ],		[ 2 ] );	// --> before middle `listItem`505				testList( 'before last li',		[ 1, 2 ],		[ 3 ] );	// --> before last `listItem`506				testList( 'after last li',		[ 1, 3 ],		[ 4 ] );	// --> after last `listItem` / before `paragraph`507				testList( 'after ul',			[ 2 ],			[ 4 ] );	// --> after last `listItem` / before `paragraph`508				testList( 'before ol',			[ 3 ],			[ 5 ] );	// --> before numbered `listItem`509				testList( 'before only li',		[ 3, 0 ],		[ 5 ] );	// --> before numbered `listItem`510				testList( 'after only li',		[ 3, 1 ],		[ 6 ] );	// --> after numbered `listItem`511				testList( 'after ol',			[ 4 ],			[ 6 ] );	// --> after numbered `listItem`512			} );513			describe( 'model to view', () => {514				function testList( testName, modelPath, viewPath ) {515					it( testName, () => {516						const modelPos = model.createPositionFromPath( modelRoot, modelPath );517						const viewPos = mapper.toViewPosition( modelPos );518						expect( viewPos.root ).to.equal( viewRoot );519						expect( getViewPath( viewPos ) ).to.deep.equal( viewPath );520					} );521				}522				testList( 'before first listItem',			[ 1 ],		[ 1 ] );			// --> before ul523				testList( 'beginning of first listItem',	[ 1, 0 ],	[ 1, 0, 0, 0 ] );	// --> beginning of `b` text node524				testList( 'end of first listItem',			[ 1, 1 ],	[ 1, 0, 0, 1 ] );	// --> end of `b` text node525				testList( 'before middle listItem',			[ 2 ],		[ 1, 1 ] );			// --> before middle li526				testList( 'before last listItem',			[ 3 ],		[ 1, 2 ] );			// --> before last li527				testList( 'after last listItem',			[ 4 ],		[ 2 ] );			// --> after ul528				testList( 'before numbered listItem',		[ 5 ],		[ 3 ] );			// --> before ol529				testList( 'after numbered listItem',		[ 6 ],		[ 4 ] );			// --> after ol530			} );531		} );532		describe( 'convert changes', () => {533			describe( 'insert', () => {534				testInsert(535					'list item at the beginning of same list type',536					'<paragraph>p</paragraph>' +537					'[<listItem listIndent="0" listType="bulleted">x</listItem>]' +538					'<listItem listIndent="0" listType="bulleted">a</listItem>',539					'<p>p</p>' +540					'<ul>' +541						'<li>x</li>' +542						'<li>a</li>' +543					'</ul>'544				);545				testInsert(546					'list item in the middle of same list type',547					'<paragraph>p</paragraph>' +548					'<listItem listIndent="0" listType="bulleted">a</listItem>' +549					'[<listItem listIndent="0" listType="bulleted">x</listItem>]' +550					'<listItem listIndent="0" listType="bulleted">b</listItem>',551					'<p>p</p>' +552					'<ul>' +553						'<li>a</li>' +554						'<li>x</li>' +555						'<li>b</li>' +556					'</ul>'557				);558				testInsert(559					'list item at the end of same list type',560					'<paragraph>p</paragraph>' +561					'<listItem listIndent="0" listType="bulleted">a</listItem>' +562					'[<listItem listIndent="0" listType="bulleted">x</listItem>]',563					'<p>p</p>' +564					'<ul>' +565						'<li>a</li>' +566						'<li>x</li>' +567					'</ul>'568				);569				testInsert(570					'list item at the beginning of different list type',571					'<paragraph>p</paragraph>' +572					'[<listItem listIndent="0" listType="numbered">x</listItem>]' +573					'<listItem listIndent="0" listType="bulleted">a</listItem>',574					'<p>p</p>' +575					'<ol>' +576						'<li>x</li>' +577					'</ol>' +578					'<ul>' +579						'<li>a</li>' +580					'</ul>'581				);582				testInsert(583					'list item in the middle of different list type',584					'<paragraph>p</paragraph>' +585					'<listItem listIndent="0" listType="bulleted">a</listItem>' +586					'[<listItem listIndent="0" listType="numbered">x</listItem>]' +587					'<listItem listIndent="0" listType="bulleted">b</listItem>',588					'<p>p</p>' +589					'<ul>' +590						'<li>a</li>' +591					'</ul>' +592					'<ol>' +593						'<li>x</li>' +594					'</ol>' +595					'<ul>' +596						'<li>b</li>' +597					'</ul>'598				);599				testInsert(600					'list item at the end of different list type',601					'<paragraph>p</paragraph>' +602					'<listItem listIndent="0" listType="bulleted">a</listItem>' +603					'[<listItem listIndent="0" listType="numbered">x</listItem>]',604					'<p>p</p>' +605					'<ul>' +606						'<li>a</li>' +607					'</ul>' +608					'<ol>' +609						'<li>x</li>' +610					'</ol>'611				);612				testInsert(613					'element between list items',614					'<listItem listIndent="0" listType="bulleted">a</listItem>' +615					'[<paragraph>x</paragraph>]' +616					'<listItem listIndent="0" listType="bulleted">a</listItem>',617					'<ul>' +618						'<li>a</li>' +619					'</ul>' +620					'<p>x</p>' +621					'<ul>' +622						'<li>a</li>' +623					'</ul>'624				);625			} );626			describe( 'remove', () => {627				testRemove(628					'remove the first list item',629					'<paragraph>p</paragraph>' +630					'[<listItem listIndent="0" listType="bulleted">a</listItem>]' +631					'<listItem listIndent="0" listType="bulleted">b</listItem>' +632					'<listItem listIndent="0" listType="bulleted">c</listItem>',633					'<p>p</p>' +634					'<ul>' +635						'<li>b</li>' +636						'<li>c</li>' +637					'</ul>'638				);639				testRemove(640					'remove list item from the middle',641					'<paragraph>p</paragraph>' +642					'<listItem listIndent="0" listType="bulleted">a</listItem>' +643					'[<listItem listIndent="0" listType="bulleted">b</listItem>]' +644					'<listItem listIndent="0" listType="bulleted">c</listItem>',645					'<p>p</p>' +646					'<ul>' +647						'<li>a</li>' +648						'<li>c</li>' +649					'</ul>'650				);651				testRemove(652					'remove the last list item',653					'<paragraph>p</paragraph>' +654					'<listItem listIndent="0" listType="bulleted">a</listItem>' +655					'<listItem listIndent="0" listType="bulleted">b</listItem>' +656					'[<listItem listIndent="0" listType="bulleted">c</listItem>]',657					'<p>p</p>' +658					'<ul>' +659						'<li>a</li>' +660						'<li>b</li>' +661					'</ul>'662				);663				testRemove(664					'remove the only list item',665					'<paragraph>p</paragraph>' +666					'[<listItem listIndent="0" listType="bulleted">x</listItem>]' +667					'<paragraph>p</paragraph>',668					'<p>p</p>' +669					'<p>p</p>'670				);671				testRemove(672					'remove element from between lists of same type',673					'<paragraph>p</paragraph>' +674					'<listItem listIndent="0" listType="bulleted">a</listItem>' +675					'[<paragraph>x</paragraph>]' +676					'<listItem listIndent="0" listType="bulleted">b</listItem>' +677					'<paragraph>p</paragraph>',678					'<p>p</p>' +679					'<ul>' +680						'<li>a</li>' +681						'<li>b</li>' +682					'</ul>' +683					'<p>p</p>'684				);685				testRemove(686					'remove element from between lists of different type',687					'<paragraph>p</paragraph>' +688					'<listItem listIndent="0" listType="bulleted">a</listItem>' +689					'[<paragraph>x</paragraph>]' +690					'<listItem listIndent="0" listType="numbered">b</listItem>' +691					'<paragraph>p</paragraph>',692					'<p>p</p>' +693					'<ul>' +694						'<li>a</li>' +695					'</ul>' +696					'<ol>' +697						'<li>b</li>' +698					'</ol>' +699					'<p>p</p>'700				);701			} );702			describe( 'change type', () => {703				testChangeType(704					'change first list item',705					'<paragraph>p</paragraph>' +706					'[<listItem listIndent="0" listType="bulleted">a</listItem>]' +707					'<listItem listIndent="0" listType="bulleted">b</listItem>' +708					'<listItem listIndent="0" listType="bulleted">c</listItem>',709					'<p>p</p>' +710					'<ol>' +711						'<li>a</li>' +712					'</ol>' +713					'<ul>' +714						'<li>b</li>' +715						'<li>c</li>' +716					'</ul>'717				);718				testChangeType(719					'change middle list item',720					'<paragraph>p</paragraph>' +721					'<listItem listIndent="0" listType="bulleted">a</listItem>' +722					'[<listItem listIndent="0" listType="bulleted">b</listItem>]' +723					'<listItem listIndent="0" listType="bulleted">c</listItem>',724					'<p>p</p>' +725					'<ul>' +726						'<li>a</li>' +727					'</ul>' +728					'<ol>' +729						'<li>b</li>' +730					'</ol>' +731					'<ul>' +732						'<li>c</li>' +733					'</ul>'734				);735				testChangeType(736					'change last list item',737					'<paragraph>p</paragraph>' +738					'<listItem listIndent="0" listType="bulleted">a</listItem>' +739					'<listItem listIndent="0" listType="bulleted">b</listItem>' +740					'[<listItem listIndent="0" listType="bulleted">c</listItem>]',741					'<p>p</p>' +742					'<ul>' +743						'<li>a</li>' +744						'<li>b</li>' +745					'</ul>' +746					'<ol>' +747						'<li>c</li>' +748					'</ol>'749				);750				testChangeType(751					'change only list item',752					'<paragraph>p</paragraph>' +753					'[<listItem listIndent="0" listType="bulleted">a</listItem>]' +754					'<paragraph>p</paragraph>',755					'<p>p</p>' +756					'<ol>' +757						'<li>a</li>' +758					'</ol>' +759					'<p>p</p>'760				);761				testChangeType(762					'change element at the edge of two different lists #1',763					'<listItem listIndent="0" listType="bulleted">a</listItem>' +764					'<listItem listIndent="0" listType="bulleted">b</listItem>' +765					'[<listItem listIndent="0" listType="bulleted">c</listItem>]' +766					'<listItem listIndent="0" listType="numbered">d</listItem>',767					'<ul>' +768						'<li>a</li>' +769						'<li>b</li>' +770					'</ul>' +771					'<ol>' +772						'<li>c</li>' +773						'<li>d</li>' +774					'</ol>'775				);776				testChangeType(777					'change element at the edge of two different lists #1',778					'<listItem listIndent="0" listType="numbered">a</listItem>' +779					'[<listItem listIndent="0" listType="bulleted">b</listItem>]' +780					'<listItem listIndent="0" listType="bulleted">c</listItem>' +781					'<listItem listIndent="0" listType="bulleted">d</listItem>',782					'<ol>' +783						'<li>a</li>' +784						'<li>b</li>' +785					'</ol>' +786					'<ul>' +787						'<li>c</li>' +788						'<li>d</li>' +789					'</ul>'790				);791				testChangeType(792					'change multiple elements #1',793					'<listItem listIndent="0" listType="bulleted">a</listItem>' +794					'[<listItem listIndent="0" listType="bulleted">b</listItem>' +795					'<listItem listIndent="0" listType="bulleted">c</listItem>]' +796					'<listItem listIndent="0" listType="bulleted">d</listItem>',797					'<ul>' +798						'<li>a</li>' +799					'</ul>' +800					'<ol>' +801						'<li>b</li>' +802						'<li>c</li>' +803					'</ol>' +804					'<ul>' +805						'<li>d</li>' +806					'</ul>'807				);808				testChangeType(809					'change multiple elements #2',810					'<listItem listIndent="0" listType="numbered">a</listItem>' +811					'[<listItem listIndent="0" listType="bulleted">b</listItem>' +812					'<listItem listIndent="0" listType="bulleted">c</listItem>]' +813					'<listItem listIndent="0" listType="numbered">d</listItem>',814					'<ol>' +815						'<li>a</li>' +816						'<li>b</li>' +817						'<li>c</li>' +818						'<li>d</li>' +819					'</ol>'820				);821			} );822			describe( 'rename from list item', () => {823				testRenameFromListItem(824					'rename first list item',825					'[<listItem listIndent="0" listType="bulleted">a</listItem>]' +826					'<listItem listIndent="0" listType="bulleted">b</listItem>',827					'<p>a</p>' +828					'<ul>' +829						'<li>b</li>' +830					'</ul>'831				);832				testRenameFromListItem(833					'rename middle list item',834					'<listItem listIndent="0" listType="bulleted">a</listItem>' +835					'[<listItem listIndent="0" listType="bulleted">b</listItem>]' +836					'<listItem listIndent="0" listType="bulleted">c</listItem>',837					'<ul>' +838						'<li>a</li>' +839					'</ul>' +840					'<p>b</p>' +841					'<ul>' +842						'<li>c</li>' +843					'</ul>'844				);845				testRenameFromListItem(846					'rename last list item',847					'<listItem listIndent="0" listType="bulleted">a</listItem>' +848					'[<listItem listIndent="0" listType="bulleted">b</listItem>]',849					'<ul>' +850						'<li>a</li>' +851					'</ul>' +852					'<p>b</p>'853				);854				testRenameFromListItem(855					'rename only list item',856					'<paragraph>p</paragraph>' +857					'[<listItem listIndent="0" listType="bulleted">x</listItem>]' +858					'<paragraph>p</paragraph>',859					'<p>p</p>' +860					'<p>x</p>' +861					'<p>p</p>'862				);863			} );864			describe( 'rename to list item (with attribute change)', () => {865				testRenameToListItem(866					'only paragraph', 0,867					'[<paragraph>a</paragraph>]',868					'<ul>' +869						'<li>a</li>' +870					'</ul>'871				);872				testRenameToListItem(873					'paragraph between paragraphs', 0,874					'<paragraph>x</paragraph>' +875					'[<paragraph>a</paragraph>]' +876					'<paragraph>x</paragraph>',877					'<p>x</p>' +878					'<ul>' +879						'<li>a</li>' +880					'</ul>' +881					'<p>x</p>'882				);883				testRenameToListItem(884					'element before list of same type', 0,885					'[<paragraph>x</paragraph>]' +886					'<listItem listIndent="0" listType="bulleted">a</listItem>',887					'<ul>' +888						'<li>x</li>' +889						'<li>a</li>' +890					'</ul>'891				);892				testRenameToListItem(893					'element after list of same type', 0,894					'<listItem listIndent="0" listType="bulleted">a</listItem>' +895					'[<paragraph>x</paragraph>]',896					'<ul>' +897						'<li>a</li>' +898						'<li>x</li>' +899					'</ul>'900				);901				testRenameToListItem(902					'element before list of different type', 0,903					'[<paragraph>x</paragraph>]' +904					'<listItem listIndent="0" listType="numbered">a</listItem>',905					'<ul>' +906						'<li>x</li>' +907					'</ul>' +908					'<ol>' +909						'<li>a</li>' +910					'</ol>'911				);912				testRenameToListItem(913					'element after list of different type', 0,914					'<listItem listIndent="0" listType="numbered">a</listItem>' +915					'[<paragraph>x</paragraph>]',916					'<ol>' +917						'<li>a</li>' +918					'</ol>' +919					'<ul>' +920						'<li>x</li>' +921					'</ul>'922				);923				testRenameToListItem(924					'element between lists of same type', 0,925					'<listItem listIndent="0" listType="bulleted">a</listItem>' +926					'[<paragraph>x</paragraph>]' +927					'<listItem listIndent="0" listType="bulleted">b</listItem>',928					'<ul>' +929						'<li>a</li>' +930						'<li>x</li>' +931						'<li>b</li>' +932					'</ul>'933				);934			} );935			describe( 'move', () => {936				testMove(937					'list item inside same list',938					'<paragraph>p</paragraph>' +939					'<listItem listIndent="0" listType="bulleted">a</listItem>' +940					'[<listItem listIndent="0" listType="bulleted">b</listItem>]' +941					'<listItem listIndent="0" listType="bulleted">c</listItem>',942					4, // Move after last item.943					'<p>p</p>' +944					'<ul>' +945						'<li>a</li>' +946						'<li>c</li>' +947						'<li>b</li>' +948					'</ul>'949				);950				testMove(951					'out list item from list',952					'<paragraph>p</paragraph>' +953					'<listItem listIndent="0" listType="bulleted">a</listItem>' +954					'[<listItem listIndent="0" listType="bulleted">b</listItem>]' +955					'<paragraph>p</paragraph>',956					4, // Move after second paragraph.957					'<p>p</p>' +958					'<ul>' +959						'<li>a</li>' +960					'</ul>' +961					'<p>p</p>' +962					'<ul>' +963						'<li>b</li>' +964					'</ul>'965				);966				testMove(967					'the only list item',968					'<paragraph>p</paragraph>' +969					'[<listItem listIndent="0" listType="bulleted">a</listItem>]' +970					'<paragraph>p</paragraph>',971					3, // Move after second paragraph.972					'<p>p</p>' +973					'<p>p</p>' +974					'<ul>' +975						'<li>a</li>' +976					'</ul>'977				);978				testMove(979					'list item between two lists of same type',980					'<listItem listIndent="0" listType="bulleted">a</listItem>' +981					'[<listItem listIndent="0" listType="bulleted">b</listItem>]' +982					'<paragraph>p</paragraph>' +983					'<listItem listIndent="0" listType="bulleted">c</listItem>' +984					'<listItem listIndent="0" listType="bulleted">d</listItem>',985					4, // Move between list item "c" and list item "d'.986					'<ul>' +987						'<li>a</li>' +988					'</ul>' +989					'<p>p</p>' +990					'<ul>' +991						'<li>c</li>' +992						'<li>b</li>' +993						'<li>d</li>' +994					'</ul>'995				);996				testMove(997					'list item between two lists of different type',998					'<listItem listIndent="0" listType="bulleted">a</listItem>' +999					'[<listItem listIndent="0" listType="bulleted">b</listItem>]' +1000					'<paragraph>p</paragraph>' +1001					'<listItem listIndent="0" listType="numbered">c</listItem>' +1002					'<listItem listIndent="0" listType="numbered">d</listItem>',1003					4, // Move between list item "c" and list item "d'.1004					'<ul>' +1005						'<li>a</li>' +1006					'</ul>' +1007					'<p>p</p>' +1008					'<ol>' +1009						'<li>c</li>' +1010					'</ol>' +1011					'<ul>' +1012						'<li>b</li>' +1013					'</ul>' +1014					'<ol>' +1015						'<li>d</li>' +1016					'</ol>'1017				);1018				testMove(1019					'element between list items',1020					'<listItem listIndent="0" listType="bulleted">a</listItem>' +1021					'<listItem listIndent="0" listType="bulleted">b</listItem>' +1022					'[<paragraph>p</paragraph>]',1023					1, // Move between list item "a" and list item "b'.1024					'<ul>' +1025						'<li>a</li>' +1026					'</ul>' +1027					'<p>p</p>' +1028					'<ul>' +1029						'<li>b</li>' +1030					'</ul>'1031				);1032			} );1033		} );1034	} );1035	describe( 'nested lists', () => {1036		describe( 'setting data', () => {1037			function testList( string, expectedString = null ) {1038				return () => {1039					editor.setData( string );1040					assertEqualMarkup( editor.getData(), expectedString || string );1041				};1042			}1043			describe( 'non HTML compliant list fixing', () => {1044				it( 'ul in ul', testList(1045					'<ul>' +1046						'<ul>' +1047							'<li>1.1</li>' +1048						'</ul>' +1049					'</ul>',1050					'<ul>' +1051						'<li>1.1</li>' +1052					'</ul>'1053				) );1054				it( 'ul in ol', testList(1055					'<ol>' +1056						'<ul>' +1057							'<li>1.1</li>' +1058						'</ul>' +1059					'</ol>',1060					'<ul>' +1061					'<li>1.1</li>' +1062					'</ul>'1063				) );1064				it( 'ul in ul (previous sibling is li)', testList(1065					'<ul>' +1066						'<li>1</li>' +1067						'<ul>' +1068							'<li>2.1</li>' +1069						'</ul>' +1070					'</ul>',1071					'<ul>' +1072						'<li>1' +1073							'<ul>' +1074								'<li>2.1</li>' +1075							'</ul>' +1076						'</li>' +1077					'</ul>'1078				) );1079				it( 'ul in deeply nested ul - base index > 0 #1', testList(1080					'<ul>' +1081						'<li>1.1</li>' +1082						'<li>1.2' +1083							'<ul>' +1084								'<ul>' +1085									'<ul>' +1086										'<ul>' +1087											'<li>2.1</li>' +1088										'</ul>' +1089									'</ul>' +1090								'</ul>' +1091							'</ul>' +1092						'</li>' +1093					'</ul>',1094					'<ul>' +1095						'<li>1.1</li>' +1096						'<li>1.2' +1097							'<ul>' +1098								'<li>2.1</li>' +1099							'</ul>' +1100						'</li>' +1101					'</ul>'1102				) );1103				it( 'ul in deeply nested ul - base index > 0 #2', testList(1104					'<ul>' +1105						'<li>1.1</li>' +1106						'<li>1.2' +1107							'<ul>' +1108								'<li>2.1</li>' +1109								'<ul>' +1110									'<ul>' +1111										'<ul>' +1112											'<li>3.1</li>' +1113										'</ul>' +1114									'</ul>' +1115								'</ul>' +1116								'<li>2.2</li>' +1117							'</ul>' +1118						'</li>' +1119					'</ul>',1120					'<ul>' +1121						'<li>1.1</li>' +1122						'<li>1.2' +1123							'<ul>' +1124								'<li>2.1' +1125									'<ul>' +1126										'<li>3.1</li>' +1127									'</ul>' +1128								'</li>' +1129								'<li>2.2</li>' +1130							'</ul>' +1131						'</li>' +1132					'</ul>'1133				) );1134				it( 'ul in deeply nested ul inside li', testList(1135					'<ul>' +1136						'<li>A' +1137							'<ul>' +1138								'<ul>' +1139									'<ul>' +1140										'<ul>' +1141											'<li>B</li>' +1142										'</ul>' +1143									'</ul>' +1144								'</ul>' +1145								'<li>C</li>' +1146							'</ul>' +1147						'</li>' +1148					'</ul>',1149					'<ul>' +1150					'<li>A' +1151						'<ul>' +1152							'<li>B</li>' +1153							'<li>C</li>' +1154						'</ul>' +1155					'</li>' +1156					'</ul>'1157				) );1158				it( 'ul in deeply nested ul/ol', testList(1159					'<ul>' +1160						'<li>A' +1161							'<ol>' +1162								'<ul>' +1163									'<ol>' +1164										'<ul>' +1165											'<li>B</li>' +1166										'</ul>' +1167									'</ol>' +1168								'</ul>' +1169								'<li>C</li>' +1170							'</ol>' +1171						'</li>' +1172					'</ul>',1173					'<ul>' +1174						'<li>A' +1175						'<ul>' +1176							'<li>B</li>' +1177							'<li>C</li>' +1178						'</ul>' +1179						'</li>' +1180					'</ul>'1181				) );1182				it( 'ul in ul (complex case)', testList(1183					'<ol>' +1184						'<li>1</li>' +1185						'<ul>' +1186							'<li>A</li>' +1187							'<ol>' +1188								'<li>1</li>' +1189							'</ol>' +1190						'</ul>' +1191						'<li>2</li>' +1192						'<li>3</li>' +1193						'<ul>' +1194							'<li>A</li>' +1195							'<li>B</li>' +1196						'</ul>' +1197					'</ol>' +1198					'<ul>' +1199						'<li>A</li>' +1200						'<ol>' +1201							'<li>1</li>' +1202							'<li>2</li>' +1203						'</ol>' +1204					'</ul>',1205					'<ol>' +1206						'<li>1' +1207							'<ul>' +1208								'<li>A' +1209									'<ol>' +1210										'<li>1</li>' +1211									'</ol>' +1212								'</li>' +1213							'</ul>' +1214						'</li>' +1215						'<li>2</li>' +1216						'<li>3' +1217							'<ul>' +1218								'<li>A</li>' +1219								'<li>B</li>' +1220							'</ul>' +1221						'</li>' +1222					'</ol>' +1223					'<ul>' +1224						'<li>A' +1225							'<ol>' +1226								'<li>1</li>' +1227								'<li>2</li>' +1228							'</ol>' +1229						'</li>' +1230					'</ul>'1231				) );1232				it( 'ol in ol (deep structure)', testList(1233					'<ol>' +1234						'<li>A1</li>' +1235						'<ol>' +1236							'<ol>' +1237								'<ol>' +1238									'<ol>' +1239										'<ol>' +1240											'<ol>' +1241												'<ol>' +1242													'<li>B8</li>' +1243												'</ol>' +1244											'</ol>' +1245										'</ol>' +1246									'</ol>' +1247								'</ol>' +1248								'<li>C3</li>' +1249								'<ol>' +1250									'<li>D4</li>' +1251								'</ol>' +1252							'</ol>' +1253							'<li>E2</li>' +1254						'</ol>' +1255					'</ol>',1256					'<ol>' +1257						'<li>A1' +1258							'<ol>' +1259								'<li>B8</li>' +1260								'<li>C3' +1261									'<ol>' +1262										'<li>D4</li>' +1263									'</ol>' +1264								'</li>' +1265								'<li>E2</li>' +1266							'</ol>' +1267						'</li>' +1268					'</ol>'1269				) );1270				it( 'block elements wrapping nested ul', testList(1271					'text before' +1272					'<ul>' +1273						'<li>' +1274							'text' +1275							'<div>' +1276								'<ul>' +1277									'<li>inner text</li>' +1278								'</ul>' +1279							'</div>' +1280						'</li>' +1281					'</ul>',1282					'<p>text before</p>' +1283					'<ul>' +1284						'<li>' +1285							'text' +1286							'<ul>' +1287								'<li>inner text</li>' +1288							'</ul>' +1289						'</li>' +1290					'</ul>'1291				) );1292				it( 'block elements wrapping nested ul - invalid blocks', testList(1293					'<ul>' +1294						'<li>' +1295							'a' +1296							'<table>' +1297								'<tr>' +1298									'<td>' +1299										'<div>' +1300											'<ul>' +1301												'<li>b</li>' +1302												'<li>c' +1303													'<ul>' +1304														'<li>' +1305															'd' +1306															'<table>' +1307																'<tr>' +1308																	'<td>' +1309																		'e' +1310																	'</td>' +1311																'</tr>' +1312															'</table>' +1313														'</li>' +1314													'</ul>' +1315												'</li>' +1316											'</ul>' +1317										'</div>' +1318									'</td>' +1319								'</tr>' +1320							'</table>' +1321							'f' +1322						'</li>' +1323						'<li>g</li>' +1324					'</ul>',1325					'<ul>' +1326						'<li>a</li>' +1327					'</ul>' +1328					'<figure class="table">' +1329						'<table>' +1330							'<tbody>' +1331								'<tr>' +1332									'<td>' +1333										'<ul>' +1334											'<li>b</li>' +1335											'<li>c<ul>' +1336											'<li>d</li>' +1337										'</ul>' +1338										'</li>' +1339										'</ul>' +1340										'<p>e</p>' +1341									'</td>' +1342								'</tr>' +1343							'</tbody>' +1344						'</table>' +1345					'</figure>' +1346					'<ul>' +1347					'<li>f</li>' +1348					'<li>g</li>' +1349					'</ul>'1350				) );1351				it( 'deeply nested block elements wrapping nested ul', testList(1352					'<ul>' +1353							'<li>' +1354								'a' +1355								'<div>' +1356									'<div>' +1357										'<ul>' +1358											'<li>b</li>' +1359											'<li>c' +1360												'<ul>' +1361													'<li>d' +1362														'<div>' +1363															'<ul>' +1364																'<li>e</li>' +1365															'</ul>' +1366														'</div>' +1367													'</li>' +1368												'</ul>' +1369											'</li>' +1370										'</ul>' +1371									'</div>' +1372								'</div>' +1373								'f' +1374							'</li>' +1375						'<li>g</li>' +1376						'</ul>' +1377					'</ul>',1378					'<ul>' +1379						'<li>a' +1380							'<ul>' +1381								'<li>b</li>' +1382								'<li>c' +1383									'<ul>' +1384										'<li>d' +1385											'<ul>' +1386												'<li>e</li>' +1387											'</ul>' +1388										'</li>' +1389									'</ul>' +1390								'</li>' +1391							'</ul>' +1392						'</li>' +1393						'<li>f</li>' +1394						'<li>g</li>' +1395					'</ul>'1396				) );1397			} );1398			it( 'bullet list simple structure', testList(1399				'<p>foo</p>' +1400				'<ul>' +1401					'<li>' +1402						'1' +1403						'<ul>' +1404							'<li>1.1</li>' +1405						'</ul>' +1406					'</li>' +1407				'</ul>' +1408				'<p>bar</p>'1409			) );1410			it( 'bullet list deep structure', testList(1411				'<p>foo</p>' +1412				'<ul>' +1413					'<li>' +1414						'1' +1415						'<ul>' +1416							'<li>' +1417								'1.1' +1418								'<ul><li>1.1.1</li><li>1.1.2</li><li>1.1.3</li><li>1.1.4</li></ul>' +1419							'</li>' +1420							'<li>' +1421								'1.2' +1422								'<ul><li>1.2.1</li></ul>' +1423							'</li>' +1424						'</ul>' +1425					'</li>' +1426					'<li>2</li>' +1427					'<li>' +1428						'3' +1429						'<ul>' +1430							'<li>' +1431								'3.1' +1432								'<ul>' +1433									'<li>' +1434										'3.1.1' +1435										'<ul><li>3.1.1.1</li></ul>' +1436									'</li>' +1437									'<li>3.1.2</li>' +1438								'</ul>' +1439							'</li>' +1440						'</ul>' +1441					'</li>' +1442				'</ul>' +1443				'<p>bar</p>'1444			) );1445			it( 'mixed lists deep structure', testList(1446				'<p>foo</p>' +1447				'<ul>' +1448					'<li>' +1449						'1' +1450						'<ul>' +1451							'<li>' +1452								'1.1' +1453								'<ul><li>1.1.1</li><li>1.1.2</li></ul>' +1454								'<ol><li>1.1.3</li><li>1.1.4</li></ol>' +1455							'</li>' +1456							'<li>' +1457								'1.2' +1458								'<ul><li>1.2.1</li></ul>' +1459							'</li>' +1460						'</ul>' +1461					'</li>' +1462					'<li>2</li>' +1463					'<li>' +1464						'3' +1465						'<ol>' +1466							'<li>' +1467								'3.1' +1468								'<ul>' +1469									'<li>' +1470										'3.1.1' +1471										'<ol><li>3.1.1.1</li></ol>' +1472										'<ul><li>3.1.1.2</li></ul>' +1473									'</li>' +1474									'<li>3.1.2</li>' +1475								'</ul>' +1476							'</li>' +1477						'</ol>' +1478						'<ul>' +1479							'<li>3.2</li>' +1480							'<li>3.3</li>' +1481						'</ul>' +1482					'</li>' +1483				'</ul>' +1484				'<p>bar</p>',1485				'<p>foo</p>' +1486				'<ul>' +1487					'<li>' +1488						'1' +1489						'<ul>' +1490							'<li>' +1491								'1.1' +1492								'<ul><li>1.1.1</li><li>1.1.2</li><li>1.1.3</li><li>1.1.4</li></ul>' +1493							'</li>' +1494							'<li>' +1495								'1.2' +1496								'<ul><li>1.2.1</li></ul>' +1497							'</li>' +1498						'</ul>' +1499					'</li>' +1500					'<li>2</li>' +1501					'<li>' +1502						'3' +1503						'<ol>' +1504							'<li>' +1505								'3.1' +1506								'<ul>' +1507									'<li>' +1508										'3.1.1' +1509										'<ol><li>3.1.1.1</li><li>3.1.1.2</li></ol>' +1510									'</li>' +1511									'<li>3.1.2</li>' +1512								'</ul>' +1513							'</li>' +1514							'<li>3.2</li>' +1515							'<li>3.3</li>' +1516						'</ol>' +1517					'</li>' +1518				'</ul>' +1519				'<p>bar</p>'1520			) );1521			it( 'mixed lists deep structure, white spaces, incorrect content, empty items', testList(1522				'<p>foo</p>' +1523				'<ul>' +1524				'	xxx' +1525				'	<li>' +1526				'		1' +1527				'		<ul>' +1528				'			xxx' +1529				'			<li>' +1530				'				<ul><li></li><li>1.1.2</li></ul>' +1531				'				<ol><li>1.1.3</li><li>1.1.4</li></ol>' +		// Will be changed to <ul>.1532				'			</li>' +1533				'			<li>' +1534				'				<ul><li>1.2.1</li></ul>' +1535				'			</li>' +1536				'			xxx' +1537				'		</ul>' +1538				'	</li>' +1539				'	<li>2</li>' +1540				'	<li>' +1541				'		<ol>' +1542				'			<p>xxx</p>' +1543				'			<li>' +1544				'				3<strong>.</strong>1' +							// Test multiple text nodes in <li>.1545				'				<ul>' +1546				'					<li>' +1547				'						3.1.1' +1548				'						<ol><li>3.1.1.1</li></ol>' +1549				'						<ul><li>3.1.1.2</li></ul>' +			// Will be changed to <ol>.1550				'					</li>' +1551				'					<li>3.1.2</li>' +1552				'				</ul>' +1553				'			</li>' +1554				'		</ol>' +1555				'		<p>xxx</p>' +1556				'		<ul>' +													// Since <p> gets removed, this will become <ol>.1557				'			<li>3.2</li>' +1558				'			<li>3.3</li>' +1559				'		</ul>' +1560				'	</li>' +1561				'	<p>xxx</p>' +1562				'</ul>' +1563				'<p>bar</p>',1564				'<p>foo</p>' +1565				'<ul>' +1566					'<li>' +1567						'1' +1568						'<ul>' +1569							'<li>' +1570								'&nbsp;' +1571								'<ul>' +1572									'<li>&nbsp;</li>' +1573									'<li>1.1.2</li>' +1574									'<li>1.1.3</li>' +1575									'<li>1.1.4</li>' +1576								'</ul>' +1577							'</li>' +1578							'<li>' +1579								'&nbsp;' +1580								'<ul><li>1.2.1</li></ul>' +1581							'</li>' +1582						'</ul>' +1583					'</li>' +1584					'<li>2</li>' +1585					'<li>' +1586						'&nbsp;' +1587						'<ol>' +1588							'<li>' +1589								'3<strong>.</strong>1' +1590								'<ul>' +1591									'<li>' +1592										'3.1.1' +1593										'<ol>' +1594											'<li>3.1.1.1</li>' +1595											'<li>3.1.1.2</li>' +1596										'</ol>' +1597									'</li>' +1598									'<li>3.1.2</li>' +1599								'</ul>' +1600							'</li>' +1601							'<li>3.2</li>' +1602							'<li>3.3</li>' +1603						'</ol>' +1604					'</li>' +1605				'</ul>' +1606				'<p>bar</p>'1607			) );1608			describe( 'model tests for nested lists', () => {1609				it( 'should properly set listIndent and listType', () => {1610					// <ol> in the middle will be fixed by postfixer to bulleted list.1611					editor.setData(1612						'<p>foo</p>' +1613						'<ul>' +1614							'<li>' +1615								'1' +1616								'<ul>' +1617									'<li>1.1</li>' +1618								'</ul>' +1619								'<ol>' +1620									'<li>' +1621										'1.2' +1622										'<ol>' +1623											'<li>1.2.1</li>' +1624										'</ol>' +1625									'</li>' +1626									'<li>1.3</li>' +1627								'</ol>' +1628							'</li>' +1629							'<li>2</li>' +1630						'</ul>' +1631						'<p>bar</p>'1632					);1633					const expectedModelData =1634						'<paragraph>foo</paragraph>' +1635						'<listItem listIndent="0" listType="bulleted">1</listItem>' +1636						'<listItem listIndent="1" listType="bulleted">1.1</listItem>' +1637						'<listItem listIndent="1" listType="bulleted">1.2</listItem>' +1638						'<listItem listIndent="2" listType="numbered">1.2.1</listItem>' +1639						'<listItem listIndent="1" listType="bulleted">1.3</listItem>' +1640						'<listItem listIndent="0" listType="bulleted">2</listItem>' +1641						'<paragraph>bar</paragraph>';1642					assertEqualMarkup( getModelData( model, { withoutSelection: true } ), expectedModelData );1643				} );1644				it( 'should properly listIndent when list nested in other block', () => {1645					editor.setData(1646						'<ul>' +1647							'<li>' +1648								'a' +1649								'<table>' +1650									'<tr>' +1651									'<td>' +1652										'<div>' +1653											'<ul>' +1654											'<li>b</li>' +1655											'<li>c' +1656												'<ul>' +1657													'<li>' +1658														'd' +1659														'<table>' +1660															'<tr>' +1661																'<td>e</td>' +1662															'</tr>' +1663														'</table>' +1664													'</li>' +1665												'</ul>' +1666											'</li>' +1667											'</ul>' +1668										'</div>' +1669									'</td>' +1670									'</tr>' +1671								'</table>' +1672								'f' +1673								'</li>' +1674							'<li>g</li>' +1675						'</ul>'1676					);1677					const expectedModelData =1678						'<listItem listIndent="0" listType="bulleted">a</listItem>' +1679						'<table>' +1680							'<tableRow>' +1681								'<tableCell>' +1682									'<listItem listIndent="0" listType="bulleted">b</listItem>' +1683									'<listItem listIndent="0" listType="bulleted">c</listItem>' +1684									'<listItem listIndent="1" listType="bulleted">d</listItem>' +1685									'<paragraph>e</paragraph>' +1686								'</tableCell>' +1687							'</tableRow>' +1688						'</table>' +1689						'<listItem listIndent="0" listType="bulleted">f</listItem>' +1690						'<listItem listIndent="0" listType="bulleted">g</listItem>';1691					assertEqualMarkup( getModelData( model, { withoutSelection: true } ), expectedModelData );1692				} );1693			} );1694		} );1695		describe( 'position mapping', () => {1696			let mapper;1697			beforeEach( () => {1698				mapper = editor.editing.mapper;1699				editor.setData(1700					'<ul>' +1701						'<li>a</li>' +1702						'<li>' +1703							'bbb' +1704							'<ol>' +1705								'<li>c</li>' +1706								'<li>d</li>' +1707								'<li>e</li>' +1708								'<li>' +1709									'<ul>' +1710										'<li>g</li>' +1711										'<li>h</li>' +1712										'<li>i</li>' +1713									'</ul>' +1714								'</li>' +1715								'<li>j</li>' +1716							'</ol>' +1717						'</li>' +1718						'<li>k</li>' +1719					'</ul>'1720				);1721			} );1722			/*1723				<listItem listIndent=0 listType="bulleted">a</listItem>1724				<listItem listIndent=0 listType="bulleted">bbb</listItem>1725				<listItem listIndent=1 listType="numbered">c</listItem>1726				<listItem listIndent=1 listType="numbered">d</listItem>1727				<listItem listIndent=1 listType="numbered">e</listItem>1728				<listItem listIndent=1 listType="numbered"></listItem>1729				<listItem listIndent=2 listType="bulleted">g</listItem>1730				<listItem listIndent=2 listType="bulleted">h</listItem>1731				<listItem listIndent=2 listType="bullered">i</listItem>1732				<listItem listIndent=1 listType="numbered">j</listItem>1733				<listItem listIndent=0 listType="bulleted">k</listItem>1734			 */1735			describe( 'view to model', () => {1736				function testList( testName, viewPath, modelPath ) {1737					it( testName, () => {1738						const viewPos = getViewPosition( viewRoot, viewPath, view );1739						const modelPos = mapper.toModelPosition( viewPos );1740						expect( modelPos.root ).to.equal( modelRoot );1741						expect( modelPos.path ).to.deep.equal( modelPath );1742					} );1743				}1744				testList( 'before ul#1',		[ 0 ],					[ 0 ] );	// --> before listItem "a"1745				testList( 'before li "a"',		[ 0, 0 ],				[ 0 ] );	// --> before listItem "a"1746				testList( 'before "a"',			[ 0, 0, 0 ],			[ 0, 0 ] );	// --> beginning of listItem "a"1747				testList( 'after "a"',			[ 0, 0, 1 ],			[ 0, 1 ] );	// --> end of listItem "a"1748				testList( 'before li "bbb"',	[ 0, 1 ],				[ 1 ] );	// --> before listItem "bbb"1749				testList( 'before "bbb"',		[ 0, 1, 0 ],			[ 1, 0 ] );	// --> beginning of listItem "bbb"1750				testList( 'after "bbb"',		[ 0, 1, 1 ],			[ 1, 3 ] );	// --> end of listItem "bbb"1751				testList( 'before li "c"',		[ 0, 1, 1, 0 ],			[ 2 ] );	// --> before listItem "c"1752				testList( 'before "c"',			[ 0, 1, 1, 0, 0 ],		[ 2, 0 ] );	// --> beginning of listItem "c"1753				testList( 'after "c"',			[ 0, 1, 1, 0, 1 ],		[ 2, 1 ] );	// --> end of listItem "c"1754				testList( 'before li "d"',		[ 0, 1, 1, 1 ],			[ 3 ] );	// --> before listItem "d"1755				testList( 'before li "e"',		[ 0, 1, 1, 2 ],			[ 4 ] );	// --> before listItem "e"1756				testList( 'before "empty" li',	[ 0, 1, 1, 3 ],			[ 5 ] );	// --> before "empty" listItem1757				testList( 'before ul#2',		[ 0, 1, 1, 3, 0 ],		[ 5, 0 ] ); // --> inside "empty" listItem1758				testList( 'before li "g"',		[ 0, 1, 1, 3, 0, 0 ],	[ 6 ] );	// --> before listItem "g"1759				testList( 'before li "h"',		[ 0, 1, 1, 3, 0, 1 ],	[ 7 ] );	// --> before listItem "h"1760				testList( 'before li "i"',		[ 0, 1, 1, 3, 0, 2 ],	[ 8 ] );	// --> before listItem "i"1761				testList( 'after li "i"',		[ 0, 1, 1, 3, 0, 3 ],	[ 9 ] );	// --> before listItem "j"1762				testList( 'after ul#2',			[ 0, 1, 1, 3, 1 ],		[ 9 ] );	// --> before listItem "j"1763				testList( 'before li "j"',		[ 0, 1, 1, 4 ],			[ 9 ] );	// --> before listItem "j"1764				testList( 'after li "j"',		[ 0, 1, 1, 5 ],			[ 10 ] );	// --> before listItem "k"1765				testList( 'end of li "bbb"',	[ 0, 1, 2 ],			[ 10 ] );	// --> before listItem "k"1766				testList( 'before li "k"',		[ 0, 2 ],				[ 10 ] );	// --> before listItem "k"1767				testList( 'after li "k"',		[ 0, 3 ],				[ 11 ] );	// --> after listItem "k"1768				testList( 'after ul',			[ 1 ],					[ 11 ] );	// --> after listItem "k"1769			} );1770			describe( 'model to view', () => {1771				function testList( testName, modelPath, viewPath ) {1772					it( testName, () => {1773						const modelPos = model.createPositionFromPath( modelRoot, modelPath );1774						const viewPos = mapper.toViewPosition( modelPos );1775						expect( viewPos.root ).to.equal( viewRoot );1776						expect( getViewPath( viewPos ) ).to.deep.equal( viewPath );1777					} );1778				}1779				testList( 'before listItem "a"',			[ 0 ],		[ 0 ] );				// --> before ul1780				testList( 'beginning of listItem "a"',		[ 0, 0 ],	[ 0, 0, 0, 0 ] );		// --> beginning of "a" text node1781				testList( 'end of listItem "a"',			[ 0, 1 ],	[ 0, 0, 0, 1 ] );		// --> end of "a" text node1782				testList( 'before listItem "bbb"',			[ 1 ],		[ 0, 1 ] );				// --> before li "bbb"1783				testList( 'beginning of listItem "bbb"',	[ 1, 0 ],	[ 0, 1, 0, 0 ] );		// --> beginning of "bbb" text node1784				testList( 'end of listItem "bbb"',			[ 1, 3 ],	[ 0, 1, 0, 3 ] );		// --> end of "bbb" text node1785				testList( 'before listItem "c"',			[ 2 ],		[ 0, 1, 1, 0 ] );		// --> before li "c"1786				testList( 'beginning of listItem "c"',		[ 2, 0 ],	[ 0, 1, 1, 0, 0, 0 ] );	// --> beginning of "c" text node1787				testList( 'end of listItem "c"',			[ 2, 1 ],	[ 0, 1, 1, 0, 0, 1 ] );	// --> end of "c" text node1788				testList( 'before listItem "d"',			[ 3 ],		[ 0, 1, 1, 1 ] );		// --> before li "d"1789				testList( 'before listItem "e"',			[ 4 ],		[ 0, 1, 1, 2 ] );		// --> before li "e"1790				testList( 'before "empty" listItem',		[ 5 ],		[ 0, 1, 1, 3 ] );		// --> before "empty" li1791				testList( 'inside "empty" listItem',		[ 5, 0 ],	[ 0, 1, 1, 3, 0 ] );	// --> before ul1792				testList( 'before listItem "g"',			[ 6 ],		[ 0, 1, 1, 3, 0, 0 ] );	// --> before li "g"1793				testList( 'before listItem "h"',			[ 7 ],		[ 0, 1, 1, 3, 0, 1 ] );	// --> before li "h"1794				testList( 'before listItem "i"',			[ 8 ],		[ 0, 1, 1, 3, 0, 2 ] );	// --> before li "i"1795				testList( 'before listItem "j"',			[ 9 ],		[ 0, 1, 1, 4 ] );		// --> before li "j"1796				testList( 'before listItem "k"',			[ 10 ],		[ 0, 2 ] );				// --> before li "k"1797				testList( 'after listItem "k"',				[ 11 ],		[ 1 ] );				// --> after ul1798			} );1799		} );1800		describe( 'convert changes', () => {1801			describe( 'insert', () => {1802				describe( 'same list type', () => {1803					testInsert(1804						'after smaller indent',1805						'<paragraph>p</paragraph>' +1806						'<listItem listIndent="0" listType="bulleted">1</listItem>' +1807						'[<listItem listIndent="1" listType="bulleted">x</listItem>]',1808						'<p>p</p>' +1809						'<ul>' +1810							'<li>' +1811								'1' +1812								'<ul>' +1813									'<li>x</li>' +1814								'</ul>' +1815							'</li>' +1816						'</ul>'1817					);1818					testInsert(1819						'after smaller indent, before same indent',1820						'<paragraph>p</paragraph>' +1821						'<listItem listIndent="0" listType="bulleted">1</listItem>' +1822						'[<listItem listIndent="1" listType="bulleted">x</listItem>]' +1823						'<listItem listIndent="1" listType="bulleted">1.1</listItem>',1824						'<p>p</p>' +1825						'<ul>' +1826							'<li>' +1827								'1' +1828								'<ul>' +1829									'<li>x</li>' +1830									'<li>1.1</li>' +1831								'</ul>' +1832							'</li>' +1833						'</ul>'1834					);1835					testInsert(1836						'after smaller indent, before smaller indent',1837						'<paragraph>p</paragraph>' +1838						'<listItem listIndent="0" listType="bulleted">1</listItem>' +1839						'[<listItem listIndent="1" listType="bulleted">x</listItem>]' +1840						'<listItem listIndent="0" listType="bulleted">2</listItem>',1841						'<p>p</p>' +1842						'<ul>' +1843							'<li>' +1844								'1' +1845								'<ul>' +1846									'<li>x</li>' +1847								'</ul>' +1848							'</li>' +1849							'<li>2</li>' +1850						'</ul>'1851					);1852					testInsert(1853						'after same indent',1854						'<paragraph>p</paragraph>' +1855						'<listItem listIndent="0" listType="bulleted">1</listItem>' +1856						'<listItem listIndent="1" listType="bulleted">1.1</listItem>' +1857						'[<listItem listIndent="1" listType="bulleted">x</listItem>]',1858						'<p>p</p>' +1859						'<ul>' +1860							'<li>' +1861								'1' +1862								'<ul>' +1863									'<li>1.1</li>' +1864									'<li>x</li>' +1865								'</ul>' +1866							'</li>' +1867						'</ul>'1868					);1869					testInsert(1870						'after same indent, before bigger indent',1871						'<paragraph>p</paragraph>' +1872						'<listItem listIndent="0" listType="bulleted">1</listItem>' +1873						'[<listItem listIndent="0" listType="bulleted">x</listItem>]' +1874						'<listItem listIndent="1" listType="bulleted">1.1</listItem>',1875						'<p>p</p>' +1876						'<ul>' +1877							'<li>1</li>' +1878							'<li>' +1879								'x' +1880								'<ul>' +1881									'<li>1.1</li>' +1882								'</ul>' +1883							'</li>' +1884						'</ul>'1885					);1886					testInsert(1887						'after bigger indent, before bigger indent',1888						'<paragraph>p</paragraph>' +1889						'<listItem listIndent="0" listType="bulleted">1</listItem>' +1890						'<listItem listIndent="1" listType="bulleted">1.1</listItem>' +1891						'[<listItem listIndent="0" listType="bulleted">x</listItem>]' +1892						'<listItem listIndent="1" listType="bulleted">1.2</listItem>',1893						'<p>p</p>' +1894						'<ul>' +1895							'<li>' +1896								'1' +1897								'<ul>' +1898									'<li>1.1</li>' +1899								'</ul>' +1900							'</li>' +1901							'<li>' +1902								'x' +1903								'<ul>' +1904									'<li>1.2</li>' +1905								'</ul>' +1906							'</li>' +1907						'</ul>'1908					);1909					testInsert(1910						'list items with too big indent',1911						'<listItem listIndent="0" listType="bulleted">a</listItem>' +1912						'<listItem listIndent="1" listType="bulleted">b</listItem>' +1913						'[<listItem listIndent="4" listType="bulleted">x</listItem>' + // This indent should be fixed by post fixer.1914						'<listItem listIndent="5" listType="bulleted">x</listItem>' + // This indent should be fixed by post fixer.1915						'<listItem listIndent="4" listType="bulleted">x</listItem>]' + // This indent should be fixed by post fixer.1916						'<listItem listIndent="1" listType="bulleted">c</listItem>',1917						'<ul>' +1918							'<li>' +1919								'a' +1920								'<ul>' +1921									'<li>' +1922										'b' +1923										'<ul>' +1924											'<li>' +1925												'x' +1926												'<ul>' +1927													'<li>x</li>' +1928												'</ul>' +1929											'</li>' +1930											'<li>x</li>' +1931										'</ul>' +1932									'</li>' +1933									'<li>c</li>' +1934								'</ul>' +1935							'</li>' +1936						'</ul>'1937					);1938				} );1939				describe( 'different list type', () => {1940					testInsert(1941						'after smaller indent, before same indent',1942						'<paragraph>p</paragraph>' +1943						'<listItem listIndent="0" listType="bulleted">1</listItem>' +1944						'[<listItem listIndent="1" listType="numbered">x</listItem>]' + // This type should be fixed by post fixer.1945						'<listItem listIndent="1" listType="bulleted">1.1</listItem>',1946						'<p>p</p>' +1947						'<ul>' +1948							'<li>' +1949								'1' +1950								'<ol>' +1951									'<li>x</li>' +1952									'<li>1.1</li>' +1953								'</ol>' +1954							'</li>' +1955						'</ul>'1956					);1957					testInsert(1958						'after same indent',1959						'<paragraph>p</paragraph>' +1960						'<listItem listIndent="0" listType="bulleted">1</listItem>' +1961						'<listItem listIndent="1" listType="bulleted">1.1</listItem>' +1962						'[<listItem listIndent="1" listType="numbered">x</listItem>]', // This type should be fixed by post fixer.1963						'<p>p</p>' +1964						'<ul>' +1965							'<li>' +1966								'1' +1967								'<ul>' +1968									'<li>1.1</li>' +1969									'<li>x</li>' +1970								'</ul>' +1971							'</li>' +1972						'</ul>'1973					);1974					testInsert(1975						'after same indent, before bigger indent',1976						'<paragraph>p</paragraph>' +1977						'<listItem listIndent="0" listType="bulleted">1</listItem>' +1978						'[<listItem listIndent="0" listType="numbered">x</listItem>]' +1979						'<listItem listIndent="1" listType="bulleted">1.1</listItem>',1980						'<p>p</p>' +1981						'<ul>' +1982							'<li>1</li>' +1983						'</ul>' +1984						'<ol>' +1985							'<li>' +1986								'x' +1987								'<ul>' +1988									'<li>1.1</li>' +1989								'</ul>' +1990							'</li>' +1991						'</ol>'1992					);1993					testInsert(1994						'after bigger indent, before bigger indent',1995						'<paragraph>p</paragraph>' +1996						'<listItem listIndent="0" listType="bulleted">1</listItem>' +1997						'<listItem listIndent="1" listType="bulleted">1.1</listItem>' +1998						'[<listItem listIndent="0" listType="numbered">x</listItem>]' +1999						'<listItem listIndent="1" listType="bulleted">1.2</listItem>',2000						'<p>p</p>' +2001						'<ul>' +2002							'<li>' +2003								'1' +2004								'<ul>' +2005									'<li>1.1</li>' +2006								'</ul>' +2007							'</li>' +2008						'</ul>' +2009						'<ol>' +2010							'<li>' +2011								'x' +2012								'<ul>' +2013									'<li>1.2</li>' +2014								'</ul>' +2015							'</li>' +2016						'</ol>'2017					);2018					testInsert(2019						'after bigger indent, in nested list, different type',2020						'<listItem listIndent="0" listType="bulleted">a</listItem>' +2021						'<listItem listIndent="1" listType="bulleted">b</listItem>' +2022						'<listItem listIndent="2" listType="bulleted">c</listItem>' +2023						'[<listItem listIndent="1" listType="numbered">x</listItem>]', // This type should be fixed by post fixer.2024						'<ul>' +2025							'<li>' +2026								'a' +2027								'<ul>' +2028									'<li>' +2029										'b' +2030										'<ul>' +2031											'<li>c</li>' +2032										'</ul>' +2033									'</li>' +2034									'<li>x</li>' +2035								'</ul>' +2036							'</li>' +2037						'</ul>'2038					);2039				} );2040				// This case is pretty complex but it tests various edge cases concerning splitting lists.2041				testInsert(2042					'element between nested list items - complex',2043					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2044					'<listItem listIndent="1" listType="bulleted">b</listItem>' +2045					'<listItem listIndent="2" listType="bulleted">c</listItem>' +2046					'<listItem listIndent="3" listType="numbered">d</listItem>' +2047					'[<paragraph>x</paragraph>]' +2048					'<listItem listIndent="3" listType="numbered">e</listItem>' + // This indent should be fixed by post fixer.2049					'<listItem listIndent="2" listType="bulleted">f</listItem>' + // This indent should be fixed by post fixer.2050					'<listItem listIndent="3" listType="bulleted">g</listItem>' + // This indent should be fixed by post fixer.2051					'<listItem listIndent="1" listType="bulleted">h</listItem>' + // This indent should be fixed by post fixer.2052					'<listItem listIndent="2" listType="numbered">i</listItem>' + // This indent should be fixed by post fixer.2053					'<listItem listIndent="0" listType="numbered">j</listItem>' + // This indent should be fixed by post fixer.2054					'<paragraph>p</paragraph>',2055					'<ul>' +2056						'<li>' +2057							'a' +2058							'<ul>' +2059								'<li>' +2060									'b' +2061									'<ul>' +2062										'<li>' +2063											'c' +2064											'<ol>' +2065												'<li>d</li>' +2066											'</ol>' +2067										'</li>' +2068									'</ul>' +2069								'</li>' +2070							'</ul>' +2071						'</li>' +2072					'</ul>' +2073					'<p>x</p>' +2074					'<ol>' +2075						'<li>e</li>' +2076					'</ol>' +2077					'<ul>' +2078						'<li>' +2079							'f' +2080							'<ul>' +2081								'<li>g</li>' +2082							'</ul>' +2083						'</li>' +2084						'<li>' +2085							'h' +2086							'<ol>' +2087								'<li>i</li>' +2088							'</ol>' +2089						'</li>' +2090					'</ul>' +2091					'<ol>' +2092						'<li>j</li>' +2093					'</ol>' +2094					'<p>p</p>',2095					false2096				);2097				testInsert(2098					'element before indent "hole"',2099					'<listItem listIndent="0" listType="bulleted">1</listItem>' +2100					'<listItem listIndent="1" listType="bulleted">1.1</listItem>' +2101					'[<paragraph>x</paragraph>]' +2102					'<listItem listIndent="2" listType="bulleted">1.1.1</listItem>' + // This indent should be fixed by post fixer.2103					'<listItem listIndent="0" listType="bulleted">2</listItem>',2104					'<ul>' +2105						'<li>' +2106							'1' +2107							'<ul>' +2108								'<li>1.1</li>' +2109							'</ul>' +2110						'</li>' +2111					'</ul>' +2112					'<p>x</p>' +2113					'<ul>' +2114						'<li>1.1.1</li>' +2115						'<li>2</li>' +2116					'</ul>',2117					false2118				);2119				_test(2120					'two list items with mismatched types inserted in one batch',2121					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2122					'<listItem listIndent="1" listType="bulleted">b</listItem>[]',2123					'<ul>' +2124						'<li>' +2125							'a' +2126							'<ul>' +2127								'<li>b</li>' +2128								'<li>c</li>' +2129								'<li>d</li>' +2130							'</ul>' +2131						'</li>' +2132					'</ul>',2133					() => {2134						const item1 = '<listItem listIndent="1" listType="numbered">c</listItem>';2135						const item2 = '<listItem listIndent="1" listType="bulleted">d</listItem>';2136						model.change( writer => {2137							writer.append( parseModel( item1, model.schema ), modelRoot );2138							writer.append( parseModel( item2, model.schema ), modelRoot );2139						} );2140					}2141				);2142			} );2143			describe( 'remove', () => {2144				testRemove(2145					'the first nested item',2146					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2147					'[<listItem listIndent="1" listType="bulleted">b</listItem>]' +2148					'<listItem listIndent="1" listType="bulleted">c</listItem>',2149					'<ul>' +2150						'<li>' +2151							'a' +2152							'<ul>' +2153								'<li>c</li>' +2154							'</ul>' +2155						'</li>' +2156					'</ul>'2157				);2158				testRemove(2159					'nested item from the middle',2160					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2161					'<listItem listIndent="1" listType="bulleted">b</listItem>' +2162					'[<listItem listIndent="1" listType="bulleted">c</listItem>]' +2163					'<listItem listIndent="1" listType="bulleted">d</listItem>',2164					'<ul>' +2165						'<li>' +2166							'a' +2167							'<ul>' +2168								'<li>b</li>' +2169								'<li>d</li>' +2170							'</ul>' +2171						'</li>' +2172					'</ul>'2173				);2174				testRemove(2175					'the last nested item',2176					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2177					'<listItem listIndent="1" listType="bulleted">b</listItem>' +2178					'[<listItem listIndent="1" listType="bulleted">c</listItem>]',2179					'<ul>' +2180						'<li>' +2181							'a' +2182							'<ul>' +2183								'<li>b</li>' +2184							'</ul>' +2185						'</li>' +2186					'</ul>'2187				);2188				testRemove(2189					'the only nested item',2190					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2191					'[<listItem listIndent="1" listType="bulleted">c</listItem>]',2192					'<ul>' +2193						'<li>a</li>' +2194					'</ul>'2195				);2196				testRemove(2197					'list item that separates two nested lists of same type',2198					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2199					'<listItem listIndent="1" listType="numbered">b</listItem>' +2200					'[<listItem listIndent="0" listType="bulleted">c</listItem>]' +2201					'<listItem listIndent="1" listType="numbered">d</listItem>',2202					'<ul>' +2203						'<li>' +2204							'a' +2205							'<ol>' +2206								'<li>b</li>' +2207								'<li>d</li>' +2208							'</ol>' +2209						'</li>' +2210					'</ul>'2211				);2212				testRemove(2213					'list item that separates two nested lists of different type',2214					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2215					'<listItem listIndent="1" listType="numbered">b</listItem>' +2216					'[<listItem listIndent="0" listType="bulleted">c</listItem>]' +2217					'<listItem listIndent="1" listType="bulleted">d</listItem>', // This type should be fixed by post fixer.2218					'<ul>' +2219						'<li>' +2220							'a' +2221							'<ol>' +2222								'<li>b</li>' +2223								'<li>d</li>' +2224							'</ol>' +2225						'</li>' +2226					'</ul>'2227				);2228				testRemove(2229					'item that has nested lists, previous item has same indent',2230					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2231					'[<listItem listIndent="0" listType="bulleted">b</listItem>]' +2232					'<listItem listIndent="1" listType="bulleted">c</listItem>' +2233					'<listItem listIndent="1" listType="bulleted">d</listItem>',2234					'<ul>' +2235						'<li>' +2236							'a' +2237							'<ul>' +2238								'<li>c</li>' +2239								'<li>d</li>' +2240							'</ul>' +2241						'</li>' +2242					'</ul>'2243				);2244				testRemove(2245					'item that has nested lists, previous item has smaller indent',2246					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2247					'[<listItem listIndent="1" listType="bulleted">b</listItem>]' +2248					'<listItem listIndent="2" listType="bulleted">c</listItem>' + // This indent should be fixed by post fixer.2249					'<listItem listIndent="2" listType="bulleted">d</listItem>', // This indent should be fixed by post fixer.2250					'<ul>' +2251						'<li>' +2252							'a' +2253							'<ul>' +2254								'<li>c</li>' +2255								'<li>d</li>' +2256							'</ul>' +2257						'</li>' +2258					'</ul>'2259				);2260				testRemove(2261					'item that has nested lists, previous item has bigger indent by 1',2262					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2263					'<listItem listIndent="1" listType="bulleted">b</listItem>' +2264					'[<listItem listIndent="0" listType="bulleted">c</listItem>]' +2265					'<listItem listIndent="1" listType="bulleted">d</listItem>' +2266					'<listItem listIndent="2" listType="numbered">e</listItem>',2267					'<ul>' +2268						'<li>' +2269							'a' +2270							'<ul>' +2271								'<li>b</li>' +2272								'<li>' +2273									'd' +2274									'<ol>' +2275										'<li>e</li>' +2276									'</ol>' +2277								'</li>' +2278							'</ul>' +2279						'</li>' +2280					'</ul>'2281				);2282				testRemove(2283					'item that has nested lists, previous item has bigger indent by 2',2284					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2285					'<listItem listIndent="1" listType="bulleted">b</listItem>' +2286					'<listItem listIndent="2" listType="bulleted">c</listItem>' +2287					'[<listItem listIndent="0" listType="bulleted">d</listItem>]' +2288					'<listItem listIndent="1" listType="bulleted">e</listItem>',2289					'<ul>' +2290						'<li>' +2291							'a' +2292							'<ul>' +2293								'<li>' +2294									'b' +2295									'<ul>' +2296										'<li>c</li>' +2297									'</ul>' +2298								'</li>' +2299								'<li>e</li>' +2300							'</ul>' +2301						'</li>' +2302					'</ul>'2303				);2304				testRemove(2305					'first list item that has nested list',2306					'[<listItem listIndent="0" listType="bulleted">a</listItem>]' +2307					'<listItem listIndent="1" listType="bulleted">b</listItem>' + // This indent should be fixed by post fixer.2308					'<listItem listIndent="2" listType="bulleted">c</listItem>', // This indent should be fixed by post fixer.2309					'<ul>' +2310						'<li>' +2311							'b' +2312							'<ul>' +2313								'<li>c</li>' +2314							'</ul>' +2315						'</li>' +2316					'</ul>'2317				);2318			} );2319			describe( 'change type', () => {2320				testChangeType(2321					'list item that has nested items',2322					'[<listItem listIndent="0" listType="numbered">a</listItem>]' +2323					'<listItem listIndent="1" listType="bulleted">b</listItem>' +2324					'<listItem listIndent="1" listType="bulleted">c</listItem>',2325					'<ul>' +2326						'<li>' +2327							'a' +2328							'<ul>' +2329								'<li>b</li>' +2330								'<li>c</li>' +2331							'</ul>' +2332						'</li>' +2333					'</ul>'2334				);2335				// The change will be "prevented" by post fixer.2336				testChangeType(2337					'list item that is a nested item',2338					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2339					'<listItem listIndent="1" listType="numbered">b</listItem>' +2340					'[<listItem listIndent="1" listType="numbered">c</listItem>]' +2341					'<listItem listIndent="1" listType="numbered">d</listItem>',2342					'<ul>' +2343						'<li>' +2344							'a' +2345							'<ol>' +2346								'<li>b</li>' +2347								'<li>c</li>' +2348								'<li>d</li>' +2349							'</ol>' +2350						'</li>' +2351					'</ul>'2352				);2353			} );2354			describe( 'change indent', () => {2355				describe( 'same list type', () => {2356					testChangeIndent(2357						'indent last item of flat list', 1,2358						'<listItem listIndent="0" listType="bulleted">a</listItem>' +2359						'[<listItem listIndent="0" listType="bulleted">b</listItem>]',2360						'<ul>' +2361							'<li>' +2362								'a' +2363								'<ul>' +2364									'<li>b</li>' +2365								'</ul>' +2366							'</li>' +2367						'</ul>'2368					);2369					testChangeIndent(2370						'indent middle item of flat list', 1,2371						'<listItem listIndent="0" listType="bulleted">a</listItem>' +2372						'[<listItem listIndent="0" listType="bulleted">b</listItem>]' +2373						'<listItem listIndent="0" listType="bulleted">c</listItem>',2374						'<ul>' +2375							'<li>' +2376								'a' +2377								'<ul>' +2378									'<li>b</li>' +2379								'</ul>' +2380							'</li>' +2381							'<li>c</li>' +2382						'</ul>'2383					);2384					testChangeIndent(2385						'indent last item in nested list', 2,2386						'<listItem listIndent="0" listType="bulleted">a</listItem>' +2387						'<listItem listIndent="1" listType="bulleted">b</listItem>' +2388						'[<listItem listIndent="1" listType="bulleted">c</listItem>]',2389						'<ul>' +2390							'<li>' +2391								'a' +2392								'<ul>' +2393									'<li>' +2394										'b' +2395										'<ul>' +2396											'<li>c</li>' +2397										'</ul>' +2398									'</li>' +2399								'</ul>' +2400							'</li>' +2401						'</ul>'2402					);2403					testChangeIndent(2404						'indent middle item in nested list', 2,2405						'<listItem listIndent="0" listType="bulleted">a</listItem>' +2406						'<listItem listIndent="1" listType="bulleted">b</listItem>' +2407						'[<listItem listIndent="1" listType="bulleted">c</listItem>]' +2408						'<listItem listIndent="1" listType="bulleted">d</listItem>',2409						'<ul>' +2410							'<li>' +2411								'a' +2412								'<ul>' +2413									'<li>' +2414										'b' +2415										'<ul>' +2416											'<li>c</li>' +2417										'</ul>' +2418									'</li>' +2419									'<li>d</li>' +2420								'</ul>' +2421							'</li>' +2422						'</ul>'2423					);2424					// Keep in mind that this test is different than "executing command on item that has nested list".2425					// A command is automatically indenting nested items so the hierarchy is preserved.2426					// Here we test conversion and the change is simple changing indent of one item.2427					// This may be true also for other tests in this suite, keep this in mind.2428					testChangeIndent(2429						'indent item that has nested list', 1,2430						'<listItem listIndent="0" listType="bulleted">a</listItem>' +2431						'[<listItem listIndent="0" listType="bulleted">b</listItem>]' +2432						'<listItem listIndent="1" listType="bulleted">c</listItem>',2433						'<ul>' +2434							'<li>' +2435								'a' +2436								'<ul>' +2437									'<li>b</li>' +2438									'<li>c</li>' +2439								'</ul>' +2440							'</li>' +2441						'</ul>'2442					);2443					testChangeIndent(2444						'indent item that in view is a next sibling of item that has nested list', 1,2445						'<listItem listIndent="0" listType="bulleted">a</listItem>' +2446						'<listItem listIndent="1" listType="bulleted">b</listItem>' +2447						'[<listItem listIndent="0" listType="bulleted">c</listItem>]' +2448						'<listItem listIndent="1" listType="bulleted">d</listItem>',2449						'<ul>' +2450							'<li>' +2451								'a' +2452								'<ul>' +2453									'<li>b</li>' +2454									'<li>c</li>' +2455									'<li>d</li>' +2456								'</ul>' +2457							'</li>' +2458						'</ul>'2459					);2460					testChangeIndent(2461						'outdent the first item of nested list', 0,2462						'<listItem listIndent="0" listType="bulleted">a</listItem>' +2463						'[<listItem listIndent="1" listType="bulleted">b</listItem>]' +2464						'<listItem listIndent="1" listType="bulleted">c</listItem>' +2465						'<listItem listIndent="1" listType="bulleted">d</listItem>',2466						'<ul>' +2467							'<li>a</li>' +2468							'<li>' +2469								'b' +2470								'<ul>' +2471									'<li>c</li>' +2472									'<li>d</li>' +2473								'</ul>' +2474							'</li>' +2475						'</ul>'2476					);2477					testChangeIndent(2478						'outdent item from the middle of nested list', 0,2479						'<listItem listIndent="0" listType="bulleted">a</listItem>' +2480						'<listItem listIndent="1" listType="bulleted">b</listItem>' +2481						'[<listItem listIndent="1" listType="bulleted">c</listItem>]' +2482						'<listItem listIndent="1" listType="bulleted">d</listItem>',2483						'<ul>' +2484							'<li>' +2485								'a' +2486								'<ul>' +2487									'<li>b</li>' +2488								'</ul>' +2489							'</li>' +2490							'<li>' +2491								'c' +2492								'<ul>' +2493									'<li>d</li>' +2494								'</ul>' +2495							'</li>' +2496						'</ul>'2497					);2498					testChangeIndent(2499						'outdent the last item of nested list', 0,2500						'<listItem listIndent="0" listType="bulleted">a</listItem>' +2501						'<listItem listIndent="1" listType="bulleted">b</listItem>' +2502						'[<listItem listIndent="1" listType="bulleted">c</listItem>]',2503						'<ul>' +2504							'<li>' +2505								'a' +2506								'<ul>' +2507									'<li>b</li>' +2508								'</ul>' +2509							'</li>' +2510							'<li>c</li>' +2511						'</ul>'2512					);2513					testChangeIndent(2514						'outdent the only item of nested list', 1,2515						'<listItem listIndent="0" listType="bulleted">a</listItem>' +2516						'<listItem listIndent="1" listType="bulleted">b</listItem>' +2517						'[<listItem listIndent="2" listType="bulleted">c</listItem>]' +2518						'<listItem listIndent="1" listType="bulleted">d</listItem>',2519						'<ul>' +2520							'<li>' +2521								'a' +2522								'<ul>' +2523									'<li>b</li>' +2524									'<li>c</li>' +2525									'<li>d</li>' +2526								'</ul>' +2527							'</li>' +2528						'</ul>'2529					);2530					testChangeIndent(2531						'outdent item by two', 0,2532						'<listItem listIndent="0" listType="bulleted">a</listItem>' +2533						'<listItem listIndent="1" listType="bulleted">b</listItem>' +2534						'[<listItem listIndent="2" listType="bulleted">c</listItem>]' +2535						'<listItem listIndent="0" listType="bulleted">d</listItem>',2536						'<ul>' +2537							'<li>' +2538								'a' +2539								'<ul>' +2540									'<li>b</li>' +2541								'</ul>' +2542							'</li>' +2543							'<li>c</li>' +2544							'<li>d</li>' +2545						'</ul>'2546					);2547				} );2548				describe( 'different list type', () => {2549					testChangeIndent(2550						'indent middle item of flat list', 1,2551						'<listItem listIndent="0" listType="bulleted">a</listItem>' +2552						'[<listItem listIndent="0" listType="numbered">b</listItem>]' +2553						'<listItem listIndent="0" listType="bulleted">c</listItem>',2554						'<ul>' +2555							'<li>' +2556								'a' +2557								'<ol>' +2558									'<li>b</li>' +2559								'</ol>' +2560							'</li>' +2561							'<li>c</li>' +2562						'</ul>'2563					);2564					testChangeIndent(2565						'indent item that has nested list', 1,2566						'<listItem listIndent="0" listType="bulleted">a</listItem>' +2567						'[<listItem listIndent="0" listType="numbered">b</listItem>]' +2568						'<listItem listIndent="1" listType="bulleted">c</listItem>',2569						'<ul>' +2570							'<li>' +2571								'a' +2572								'<ol>' +2573									'<li>b</li>' +2574									'<li>c</li>' +2575								'</ol>' +2576							'</li>' +2577						'</ul>'2578					);2579					testChangeIndent(2580						'indent item that in view is a next sibling of item that has nested list #1', 1,2581						'<listItem listIndent="0" listType="bulleted">a</listItem>' +2582						'<listItem listIndent="1" listType="bulleted">b</listItem>' +2583						'[<listItem listIndent="0" listType="numbered">c</listItem>]' +2584						'<listItem listIndent="1" listType="bulleted">d</listItem>',2585						'<ul>' +2586							'<li>' +2587								'a' +2588								'<ul>' +2589									'<li>b</li>' +2590									'<li>c</li>' +2591									'<li>d</li>' +2592								'</ul>' +2593							'</li>' +2594						'</ul>'2595					);2596					testChangeIndent(2597						'outdent the first item of nested list', 0,2598						'<listItem listIndent="0" listType="bulleted">a</listItem>' +2599						'[<listItem listIndent="1" listType="bulleted">b</listItem>]' +2600						'<listItem listIndent="1" listType="bulleted">c</listItem>' +2601						'<listItem listIndent="1" listType="bulleted">d</listItem>',2602						'<ul>' +2603							'<li>a</li>' +2604							'<li>' +2605								'b' +2606								'<ul>' +2607									'<li>c</li>' +2608									'<li>d</li>' +2609								'</ul>' +2610							'</li>' +2611						'</ul>'2612					);2613					testChangeIndent(2614						'outdent the only item of nested list', 1,2615						'<listItem listIndent="0" listType="bulleted">a</listItem>' +2616						'<listItem listIndent="1" listType="bulleted">b</listItem>' +2617						'[<listItem listIndent="2" listType="bulleted">c</listItem>]' +2618						'<listItem listIndent="1" listType="bulleted">d</listItem>',2619						'<ul>' +2620							'<li>' +2621								'a' +2622								'<ul>' +2623									'<li>b</li>' +2624									'<li>c</li>' +2625									'<li>d</li>' +2626								'</ul>' +2627							'</li>' +2628						'</ul>'2629					);2630					testChangeIndent(2631						'outdent item by two', 0,2632						'<listItem listIndent="0" listType="bulleted">a</listItem>' +2633						'<listItem listIndent="1" listType="bulleted">b</listItem>' +2634						'[<listItem listIndent="2" listType="numbered">c</listItem>]' +2635						'<listItem listIndent="0" listType="bulleted">d</listItem>',2636						'<ul>' +2637							'<li>' +2638								'a' +2639								'<ul>' +2640									'<li>b</li>' +2641								'</ul>' +2642							'</li>' +2643						'</ul>' +2644						'<ol>' +2645							'<li>c</li>' +2646						'</ol>' +2647						'<ul>' +2648							'<li>d</li>' +2649						'</ul>'2650					);2651				} );2652			} );2653			describe( 'rename from list item', () => {2654				testRenameFromListItem(2655					'rename nested item from the middle #1',2656					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2657					'<listItem listIndent="1" listType="bulleted">b</listItem>' +2658					'[<listItem listIndent="1" listType="bulleted">c</listItem>]' +2659					'<listItem listIndent="1" listType="bulleted">d</listItem>', // This indent should be fixed by post fixer.2660					'<ul>' +2661						'<li>' +2662							'a' +2663							'<ul>' +2664								'<li>b</li>' +2665							'</ul>' +2666						'</li>' +2667					'</ul>' +2668					'<p>c</p>' +2669					'<ul>' +2670						'<li>d</li>' +2671					'</ul>',2672					false2673				);2674				testRenameFromListItem(2675					'rename nested item from the middle #2 - nightmare example',2676					// Indents in this example should be fixed by post fixer.2677					// This nightmare example checks if structure of the list is kept as intact as possible.2678					'<listItem listIndent="0" listType="bulleted">a</listItem>' +	// a --------			-->  a --------2679					'<listItem listIndent="1" listType="bulleted">b</listItem>' +	//   b --------			-->    b --------2680					'[<listItem listIndent="2" listType="bulleted">c</listItem>]' +	//     c --------		--> --------2681					'<listItem listIndent="3" listType="bulleted">d</listItem>' +	//       d --------		-->  d --------2682					'<listItem listIndent="3" listType="bulleted">e</listItem>' +	//       e --------		-->  e --------2683					'<listItem listIndent="4" listType="bulleted">f</listItem>' +	//         f --------	-->    f --------2684					'<listItem listIndent="2" listType="bulleted">g</listItem>' +	//     g --------		-->  g --------2685					'<listItem listIndent="3" listType="bulleted">h</listItem>' +	//       h --------		-->    h --------2686					'<listItem listIndent="4" listType="bulleted">i</listItem>' +	//         i --------	-->      i --------2687					'<listItem listIndent="1" listType="bulleted">j</listItem>' +	//   j --------			-->  j --------2688					'<listItem listIndent="2" listType="bulleted">k</listItem>' +	//     k --------		-->    k --------2689					'<listItem listIndent="0" listType="bulleted">l</listItem>' +	// l --------			-->  l --------2690					'<listItem listIndent="1" listType="bulleted">m</listItem>',	//   m --------			-->    m --------2691					'<ul>' +2692						'<li>' +2693							'a' +2694							'<ul>' +2695								'<li>b</li>' +2696							'</ul>' +2697						'</li>' +2698					'</ul>' +2699					'<p>c</p>' +2700					'<ul>' +2701						'<li>d</li>' +2702						'<li>' +2703							'e' +2704							'<ul>' +2705								'<li>f</li>' +2706							'</ul>' +2707						'</li>' +2708						'<li>' +2709							'g' +2710							'<ul>' +2711								'<li>' +2712									'h' +2713									'<ul>' +2714										'<li>i</li>' +2715									'</ul>' +2716								'</li>' +2717							'</ul>' +2718						'</li>' +2719						'<li>' +2720							'j' +2721							'<ul>' +2722								'<li>k</li>' +2723							'</ul>' +2724						'</li>' +2725						'<li>' +2726							'l' +2727							'<ul>' +2728								'<li>m</li>' +2729							'</ul>' +2730						'</li>' +2731					'</ul>',2732					false2733				);2734				testRenameFromListItem(2735					'rename nested item from the middle #3 - manual test example',2736					// Indents in this example should be fixed by post fixer.2737					// This example checks a bug found by testing manual test.2738					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2739					'<listItem listIndent="1" listType="bulleted">b</listItem>' +2740					'[<listItem listIndent="2" listType="bulleted">c</listItem>]' +2741					'<listItem listIndent="1" listType="bulleted">d</listItem>' +2742					'<listItem listIndent="2" listType="bulleted">e</listItem>' +2743					'<listItem listIndent="2" listType="bulleted">f</listItem>' +2744					'<listItem listIndent="2" listType="bulleted">g</listItem>' +2745					'<listItem listIndent="2" listType="bulleted">h</listItem>' +2746					'<listItem listIndent="0" listType="bulleted"></listItem>' +2747					'<listItem listIndent="1" listType="bulleted"></listItem>' +2748					'<listItem listIndent="2" listType="numbered">k</listItem>' +2749					'<listItem listIndent="2" listType="numbered">l</listItem>',2750					'<ul>' +2751						'<li>' +2752							'a' +2753							'<ul>' +2754								'<li>b</li>' +2755							'</ul>' +2756						'</li>' +2757					'</ul>' +2758					'<p>c</p>' +2759					'<ul>' +2760						'<li>' +2761							'd' +2762							'<ul>' +2763								'<li>e</li>' +2764								'<li>f</li>' +2765								'<li>g</li>' +2766								'<li>h</li>' +2767							'</ul>' +2768						'</li>' +2769						'<li>' +2770							'<ul>' +2771								'<li>' +2772									'<ol>' +2773										'<li>k</li>' +2774										'<li>l</li>' +2775									'</ol>' +2776								'</li>' +2777							'</ul>' +2778						'</li>' +2779					'</ul>',2780					false2781				);2782				testRenameFromListItem(2783					'rename the only nested item',2784					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2785					'[<listItem listIndent="1" listType="bulleted">b</listItem>]',2786					'<ul>' +2787						'<li>a</li>' +2788					'</ul>' +2789					'<p>b</p>'2790				);2791			} );2792			describe( 'rename to list item (with attribute change)', () => {2793				testRenameToListItem(2794					'element into first item in nested list', 1,2795					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2796					'[<paragraph>b</paragraph>]',2797					'<ul>' +2798						'<li>' +2799							'a' +2800							'<ul>' +2801								'<li>b</li>' +2802							'</ul>' +2803						'</li>' +2804					'</ul>'2805				);2806				testRenameToListItem(2807					'element into last item in nested list', 1,2808					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2809					'<listItem listIndent="1" listType="bulleted">b</listItem>' +2810					'[<paragraph>c</paragraph>]',2811					'<ul>' +2812						'<li>' +2813							'a' +2814							'<ul>' +2815								'<li>b</li>' +2816								'<li>c</li>' +2817							'</ul>' +2818						'</li>' +2819					'</ul>'2820				);2821				testRenameToListItem(2822					'element into a first item in deeply nested list', 2,2823					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2824					'<listItem listIndent="1" listType="bulleted">b</listItem>' +2825					'[<paragraph>c</paragraph>]' +2826					'<listItem listIndent="0" listType="bulleted">d</listItem>',2827					'<ul>' +2828						'<li>' +2829							'a' +2830							'<ul>' +2831								'<li>' +2832									'b' +2833									'<ul>' +2834										'<li>c</li>' +2835									'</ul>' +2836								'</li>' +2837							'</ul>' +2838						'</li>' +2839						'<li>d</li>' +2840					'</ul>'2841				);2842			} );2843			describe( 'move', () => {2844				// Since move is in fact remove + insert and does not event have its own converter, only a few cases will be tested here.2845				testMove(2846					'out nested list items',2847					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2848					'[<listItem listIndent="1" listType="bulleted">b</listItem>' +2849					'<listItem listIndent="2" listType="bulleted">c</listItem>]' +2850					'<listItem listIndent="3" listType="bulleted">d</listItem>' + // This indent should be fixed by post fixer.2851					'<listItem listIndent="4" listType="bulleted">e</listItem>' + // This indent should be fixed by post fixer.2852					'<paragraph>x</paragraph>',2853					6,2854					'<ul>' +2855						'<li>' +2856							'a' +2857							'<ul>' +2858								'<li>' +2859									'd' +2860									'<ul>' +2861										'<li>e</li>' +2862									'</ul>' +2863								'</li>' +2864							'</ul>' +2865						'</li>' +2866					'</ul>' +2867					'<p>x</p>' +2868					'<ul>' +2869						'<li>' +2870							'b' +2871							'<ul>' +2872								'<li>c</li>' +2873							'</ul>' +2874						'</li>' +2875					'</ul>'2876				);2877				testMove(2878					'nested list items between lists of same type',2879					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2880					'<listItem listIndent="1" listType="bulleted">b</listItem>' +2881					'[<listItem listIndent="2" listType="bulleted">c</listItem>' +2882					'<listItem listIndent="3" listType="bulleted">d</listItem>]' +2883					'<listItem listIndent="4" listType="bulleted">e</listItem>' +2884					'<paragraph>x</paragraph>' +2885					'<listItem listIndent="0" listType="bulleted">f</listItem>' +2886					'<listItem listIndent="0" listType="bulleted">g</listItem>',2887					7,2888					'<ul>' +2889						'<li>' +2890							'a' +2891							'<ul>' +2892								'<li>' +2893									'b' +2894									'<ul>' +2895										'<li>e</li>' +2896									'</ul>' +2897								'</li>' +2898							'</ul>' +2899						'</li>' +2900					'</ul>' +2901					'<p>x</p>' +2902					'<ul>' +2903						'<li>' +2904							'f' +2905							'<ul>' +2906								'<li>' +2907									'c' +2908									'<ul>' +2909										'<li>d</li>' +2910									'</ul>' +2911								'</li>' +2912							'</ul>' +2913						'</li>' +2914						'<li>g</li>' +2915					'</ul>'2916				);2917				testMove(2918					'nested list items between lists of different type',2919					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2920					'<listItem listIndent="1" listType="bulleted">b</listItem>' +2921					'[<listItem listIndent="2" listType="bulleted">c</listItem>' +2922					'<listItem listIndent="3" listType="bulleted">d</listItem>]' +2923					'<listItem listIndent="4" listType="bulleted">e</listItem>' +2924					'<paragraph>x</paragraph>' +2925					'<listItem listIndent="0" listType="numbered">f</listItem>' +2926					'<listItem listIndent="1" listType="numbered">g</listItem>',2927					7,2928					'<ul>' +2929						'<li>' +2930							'a' +2931							'<ul>' +2932								'<li>' +2933									'b' +2934									'<ul>' +2935										'<li>e</li>' +2936									'</ul>' +2937								'</li>' +2938							'</ul>' +2939						'</li>' +2940					'</ul>' +2941					'<p>x</p>' +2942					'<ol>' +2943						'<li>' +2944							'f' +2945							'<ul>' +2946								'<li>' +2947									'c' +2948									'<ul>' +2949										'<li>d</li>' +2950									'</ul>' +2951								'</li>' +2952								'<li>g</li>' +2953							'</ul>' +2954						'</li>' +2955					'</ol>',2956					false2957				);2958				testMove(2959					'element between nested list',2960					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2961					'<listItem listIndent="1" listType="bulleted">b</listItem>' +2962					'<listItem listIndent="2" listType="bulleted">c</listItem>' +2963					'<listItem listIndent="3" listType="bulleted">d</listItem>' +2964					'[<paragraph>x</paragraph>]',2965					2,2966					'<ul>' +2967						'<li>' +2968							'a' +2969							'<ul>' +2970								'<li>b</li>' +2971							'</ul>' +2972						'</li>' +2973					'</ul>' +2974					'<p>x</p>' +2975					'<ul>' +2976						'<li>' +2977							'c' +2978							'<ul>' +2979								'<li>d</li>' +2980							'</ul>' +2981						'</li>' +2982					'</ul>',2983					false2984				);2985				testMove(2986					'multiple nested list items of different types #1 - fix at start',2987					'<listItem listIndent="0" listType="bulleted">a</listItem>' +2988					'<listItem listIndent="1" listType="bulleted">b</listItem>' +2989					'[<listItem listIndent="1" listType="bulleted">c</listItem>' +2990					'<listItem listIndent="0" listType="bulleted">d</listItem>' +2991					'<listItem listIndent="1" listType="numbered">e</listItem>]' +2992					'<listItem listIndent="1" listType="numbered">f</listItem>' +2993					'<listItem listIndent="0" listType="bulleted">g</listItem>' +2994					'<listItem listIndent="1" listType="numbered">h</listItem>' +2995					'<listItem listIndent="1" listType="numbered">i</listItem>',2996					8,2997					'<ul>' +2998						'<li>' +2999							'a' +3000							'<ul>' +3001								'<li>b</li>' +3002								'<li>f</li>' +3003							'</ul>' +3004						'</li>' +3005						'<li>' +3006							'g' +3007							'<ol>' +3008								'<li>h</li>' +3009								'<li>c</li>' +3010							'</ol>' +3011						'</li>' +3012						'<li>' +3013							'd' +3014							'<ol>' +3015								'<li>e</li>' +3016								'<li>i</li>' +3017							'</ol>' +3018						'</li>' +3019					'</ul>'3020				);3021				testMove(3022					'multiple nested list items of different types #2 - fix at end',3023					'<listItem listIndent="0" listType="bulleted">a</listItem>' +3024					'<listItem listIndent="1" listType="bulleted">b</listItem>' +3025					'[<listItem listIndent="1" listType="bulleted">c</listItem>' +3026					'<listItem listIndent="0" listType="bulleted">d</listItem>' +3027					'<listItem listIndent="1" listType="numbered">e</listItem>]' +3028					'<listItem listIndent="1" listType="numbered">f</listItem>' +3029					'<listItem listIndent="0" listType="bulleted">g</listItem>' +3030					'<listItem listIndent="1" listType="bulleted">h</listItem>' +3031					'<listItem listIndent="1" listType="bulleted">i</listItem>',3032					8,3033					'<ul>' +3034						'<li>' +3035							'a' +3036							'<ul>' +3037								'<li>b</li>' +3038								'<li>f</li>' +3039							'</ul>' +3040						'</li>' +3041						'<li>' +3042							'g' +3043							'<ul>' +3044								'<li>h</li>' +3045								'<li>c</li>' +3046							'</ul>' +3047						'</li>' +3048						'<li>' +3049							'd' +3050							'<ol>' +3051								'<li>e</li>' +3052								'<li>i</li>' +3053							'</ol>' +3054						'</li>' +3055					'</ul>'3056				);3057			} );3058		} );3059	} );3060	describe( 'post fixer', () => {3061		describe( 'insert', () => {3062			function testList( input, inserted, output ) {3063				return () => {3064					// Wrap all changes in one block to avoid post-fixing the selection3065					// (which may be incorret) in the meantime.3066					model.change( () => {3067						setModelData( model, input );3068						model.change( writer => {3069							writer.insert( parseModel( inserted, model.schema ), modelDoc.selection.getFirstPosition() );3070						} );3071					} );3072					expect( getModelData( model, { withoutSelection: true } ) ).to.equal( output );3073				};3074			}3075			it( 'element before nested list', testList(3076				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3077				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3078				'[]' +3079				'<listItem listIndent="2" listType="bulleted">d</listItem>' +3080				'<listItem listIndent="2" listType="bulleted">e</listItem>' +3081				'<listItem listIndent="3" listType="bulleted">f</listItem>',3082				'<paragraph>x</paragraph>',3083				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3084				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3085				'<paragraph>x</paragraph>' +3086				'<listItem listIndent="0" listType="bulleted">d</listItem>' +3087				'<listItem listIndent="0" listType="bulleted">e</listItem>' +3088				'<listItem listIndent="1" listType="bulleted">f</listItem>'3089			) );3090			it( 'list item before nested list', testList(3091				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3092				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3093				'[]' +3094				'<listItem listIndent="2" listType="bulleted">d</listItem>' +3095				'<listItem listIndent="2" listType="bulleted">e</listItem>' +3096				'<listItem listIndent="3" listType="bulleted">f</listItem>',3097				'<listItem listIndent="0" listType="bulleted">x</listItem>',3098				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3099				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3100				'<listItem listIndent="0" listType="bulleted">x</listItem>' +3101				'<listItem listIndent="1" listType="bulleted">d</listItem>' +3102				'<listItem listIndent="1" listType="bulleted">e</listItem>' +3103				'<listItem listIndent="2" listType="bulleted">f</listItem>'3104			) );3105			it( 'multiple list items with too big indent', testList(3106				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3107				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3108				'[]' +3109				'<listItem listIndent="1" listType="bulleted">c</listItem>',3110				'<listItem listIndent="4" listType="bulleted">x</listItem>' +3111				'<listItem listIndent="5" listType="bulleted">x</listItem>' +3112				'<listItem listIndent="4" listType="bulleted">x</listItem>',3113				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3114				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3115				'<listItem listIndent="2" listType="bulleted">x</listItem>' +3116				'<listItem listIndent="3" listType="bulleted">x</listItem>' +3117				'<listItem listIndent="2" listType="bulleted">x</listItem>' +3118				'<listItem listIndent="1" listType="bulleted">c</listItem>'3119			) );3120			it( 'item with different type - top level list', testList(3121				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3122				'<listItem listIndent="0" listType="bulleted">b</listItem>' +3123				'[]' +3124				'<listItem listIndent="0" listType="bulleted">c</listItem>',3125				'<listItem listIndent="0" listType="numbered">x</listItem>',3126				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3127				'<listItem listIndent="0" listType="bulleted">b</listItem>' +3128				'<listItem listIndent="0" listType="numbered">x</listItem>' +3129				'<listItem listIndent="0" listType="bulleted">c</listItem>'3130			) );3131			it( 'multiple items with different type - nested list', testList(3132				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3133				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3134				'[]' +3135				'<listItem listIndent="2" listType="bulleted">c</listItem>',3136				'<listItem listIndent="1" listType="numbered">x</listItem>' +3137				'<listItem listIndent="2" listType="numbered">x</listItem>',3138				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3139				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3140				'<listItem listIndent="1" listType="bulleted">x</listItem>' +3141				'<listItem listIndent="2" listType="numbered">x</listItem>' +3142				'<listItem listIndent="2" listType="numbered">c</listItem>'3143			) );3144			it( 'item with different type, in nested list, after nested list', testList(3145				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3146				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3147				'<listItem listIndent="2" listType="bulleted">c</listItem>' +3148				'[]',3149				'<listItem listIndent="1" listType="numbered">x</listItem>',3150				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3151				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3152				'<listItem listIndent="2" listType="bulleted">c</listItem>' +3153				'<listItem listIndent="1" listType="bulleted">x</listItem>'3154			) );3155			it( 'two list items with mismatched types inserted in one batch', () => {3156				const input =3157					'<listItem listIndent="0" listType="bulleted">a</listItem>' +3158					'<listItem listIndent="1" listType="bulleted">b</listItem>';3159				const output =3160					'<listItem listIndent="0" listType="bulleted">a</listItem>' +3161					'<listItem listIndent="1" listType="bulleted">b</listItem>' +3162					'<listItem listIndent="1" listType="bulleted">c</listItem>' +3163					'<listItem listIndent="1" listType="bulleted">d</listItem>';3164				setModelData( model, input );3165				const item1 = '<listItem listIndent="1" listType="numbered">c</listItem>';3166				const item2 = '<listItem listIndent="1" listType="bulleted">d</listItem>';3167				model.change( writer => {3168					writer.append( parseModel( item1, model.schema ), modelRoot );3169					writer.append( parseModel( item2, model.schema ), modelRoot );3170				} );3171				expect( getModelData( model, { withoutSelection: true } ) ).to.equal( output );3172			} );3173		} );3174		describe( 'remove', () => {3175			function testList( input, output ) {3176				return () => {3177					model.change( writer => {3178						setModelData( model, input );3179						writer.remove( modelDoc.selection.getFirstRange() );3180					} );3181					expect( getModelData( model, { withoutSelection: true } ) ).to.equal( output );3182				};3183			}3184			it( 'first list item', testList(3185				'[<listItem listIndent="0" listType="bulleted">a</listItem>]' +3186				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3187				'<listItem listIndent="2" listType="bulleted">c</listItem>',3188				'<listItem listIndent="0" listType="bulleted">b</listItem>' +3189				'<listItem listIndent="1" listType="bulleted">c</listItem>'3190			) );3191			it( 'first list item of nested list', testList(3192				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3193				'[<listItem listIndent="1" listType="bulleted">b</listItem>]' +3194				'<listItem listIndent="2" listType="bulleted">c</listItem>' +3195				'<listItem listIndent="3" listType="bulleted">d</listItem>' +3196				'<listItem listIndent="1" listType="bulleted">e</listItem>' +3197				'<listItem listIndent="2" listType="bulleted">f</listItem>',3198				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3199				'<listItem listIndent="1" listType="bulleted">c</listItem>' +3200				'<listItem listIndent="2" listType="bulleted">d</listItem>' +3201				'<listItem listIndent="1" listType="bulleted">e</listItem>' +3202				'<listItem listIndent="2" listType="bulleted">f</listItem>'3203			) );3204			it( 'selection over two different nested lists of same indent', testList(3205				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3206				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3207				'[<listItem listIndent="1" listType="bulleted">c</listItem>' +3208				'<listItem listIndent="0" listType="bulleted">d</listItem>' +3209				'<listItem listIndent="1" listType="numbered">e</listItem>]' +3210				'<listItem listIndent="1" listType="numbered">f</listItem>',3211				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3212				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3213				'<listItem listIndent="1" listType="bulleted">f</listItem>'3214			) );3215		} );3216		describe( 'move', () => {3217			function testList( input, offset, output ) {3218				return () => {3219					model.change( writer => {3220						setModelData( model, input );3221						const targetPosition = writer.createPositionAt( modelRoot, offset );3222						writer.move( modelDoc.selection.getFirstRange(), targetPosition );3223					} );3224					expect( getModelData( model, { withoutSelection: true } ) ).to.equal( output );3225				};3226			}3227			it( 'nested list item out of list structure', testList(3228				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3229				'[<listItem listIndent="1" listType="bulleted">b</listItem>' +3230				'<listItem listIndent="2" listType="bulleted">c</listItem>]' +3231				'<listItem listIndent="3" listType="bulleted">d</listItem>' +3232				'<listItem listIndent="4" listType="bulleted">e</listItem>' +3233				'<paragraph>x</paragraph>',3234				6,3235				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3236				'<listItem listIndent="1" listType="bulleted">d</listItem>' +3237				'<listItem listIndent="2" listType="bulleted">e</listItem>' +3238				'<paragraph>x</paragraph>' +3239				'<listItem listIndent="0" listType="bulleted">b</listItem>' +3240				'<listItem listIndent="1" listType="bulleted">c</listItem>'3241			) );3242			it( 'list items between lists', testList(3243				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3244				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3245				'[<listItem listIndent="2" listType="bulleted">c</listItem>' +3246				'<listItem listIndent="3" listType="bulleted">d</listItem>]' +3247				'<listItem listIndent="4" listType="bulleted">e</listItem>' +3248				'<paragraph>x</paragraph>' +3249				'<listItem listIndent="0" listType="bulleted">f</listItem>' +3250				'<listItem listIndent="0" listType="bulleted">g</listItem>',3251				7,3252				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3253				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3254				'<listItem listIndent="2" listType="bulleted">e</listItem>' +3255				'<paragraph>x</paragraph>' +3256				'<listItem listIndent="0" listType="bulleted">f</listItem>' +3257				'<listItem listIndent="1" listType="bulleted">c</listItem>' +3258				'<listItem listIndent="2" listType="bulleted">d</listItem>' +3259				'<listItem listIndent="0" listType="bulleted">g</listItem>'3260			) );3261			it( 'element in between nested list items', testList(3262				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3263				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3264				'<listItem listIndent="2" listType="bulleted">c</listItem>' +3265				'<listItem listIndent="3" listType="bulleted">d</listItem>' +3266				'[<paragraph>x</paragraph>]',3267				2,3268				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3269				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3270				'<paragraph>x</paragraph>' +3271				'<listItem listIndent="0" listType="bulleted">c</listItem>' +3272				'<listItem listIndent="1" listType="bulleted">d</listItem>'3273			) );3274			it( 'multiple nested list items of different types #1 - fix at start', testList(3275				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3276				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3277				'[<listItem listIndent="1" listType="bulleted">c</listItem>' +3278				'<listItem listIndent="0" listType="bulleted">d</listItem>' +3279				'<listItem listIndent="1" listType="numbered">e</listItem>]' +3280				'<listItem listIndent="1" listType="numbered">f</listItem>' +3281				'<listItem listIndent="0" listType="bulleted">g</listItem>' +3282				'<listItem listIndent="1" listType="numbered">h</listItem>' +3283				'<listItem listIndent="1" listType="numbered">i</listItem>',3284				8,3285				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3286				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3287				'<listItem listIndent="1" listType="bulleted">f</listItem>' +3288				'<listItem listIndent="0" listType="bulleted">g</listItem>' +3289				'<listItem listIndent="1" listType="numbered">h</listItem>' +3290				'<listItem listIndent="1" listType="numbered">c</listItem>' +3291				'<listItem listIndent="0" listType="bulleted">d</listItem>' +3292				'<listItem listIndent="1" listType="numbered">e</listItem>' +3293				'<listItem listIndent="1" listType="numbered">i</listItem>'3294			) );3295			it( 'multiple nested list items of different types #2 - fix at end', testList(3296				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3297				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3298				'[<listItem listIndent="1" listType="bulleted">c</listItem>' +3299				'<listItem listIndent="0" listType="bulleted">d</listItem>' +3300				'<listItem listIndent="1" listType="numbered">e</listItem>]' +3301				'<listItem listIndent="1" listType="numbered">f</listItem>' +3302				'<listItem listIndent="0" listType="bulleted">g</listItem>' +3303				'<listItem listIndent="1" listType="bulleted">h</listItem>' +3304				'<listItem listIndent="1" listType="bulleted">i</listItem>',3305				8,3306				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3307				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3308				'<listItem listIndent="1" listType="bulleted">f</listItem>' +3309				'<listItem listIndent="0" listType="bulleted">g</listItem>' +3310				'<listItem listIndent="1" listType="bulleted">h</listItem>' +3311				'<listItem listIndent="1" listType="bulleted">c</listItem>' +3312				'<listItem listIndent="0" listType="bulleted">d</listItem>' +3313				'<listItem listIndent="1" listType="numbered">e</listItem>' +3314				'<listItem listIndent="1" listType="numbered">i</listItem>'3315			) );3316			// #78.3317			it( 'move out of container', testList(3318				'<blockQuote>' +3319				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3320				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3321				'<listItem listIndent="1" listType="bulleted">c</listItem>' +3322				'<listItem listIndent="1" listType="bulleted">d</listItem>' +3323				'[<listItem listIndent="2" listType="bulleted">e</listItem>]' +3324				'</blockQuote>',3325				0,3326				'<listItem listIndent="0" listType="bulleted">e</listItem>' +3327				'<blockQuote>' +3328				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3329				'<listItem listIndent="1" listType="bulleted">b</listItem>' +3330				'<listItem listIndent="1" listType="bulleted">c</listItem>' +3331				'<listItem listIndent="1" listType="bulleted">d</listItem>' +3332				'</blockQuote>'3333			) );3334		} );3335		describe( 'rename', () => {3336			it( 'rename nested item', () => {3337				const modelBefore =3338					'<listItem listIndent="0" listType="bulleted">a</listItem>' +3339					'<listItem listIndent="1" listType="bulleted">b</listItem>' +3340					'[<listItem listIndent="2" listType="bulleted">c</listItem>]' +3341					'<listItem listIndent="2" listType="bulleted">d</listItem>' +3342					'<listItem listIndent="3" listType="bulleted">e</listItem>' +3343					'<listItem listIndent="1" listType="bulleted">f</listItem>' +3344					'<listItem listIndent="2" listType="bulleted">g</listItem>' +3345					'<listItem listIndent="1" listType="bulleted">h</listItem>' +3346					'<listItem listIndent="2" listType="bulleted">i</listItem>';3347				const expectedModel =3348					'<listItem listIndent="0" listType="bulleted">a</listItem>' +3349					'<listItem listIndent="1" listType="bulleted">b</listItem>' +3350					'<paragraph>c</paragraph>' +3351					'<listItem listIndent="0" listType="bulleted">d</listItem>' +3352					'<listItem listIndent="1" listType="bulleted">e</listItem>' +3353					'<listItem listIndent="0" listType="bulleted">f</listItem>' +3354					'<listItem listIndent="1" listType="bulleted">g</listItem>' +3355					'<listItem listIndent="0" listType="bulleted">h</listItem>' +3356					'<listItem listIndent="1" listType="bulleted">i</listItem>';3357				model.change( writer => {3358					setModelData( model, modelBefore );3359					const element = modelDoc.selection.getFirstPosition().nodeAfter;3360					writer.rename( element, 'paragraph' );3361				} );3362				expect( getModelData( model, { withoutSelection: true } ) ).to.equal( expectedModel );3363			} );3364		} );3365	} );3366	describe( 'paste and insertContent integration', () => {3367		it( 'should be triggered on DataController#insertContent()', () => {3368			setModelData( model,3369				'<listItem listType="bulleted" listIndent="0">A</listItem>' +3370				'<listItem listType="bulleted" listIndent="1">B[]</listItem>' +3371				'<listItem listType="bulleted" listIndent="2">C</listItem>'3372			);3373			editor.model.insertContent(3374				parseModel(3375					'<listItem listType="bulleted" listIndent="0">X</listItem>' +3376					'<listItem listType="bulleted" listIndent="1">Y</listItem>',3377					model.schema3378				)3379			);3380			expect( getModelData( model ) ).to.equal(3381				'<listItem listIndent="0" listType="bulleted">A</listItem>' +3382				'<listItem listIndent="1" listType="bulleted">BX</listItem>' +3383				'<listItem listIndent="2" listType="bulleted">Y[]</listItem>' +3384				'<listItem listIndent="2" listType="bulleted">C</listItem>'3385			);3386		} );3387		it( 'should be triggered when selectable is passed', () => {3388			setModelData( model,3389				'<listItem listType="bulleted" listIndent="0">A</listItem>' +3390				'<listItem listType="bulleted" listIndent="1">B[]</listItem>' +3391				'<listItem listType="bulleted" listIndent="2">C</listItem>'3392			);3393			model.insertContent(3394				parseModel(3395					'<listItem listType="bulleted" listIndent="0">X</listItem>' +3396					'<listItem listType="bulleted" listIndent="1">Y</listItem>',3397					model.schema3398				),3399				model.createRange(3400					model.createPositionFromPath( modelRoot, [ 1, 1 ] ),3401					model.createPositionFromPath( modelRoot, [ 1, 1 ] )3402				)3403			);3404			expect( getModelData( model ) ).to.equal(3405				'<listItem listIndent="0" listType="bulleted">A</listItem>' +3406				'<listItem listIndent="1" listType="bulleted">B[]X</listItem>' +3407				'<listItem listIndent="2" listType="bulleted">Y</listItem>' +3408				'<listItem listIndent="2" listType="bulleted">C</listItem>'3409			);3410		} );3411		// Just checking that it doesn't crash. #693412		it( 'should work if an element is passed to DataController#insertContent()', () => {3413			setModelData( model,3414				'<listItem listType="bulleted" listIndent="0">A</listItem>' +3415				'<listItem listType="bulleted" listIndent="1">B[]</listItem>' +3416				'<listItem listType="bulleted" listIndent="2">C</listItem>'3417			);3418			model.change( writer => {3419				const listItem = writer.createElement( 'listItem', { listType: 'bulleted', listIndent: '0' } );3420				writer.insertText( 'X', listItem );3421				model.insertContent( listItem );3422			} );3423			expect( getModelData( model ) ).to.equal(3424				'<listItem listIndent="0" listType="bulleted">A</listItem>' +3425				'<listItem listIndent="1" listType="bulleted">BX[]</listItem>' +3426				'<listItem listIndent="2" listType="bulleted">C</listItem>'3427			);3428		} );3429		// Just checking that it doesn't crash. #693430		it( 'should work if an element is passed to DataController#insertContent() - case #69', () => {3431			setModelData( model,3432				'<listItem listType="bulleted" listIndent="0">A</listItem>' +3433				'<listItem listType="bulleted" listIndent="1">B[]</listItem>' +3434				'<listItem listType="bulleted" listIndent="2">C</listItem>'3435			);3436			model.change( writer => {3437				model.insertContent( writer.createText( 'X' ) );3438			} );3439			expect( getModelData( model ) ).to.equal(3440				'<listItem listIndent="0" listType="bulleted">A</listItem>' +3441				'<listItem listIndent="1" listType="bulleted">BX[]</listItem>' +3442				'<listItem listIndent="2" listType="bulleted">C</listItem>'3443			);3444		} );3445		it( 'should fix indents of pasted list items', () => {3446			setModelData( model,3447				'<listItem listType="bulleted" listIndent="0">A</listItem>' +3448				'<listItem listType="bulleted" listIndent="1">B[]</listItem>' +3449				'<listItem listType="bulleted" listIndent="2">C</listItem>'3450			);3451			const clipboard = editor.plugins.get( 'Clipboard' );3452			clipboard.fire( 'inputTransformation', {3453				content: parseView( '<ul><li>X<ul><li>Y</li></ul></li></ul>' )3454			} );3455			expect( getModelData( model ) ).to.equal(3456				'<listItem listIndent="0" listType="bulleted">A</listItem>' +3457				'<listItem listIndent="1" listType="bulleted">BX</listItem>' +3458				'<listItem listIndent="2" listType="bulleted">Y[]</listItem>' +3459				'<listItem listIndent="2" listType="bulleted">C</listItem>'3460			);3461		} );3462		it( 'should not fix indents of list items that are separated by non-list element', () => {3463			setModelData( model,3464				'<listItem listType="bulleted" listIndent="0">A</listItem>' +3465				'<listItem listType="bulleted" listIndent="1">B[]</listItem>' +3466				'<listItem listType="bulleted" listIndent="2">C</listItem>'3467			);3468			const clipboard = editor.plugins.get( 'Clipboard' );3469			clipboard.fire( 'inputTransformation', {3470				content: parseView( '<ul><li>W<ul><li>X</li></ul></li></ul><p>Y</p><ul><li>Z</li></ul>' )3471			} );3472			expect( getModelData( model ) ).to.equal(3473				'<listItem listIndent="0" listType="bulleted">A</listItem>' +3474				'<listItem listIndent="1" listType="bulleted">BW</listItem>' +3475				'<listItem listIndent="2" listType="bulleted">X</listItem>' +3476				'<paragraph>Y</paragraph>' +3477				'<listItem listIndent="0" listType="bulleted">Z[]</listItem>' +3478				'<listItem listIndent="1" listType="bulleted">C</listItem>'3479			);3480		} );3481		it( 'should co-work correctly with post fixer', () => {3482			setModelData( model,3483				'<listItem listType="bulleted" listIndent="0">A</listItem>' +3484				'<listItem listType="bulleted" listIndent="1">B[]</listItem>' +3485				'<listItem listType="bulleted" listIndent="2">C</listItem>'3486			);3487			const clipboard = editor.plugins.get( 'Clipboard' );3488			clipboard.fire( 'inputTransformation', {3489				content: parseView( '<p>X</p><ul><li>Y</li></ul>' )3490			} );3491			expect( getModelData( model ) ).to.equal(3492				'<listItem listIndent="0" listType="bulleted">A</listItem>' +3493				'<listItem listIndent="1" listType="bulleted">BX</listItem>' +3494				'<listItem listIndent="0" listType="bulleted">Y[]</listItem>' +3495				'<listItem listIndent="1" listType="bulleted">C</listItem>'3496			);3497		} );3498		it( 'should work if items are pasted between listItem elements', () => {3499			// Wrap all changes in one block to avoid post-fixing the selection3500			// (which may be incorret) in the meantime.3501			model.change( () => {3502				setModelData( model,3503					'<listItem listType="bulleted" listIndent="0">A</listItem>' +3504					'<listItem listType="bulleted" listIndent="1">B</listItem>[]' +3505					'<listItem listType="bulleted" listIndent="2">C</listItem>'3506				);3507				const clipboard = editor.plugins.get( 'Clipboard' );3508				clipboard.fire( 'inputTransformation', {3509					content: parseView( '<ul><li>X<ul><li>Y</li></ul></li></ul>' )3510				} );3511			} );3512			expect( getModelData( model ) ).to.equal(3513				'<listItem listIndent="0" listType="bulleted">A</listItem>' +3514				'<listItem listIndent="1" listType="bulleted">B</listItem>' +3515				'<listItem listIndent="1" listType="bulleted">X</listItem>' +3516				'<listItem listIndent="2" listType="bulleted">Y[]</listItem>' +3517				'<listItem listIndent="2" listType="bulleted">C</listItem>'3518			);3519		} );3520		it( 'should create correct model when list items are pasted in top-level list', () => {3521			setModelData( model,3522				'<listItem listType="bulleted" listIndent="0">A[]</listItem>' +3523				'<listItem listType="bulleted" listIndent="1">B</listItem>'3524			);3525			const clipboard = editor.plugins.get( 'Clipboard' );3526			clipboard.fire( 'inputTransformation', {3527				content: parseView( '<ul><li>X<ul><li>Y</li></ul></li></ul>' )3528			} );3529			expect( getModelData( model ) ).to.equal(3530				'<listItem listIndent="0" listType="bulleted">AX</listItem>' +3531				'<listItem listIndent="1" listType="bulleted">Y[]</listItem>' +3532				'<listItem listIndent="1" listType="bulleted">B</listItem>'3533			);3534		} );3535		it( 'should create correct model when list items are pasted in non-list context', () => {3536			setModelData( model,3537				'<paragraph>A[]</paragraph>' +3538				'<paragraph>B</paragraph>'3539			);3540			const clipboard = editor.plugins.get( 'Clipboard' );3541			clipboard.fire( 'inputTransformation', {3542				content: parseView( '<ul><li>X<ul><li>Y</li></ul></li></ul>' )3543			} );3544			expect( getModelData( model ) ).to.equal(3545				'<paragraph>AX</paragraph>' +3546				'<listItem listIndent="0" listType="bulleted">Y[]</listItem>' +3547				'<paragraph>B</paragraph>'3548			);3549		} );3550		it( 'should not crash when "empty content" is inserted', () => {3551			setModelData( model, '<paragraph>[]</paragraph>' );3552			expect( () => {3553				model.change( writer => {3554					editor.model.insertContent( writer.createDocumentFragment() );3555				} );3556			} ).not.to.throw();3557		} );3558		it( 'should correctly handle item that is pasted without its parent', () => {3559			// Wrap all changes in one block to avoid post-fixing the selection3560			// (which may be incorret) in the meantime.3561			model.change( () => {3562				setModelData( model,3563					'<paragraph>Foo</paragraph>' +3564					'<listItem listType="numbered" listIndent="0">A</listItem>' +3565					'<listItem listType="numbered" listIndent="1">B</listItem>' +3566					'[]' +3567					'<paragraph>Bar</paragraph>'3568				);3569				const clipboard = editor.plugins.get( 'Clipboard' );3570				clipboard.fire( 'inputTransformation', {3571					content: parseView( '<li>X</li>' )3572				} );3573			} );3574			expect( getModelData( model ) ).to.equal(3575				'<paragraph>Foo</paragraph>' +3576				'<listItem listIndent="0" listType="numbered">A</listItem>' +3577				'<listItem listIndent="1" listType="numbered">B</listItem>' +3578				'<listItem listIndent="1" listType="numbered">X[]</listItem>' +3579				'<paragraph>Bar</paragraph>'3580			);3581		} );3582		it( 'should correctly handle item that is pasted without its parent #2', () => {3583			// Wrap all changes in one block to avoid post-fixing the selection3584			// (which may be incorret) in the meantime.3585			model.change( () => {3586				setModelData( model,3587					'<paragraph>Foo</paragraph>' +3588					'<listItem listType="numbered" listIndent="0">A</listItem>' +3589					'<listItem listType="numbered" listIndent="1">B</listItem>' +3590					'[]' +3591					'<paragraph>Bar</paragraph>'3592				);3593				const clipboard = editor.plugins.get( 'Clipboard' );3594				clipboard.fire( 'inputTransformation', {3595					content: parseView( '<li>X<ul><li>Y</li></ul></li>' )3596				} );3597			} );3598			expect( getModelData( model ) ).to.equal(3599				'<paragraph>Foo</paragraph>' +3600				'<listItem listIndent="0" listType="numbered">A</listItem>' +3601				'<listItem listIndent="1" listType="numbered">B</listItem>' +3602				'<listItem listIndent="1" listType="numbered">X</listItem>' +3603				'<listItem listIndent="2" listType="bulleted">Y[]</listItem>' +3604				'<paragraph>Bar</paragraph>'3605			);3606		} );3607		it( 'should handle block elements inside pasted list #1', () => {3608			setModelData( model,3609				'<listItem listType="bulleted" listIndent="0">A</listItem>' +3610				'<listItem listType="bulleted" listIndent="1">B[]</listItem>' +3611				'<listItem listType="bulleted" listIndent="2">C</listItem>'3612			);3613			const clipboard = editor.plugins.get( 'Clipboard' );3614			clipboard.fire( 'inputTransformation', {3615				content: parseView( '<ul><li>W<ul><li>X<p>Y</p>Z</li></ul></li></ul>' )3616			} );3617			expect( getModelData( model ) ).to.equal(3618				'<listItem listIndent="0" listType="bulleted">A</listItem>' +3619				'<listItem listIndent="1" listType="bulleted">BW</listItem>' +3620				'<listItem listIndent="2" listType="bulleted">X</listItem>' +3621				'<paragraph>Y</paragraph>' +3622				'<listItem listIndent="0" listType="bulleted">Z[]</listItem>' +3623				'<listItem listIndent="1" listType="bulleted">C</listItem>'3624			);3625		} );3626		it( 'should handle block elements inside pasted list #2', () => {3627			setModelData( model,3628				'<listItem listType="bulleted" listIndent="0">A[]</listItem>' +3629				'<listItem listType="bulleted" listIndent="1">B</listItem>' +3630				'<listItem listType="bulleted" listIndent="2">C</listItem>'3631			);3632			const clipboard = editor.plugins.get( 'Clipboard' );3633			clipboard.fire( 'inputTransformation', {3634				content: parseView( '<ul><li>W<ul><li>X<p>Y</p>Z</li></ul></li></ul>' )3635			} );3636			expect( getModelData( model ) ).to.equal(3637				'<listItem listIndent="0" listType="bulleted">AW</listItem>' +3638				'<listItem listIndent="1" listType="bulleted">X</listItem>' +3639				'<paragraph>Y</paragraph>' +3640				'<listItem listIndent="0" listType="bulleted">Z[]</listItem>' +3641				'<listItem listIndent="0" listType="bulleted">B</listItem>' +3642				'<listItem listIndent="1" listType="bulleted">C</listItem>'3643			);3644		} );3645		it( 'should handle block elements inside pasted list #3', () => {3646			setModelData( model,3647				'<listItem listType="bulleted" listIndent="0">A[]</listItem>' +3648				'<listItem listType="bulleted" listIndent="1">B</listItem>' +3649				'<listItem listType="bulleted" listIndent="2">C</listItem>'3650			);3651			const clipboard = editor.plugins.get( 'Clipboard' );3652			clipboard.fire( 'inputTransformation', {3653				content: parseView( '<ul><li><p>W</p><p>X</p><p>Y</p></li><li>Z</li></ul>' )3654			} );3655			expect( getModelData( model ) ).to.equal(3656				'<listItem listIndent="0" listType="bulleted">AW</listItem>' +3657				'<paragraph>X</paragraph>' +3658				'<paragraph>Y</paragraph>' +3659				'<listItem listIndent="0" listType="bulleted">Z[]</listItem>' +3660				'<listItem listIndent="1" listType="bulleted">B</listItem>' +3661				'<listItem listIndent="2" listType="bulleted">C</listItem>'3662			);3663		} );3664		// https://github.com/ckeditor/ckeditor5-list/issues/126#issuecomment-5182067433665		it( 'should properly handle split of list items with non-standard converters', () => {3666			setModelData( model,3667				'<listItem listType="bulleted" listIndent="0">A[]</listItem>' +3668				'<listItem listType="bulleted" listIndent="1">B</listItem>' +3669				'<listItem listType="bulleted" listIndent="2">C</listItem>'3670			);3671			editor.model.schema.register( 'splitBlock', { inheritAllFrom: '$block' } );3672			editor.conversion.for( 'downcast' ).elementToElement( { model: 'splitBlock', view: 'splitBlock' } );3673			editor.conversion.for( 'upcast' ).add( dispatcher => dispatcher.on( 'element:splitBlock', ( evt, data, conversionApi ) => {3674				conversionApi.consumable.consume( data.viewItem, { name: true } );3675				// Use split to allowed parent logic to simulate a non-standard use of `modelCursor` after split.3676				const splitBlock = conversionApi.writer.createElement( 'splitBlock' );3677				conversionApi.safeInsert( splitBlock, data.modelCursor );3678				data.modelRange = conversionApi.writer.createRangeOn( splitBlock );3679				data.modelCursor = conversionApi.writer.createPositionAfter( splitBlock );3680			} ) );3681			const clipboard = editor.plugins.get( 'Clipboard' );3682			clipboard.fire( 'inputTransformation', {3683				content: parseView( '<ul><li>a<splitBlock></splitBlock>b</li></ul>' )3684			} );3685			expect( getModelData( model, { withoutSelection: true } ) ).to.equal(3686				'<listItem listIndent="0" listType="bulleted">Aa</listItem>' +3687				'<splitBlock></splitBlock>' +3688				'<listItem listIndent="0" listType="bulleted">b</listItem>' +3689				'<listItem listIndent="1" listType="bulleted">B</listItem>' +3690				'<listItem listIndent="2" listType="bulleted">C</listItem>'3691			);3692		} );3693	} );3694	describe( 'other', () => {3695		it( 'model insert converter should not fire if change was already consumed', () => {3696			editor.editing.downcastDispatcher.on( 'insert:listItem', ( evt, data, conversionApi ) => {3697				conversionApi.consumable.consume( data.item, 'attribute:listType' );3698				conversionApi.consumable.consume( data.item, 'attribute:listIndent' );3699			}, { priority: 'highest' } );3700			editor.conversion.for( 'downcast' )3701				.elementToElement( { model: 'listItem', view: 'p', converterPriority: 'highest' } );3702			// Paragraph is needed, otherwise selection throws.3703			setModelData( model, '<paragraph>x</paragraph><listItem listIndent="0" listType="bulleted">y</listItem>' );3704			expect( getViewData( editor.editing.view, { withoutSelection: true } ) ).to.equal( '<p>x</p><p>y</p>' );3705		} );3706		it( 'model remove converter should be possible to overwrite', () => {3707			editor.editing.downcastDispatcher.on( 'remove:listItem', evt => {3708				evt.stop();3709			}, { priority: 'highest' } );3710			// Paragraph is needed to prevent autoparagraphing of empty editor.3711			setModelData( model, '<paragraph>x</paragraph><listItem listIndent="0" listType="bulleted"></listItem>' );3712			model.change( writer => {3713				writer.remove( modelRoot.getChild( 1 ) );3714			} );3715			expect( getViewData( editor.editing.view, { withoutSelection: true } ) ).to.equal( '<p>x</p><ul><li></li></ul>' );3716		} );3717		it( 'model change type converter should not fire if change was already consumed', () => {3718			editor.editing.downcastDispatcher.on( 'attribute:listType', ( evt, data, conversionApi ) => {3719				conversionApi.consumable.consume( data.item, 'attribute:listType' );3720			}, { priority: 'highest' } );3721			setModelData( model, '<listItem listIndent="0" listType="bulleted"></listItem>' );3722			model.change( writer => {3723				writer.setAttribute( 'listType', 'numbered', modelRoot.getChild( 0 ) );3724			} );3725			expect( getViewData( editor.editing.view, { withoutSelection: true } ) ).to.equal( '<ul><li></li></ul>' );3726		} );3727		it( 'model change indent converter should not fire if change was already consumed', () => {3728			editor.editing.downcastDispatcher.on( 'attribute:listIndent', ( evt, data, conversionApi ) => {3729				conversionApi.consumable.consume( data.item, 'attribute:listIndent' );3730			}, { priority: 'highest' } );3731			setModelData(3732				model,3733				'<listItem listIndent="0" listType="bulleted">a</listItem><listItem listIndent="0" listType="bulleted">b</listItem>'3734			);3735			model.change( writer => {3736				writer.setAttribute( 'listIndent', 1, modelRoot.getChild( 1 ) );3737			} );3738			expect( getViewData( editor.editing.view, { withoutSelection: true } ) ).to.equal( '<ul><li>a</li><li>b</li></ul>' );3739		} );3740		it( 'view li converter should not fire if change was already consumed', () => {3741			editor.data.upcastDispatcher.on( 'element:li', ( evt, data, conversionApi ) => {3742				conversionApi.consumable.consume( data.viewItem, { name: true } );3743			}, { priority: 'highest' } );3744			editor.setData( '<p></p><ul><li></li></ul>' );3745			expect( getModelData( model, { withoutSelection: true } ) ).to.equal( '<paragraph></paragraph>' );3746		} );3747		it( 'view ul converter should not fire if change was already consumed', () => {3748			editor.data.upcastDispatcher.on( 'element:ul', ( evt, data, conversionApi ) => {3749				conversionApi.consumable.consume( data.viewItem, { name: true } );3750			}, { priority: 'highest' } );3751			editor.setData( '<p></p><ul><li></li></ul>' );3752			expect( getModelData( model, { withoutSelection: true } ) ).to.equal( '<paragraph></paragraph>' );3753		} );3754		it( 'view converter should pass model range in data.modelRange', () => {3755			editor.data.upcastDispatcher.on( 'element:ul', ( evt, data ) => {3756				expect( data.modelRange ).to.be.instanceof( ModelRange );3757			}, { priority: 'lowest' } );3758			editor.setData( '<ul><li>Foo</li><li>Bar</li></ul>' );3759		} );3760		// This test tests the fix in `injectViewList` helper.3761		it( 'ul and ol should not be inserted before ui element - injectViewList()', () => {3762			editor.setData( '<ul><li>Foo</li><li>Bar</li></ul>' );3763			// Append ui element at the end of first <li>.3764			view.change( writer => {3765				const firstChild = viewDoc.getRoot().getChild( 0 ).getChild( 0 );3766				const uiElement = writer.createUIElement( 'span' );3767				writer.insert( writer.createPositionAt( firstChild, 'end' ), uiElement );3768			} );3769			expect( getViewData( editor.editing.view, { withoutSelection: true } ) )3770				.to.equal( '<ul><li>Foo<span></span></li><li>Bar</li></ul>' );3771			model.change( writer => {3772				// Change indent of the second list item.3773				writer.setAttribute( 'listIndent', 1, modelRoot.getChild( 1 ) );3774			} );3775			// Check if the new <ul> was added at correct position.3776			expect( getViewData( editor.editing.view, { withoutSelection: true } ) )3777				.to.equal( '<ul><li>Foo<span></span><ul><li>Bar</li></ul></li></ul>' );3778		} );3779		// This test tests the fix in `hoistNestedLists` helper.3780		it( 'ul and ol should not be inserted before ui element - hoistNestedLists()', () => {3781			editor.setData( '<ul><li>Foo</li><li>Bar<ul><li>Xxx</li><li>Yyy</li></ul></li></ul>' );3782			// Append ui element at the end of first <li>.3783			view.change( writer => {3784				const firstChild = viewDoc.getRoot().getChild( 0 ).getChild( 0 );3785				const uiElement = writer.createUIElement( 'span' );3786				writer.insert( writer.createPositionAt( firstChild, 'end' ), uiElement );3787			} );3788			expect( getViewData( editor.editing.view, { withoutSelection: true } ) )3789				.to.equal( '<ul><li>Foo<span></span></li><li>Bar<ul><li>Xxx</li><li>Yyy</li></ul></li></ul>' );3790			model.change( writer => {3791				// Remove second list item. Expect that its sub-list will be moved to first list item.3792				writer.remove( modelRoot.getChild( 1 ) );3793			} );3794			// Check if the <ul> was added at correct position.3795			expect( getViewData( editor.editing.view, { withoutSelection: true } ) )3796				.to.equal( '<ul><li>Foo<span></span><ul><li>Xxx</li><li>Yyy</li></ul></li></ul>' );3797		} );3798		describe( 'remove converter should properly handle ui elements', () => {3799			let liFoo, liBar;3800			beforeEach( () => {3801				editor.setData( '<ul><li>Foo</li><li>Bar</li></ul>' );3802				liFoo = modelRoot.getChild( 0 );3803				liBar = modelRoot.getChild( 1 );3804			} );3805			it( 'ui element before <ul>', () => {3806				view.change( writer => {3807					// Append ui element before <ul>.3808					writer.insert( writer.createPositionAt( viewRoot, 0 ), writer.createUIElement( 'span' ) );3809				} );3810				model.change( writer => {3811					writer.remove( liFoo );3812				} );3813				expect( getViewData( editor.editing.view, { withoutSelection: true } ) )3814					.to.equal( '<span></span><ul><li>Bar</li></ul>' );3815			} );3816			it( 'ui element before first <li>', () => {3817				view.change( writer => {3818					// Append ui element before <ul>.3819					writer.insert( writer.createPositionAt( viewRoot.getChild( 0 ), 0 ), writer.createUIElement( 'span' ) );3820				} );3821				model.change( writer => {3822					writer.remove( liFoo );3823				} );3824				expect( getViewData( editor.editing.view, { withoutSelection: true } ) )3825					.to.equal( '<ul><span></span><li>Bar</li></ul>' );3826			} );3827			it( 'ui element in the middle of list', () => {3828				view.change( writer => {3829					// Append ui element before <ul>.3830					writer.insert( writer.createPositionAt( viewRoot.getChild( 0 ), 'end' ), writer.createUIElement( 'span' ) );3831				} );3832				model.change( writer => {3833					writer.remove( liBar );3834				} );3835				expect( getViewData( editor.editing.view, { withoutSelection: true } ) )3836					.to.equal( '<ul><li>Foo</li><span></span></ul>' );3837			} );3838		} );3839	} );3840	describe( 'schema checking and parent splitting', () => {3841		beforeEach( () => {3842			// Since this part of test tests only view->model conversion editing pipeline is not necessary.3843			editor.editing.destroy();3844		} );3845		it( 'list should be not converted when modelCursor and its ancestors disallow to insert list', () => {3846			model.document.createRoot( '$title', 'title' );3847			model.schema.register( '$title', {3848				disallow: '$block',3849				allow: 'inline'3850			} );3851			editor.data.set( { title: '<ul><li>foo</li></ul>' } );3852			expect( getModelData( model, { rootName: 'title', withoutSelection: true } ) ).to.equal( '' );3853		} );3854		it( 'should split parent element when one of modelCursor ancestors allows to insert list - in the middle', () => {3855			editor.conversion.for( 'upcast' ).elementToElement( { view: 'div', model: 'div' } );3856			model.schema.register( 'div', { inheritAllFrom: '$block' } );3857			editor.setData(3858				'<div>' +3859					'abc' +3860					'<ul>' +3861						'<li>foo</li>' +3862					'</ul>' +3863					'def' +3864				'</div>'3865			);3866			expect( getModelData( model, { withoutSelection: true } ) ).to.equal(3867				'<div>abc</div>' +3868				'<listItem listIndent="0" listType="bulleted">foo</listItem>' +3869				'<div>def</div>'3870			);3871		} );3872		it( 'should split parent element when one of modelCursor ancestors allows to insert list - at the end', () => {3873			editor.conversion.for( 'upcast' ).elementToElement( { view: 'div', model: 'div' } );3874			model.schema.register( 'div', { inheritAllFrom: '$block' } );3875			editor.setData(3876				'<div>' +3877					'abc' +3878					'<ul>' +3879						'<li>foo</li>' +3880					'</ul>' +3881				'</div>'3882			);3883			expect( getModelData( model, { withoutSelection: true } ) ).to.equal(3884				'<div>abc</div>' +3885				'<listItem listIndent="0" listType="bulleted">foo</listItem>'3886			);3887		} );3888		it( 'should split parent element when one of modelCursor ancestors allows to insert list - at the beginning', () => {3889			editor.conversion.for( 'upcast' ).elementToElement( { view: 'div', model: 'div' } );3890			model.schema.register( 'div', { inheritAllFrom: '$block' } );3891			editor.setData(3892				'<div>' +3893					'<ul>' +3894						'<li>foo</li>' +3895					'</ul>' +3896					'def' +3897				'</div>'3898			);3899			expect( getModelData( model, { withoutSelection: true } ) ).to.equal(3900				'<listItem listIndent="0" listType="bulleted">foo</listItem>' +3901				'<div>def</div>'3902			);3903		} );3904		// https://github.com/ckeditor/ckeditor5-list/issues/1213905		it( 'should correctly set data.modelCursor', () => {3906			editor.setData(3907				'<ul>' +3908					'<li>a</li>' +3909					'<li>b</li>' +3910				'</ul>' +3911				'c'3912			);3913			expect( getModelData( model, { withoutSelection: true } ) ).to.equal(3914				'<listItem listIndent="0" listType="bulleted">a</listItem>' +3915				'<listItem listIndent="0" listType="bulleted">b</listItem>' +3916				'<paragraph>c</paragraph>'3917			);3918		} );3919		// https://github.com/ckeditor/ckeditor5/issues/15723920		it( 'should not crash if list item contains autoparagraphed block that will be split', () => {3921			// Creating a new editor as we need HeadingEditing. Cannot add HeadingEditing to the `describe` at the beginning of the3922			// test file because other tests assume that headings are not available.3923			return VirtualTestEditor3924				.create( {3925					plugins: [ ListEditing, HeadingEditing ]3926				} )3927				.then( editor => {3928					editor.setData( '<ul><li><div><h2>Foo</h2></div></li></ul>' );3929					expect( getModelData( editor.model, { withoutSelection: true } ) ).to.equal( '<heading1>Foo</heading1>' );3930				} );3931		} );3932	} );3933	function getViewPosition( root, path, view ) {3934		let parent = root;3935		while ( path.length > 1 ) {3936			parent = parent.getChild( path.shift() );3937		}3938		return view.createPositionAt( parent, path[ 0 ] );3939	}3940	function getViewPath( position ) {3941		const path = [ position.offset ];3942		let parent = position.parent;3943		while ( parent.parent ) {3944			path.unshift( parent.index );3945			parent = parent.parent;3946		}3947		return path;3948	}3949	function testInsert( testName, input, output, testUndo = true ) {3950		// Cut out inserted element that is between '[' and ']' characters.3951		const selStart = input.indexOf( '[' ) + 1;3952		const selEnd = input.indexOf( ']' );3953		const item = input.substring( selStart, selEnd );3954		const modelInput = input.substring( 0, selStart ) + input.substring( selEnd );3955		const actionCallback = selection => {3956			model.change( writer => {3957				writer.insert( parseModel( item, model.schema ), selection.getFirstPosition() );3958			} );3959		};3960		_test( testName, modelInput, output, actionCallback, testUndo );3961	}3962	function testRemove( testName, input, output ) {3963		const actionCallback = selection => {3964			model.change( writer => {3965				writer.remove( selection.getFirstRange() );3966			} );3967		};3968		_test( testName, input, output, actionCallback );3969	}3970	function testChangeType( testName, input, output ) {3971		const actionCallback = selection => {3972			const element = selection.getFirstPosition().nodeAfter;3973			const newType = element.getAttribute( 'listType' ) == 'numbered' ? 'bulleted' : 'numbered';3974			model.change( writer => {3975				const itemsToChange = Array.from( selection.getSelectedBlocks() );3976				for ( const item of itemsToChange ) {3977					writer.setAttribute( 'listType', newType, item );3978				}3979			} );3980		};3981		_test( testName, input, output, actionCallback );3982	}3983	function testRenameFromListItem( testName, input, output, testUndo = true ) {3984		const actionCallback = selection => {3985			const element = selection.getFirstPosition().nodeAfter;3986			model.change( writer => {3987				writer.rename( element, 'paragraph' );3988				writer.removeAttribute( 'listType', element );3989				writer.removeAttribute( 'listIndent', element );3990			} );3991		};3992		_test( testName, input, output, actionCallback, testUndo );3993	}3994	function testRenameToListItem( testName, newIndent, input, output ) {3995		const actionCallback = selection => {3996			const element = selection.getFirstPosition().nodeAfter;3997			model.change( writer => {3998				writer.setAttributes( { listType: 'bulleted', listIndent: newIndent }, element );3999				writer.rename( element, 'listItem' );4000			} );4001		};4002		_test( testName, input, output, actionCallback );4003	}4004	function testChangeIndent( testName, newIndent, input, output ) {4005		const actionCallback = selection => {4006			model.change( writer => {4007				writer.setAttribute( 'listIndent', newIndent, selection.getFirstRange() );4008			} );4009		};4010		_test( testName, input, output, actionCallback );4011	}4012	function testMove( testName, input, rootOffset, output, testUndo = true ) {4013		const actionCallback = selection => {4014			model.change( writer => {4015				const targetPosition = writer.createPositionAt( modelRoot, rootOffset );4016				writer.move( selection.getFirstRange(), targetPosition );4017			} );4018		};4019		_test( testName, input, output, actionCallback, testUndo );4020	}4021	function _test( testName, input, output, actionCallback, testUndo ) {4022		it( testName, () => {4023			const callbackSelection = prepareTest( model, input );4024			actionCallback( callbackSelection );4025			expect( getViewData( view, { withoutSelection: true } ) ).to.equal( output );4026		} );4027		if ( testUndo ) {4028			it( testName + ' (undo integration)', () => {4029				const callbackSelection = prepareTest( model, input );4030				const modelBefore = getModelData( model );4031				const viewBefore = getViewData( view, { withoutSelection: true } );4032				actionCallback( callbackSelection );4033				const modelAfter = getModelData( model );4034				const viewAfter = getViewData( view, { withoutSelection: true } );4035				editor.execute( 'undo' );4036				expect( getModelData( model ) ).to.equal( modelBefore );4037				expect( getViewData( view, { withoutSelection: true } ) ).to.equal( viewBefore );4038				editor.execute( 'redo' );4039				expect( getModelData( model ) ).to.equal( modelAfter );4040				expect( getViewData( view, { withoutSelection: true } ) ).to.equal( viewAfter );4041			} );4042		}4043		function prepareTest( model, input ) {4044			const modelRoot = model.document.getRoot( 'main' );4045			// Parse data string to model.4046			const parsedResult = parseModel( input, model.schema, { context: [ modelRoot.name ] } );4047			// Retrieve DocumentFragment and Selection from parsed model.4048			const modelDocumentFragment = parsedResult.model;4049			const selection = parsedResult.selection;4050			// Ensure no undo step is generated.4051			model.enqueueChange( 'transparent', writer => {4052				// Replace existing model in document by new one.4053				writer.remove( writer.createRangeIn( modelRoot ) );4054				writer.insert( modelDocumentFragment, modelRoot );4055				// Clean up previous document selection.4056				writer.setSelection( null );4057				writer.removeSelectionAttribute( model.document.selection.getAttributeKeys() );4058			} );4059			const ranges = [];4060			for ( const range of selection.getRanges() ) {4061				const start = model.createPositionFromPath( modelRoot, range.start.path );4062				const end = model.createPositionFromPath( modelRoot, range.end.path );4063				ranges.push( model.createRange( start, end ) );4064			}4065			return model.createSelection( ranges );4066		}4067	}...

Full Screen

Full Screen

liststyleediting.js

Source:liststyleediting.js Github

copy

Full Screen

1/**2 * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.3 * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license4 */5import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';6import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';7import Typing from '@ckeditor/ckeditor5-typing/src/typing';8import UndoEditing from '@ckeditor/ckeditor5-undo/src/undoediting';9import { getData as getModelData, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';10import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';11import ListStyleEditing from '../src/liststyleediting';12import TodoListEditing from '../src/todolistediting';13import ListStyleCommand from '../src/liststylecommand';14describe( 'ListStyleEditing', () => {15	let editor, model, view;16	beforeEach( () => {17		return VirtualTestEditor18			.create( {19				plugins: [ Paragraph, ListStyleEditing, UndoEditing ]20			} )21			.then( newEditor => {22				editor = newEditor;23				model = editor.model;24				view = editor.editing.view;25			} );26	} );27	afterEach( () => {28		return editor.destroy();29	} );30	it( 'should have pluginName', () => {31		expect( ListStyleEditing.pluginName ).to.equal( 'ListStyleEditing' );32	} );33	it( 'should be loaded', () => {34		expect( editor.plugins.get( ListStyleEditing ) ).to.be.instanceOf( ListStyleEditing );35	} );36	describe( 'schema rules', () => {37		it( 'should allow set `listStyle` on the `listItem`', () => {38			expect( model.schema.checkAttribute( [ '$root', 'listItem' ], 'listStyle' ) ).to.be.true;39		} );40	} );41	describe( 'command', () => {42		it( 'should register listStyle command', () => {43			const command = editor.commands.get( 'listStyle' );44			expect( command ).to.be.instanceOf( ListStyleCommand );45		} );46	} );47	describe( 'conversion in data pipeline', () => {48		describe( 'model to data', () => {49			it( 'should convert single list (type: bulleted)', () => {50				setModelData( model,51					'<listItem listIndent="0" listType="bulleted">Foo</listItem>' +52					'<listItem listIndent="0" listType="bulleted">Bar</listItem>'53				);54				expect( editor.getData() ).to.equal( '<ul><li>Foo</li><li>Bar</li></ul>' );55			} );56			it( 'should convert single list (type: numbered)', () => {57				setModelData( model,58					'<listItem listIndent="0" listType="numbered">Foo</listItem>' +59					'<listItem listIndent="0" listType="numbered">Bar</listItem>'60				);61				expect( editor.getData() ).to.equal( '<ol><li>Foo</li><li>Bar</li></ol>' );62			} );63			it( 'should convert single list (type: bulleted, style: default)', () => {64				setModelData( model,65					'<listItem listIndent="0" listType="bulleted" listStyle="default">Foo</listItem>' +66					'<listItem listIndent="0" listType="bulleted" listStyle="default">Bar</listItem>'67				);68				expect( editor.getData() ).to.equal( '<ul><li>Foo</li><li>Bar</li></ul>' );69			} );70			it( 'should convert single list (type: numbered, style: default)', () => {71				setModelData( model,72					'<listItem listIndent="0" listType="numbered" listStyle="default">Foo</listItem>' +73					'<listItem listIndent="0" listType="numbered" listStyle="default">Bar</listItem>'74				);75				expect( editor.getData() ).to.equal( '<ol><li>Foo</li><li>Bar</li></ol>' );76			} );77			it( 'should convert single list (type: bulleted, style: circle)', () => {78				setModelData( model,79					'<listItem listIndent="0" listType="bulleted" listStyle="circle">Foo</listItem>' +80					'<listItem listIndent="0" listType="bulleted" listStyle="circle">Bar</listItem>'81				);82				expect( editor.getData() ).to.equal( '<ul style="list-style-type:circle;"><li>Foo</li><li>Bar</li></ul>' );83			} );84			it( 'should convert single list (type: numbered, style: upper-alpha)', () => {85				setModelData( model,86					'<listItem listIndent="0" listType="numbered" listStyle="upper-alpha">Foo</listItem>' +87					'<listItem listIndent="0" listType="numbered" listStyle="upper-alpha">Bar</listItem>'88				);89				expect( editor.getData() ).to.equal( '<ol style="list-style-type:upper-alpha;"><li>Foo</li><li>Bar</li></ol>' );90			} );91			it( 'should convert nested bulleted lists (main: circle, nested: disc)', () => {92				setModelData( model,93					'<listItem listIndent="0" listType="bulleted" listStyle="circle">Foo 1</listItem>' +94					'<listItem listIndent="1" listType="bulleted" listStyle="disc">Bar 1</listItem>' +95					'<listItem listIndent="1" listType="bulleted" listStyle="disc">Bar 2</listItem>' +96					'<listItem listIndent="0" listType="bulleted" listStyle="circle">Foo 2</listItem>' +97					'<listItem listIndent="0" listType="bulleted" listStyle="circle">Foo 3</listItem>'98				);99				expect( editor.getData() ).to.equal(100					'<ul style="list-style-type:circle;">' +101						'<li>Foo 1' +102							'<ul style="list-style-type:disc;">' +103								'<li>Bar 1</li>' +104								'<li>Bar 2</li>' +105							'</ul>' +106						'</li>' +107						'<li>Foo 2</li>' +108						'<li>Foo 3</li>' +109					'</ul>'110				);111			} );112			it( 'should convert nested numbered lists (main: decimal-leading-zero, nested: lower-latin)', () => {113				setModelData( model,114					'<listItem listIndent="0" listType="numbered" listStyle="decimal-leading-zero">Foo 1</listItem>' +115					'<listItem listIndent="1" listType="numbered" listStyle="lower-latin">Bar 1</listItem>' +116					'<listItem listIndent="1" listType="numbered" listStyle="lower-latin">Bar 2</listItem>' +117					'<listItem listIndent="0" listType="numbered" listStyle="decimal-leading-zero">Foo 2</listItem>' +118					'<listItem listIndent="0" listType="numbered" listStyle="decimal-leading-zero">Foo 3</listItem>'119				);120				expect( editor.getData() ).to.equal(121					'<ol style="list-style-type:decimal-leading-zero;">' +122						'<li>Foo 1' +123							'<ol style="list-style-type:lower-latin;">' +124								'<li>Bar 1</li>' +125								'<li>Bar 2</li>' +126							'</ol>' +127						'</li>' +128						'<li>Foo 2</li>' +129						'<li>Foo 3</li>' +130					'</ol>'131				);132			} );133			it( 'should convert nested mixed lists (ul>ol, main: square, nested: lower-roman)', () => {134				setModelData( model,135					'<listItem listIndent="0" listType="bulleted" listStyle="square">Foo 1</listItem>' +136					'<listItem listIndent="1" listType="numbered" listStyle="lower-roman">Bar 1</listItem>' +137					'<listItem listIndent="1" listType="numbered" listStyle="lower-roman">Bar 2</listItem>' +138					'<listItem listIndent="0" listType="bulleted" listStyle="square">Foo 2</listItem>' +139					'<listItem listIndent="0" listType="bulleted" listStyle="square">Foo 3</listItem>'140				);141				expect( editor.getData() ).to.equal(142					'<ul style="list-style-type:square;">' +143						'<li>Foo 1' +144							'<ol style="list-style-type:lower-roman;">' +145								'<li>Bar 1</li>' +146								'<li>Bar 2</li>' +147							'</ol>' +148						'</li>' +149						'<li>Foo 2</li>' +150						'<li>Foo 3</li>' +151					'</ul>'152				);153			} );154			it( 'should produce nested lists (different `listIndent` attribute)', () => {155				setModelData( model,156					'<listItem listIndent="0" listType="numbered" listStyle="decimal">Foo 1</listItem>' +157					'<listItem listIndent="0" listType="numbered" listStyle="decimal">Foo 2</listItem>' +158					'<listItem listIndent="1" listType="numbered" listStyle="decimal">Bar 1</listItem>' +159					'<listItem listIndent="1" listType="numbered" listStyle="decimal">Bar 2</listItem>'160				);161				expect( editor.getData() ).to.equal(162					'<ol style="list-style-type:decimal;">' +163						'<li>Foo 1</li>' +164						'<li>Foo 2' +165							'<ol style="list-style-type:decimal;">' +166								'<li>Bar 1</li>' +167								'<li>Bar 2</li>' +168							'</ol>' +169						'</li>' +170					'</ol>'171				);172			} );173			it( 'should produce two different lists (different `listType` attribute)', () => {174				setModelData( model,175					'<listItem listIndent="0" listType="numbered" listStyle="decimal">Foo 1</listItem>' +176					'<listItem listIndent="0" listType="numbered" listStyle="decimal">Foo 2</listItem>' +177					'<listItem listIndent="0" listType="bulleted" listStyle="disc">Bar 1</listItem>' +178					'<listItem listIndent="0" listType="bulleted" listStyle="disc">Bar 2</listItem>'179				);180				expect( editor.getData() ).to.equal(181					'<ol style="list-style-type:decimal;">' +182						'<li>Foo 1</li>' +183						'<li>Foo 2</li>' +184					'</ol>' +185					'<ul style="list-style-type:disc;">' +186						'<li>Bar 1</li>' +187						'<li>Bar 2</li>' +188					'</ul>'189				);190			} );191			it( 'should produce two different lists (different `listStyle` attribute)', () => {192				setModelData( model,193					'<listItem listIndent="0" listType="bulleted" listStyle="disc">Foo 1</listItem>' +194					'<listItem listIndent="0" listType="bulleted" listStyle="disc">Foo 2</listItem>' +195					'<listItem listIndent="0" listType="bulleted" listStyle="circle">Bar 1</listItem>' +196					'<listItem listIndent="0" listType="bulleted" listStyle="circle">Bar 2</listItem>'197				);198				expect( editor.getData() ).to.equal(199					'<ul style="list-style-type:disc;">' +200						'<li>Foo 1</li>' +201						'<li>Foo 2</li>' +202					'</ul>' +203					'<ul style="list-style-type:circle;">' +204						'<li>Bar 1</li>' +205						'<li>Bar 2</li>' +206					'</ul>'207				);208			} );209			it( 'should not allow to set the `listStyle` attribute in to-do list item', () => {210				setModelData( model, '<listItem listIndent="0" listType="todo">Foo</listItem>' );211				const listItem = model.document.getRoot().getChild( 0 );212				expect( listItem.hasAttribute( 'listItem' ) ).to.be.false;213				model.change( writer => {214					writer.setAttribute( 'listType', 'foo', listItem );215				} );216				expect( listItem.hasAttribute( 'listItem' ) ).to.be.false;217			} );218		} );219		describe( 'view to model', () => {220			it( 'should convert single list (type: bulleted)', () => {221				editor.setData( '<ul><li>Foo</li><li>Bar</li></ul>' );222				expect( getModelData( model, { withoutSelection: true } ) ).to.equal(223					'<listItem listIndent="0" listStyle="default" listType="bulleted">Foo</listItem>' +224					'<listItem listIndent="0" listStyle="default" listType="bulleted">Bar</listItem>'225				);226			} );227			it( 'should convert single list (type: numbered)', () => {228				editor.setData( '<ol><li>Foo</li><li>Bar</li></ol>' );229				expect( getModelData( model, { withoutSelection: true } ) ).to.equal(230					'<listItem listIndent="0" listStyle="default" listType="numbered">Foo</listItem>' +231					'<listItem listIndent="0" listStyle="default" listType="numbered">Bar</listItem>'232				);233			} );234			it( 'should convert single list (type: bulleted, style: circle)', () => {235				editor.setData( '<ul style="list-style-type:circle;"><li>Foo</li><li>Bar</li></ul>' );236				expect( getModelData( model, { withoutSelection: true } ) ).to.equal(237					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +238					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'239				);240			} );241			it( 'should convert single list (type: numbered, style: upper-alpha)', () => {242				editor.setData( '<ol style="list-style-type:upper-alpha;"><li>Foo</li><li>Bar</li></ol>' );243				expect( getModelData( model, { withoutSelection: true } ) ).to.equal(244					'<listItem listIndent="0" listStyle="upper-alpha" listType="numbered">Foo</listItem>' +245					'<listItem listIndent="0" listStyle="upper-alpha" listType="numbered">Bar</listItem>'246				);247			} );248			it( 'should convert nested and mixed lists', () => {249				editor.setData(250					'<ol style="list-style-type:upper-alpha;">' +251						'<li>OL 1</li>' +252						'<li>OL 2' +253							'<ul style="list-style-type:circle;">' +254								'<li>UL 1</li>' +255								'<li>UL 2</li>' +256							'</ul>' +257						'</li>' +258						'<li>OL 3</li>' +259					'</ol>'260				);261				expect( getModelData( model, { withoutSelection: true } ) ).to.equal(262					'<listItem listIndent="0" listStyle="upper-alpha" listType="numbered">OL 1</listItem>' +263					'<listItem listIndent="0" listStyle="upper-alpha" listType="numbered">OL 2</listItem>' +264					'<listItem listIndent="1" listStyle="circle" listType="bulleted">UL 1</listItem>' +265					'<listItem listIndent="1" listStyle="circle" listType="bulleted">UL 2</listItem>' +266					'<listItem listIndent="0" listStyle="upper-alpha" listType="numbered">OL 3</listItem>'267				);268			} );269			it( 'should convert when the list is in the middle of the content', () => {270				editor.setData(271					'<p>Paragraph.</p>' +272					'<ol style="list-style-type:upper-alpha;">' +273						'<li>Foo</li>' +274						'<li>Bar</li>' +275					'</ol>' +276					'<p>Paragraph.</p>'277				);278				expect( getModelData( model, { withoutSelection: true } ) ).to.equal(279					'<paragraph>Paragraph.</paragraph>' +280					'<listItem listIndent="0" listStyle="upper-alpha" listType="numbered">Foo</listItem>' +281					'<listItem listIndent="0" listStyle="upper-alpha" listType="numbered">Bar</listItem>' +282					'<paragraph>Paragraph.</paragraph>'283				);284			} );285			// See: #8262.286			describe( 'list conversion with surrounding text nodes', () => {287				let editor;288				beforeEach( () => {289					return VirtualTestEditor290						.create( {291							plugins: [ ListStyleEditing ]292						} )293						.then( newEditor => {294							editor = newEditor;295						} );296				} );297				afterEach( () => {298					return editor.destroy();299				} );300				it( 'should convert a list if raw text is before the list', () => {301					editor.setData( 'Foo<ul><li>Foo</li></ul>' );302					expect( editor.getData() ).to.equal( '<p>Foo</p><ul><li>Foo</li></ul>' );303				} );304				it( 'should convert a list if raw text is after the list', () => {305					editor.setData( '<ul><li>Foo</li></ul>Foo' );306					expect( editor.getData() ).to.equal( '<ul><li>Foo</li></ul><p>Foo</p>' );307				} );308				it( 'should convert a list if it is surrender by two text nodes', () => {309					editor.setData( 'Foo<ul><li>Foo</li></ul>Foo' );310					expect( editor.getData() ).to.equal( '<p>Foo</p><ul><li>Foo</li></ul><p>Foo</p>' );311				} );312			} );313		} );314	} );315	// At this moment editing and data pipelines produce exactly the same content.316	// Just a few tests will be enough here. `model to data` block contains all cases checked.317	describe( 'conversion in editing pipeline', () => {318		describe( 'model to view', () => {319			it( 'should convert single list (type: bulleted, style: default)', () => {320				setModelData( model,321					'<listItem listIndent="0" listType="bulleted" listStyle="default">Foo</listItem>' +322					'<listItem listIndent="0" listType="bulleted" listStyle="default">Bar</listItem>'323				);324				expect( getViewData( view, { withoutSelection: true } ) ).to.equal(325					'<ul><li>Foo</li><li>Bar</li></ul>'326				);327			} );328			it( 'should convert single list (type: bulleted, style: circle)', () => {329				setModelData( model,330					'<listItem listIndent="0" listType="bulleted" listStyle="circle">Foo</listItem>' +331					'<listItem listIndent="0" listType="bulleted" listStyle="circle">Bar</listItem>'332				);333				expect( getViewData( view, { withoutSelection: true } ) ).to.equal(334					'<ul style="list-style-type:circle"><li>Foo</li><li>Bar</li></ul>'335				);336			} );337			it( 'should convert nested bulleted lists (main: circle, nested: disc)', () => {338				setModelData( model,339					'<listItem listIndent="0" listType="bulleted" listStyle="circle">Foo 1</listItem>' +340					'<listItem listIndent="1" listType="bulleted" listStyle="disc">Bar 1</listItem>' +341					'<listItem listIndent="1" listType="bulleted" listStyle="disc">Bar 2</listItem>' +342					'<listItem listIndent="0" listType="bulleted" listStyle="circle">Foo 2</listItem>' +343					'<listItem listIndent="0" listType="bulleted" listStyle="circle">Foo 3</listItem>'344				);345				expect( getViewData( view, { withoutSelection: true } ) ).to.equal(346					'<ul style="list-style-type:circle">' +347						'<li>Foo 1' +348							'<ul style="list-style-type:disc">' +349								'<li>Bar 1</li>' +350								'<li>Bar 2</li>' +351							'</ul>' +352						'</li>' +353						'<li>Foo 2</li>' +354						'<li>Foo 3</li>' +355					'</ul>'356				);357			} );358			// See: #8081.359			it( 'should convert properly nested list styles', () => {360				// ■ Level 0361				//     ▶ Level 0.1362				//         ○ Level 0.1.1363				//     ▶ Level 0.2364				//         ○ Level 0.2.1365				setModelData( model,366					'<listItem listIndent="0" listType="bulleted" listStyle="default">Level 0</listItem>' +367					'<listItem listIndent="1" listType="bulleted" listStyle="default">Level 0.1</listItem>' +368					'<listItem listIndent="2" listType="bulleted" listStyle="circle">Level 0.1.1</listItem>' +369					'<listItem listIndent="1" listType="bulleted" listStyle="default">Level 0.2</listItem>' +370					'<listItem listIndent="2" listType="bulleted" listStyle="circle">Level 0.2.1</listItem>'371				);372				expect( getViewData( view, { withoutSelection: true } ) ).to.equal(373					'<ul>' +374						'<li>Level 0' +375							'<ul>' +376								'<li>Level 0.1' +377									'<ul style="list-style-type:circle">' +378										'<li>Level 0.1.1</li>' +379									'</ul>' +380								'</li>' +381								'<li>Level 0.2' +382									'<ul style="list-style-type:circle">' +383										'<li>Level 0.2.1</li>' +384									'</ul>' +385								'</li>' +386							'</ul>' +387						'</li>' +388					'</ul>'389				);390			} );391		} );392	} );393	describe( 'integrations', () => {394		describe( 'merging a list into a styled list', () => {395			it( 'should inherit the list style attribute when merging the same kind of lists (from top, merge a single item)', () => {396				setModelData( model,397					'<paragraph>Foo Bar.[]</paragraph>' +398					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +399					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'400				);401				editor.execute( 'bulletedList' );402				expect( getModelData( model ) ).to.equal(403					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo Bar.[]</listItem>' +404					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +405					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'406				);407			} );408			it( 'should inherit the list style attribute when merging the same kind of lists (from top, merge a few items)', () => {409				setModelData( model,410					'<paragraph>[Foo Bar 1.</paragraph>' +411					'<paragraph>Foo Bar 2.]</paragraph>' +412					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +413					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'414				);415				editor.execute( 'bulletedList' );416				expect( getModelData( model ) ).to.equal(417					'<listItem listIndent="0" listStyle="circle" listType="bulleted">[Foo Bar 1.</listItem>' +418					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo Bar 2.]</listItem>' +419					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +420					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'421				);422			} );423			it( 'should not inherit anything if there is no list below the inserted list', () => {424				setModelData( model,425					'<paragraph>Foo Bar 1.[]</paragraph>' +426					'<paragraph>Foo Bar 2.</paragraph>'427				);428				editor.execute( 'bulletedList' );429				expect( getModelData( model ) ).to.equal(430					'<listItem listIndent="0" listStyle="default" listType="bulleted">Foo Bar 1.[]</listItem>' +431					'<paragraph>Foo Bar 2.</paragraph>'432				);433			} );434			it( 'should not inherit anything if replacing the entire content with a list', () => {435				setModelData( model,436					'<paragraph>Foo Bar 1.[]</paragraph>'437				);438				editor.execute( 'bulletedList' );439				expect( getModelData( model ) ).to.equal(440					'<listItem listIndent="0" listStyle="default" listType="bulleted">Foo Bar 1.[]</listItem>'441				);442			} );443			it( 'should not inherit the list style attribute when merging different kind of lists (from top, merge a single item)', () => {444				setModelData( model,445					'<paragraph>Foo Bar.[]</paragraph>' +446					'<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Foo</listItem>' +447					'<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Bar</listItem>'448				);449				editor.execute( 'bulletedList' );450				expect( getModelData( model ) ).to.equal(451					'<listItem listIndent="0" listStyle="default" listType="bulleted">Foo Bar.[]</listItem>' +452					'<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Foo</listItem>' +453					'<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Bar</listItem>'454				);455			} );456			it(457				'should not inherit the list style attribute when merging different kind of lists (from bottom, merge a single item)',458				() => {459					setModelData( model,460						'<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Foo</listItem>' +461						'<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Bar</listItem>' +462						'<paragraph>Foo Bar.[]</paragraph>'463					);464					editor.execute( 'bulletedList' );465					expect( getModelData( model ) ).to.equal(466						'<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Foo</listItem>' +467						'<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Bar</listItem>' +468						'<listItem listIndent="0" listStyle="default" listType="bulleted">Foo Bar.[]</listItem>'469					);470				}471			);472			it( 'should inherit the list style attribute when merging the same kind of lists (from bottom, merge a single item)', () => {473				setModelData( model,474					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +475					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>' +476					'<paragraph>Foo Bar.[]</paragraph>'477				);478				editor.execute( 'bulletedList' );479				expect( getModelData( model ) ).to.equal(480					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +481					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>' +482					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo Bar.[]</listItem>'483				);484			} );485			it(486				'should inherit the list style attribute from listIndent=0 element when merging the same kind of lists (from bottom)',487				() => {488					setModelData( model,489						'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +490						'<listItem listIndent="1" listStyle="square" listType="bulleted">Bar</listItem>' +491						'<listItem listIndent="2" listStyle="disc" listType="bulleted">Foo Bar</listItem>' +492						'<paragraph>Foo Bar.[]</paragraph>'493					);494					editor.execute( 'bulletedList' );495					expect( getModelData( model ) ).to.equal(496						'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +497						'<listItem listIndent="1" listStyle="square" listType="bulleted">Bar</listItem>' +498						'<listItem listIndent="2" listStyle="disc" listType="bulleted">Foo Bar</listItem>' +499						'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo Bar.[]</listItem>'500					);501				}502			);503		} );504		describe( 'modifying "listType" attribute', () => {505			it( 'should inherit the list style attribute when the modified list is the same kind of the list as next sibling', () => {506				setModelData( model,507					'<listItem listIndent="0" listStyle="default" listType="numbered">Foo Bar.[]</listItem>' +508					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +509					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'510				);511				editor.execute( 'bulletedList' );512				expect( getModelData( model ) ).to.equal(513					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo Bar.[]</listItem>' +514					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +515					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'516				);517			} );518			it( 'should inherit the list style attribute when the modified list is the same kind of the list as previous sibling', () => {519				setModelData( model,520					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +521					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>' +522					'<listItem listIndent="0" listStyle="default" listType="numbered">Foo Bar.[]</listItem>'523				);524				editor.execute( 'bulletedList' );525				expect( getModelData( model ) ).to.equal(526					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +527					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>' +528					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo Bar.[]</listItem>'529				);530			} );531			it( 'should not inherit the list style attribute when the modified list already has defined it (next sibling check)', () => {532				setModelData( model,533					'<listItem listIndent="0" listStyle="default" listType="bulleted">Foo Bar.[]</listItem>' +534					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +535					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'536				);537				editor.execute( 'listStyle', { type: 'disc' } );538				expect( getModelData( model ) ).to.equal(539					'<listItem listIndent="0" listStyle="disc" listType="bulleted">Foo Bar.[]</listItem>' +540					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +541					'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'542				);543			} );544			it(545				'should not inherit the list style attribute when the modified list already has defined it (previous sibling check)',546				() => {547					setModelData( model,548						'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +549						'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>' +550						'<listItem listIndent="0" listStyle="default" listType="bulleted">Foo Bar.[]</listItem>'551					);552					editor.execute( 'listStyle', { type: 'disc' } );553					expect( getModelData( model ) ).to.equal(554						'<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +555						'<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>' +556						'<listItem listIndent="0" listStyle="disc" listType="bulleted">Foo Bar.[]</listItem>'557					);558				}559			);560		} );561		describe( 'indenting lists', () => {562			it( 'should restore the default value for the list style attribute when indenting a single item', () => {563				setModelData( model,564					'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +565					'<listItem listIndent="1" listStyle="default" listType="bulleted">1A.</listItem>' +566					'<listItem listIndent="0" listStyle="circle" listType="bulleted">2B.</listItem>' +567					'<listItem listIndent="0" listStyle="circle" listType="bulleted">2.[]</listItem>' +568					'<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'569				);570				editor.execute( 'indentList' );571				expect( getModelData( model ) ).to.equal(572					'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +573					'<listItem listIndent="1" listStyle="default" listType="bulleted">1A.</listItem>' +574					'<listItem listIndent="0" listStyle="circle" listType="bulleted">2B.</listItem>' +575					'<listItem listIndent="1" listStyle="default" listType="bulleted">2.[]</listItem>' +576					'<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'577				);578			} );579			it( 'should restore the default value for the list style attribute when indenting a few items', () => {580				setModelData( model,581					'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +582					'<listItem listIndent="0" listStyle="circle" listType="bulleted">[2.</listItem>' +583					'<listItem listIndent="0" listStyle="circle" listType="bulleted">3.]</listItem>'584				);585				editor.execute( 'indentList' );586				expect( getModelData( model ) ).to.equal(587					'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +588					'<listItem listIndent="1" listStyle="default" listType="bulleted">[2.</listItem>' +589					'<listItem listIndent="1" listStyle="default" listType="bulleted">3.]</listItem>'590				);591			} );592			it(593				'should copy the value for the list style attribute when indenting a single item into a nested list (default value)',594				() => {595					setModelData( model,596						'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +597						'<listItem listIndent="1" listStyle="default" listType="bulleted">2.</listItem>' +598						'<listItem listIndent="0" listStyle="circle" listType="bulleted">3.[]</listItem>' +599						'<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'600					);601					editor.execute( 'indentList' );602					expect( getModelData( model ) ).to.equal(603						'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +604						'<listItem listIndent="1" listStyle="default" listType="bulleted">2.</listItem>' +605						'<listItem listIndent="1" listStyle="default" listType="bulleted">3.[]</listItem>' +606						'<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'607					);608				}609			);610			it(611				'should copy the value for the list style attribute when indenting a single item into a nested list (changed value)',612				() => {613					setModelData( model,614						'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +615						'<listItem listIndent="1" listStyle="disc" listType="bulleted">2.</listItem>' +616						'<listItem listIndent="0" listStyle="circle" listType="bulleted">3.[]</listItem>' +617						'<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'618					);619					editor.execute( 'indentList' );620					expect( getModelData( model ) ).to.equal(621						'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +622						'<listItem listIndent="1" listStyle="disc" listType="bulleted">2.</listItem>' +623						'<listItem listIndent="1" listStyle="disc" listType="bulleted">3.[]</listItem>' +624						'<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'625					);626				}627			);628			it( 'should copy the value for the list style attribute when indenting a single item into a nested list', () => {629				setModelData( model,630					'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +631					'<listItem listIndent="0" listStyle="circle" listType="bulleted">2.[]</listItem>' +632					'<listItem listIndent="1" listStyle="square" listType="bulleted">3.</listItem>' +633					'<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'634				);635				editor.execute( 'indentList' );636				expect( getModelData( model ) ).to.equal(637					'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +638					'<listItem listIndent="1" listStyle="default" listType="bulleted">2.[]</listItem>' +639					'<listItem listIndent="2" listStyle="square" listType="bulleted">3.</listItem>' +640					'<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'641				);642			} );643			it(644				'should copy the value for the list style attribute when indenting a single item into a nested list ' +645				'(many nested lists check)',646				() => {647					setModelData( model,648						'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +649						'<listItem listIndent="1" listStyle="disc" listType="bulleted">2.</listItem>' +650						'<listItem listIndent="2" listStyle="square" listType="bulleted">3.</listItem>' +651						'<listItem listIndent="0" listStyle="circle" listType="bulleted">4.[]</listItem>'652					);653					editor.execute( 'indentList' );654					expect( getModelData( model ) ).to.equal(655						'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +656						'<listItem listIndent="1" listStyle="disc" listType="bulleted">2.</listItem>' +657						'<listItem listIndent="2" listStyle="square" listType="bulleted">3.</listItem>' +658						'<listItem listIndent="1" listStyle="disc" listType="bulleted">4.[]</listItem>'659					);660				}661			);662			it( 'should inherit the list style attribute from nested list if the `listType` is other than indenting element', () => {663				setModelData( model,664					'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +665					'<listItem listIndent="1" listStyle="decimal" listType="numbered">2.</listItem>' +666					'<listItem listIndent="0" listStyle="circle" listType="bulleted">3.[]</listItem>'667				);668				editor.execute( 'indentList' );669				expect( getModelData( model ) ).to.equal(670					'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +671					'<listItem listIndent="1" listStyle="decimal" listType="numbered">2.</listItem>' +672					'<listItem listIndent="1" listStyle="decimal" listType="numbered">3.[]</listItem>'673				);674			} );675			// See: #8072.676			it( 'should not throw when indenting a list without any other content in the editor', () => {677				setModelData( model,678					'<listItem listIndent="0" listStyle="default" listType="bulleted">Foo</listItem>' +679					'<listItem listIndent="0" listStyle="default" listType="bulleted">[]</listItem>'680				);681				editor.execute( 'indentList' );682				expect( getModelData( model ) ).to.equal(683					'<listItem listIndent="0" listStyle="default" listType="bulleted">Foo</listItem>' +684					'<listItem listIndent="1" listStyle="default" listType="bulleted">[]</listItem>'685				);686			} );687		} );688		describe( 'outdenting lists', () => {689			it( 'should inherit the list style attribute from parent list (change the first nested item)', () => {690				setModelData( model,691					'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +692					'<listItem listIndent="1" listStyle="default" listType="bulleted">2.[]</listItem>' +693					'<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'694				);695				editor.execute( 'outdentList' );696				expect( getModelData( model ) ).to.equal(697					'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +698					'<listItem listIndent="0" listStyle="circle" listType="bulleted">2.[]</listItem>' +699					'<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'700				);701			} );702			it( 'should inherit the list style attribute from parent list (change the second nested item)', () => {703				setModelData( model,704					'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +705					'<listItem listIndent="1" listStyle="default" listType="bulleted">2.</listItem>' +706					'<listItem listIndent="1" listStyle="default" listType="bulleted">3.[]</listItem>'707				);708				editor.execute( 'outdentList' );709				expect( getModelData( model ) ).to.equal(710					'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +711					'<listItem listIndent="1" listStyle="default" listType="bulleted">2.</listItem>' +712					'<listItem listIndent="0" listStyle="circle" listType="bulleted">3.[]</listItem>'713				);714			} );715			it( 'should inherit the list style attribute from parent list (modifying nested lists)', () => {716				setModelData( model,717					'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +718					'<listItem listIndent="1" listStyle="default" listType="bulleted">[2.</listItem>' +719					'<listItem listIndent="2" listStyle="square" listType="bulleted">3.]</listItem>'720				);721				editor.execute( 'outdentList' );722				expect( getModelData( model ) ).to.equal(723					'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +724					'<listItem listIndent="0" listStyle="circle" listType="bulleted">[2.</listItem>' +725					'<listItem listIndent="1" listStyle="square" listType="bulleted">3.]</listItem>'726				);727			} );728			it(729				'should inherit the list style attribute from parent list (outdenting many items, including the first one in the list)',730				() => {731					setModelData( model,732						'<listItem listIndent="0" listStyle="circle" listType="bulleted">[1.</listItem>' +733						'<listItem listIndent="1" listStyle="default" listType="bulleted">2.</listItem>' +734						'<listItem listIndent="2" listStyle="square" listType="bulleted">3.]</listItem>' +735						'<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'736					);737					editor.execute( 'outdentList' );738					expect( getModelData( model ) ).to.equal(739						'<paragraph>[1.</paragraph>' +740						'<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>' +741						'<listItem listIndent="1" listStyle="square" listType="bulleted">3.]</listItem>' +742						'<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'743					);744				}745			);746			it(747				'should inherit the list style attribute from parent list (outdenting the first item that is a parent for next list)',748				() => {749					setModelData( model,750						'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.[]</listItem>' +751						'<listItem listIndent="1" listStyle="default" listType="bulleted">2.</listItem>' +752						'<listItem listIndent="2" listStyle="square" listType="bulleted">3.</listItem>' +753						'<listItem listIndent="3" listStyle="disc" listType="bulleted">4.</listItem>' +754						'<listItem listIndent="0" listStyle="circle" listType="bulleted">5.</listItem>'755					);756					editor.execute( 'outdentList' );757					expect( getModelData( model ) ).to.equal(758						'<paragraph>1.[]</paragraph>' +759						'<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>' +760						'<listItem listIndent="1" listStyle="square" listType="bulleted">3.</listItem>' +761						'<listItem listIndent="2" listStyle="disc" listType="bulleted">4.</listItem>' +762						'<listItem listIndent="0" listStyle="circle" listType="bulleted">5.</listItem>'763					);764				}765			);766			it( 'should not inherit the list style if outdented the only one item in the list', () => {767				setModelData( model,768					'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.[]</listItem>' +769					'<listItem listIndent="1" listStyle="disc" listType="bulleted">2.</listItem>' +770					'<listItem listIndent="2" listStyle="square" listType="bulleted">3.</listItem>'771				);772				editor.execute( 'outdentList' );773				expect( getModelData( model ) ).to.equal(774					'<paragraph>1.[]</paragraph>' +775					'<listItem listIndent="0" listStyle="disc" listType="bulleted">2.</listItem>' +776					'<listItem listIndent="1" listStyle="square" listType="bulleted">3.</listItem>'777				);778			} );779			it( 'should not inherit the list style if outdented the only one item in the list (a paragraph below the list)', () => {780				setModelData( model,781					'<listItem listIndent="0" listStyle="circle" listType="bulleted">1.[]</listItem>' +782					'<listItem listIndent="1" listStyle="disc" listType="bulleted">2.</listItem>' +783					'<listItem listIndent="2" listStyle="square" listType="bulleted">3.</listItem>' +784					'<paragraph>Foo</paragraph>'785				);786				editor.execute( 'outdentList' );787				expect( getModelData( model ) ).to.equal(788					'<paragraph>1.[]</paragraph