liststyleediting.js 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158
  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-license
  4. */
  5. import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
  6. import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
  7. import Typing from '@ckeditor/ckeditor5-typing/src/typing';
  8. import UndoEditing from '@ckeditor/ckeditor5-undo/src/undoediting';
  9. import { getData as getModelData, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
  10. import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';
  11. import ListStyleEditing from '../src/liststyleediting';
  12. import TodoListEditing from '../src/todolistediting';
  13. import ListStyleCommand from '../src/liststylecommand';
  14. describe( 'ListStyleEditing', () => {
  15. let editor, model, view;
  16. beforeEach( () => {
  17. return VirtualTestEditor
  18. .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. } );
  286. } );
  287. // At this moment editing and data pipelines produce exactly the same content.
  288. // Just a few tests will be enough here. `model to data` block contains all cases checked.
  289. describe( 'conversion in editing pipeline', () => {
  290. describe( 'model to view', () => {
  291. it( 'should convert single list (type: bulleted, style: default)', () => {
  292. setModelData( model,
  293. '<listItem listIndent="0" listType="bulleted" listStyle="default">Foo</listItem>' +
  294. '<listItem listIndent="0" listType="bulleted" listStyle="default">Bar</listItem>'
  295. );
  296. expect( getViewData( view, { withoutSelection: true } ) ).to.equal(
  297. '<ul><li>Foo</li><li>Bar</li></ul>'
  298. );
  299. } );
  300. it( 'should convert single list (type: bulleted, style: circle)', () => {
  301. setModelData( model,
  302. '<listItem listIndent="0" listType="bulleted" listStyle="circle">Foo</listItem>' +
  303. '<listItem listIndent="0" listType="bulleted" listStyle="circle">Bar</listItem>'
  304. );
  305. expect( getViewData( view, { withoutSelection: true } ) ).to.equal(
  306. '<ul style="list-style-type:circle"><li>Foo</li><li>Bar</li></ul>'
  307. );
  308. } );
  309. it( 'should convert nested bulleted lists (main: circle, nested: disc)', () => {
  310. setModelData( model,
  311. '<listItem listIndent="0" listType="bulleted" listStyle="circle">Foo 1</listItem>' +
  312. '<listItem listIndent="1" listType="bulleted" listStyle="disc">Bar 1</listItem>' +
  313. '<listItem listIndent="1" listType="bulleted" listStyle="disc">Bar 2</listItem>' +
  314. '<listItem listIndent="0" listType="bulleted" listStyle="circle">Foo 2</listItem>' +
  315. '<listItem listIndent="0" listType="bulleted" listStyle="circle">Foo 3</listItem>'
  316. );
  317. expect( getViewData( view, { withoutSelection: true } ) ).to.equal(
  318. '<ul style="list-style-type:circle">' +
  319. '<li>Foo 1' +
  320. '<ul style="list-style-type:disc">' +
  321. '<li>Bar 1</li>' +
  322. '<li>Bar 2</li>' +
  323. '</ul>' +
  324. '</li>' +
  325. '<li>Foo 2</li>' +
  326. '<li>Foo 3</li>' +
  327. '</ul>'
  328. );
  329. } );
  330. } );
  331. } );
  332. describe( 'integrations', () => {
  333. describe( 'merging a list into a styled list', () => {
  334. it( 'should inherit the list style attribute when merging the same kind of lists (from top, merge a single item)', () => {
  335. setModelData( model,
  336. '<paragraph>Foo Bar.[]</paragraph>' +
  337. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
  338. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'
  339. );
  340. editor.execute( 'bulletedList' );
  341. expect( getModelData( model ) ).to.equal(
  342. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo Bar.[]</listItem>' +
  343. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
  344. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'
  345. );
  346. } );
  347. it( 'should inherit the list style attribute when merging the same kind of lists (from top, merge a few items)', () => {
  348. setModelData( model,
  349. '<paragraph>[Foo Bar 1.</paragraph>' +
  350. '<paragraph>Foo Bar 2.]</paragraph>' +
  351. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
  352. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'
  353. );
  354. editor.execute( 'bulletedList' );
  355. expect( getModelData( model ) ).to.equal(
  356. '<listItem listIndent="0" listStyle="circle" listType="bulleted">[Foo Bar 1.</listItem>' +
  357. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo Bar 2.]</listItem>' +
  358. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
  359. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'
  360. );
  361. } );
  362. it( 'should not inherit anything if there is no list below the inserted list', () => {
  363. setModelData( model,
  364. '<paragraph>Foo Bar 1.[]</paragraph>' +
  365. '<paragraph>Foo Bar 2.</paragraph>'
  366. );
  367. editor.execute( 'bulletedList' );
  368. expect( getModelData( model ) ).to.equal(
  369. '<listItem listIndent="0" listStyle="default" listType="bulleted">Foo Bar 1.[]</listItem>' +
  370. '<paragraph>Foo Bar 2.</paragraph>'
  371. );
  372. } );
  373. it( 'should not inherit anything if replacing the entire content with a list', () => {
  374. setModelData( model,
  375. '<paragraph>Foo Bar 1.[]</paragraph>'
  376. );
  377. editor.execute( 'bulletedList' );
  378. expect( getModelData( model ) ).to.equal(
  379. '<listItem listIndent="0" listStyle="default" listType="bulleted">Foo Bar 1.[]</listItem>'
  380. );
  381. } );
  382. it( 'should not inherit the list style attribute when merging different kind of lists (from top, merge a single item)', () => {
  383. setModelData( model,
  384. '<paragraph>Foo Bar.[]</paragraph>' +
  385. '<listItem listIndent="0" listStyle="default" listType="numbered">Foo</listItem>' +
  386. '<listItem listIndent="0" listStyle="default" listType="numbered">Bar</listItem>'
  387. );
  388. editor.execute( 'bulletedList' );
  389. expect( getModelData( model ) ).to.equal(
  390. '<listItem listIndent="0" listStyle="default" listType="bulleted">Foo Bar.[]</listItem>' +
  391. '<listItem listIndent="0" listStyle="default" listType="numbered">Foo</listItem>' +
  392. '<listItem listIndent="0" listStyle="default" listType="numbered">Bar</listItem>'
  393. );
  394. } );
  395. it( 'should inherit the list style attribute when merging the same kind of lists (from bottom, merge a single item)', () => {
  396. setModelData( model,
  397. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
  398. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>' +
  399. '<paragraph>Foo Bar.[]</paragraph>'
  400. );
  401. editor.execute( 'bulletedList' );
  402. expect( getModelData( model ) ).to.equal(
  403. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
  404. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>' +
  405. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo Bar.[]</listItem>'
  406. );
  407. } );
  408. it(
  409. 'should inherit the list style attribute from listIndent=0 element when merging the same kind of lists (from bottom)',
  410. () => {
  411. setModelData( model,
  412. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
  413. '<listItem listIndent="1" listStyle="square" listType="bulleted">Bar</listItem>' +
  414. '<listItem listIndent="2" listStyle="disc" listType="bulleted">Foo Bar</listItem>' +
  415. '<paragraph>Foo Bar.[]</paragraph>'
  416. );
  417. editor.execute( 'bulletedList' );
  418. expect( getModelData( model ) ).to.equal(
  419. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
  420. '<listItem listIndent="1" listStyle="square" listType="bulleted">Bar</listItem>' +
  421. '<listItem listIndent="2" listStyle="disc" listType="bulleted">Foo Bar</listItem>' +
  422. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo Bar.[]</listItem>'
  423. );
  424. }
  425. );
  426. } );
  427. describe( 'indenting lists', () => {
  428. it( 'should restore the default value for the list style attribute when indenting a single item', () => {
  429. setModelData( model,
  430. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  431. '<listItem listIndent="1" listStyle="default" listType="bulleted">1A.</listItem>' +
  432. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2B.</listItem>' +
  433. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.[]</listItem>' +
  434. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  435. );
  436. editor.execute( 'indentList' );
  437. expect( getModelData( model ) ).to.equal(
  438. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  439. '<listItem listIndent="1" listStyle="default" listType="bulleted">1A.</listItem>' +
  440. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2B.</listItem>' +
  441. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.[]</listItem>' +
  442. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  443. );
  444. } );
  445. it( 'should restore the default value for the list style attribute when indenting a few items', () => {
  446. setModelData( model,
  447. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  448. '<listItem listIndent="0" listStyle="circle" listType="bulleted">[2.</listItem>' +
  449. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.]</listItem>'
  450. );
  451. editor.execute( 'indentList' );
  452. expect( getModelData( model ) ).to.equal(
  453. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  454. '<listItem listIndent="1" listStyle="default" listType="bulleted">[2.</listItem>' +
  455. '<listItem listIndent="1" listStyle="default" listType="bulleted">3.]</listItem>'
  456. );
  457. } );
  458. it(
  459. 'should copy the value for the list style attribute when indenting a single item into a nested list (default value)',
  460. () => {
  461. setModelData( model,
  462. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  463. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.</listItem>' +
  464. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.[]</listItem>' +
  465. '<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'
  466. );
  467. editor.execute( 'indentList' );
  468. expect( getModelData( model ) ).to.equal(
  469. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  470. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.</listItem>' +
  471. '<listItem listIndent="1" listStyle="default" listType="bulleted">3.[]</listItem>' +
  472. '<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'
  473. );
  474. }
  475. );
  476. it(
  477. 'should copy the value for the list style attribute when indenting a single item into a nested list (changed value)',
  478. () => {
  479. setModelData( model,
  480. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  481. '<listItem listIndent="1" listStyle="disc" listType="bulleted">2.</listItem>' +
  482. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.[]</listItem>' +
  483. '<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'
  484. );
  485. editor.execute( 'indentList' );
  486. expect( getModelData( model ) ).to.equal(
  487. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  488. '<listItem listIndent="1" listStyle="disc" listType="bulleted">2.</listItem>' +
  489. '<listItem listIndent="1" listStyle="disc" listType="bulleted">3.[]</listItem>' +
  490. '<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'
  491. );
  492. }
  493. );
  494. it( 'should copy the value for the list style attribute when indenting a single item into a nested list', () => {
  495. setModelData( model,
  496. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  497. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.[]</listItem>' +
  498. '<listItem listIndent="1" listStyle="square" listType="bulleted">3.</listItem>' +
  499. '<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'
  500. );
  501. editor.execute( 'indentList' );
  502. expect( getModelData( model ) ).to.equal(
  503. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  504. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.[]</listItem>' +
  505. '<listItem listIndent="2" listStyle="square" listType="bulleted">3.</listItem>' +
  506. '<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'
  507. );
  508. } );
  509. it(
  510. 'should copy the value for the list style attribute when indenting a single item into a nested list ' +
  511. '(many nested lists check)',
  512. () => {
  513. setModelData( model,
  514. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  515. '<listItem listIndent="1" listStyle="disc" listType="bulleted">2.</listItem>' +
  516. '<listItem listIndent="2" listStyle="square" listType="bulleted">3.</listItem>' +
  517. '<listItem listIndent="0" listStyle="circle" listType="bulleted">4.[]</listItem>'
  518. );
  519. editor.execute( 'indentList' );
  520. expect( getModelData( model ) ).to.equal(
  521. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  522. '<listItem listIndent="1" listStyle="disc" listType="bulleted">2.</listItem>' +
  523. '<listItem listIndent="2" listStyle="square" listType="bulleted">3.</listItem>' +
  524. '<listItem listIndent="1" listStyle="disc" listType="bulleted">4.[]</listItem>'
  525. );
  526. }
  527. );
  528. it( 'should inherit the list style attribute from nested list if the `listType` is other than indenting element', () => {
  529. setModelData( model,
  530. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  531. '<listItem listIndent="1" listStyle="decimal" listType="numbered">2.</listItem>' +
  532. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.[]</listItem>'
  533. );
  534. editor.execute( 'indentList' );
  535. expect( getModelData( model ) ).to.equal(
  536. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  537. '<listItem listIndent="1" listStyle="decimal" listType="numbered">2.</listItem>' +
  538. '<listItem listIndent="1" listStyle="decimal" listType="numbered">3.[]</listItem>'
  539. );
  540. } );
  541. } );
  542. describe( 'outdenting lists', () => {
  543. it( 'should inherit the list style attribute from parent list (change the first nested item)', () => {
  544. setModelData( model,
  545. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  546. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.[]</listItem>' +
  547. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  548. );
  549. editor.execute( 'outdentList' );
  550. expect( getModelData( model ) ).to.equal(
  551. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  552. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.[]</listItem>' +
  553. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  554. );
  555. } );
  556. it( 'should inherit the list style attribute from parent list (change the second nested item)', () => {
  557. setModelData( model,
  558. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  559. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.</listItem>' +
  560. '<listItem listIndent="1" listStyle="default" listType="bulleted">3.[]</listItem>'
  561. );
  562. editor.execute( 'outdentList' );
  563. expect( getModelData( model ) ).to.equal(
  564. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  565. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.</listItem>' +
  566. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.[]</listItem>'
  567. );
  568. } );
  569. it( 'should inherit the list style attribute from parent list (modifying nested lists)', () => {
  570. setModelData( model,
  571. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  572. '<listItem listIndent="1" listStyle="default" listType="bulleted">[2.</listItem>' +
  573. '<listItem listIndent="2" listStyle="square" listType="bulleted">3.]</listItem>'
  574. );
  575. editor.execute( 'outdentList' );
  576. expect( getModelData( model ) ).to.equal(
  577. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  578. '<listItem listIndent="0" listStyle="circle" listType="bulleted">[2.</listItem>' +
  579. '<listItem listIndent="1" listStyle="square" listType="bulleted">3.]</listItem>'
  580. );
  581. } );
  582. it(
  583. 'should inherit the list style attribute from parent list (outdenting many items, including the first one in the list)',
  584. () => {
  585. setModelData( model,
  586. '<listItem listIndent="0" listStyle="circle" listType="bulleted">[1.</listItem>' +
  587. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.</listItem>' +
  588. '<listItem listIndent="2" listStyle="square" listType="bulleted">3.]</listItem>' +
  589. '<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'
  590. );
  591. editor.execute( 'outdentList' );
  592. expect( getModelData( model ) ).to.equal(
  593. '<paragraph>[1.</paragraph>' +
  594. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>' +
  595. '<listItem listIndent="1" listStyle="square" listType="bulleted">3.]</listItem>' +
  596. '<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'
  597. );
  598. }
  599. );
  600. it(
  601. 'should inherit the list style attribute from parent list (outdenting the first item that is a parent for next list)',
  602. () => {
  603. setModelData( model,
  604. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.[]</listItem>' +
  605. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.</listItem>' +
  606. '<listItem listIndent="2" listStyle="square" listType="bulleted">3.</listItem>' +
  607. '<listItem listIndent="3" listStyle="disc" listType="bulleted">4.</listItem>' +
  608. '<listItem listIndent="0" listStyle="circle" listType="bulleted">5.</listItem>'
  609. );
  610. editor.execute( 'outdentList' );
  611. expect( getModelData( model ) ).to.equal(
  612. '<paragraph>1.[]</paragraph>' +
  613. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>' +
  614. '<listItem listIndent="1" listStyle="square" listType="bulleted">3.</listItem>' +
  615. '<listItem listIndent="2" listStyle="disc" listType="bulleted">4.</listItem>' +
  616. '<listItem listIndent="0" listStyle="circle" listType="bulleted">5.</listItem>'
  617. );
  618. }
  619. );
  620. it( 'should not inherit the list style if outdented the only one item in the list', () => {
  621. setModelData( model,
  622. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.[]</listItem>' +
  623. '<listItem listIndent="1" listStyle="disc" listType="bulleted">2.</listItem>' +
  624. '<listItem listIndent="2" listStyle="square" listType="bulleted">3.</listItem>'
  625. );
  626. editor.execute( 'outdentList' );
  627. expect( getModelData( model ) ).to.equal(
  628. '<paragraph>1.[]</paragraph>' +
  629. '<listItem listIndent="0" listStyle="disc" listType="bulleted">2.</listItem>' +
  630. '<listItem listIndent="1" listStyle="square" listType="bulleted">3.</listItem>'
  631. );
  632. } );
  633. it( 'should not inherit the list style if outdented the only one item in the list (a paragraph below the list)', () => {
  634. setModelData( model,
  635. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.[]</listItem>' +
  636. '<listItem listIndent="1" listStyle="disc" listType="bulleted">2.</listItem>' +
  637. '<listItem listIndent="2" listStyle="square" listType="bulleted">3.</listItem>' +
  638. '<paragraph>Foo</paragraph>'
  639. );
  640. editor.execute( 'outdentList' );
  641. expect( getModelData( model ) ).to.equal(
  642. '<paragraph>1.[]</paragraph>' +
  643. '<listItem listIndent="0" listStyle="disc" listType="bulleted">2.</listItem>' +
  644. '<listItem listIndent="1" listStyle="square" listType="bulleted">3.</listItem>' +
  645. '<paragraph>Foo</paragraph>'
  646. );
  647. } );
  648. it( 'should not inherit the list style attribute from parent list if the `listType` is other than outdenting element', () => {
  649. setModelData( model,
  650. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  651. '<listItem listIndent="1" listStyle="decimal" listType="numbered">2.[]</listItem>' +
  652. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  653. );
  654. editor.execute( 'outdentList' );
  655. expect( getModelData( model ) ).to.equal(
  656. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  657. '<listItem listIndent="0" listStyle="decimal" listType="numbered">2.[]</listItem>' +
  658. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  659. );
  660. } );
  661. it( 'should not do anything if there is no list after outdenting', () => {
  662. setModelData( model,
  663. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.[]</listItem>'
  664. );
  665. editor.execute( 'outdentList' );
  666. expect( getModelData( model ) ).to.equal(
  667. '<paragraph>1.[]</paragraph>'
  668. );
  669. } );
  670. } );
  671. describe( 'indent/outdent + undo', () => {
  672. it( 'should use the same batch for indenting a list and updating `listType` attribute', () => {
  673. setModelData( model,
  674. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  675. '<listItem listIndent="1" listStyle="default" listType="bulleted">1A.</listItem>' +
  676. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2B.</listItem>' +
  677. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.[]</listItem>' +
  678. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  679. );
  680. editor.execute( 'indentList' );
  681. editor.execute( 'undo' );
  682. expect( getModelData( model ) ).to.equal(
  683. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  684. '<listItem listIndent="1" listStyle="default" listType="bulleted">1A.</listItem>' +
  685. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2B.</listItem>' +
  686. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.[]</listItem>' +
  687. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  688. );
  689. } );
  690. it( 'should use the same batch for outdenting a list and updating `listType` attribute', () => {
  691. setModelData( model,
  692. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  693. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.[]</listItem>' +
  694. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  695. );
  696. editor.execute( 'outdentList' );
  697. editor.execute( 'undo' );
  698. expect( getModelData( model ) ).to.equal(
  699. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  700. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.[]</listItem>' +
  701. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  702. );
  703. } );
  704. } );
  705. describe( 'todo list', () => {
  706. let editor, model;
  707. beforeEach( () => {
  708. return VirtualTestEditor
  709. .create( {
  710. // TodoListEditing is at the end by design. Check `ListStyleEditing.afterInit()` call.
  711. plugins: [ Paragraph, ListStyleEditing, TodoListEditing ]
  712. } )
  713. .then( newEditor => {
  714. editor = newEditor;
  715. model = editor.model;
  716. } );
  717. } );
  718. afterEach( () => {
  719. return editor.destroy();
  720. } );
  721. it( 'should not add the `listStyle` attribute while creating a todo list', () => {
  722. setModelData( model, '<paragraph>Foo[]</paragraph>' );
  723. editor.execute( 'todoList' );
  724. expect( getModelData( model ), '<listItem listIndent="0" listType="todo">Foo[]</listItem>' );
  725. } );
  726. it( 'should not add the `listStyle` attribute while switching the list type', () => {
  727. setModelData( model, '<listItem listIndent="0" listType="bulleted">Foo[]</listItem>' );
  728. editor.execute( 'todoList' );
  729. expect( getModelData( model ), '<listItem listIndent="0" listType="todo">Foo[]</listItem>' );
  730. } );
  731. it( 'should remove the `listStyle` attribute while switching the list type that uses the list style feature', () => {
  732. setModelData( model, '<listItem listIndent="0" listType="bulleted" listStyle="circle">Foo[]</listItem>' );
  733. editor.execute( 'todoList' );
  734. expect( getModelData( model ), '<listItem listIndent="0" listType="todo">Foo[]</listItem>' );
  735. } );
  736. it( 'should not inherit the list style attribute when inserting a todo list item', () => {
  737. setModelData( model,
  738. '<paragraph>Foo Bar.[]</paragraph>' +
  739. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
  740. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'
  741. );
  742. editor.execute( 'todoList' );
  743. expect( getModelData( model ) ).to.equal(
  744. '<listItem listIndent="0" listType="todo">Foo Bar.[]</listItem>' +
  745. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
  746. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'
  747. );
  748. } );
  749. } );
  750. describe( 'removing content between two lists', () => {
  751. let editor, model;
  752. beforeEach( () => {
  753. return VirtualTestEditor
  754. .create( {
  755. plugins: [ Paragraph, ListStyleEditing, Typing ]
  756. } )
  757. .then( newEditor => {
  758. editor = newEditor;
  759. model = editor.model;
  760. } );
  761. } );
  762. afterEach( () => {
  763. return editor.destroy();
  764. } );
  765. it( 'should not do anything while removing a letter inside a listItem', () => {
  766. setModelData( model,
  767. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  768. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.[]</listItem>' +
  769. '<paragraph></paragraph>' +
  770. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  771. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  772. );
  773. editor.execute( 'delete' );
  774. expect( getModelData( model ) ).to.equal(
  775. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  776. '<listItem listIndent="0" listStyle="square" listType="bulleted">2[]</listItem>' +
  777. '<paragraph></paragraph>' +
  778. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  779. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  780. );
  781. } );
  782. it( 'should not do anything if there is a non-listItem before the removed content', () => {
  783. setModelData( model,
  784. '<paragraph>Foo</paragraph>' +
  785. '<paragraph>[]</paragraph>' +
  786. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  787. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  788. );
  789. editor.execute( 'delete' );
  790. expect( getModelData( model ) ).to.equal(
  791. '<paragraph>Foo[]</paragraph>' +
  792. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  793. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  794. );
  795. } );
  796. it( 'should not do anything if there is a non-listItem after the removed content', () => {
  797. setModelData( model,
  798. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  799. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>' +
  800. '<paragraph>[]</paragraph>' +
  801. '<paragraph>Foo</paragraph>'
  802. );
  803. editor.execute( 'delete' );
  804. expect( getModelData( model ) ).to.equal(
  805. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  806. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.[]</listItem>' +
  807. '<paragraph>Foo</paragraph>'
  808. );
  809. } );
  810. it( 'should not do anything if there is no element after the removed content', () => {
  811. setModelData( model,
  812. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  813. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>' +
  814. '<paragraph>[]</paragraph>'
  815. );
  816. editor.execute( 'delete' );
  817. expect( getModelData( model ) ).to.equal(
  818. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  819. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.[]</listItem>'
  820. );
  821. } );
  822. it(
  823. 'should modify the the `listStyle` attribute for the merged (second) list when removing content between those lists',
  824. () => {
  825. setModelData( model,
  826. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  827. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>' +
  828. '<paragraph>[]</paragraph>' +
  829. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  830. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  831. );
  832. editor.execute( 'delete' );
  833. expect( getModelData( model ) ).to.equal(
  834. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  835. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.[]</listItem>' +
  836. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  837. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>'
  838. );
  839. }
  840. );
  841. it( 'should read the `listStyle` attribute from the most outer list', () => {
  842. setModelData( model,
  843. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  844. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>' +
  845. '<listItem listIndent="1" listStyle="numbered" listType="decimal">2.1.</listItem>' +
  846. '<listItem listIndent="2" listStyle="default" listType="default">2.1.1</listItem>' +
  847. '<paragraph>[]</paragraph>' +
  848. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  849. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  850. );
  851. editor.execute( 'delete' );
  852. expect( getModelData( model ) ).to.equal(
  853. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  854. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>' +
  855. '<listItem listIndent="1" listStyle="numbered" listType="decimal">2.1.</listItem>' +
  856. '<listItem listIndent="2" listStyle="default" listType="default">2.1.1[]</listItem>' +
  857. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  858. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>'
  859. );
  860. } );
  861. it(
  862. 'should not modify the the `listStyle` attribute for the merged (second) list if merging different `listType` attribute',
  863. () => {
  864. setModelData( model,
  865. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  866. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>' +
  867. '<paragraph>[]</paragraph>' +
  868. '<listItem listIndent="0" listStyle="decimal" listType="numbered">1.</listItem>' +
  869. '<listItem listIndent="0" listStyle="decimal" listType="numbered">2.</listItem>'
  870. );
  871. editor.execute( 'delete' );
  872. expect( getModelData( model ) ).to.equal(
  873. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  874. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.[]</listItem>' +
  875. '<listItem listIndent="0" listStyle="decimal" listType="numbered">1.</listItem>' +
  876. '<listItem listIndent="0" listStyle="decimal" listType="numbered">2.</listItem>'
  877. );
  878. }
  879. );
  880. it(
  881. 'should modify the the `listStyle` attribute for the merged (second) list when removing content from both lists',
  882. () => {
  883. setModelData( model,
  884. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  885. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>' +
  886. '<listItem listIndent="0" listStyle="square" listType="bulleted">[3.</listItem>' +
  887. '<paragraph>Foo</paragraph>' +
  888. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.]</listItem>' +
  889. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  890. );
  891. editor.execute( 'delete' );
  892. expect( getModelData( model ) ).to.equal(
  893. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  894. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>' +
  895. '<listItem listIndent="0" listStyle="square" listType="bulleted">[]</listItem>' +
  896. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>'
  897. );
  898. }
  899. );
  900. it(
  901. 'should modify the the `listStyle` attribute for the merged (second) list when typing over content from both lists',
  902. () => {
  903. setModelData( model,
  904. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  905. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>' +
  906. '<listItem listIndent="0" listStyle="square" listType="bulleted">[3.</listItem>' +
  907. '<paragraph>Foo</paragraph>' +
  908. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.]</listItem>' +
  909. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  910. );
  911. editor.execute( 'input', { text: 'Foo' } );
  912. expect( getModelData( model ) ).to.equal(
  913. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  914. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>' +
  915. '<listItem listIndent="0" listStyle="square" listType="bulleted">Foo[]</listItem>' +
  916. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>'
  917. );
  918. }
  919. );
  920. it(
  921. 'should not modify the the `listStyle` if lists were not merged but the content was partially removed',
  922. () => {
  923. setModelData( model,
  924. '<listItem listIndent="0" listStyle="square" listType="bulleted">111.</listItem>' +
  925. '<listItem listIndent="0" listStyle="square" listType="bulleted">222.</listItem>' +
  926. '<listItem listIndent="0" listStyle="square" listType="bulleted">[333.</listItem>' +
  927. '<paragraph>Foo</paragraph>' +
  928. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1]11.</listItem>' +
  929. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  930. );
  931. editor.execute( 'delete' );
  932. expect( getModelData( model ) ).to.equal(
  933. '<listItem listIndent="0" listStyle="square" listType="bulleted">111.</listItem>' +
  934. '<listItem listIndent="0" listStyle="square" listType="bulleted">222.</listItem>' +
  935. '<listItem listIndent="0" listStyle="circle" listType="bulleted">[]11.</listItem>' +
  936. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  937. );
  938. }
  939. );
  940. it( 'should not do anything while typing in a list item', () => {
  941. setModelData( model,
  942. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  943. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.[]</listItem>' +
  944. '<listItem listIndent="0" listStyle="square" listType="bulleted">3.</listItem>' +
  945. '<paragraph></paragraph>' +
  946. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  947. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  948. );
  949. const modelChangeStub = sinon.stub( model, 'change' ).callThrough();
  950. simulateTyping( ' Foo' );
  951. // Each character calls `editor.model.change()`.
  952. expect( modelChangeStub.callCount ).to.equal( 4 );
  953. expect( getModelData( model ) ).to.equal(
  954. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  955. '<listItem listIndent="0" listStyle="square" listType="bulleted">2. Foo[]</listItem>' +
  956. '<listItem listIndent="0" listStyle="square" listType="bulleted">3.</listItem>' +
  957. '<paragraph></paragraph>' +
  958. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  959. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  960. );
  961. } );
  962. function simulateTyping( text ) {
  963. // While typing, every character is an atomic change.
  964. text.split( '' ).forEach( character => {
  965. editor.execute( 'input', {
  966. text: character
  967. } );
  968. } );
  969. }
  970. } );
  971. } );
  972. } );