liststyleediting.js 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177
  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="decimal-leading-zero" listType="numbered">Foo</listItem>' +
  386. '<listItem listIndent="0" listStyle="decimal-leading-zero" 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="decimal-leading-zero" listType="numbered">Foo</listItem>' +
  392. '<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Bar</listItem>'
  393. );
  394. } );
  395. it(
  396. 'should not inherit the list style attribute when merging different kind of lists (from bottom, merge a single item)',
  397. () => {
  398. setModelData( model,
  399. '<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Foo</listItem>' +
  400. '<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Bar</listItem>' +
  401. '<paragraph>Foo Bar.[]</paragraph>'
  402. );
  403. editor.execute( 'bulletedList' );
  404. expect( getModelData( model ) ).to.equal(
  405. '<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Foo</listItem>' +
  406. '<listItem listIndent="0" listStyle="decimal-leading-zero" listType="numbered">Bar</listItem>' +
  407. '<listItem listIndent="0" listStyle="default" listType="bulleted">Foo Bar.[]</listItem>'
  408. );
  409. }
  410. );
  411. it( 'should inherit the list style attribute when merging the same kind of lists (from bottom, merge a single item)', () => {
  412. setModelData( model,
  413. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
  414. '<listItem listIndent="0" listStyle="circle" listType="bulleted">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="0" listStyle="circle" listType="bulleted">Bar</listItem>' +
  421. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo Bar.[]</listItem>'
  422. );
  423. } );
  424. it(
  425. 'should inherit the list style attribute from listIndent=0 element when merging the same kind of lists (from bottom)',
  426. () => {
  427. setModelData( model,
  428. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
  429. '<listItem listIndent="1" listStyle="square" listType="bulleted">Bar</listItem>' +
  430. '<listItem listIndent="2" listStyle="disc" listType="bulleted">Foo Bar</listItem>' +
  431. '<paragraph>Foo Bar.[]</paragraph>'
  432. );
  433. editor.execute( 'bulletedList' );
  434. expect( getModelData( model ) ).to.equal(
  435. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
  436. '<listItem listIndent="1" listStyle="square" listType="bulleted">Bar</listItem>' +
  437. '<listItem listIndent="2" listStyle="disc" listType="bulleted">Foo Bar</listItem>' +
  438. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo Bar.[]</listItem>'
  439. );
  440. }
  441. );
  442. } );
  443. describe( 'indenting lists', () => {
  444. it( 'should restore the default value for the list style attribute when indenting a single item', () => {
  445. setModelData( model,
  446. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  447. '<listItem listIndent="1" listStyle="default" listType="bulleted">1A.</listItem>' +
  448. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2B.</listItem>' +
  449. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.[]</listItem>' +
  450. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  451. );
  452. editor.execute( 'indentList' );
  453. expect( getModelData( model ) ).to.equal(
  454. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  455. '<listItem listIndent="1" listStyle="default" listType="bulleted">1A.</listItem>' +
  456. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2B.</listItem>' +
  457. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.[]</listItem>' +
  458. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  459. );
  460. } );
  461. it( 'should restore the default value for the list style attribute when indenting a few items', () => {
  462. setModelData( model,
  463. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  464. '<listItem listIndent="0" listStyle="circle" listType="bulleted">[2.</listItem>' +
  465. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.]</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. );
  473. } );
  474. it(
  475. 'should copy the value for the list style attribute when indenting a single item into a nested list (default value)',
  476. () => {
  477. setModelData( model,
  478. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  479. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.</listItem>' +
  480. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.[]</listItem>' +
  481. '<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'
  482. );
  483. editor.execute( 'indentList' );
  484. expect( getModelData( model ) ).to.equal(
  485. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  486. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.</listItem>' +
  487. '<listItem listIndent="1" listStyle="default" listType="bulleted">3.[]</listItem>' +
  488. '<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'
  489. );
  490. }
  491. );
  492. it(
  493. 'should copy the value for the list style attribute when indenting a single item into a nested list (changed value)',
  494. () => {
  495. setModelData( model,
  496. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  497. '<listItem listIndent="1" listStyle="disc" listType="bulleted">2.</listItem>' +
  498. '<listItem listIndent="0" listStyle="circle" 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="disc" listType="bulleted">2.</listItem>' +
  505. '<listItem listIndent="1" listStyle="disc" listType="bulleted">3.[]</listItem>' +
  506. '<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'
  507. );
  508. }
  509. );
  510. it( 'should copy the value for the list style attribute when indenting a single item into a nested list', () => {
  511. setModelData( model,
  512. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  513. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.[]</listItem>' +
  514. '<listItem listIndent="1" listStyle="square" listType="bulleted">3.</listItem>' +
  515. '<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'
  516. );
  517. editor.execute( 'indentList' );
  518. expect( getModelData( model ) ).to.equal(
  519. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  520. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.[]</listItem>' +
  521. '<listItem listIndent="2" listStyle="square" listType="bulleted">3.</listItem>' +
  522. '<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'
  523. );
  524. } );
  525. it(
  526. 'should copy the value for the list style attribute when indenting a single item into a nested list ' +
  527. '(many nested lists check)',
  528. () => {
  529. setModelData( model,
  530. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  531. '<listItem listIndent="1" listStyle="disc" listType="bulleted">2.</listItem>' +
  532. '<listItem listIndent="2" listStyle="square" listType="bulleted">3.</listItem>' +
  533. '<listItem listIndent="0" listStyle="circle" listType="bulleted">4.[]</listItem>'
  534. );
  535. editor.execute( 'indentList' );
  536. expect( getModelData( model ) ).to.equal(
  537. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  538. '<listItem listIndent="1" listStyle="disc" listType="bulleted">2.</listItem>' +
  539. '<listItem listIndent="2" listStyle="square" listType="bulleted">3.</listItem>' +
  540. '<listItem listIndent="1" listStyle="disc" listType="bulleted">4.[]</listItem>'
  541. );
  542. }
  543. );
  544. it( 'should inherit the list style attribute from nested list if the `listType` is other than indenting element', () => {
  545. setModelData( model,
  546. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  547. '<listItem listIndent="1" listStyle="decimal" listType="numbered">2.</listItem>' +
  548. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.[]</listItem>'
  549. );
  550. editor.execute( 'indentList' );
  551. expect( getModelData( model ) ).to.equal(
  552. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  553. '<listItem listIndent="1" listStyle="decimal" listType="numbered">2.</listItem>' +
  554. '<listItem listIndent="1" listStyle="decimal" listType="numbered">3.[]</listItem>'
  555. );
  556. } );
  557. } );
  558. describe( 'outdenting lists', () => {
  559. it( 'should inherit the list style attribute from parent list (change the first nested item)', () => {
  560. setModelData( model,
  561. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  562. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.[]</listItem>' +
  563. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  564. );
  565. editor.execute( 'outdentList' );
  566. expect( getModelData( model ) ).to.equal(
  567. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  568. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.[]</listItem>' +
  569. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  570. );
  571. } );
  572. it( 'should inherit the list style attribute from parent list (change the second nested item)', () => {
  573. setModelData( model,
  574. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  575. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.</listItem>' +
  576. '<listItem listIndent="1" listStyle="default" listType="bulleted">3.[]</listItem>'
  577. );
  578. editor.execute( 'outdentList' );
  579. expect( getModelData( model ) ).to.equal(
  580. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  581. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.</listItem>' +
  582. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.[]</listItem>'
  583. );
  584. } );
  585. it( 'should inherit the list style attribute from parent list (modifying nested lists)', () => {
  586. setModelData( model,
  587. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  588. '<listItem listIndent="1" listStyle="default" listType="bulleted">[2.</listItem>' +
  589. '<listItem listIndent="2" listStyle="square" listType="bulleted">3.]</listItem>'
  590. );
  591. editor.execute( 'outdentList' );
  592. expect( getModelData( model ) ).to.equal(
  593. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  594. '<listItem listIndent="0" listStyle="circle" listType="bulleted">[2.</listItem>' +
  595. '<listItem listIndent="1" listStyle="square" listType="bulleted">3.]</listItem>'
  596. );
  597. } );
  598. it(
  599. 'should inherit the list style attribute from parent list (outdenting many items, including the first one in the list)',
  600. () => {
  601. setModelData( model,
  602. '<listItem listIndent="0" listStyle="circle" listType="bulleted">[1.</listItem>' +
  603. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.</listItem>' +
  604. '<listItem listIndent="2" listStyle="square" listType="bulleted">3.]</listItem>' +
  605. '<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'
  606. );
  607. editor.execute( 'outdentList' );
  608. expect( getModelData( model ) ).to.equal(
  609. '<paragraph>[1.</paragraph>' +
  610. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>' +
  611. '<listItem listIndent="1" listStyle="square" listType="bulleted">3.]</listItem>' +
  612. '<listItem listIndent="0" listStyle="circle" listType="bulleted">4.</listItem>'
  613. );
  614. }
  615. );
  616. it(
  617. 'should inherit the list style attribute from parent list (outdenting the first item that is a parent for next list)',
  618. () => {
  619. setModelData( model,
  620. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.[]</listItem>' +
  621. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.</listItem>' +
  622. '<listItem listIndent="2" listStyle="square" listType="bulleted">3.</listItem>' +
  623. '<listItem listIndent="3" listStyle="disc" listType="bulleted">4.</listItem>' +
  624. '<listItem listIndent="0" listStyle="circle" listType="bulleted">5.</listItem>'
  625. );
  626. editor.execute( 'outdentList' );
  627. expect( getModelData( model ) ).to.equal(
  628. '<paragraph>1.[]</paragraph>' +
  629. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>' +
  630. '<listItem listIndent="1" listStyle="square" listType="bulleted">3.</listItem>' +
  631. '<listItem listIndent="2" listStyle="disc" listType="bulleted">4.</listItem>' +
  632. '<listItem listIndent="0" listStyle="circle" listType="bulleted">5.</listItem>'
  633. );
  634. }
  635. );
  636. it( 'should not inherit the list style if outdented the only one item in the list', () => {
  637. setModelData( model,
  638. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.[]</listItem>' +
  639. '<listItem listIndent="1" listStyle="disc" listType="bulleted">2.</listItem>' +
  640. '<listItem listIndent="2" listStyle="square" listType="bulleted">3.</listItem>'
  641. );
  642. editor.execute( 'outdentList' );
  643. expect( getModelData( model ) ).to.equal(
  644. '<paragraph>1.[]</paragraph>' +
  645. '<listItem listIndent="0" listStyle="disc" listType="bulleted">2.</listItem>' +
  646. '<listItem listIndent="1" listStyle="square" listType="bulleted">3.</listItem>'
  647. );
  648. } );
  649. it( 'should not inherit the list style if outdented the only one item in the list (a paragraph below the list)', () => {
  650. setModelData( model,
  651. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.[]</listItem>' +
  652. '<listItem listIndent="1" listStyle="disc" listType="bulleted">2.</listItem>' +
  653. '<listItem listIndent="2" listStyle="square" listType="bulleted">3.</listItem>' +
  654. '<paragraph>Foo</paragraph>'
  655. );
  656. editor.execute( 'outdentList' );
  657. expect( getModelData( model ) ).to.equal(
  658. '<paragraph>1.[]</paragraph>' +
  659. '<listItem listIndent="0" listStyle="disc" listType="bulleted">2.</listItem>' +
  660. '<listItem listIndent="1" listStyle="square" listType="bulleted">3.</listItem>' +
  661. '<paragraph>Foo</paragraph>'
  662. );
  663. } );
  664. it( 'should not inherit the list style attribute from parent list if the `listType` is other than outdenting element', () => {
  665. setModelData( model,
  666. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  667. '<listItem listIndent="1" listStyle="decimal" listType="numbered">2.[]</listItem>' +
  668. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  669. );
  670. editor.execute( 'outdentList' );
  671. expect( getModelData( model ) ).to.equal(
  672. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  673. '<listItem listIndent="0" listStyle="decimal" listType="numbered">2.[]</listItem>' +
  674. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  675. );
  676. } );
  677. it( 'should not do anything if there is no list after outdenting', () => {
  678. setModelData( model,
  679. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.[]</listItem>'
  680. );
  681. editor.execute( 'outdentList' );
  682. expect( getModelData( model ) ).to.equal(
  683. '<paragraph>1.[]</paragraph>'
  684. );
  685. } );
  686. } );
  687. describe( 'indent/outdent + undo', () => {
  688. it( 'should use the same batch for indenting a list and updating `listType` attribute', () => {
  689. setModelData( model,
  690. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  691. '<listItem listIndent="1" listStyle="default" listType="bulleted">1A.</listItem>' +
  692. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2B.</listItem>' +
  693. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.[]</listItem>' +
  694. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  695. );
  696. editor.execute( 'indentList' );
  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">1A.</listItem>' +
  701. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2B.</listItem>' +
  702. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.[]</listItem>' +
  703. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  704. );
  705. } );
  706. it( 'should use the same batch for outdenting a list and updating `listType` attribute', () => {
  707. setModelData( model,
  708. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  709. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.[]</listItem>' +
  710. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  711. );
  712. editor.execute( 'outdentList' );
  713. editor.execute( 'undo' );
  714. expect( getModelData( model ) ).to.equal(
  715. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  716. '<listItem listIndent="1" listStyle="default" listType="bulleted">2.[]</listItem>' +
  717. '<listItem listIndent="0" listStyle="circle" listType="bulleted">3.</listItem>'
  718. );
  719. } );
  720. } );
  721. describe( 'todo list', () => {
  722. let editor, model;
  723. beforeEach( () => {
  724. return VirtualTestEditor
  725. .create( {
  726. // TodoListEditing is at the end by design. Check `ListStyleEditing.afterInit()` call.
  727. plugins: [ Paragraph, ListStyleEditing, TodoListEditing ]
  728. } )
  729. .then( newEditor => {
  730. editor = newEditor;
  731. model = editor.model;
  732. } );
  733. } );
  734. afterEach( () => {
  735. return editor.destroy();
  736. } );
  737. it( 'should not add the `listStyle` attribute while creating a todo list', () => {
  738. setModelData( model, '<paragraph>Foo[]</paragraph>' );
  739. editor.execute( 'todoList' );
  740. expect( getModelData( model ), '<listItem listIndent="0" listType="todo">Foo[]</listItem>' );
  741. } );
  742. it( 'should not add the `listStyle` attribute while switching the list type', () => {
  743. setModelData( model, '<listItem listIndent="0" listType="bulleted">Foo[]</listItem>' );
  744. editor.execute( 'todoList' );
  745. expect( getModelData( model ), '<listItem listIndent="0" listType="todo">Foo[]</listItem>' );
  746. } );
  747. it( 'should remove the `listStyle` attribute while switching the list type that uses the list style feature', () => {
  748. setModelData( model, '<listItem listIndent="0" listType="bulleted" listStyle="circle">Foo[]</listItem>' );
  749. editor.execute( 'todoList' );
  750. expect( getModelData( model ), '<listItem listIndent="0" listType="todo">Foo[]</listItem>' );
  751. } );
  752. it( 'should not inherit the list style attribute when inserting a todo list item', () => {
  753. setModelData( model,
  754. '<paragraph>Foo Bar.[]</paragraph>' +
  755. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
  756. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'
  757. );
  758. editor.execute( 'todoList' );
  759. expect( getModelData( model ) ).to.equal(
  760. '<listItem listIndent="0" listType="todo">Foo Bar.[]</listItem>' +
  761. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Foo</listItem>' +
  762. '<listItem listIndent="0" listStyle="circle" listType="bulleted">Bar</listItem>'
  763. );
  764. } );
  765. } );
  766. describe( 'removing content between two lists', () => {
  767. let editor, model;
  768. beforeEach( () => {
  769. return VirtualTestEditor
  770. .create( {
  771. plugins: [ Paragraph, ListStyleEditing, Typing ]
  772. } )
  773. .then( newEditor => {
  774. editor = newEditor;
  775. model = editor.model;
  776. } );
  777. } );
  778. afterEach( () => {
  779. return editor.destroy();
  780. } );
  781. it( 'should not do anything while removing a letter inside a listItem', () => {
  782. setModelData( model,
  783. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  784. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.[]</listItem>' +
  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. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  792. '<listItem listIndent="0" listStyle="square" listType="bulleted">2[]</listItem>' +
  793. '<paragraph></paragraph>' +
  794. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  795. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  796. );
  797. } );
  798. it( 'should not do anything if there is a non-listItem before the removed content', () => {
  799. setModelData( model,
  800. '<paragraph>Foo</paragraph>' +
  801. '<paragraph>[]</paragraph>' +
  802. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  803. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  804. );
  805. editor.execute( 'delete' );
  806. expect( getModelData( model ) ).to.equal(
  807. '<paragraph>Foo[]</paragraph>' +
  808. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  809. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  810. );
  811. } );
  812. it( 'should not do anything if there is a non-listItem after the removed content', () => {
  813. setModelData( model,
  814. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  815. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>' +
  816. '<paragraph>[]</paragraph>' +
  817. '<paragraph>Foo</paragraph>'
  818. );
  819. editor.execute( 'delete' );
  820. expect( getModelData( model ) ).to.equal(
  821. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  822. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.[]</listItem>' +
  823. '<paragraph>Foo</paragraph>'
  824. );
  825. } );
  826. it( 'should not do anything if there is no element after the removed content', () => {
  827. setModelData( model,
  828. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  829. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>' +
  830. '<paragraph>[]</paragraph>'
  831. );
  832. editor.execute( 'delete' );
  833. expect( getModelData( model ) ).to.equal(
  834. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  835. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.[]</listItem>'
  836. );
  837. } );
  838. it(
  839. 'should modify the the `listStyle` attribute for the merged (second) list when removing content between those lists',
  840. () => {
  841. setModelData( model,
  842. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  843. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>' +
  844. '<paragraph>[]</paragraph>' +
  845. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  846. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  847. );
  848. editor.execute( 'delete' );
  849. expect( getModelData( model ) ).to.equal(
  850. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  851. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.[]</listItem>' +
  852. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  853. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>'
  854. );
  855. }
  856. );
  857. it( 'should read the `listStyle` attribute from the most outer list', () => {
  858. setModelData( model,
  859. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  860. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>' +
  861. '<listItem listIndent="1" listStyle="numbered" listType="decimal">2.1.</listItem>' +
  862. '<listItem listIndent="2" listStyle="default" listType="default">2.1.1</listItem>' +
  863. '<paragraph>[]</paragraph>' +
  864. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  865. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  866. );
  867. editor.execute( 'delete' );
  868. expect( getModelData( model ) ).to.equal(
  869. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  870. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>' +
  871. '<listItem listIndent="1" listStyle="numbered" listType="decimal">2.1.</listItem>' +
  872. '<listItem listIndent="2" listStyle="default" listType="default">2.1.1[]</listItem>' +
  873. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  874. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>'
  875. );
  876. } );
  877. it(
  878. 'should not modify the the `listStyle` attribute for the merged (second) list if merging different `listType` attribute',
  879. () => {
  880. setModelData( model,
  881. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  882. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>' +
  883. '<paragraph>[]</paragraph>' +
  884. '<listItem listIndent="0" listStyle="decimal" listType="numbered">1.</listItem>' +
  885. '<listItem listIndent="0" listStyle="decimal" listType="numbered">2.</listItem>'
  886. );
  887. editor.execute( 'delete' );
  888. expect( getModelData( model ) ).to.equal(
  889. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  890. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.[]</listItem>' +
  891. '<listItem listIndent="0" listStyle="decimal" listType="numbered">1.</listItem>' +
  892. '<listItem listIndent="0" listStyle="decimal" listType="numbered">2.</listItem>'
  893. );
  894. }
  895. );
  896. it(
  897. 'should modify the the `listStyle` attribute for the merged (second) list when removing content from both lists',
  898. () => {
  899. setModelData( model,
  900. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  901. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>' +
  902. '<listItem listIndent="0" listStyle="square" listType="bulleted">[3.</listItem>' +
  903. '<paragraph>Foo</paragraph>' +
  904. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.]</listItem>' +
  905. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  906. );
  907. editor.execute( 'delete' );
  908. expect( getModelData( model ) ).to.equal(
  909. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  910. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>' +
  911. '<listItem listIndent="0" listStyle="square" listType="bulleted">[]</listItem>' +
  912. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>'
  913. );
  914. }
  915. );
  916. it(
  917. 'should modify the the `listStyle` attribute for the merged (second) list when typing over content from both lists',
  918. () => {
  919. setModelData( model,
  920. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  921. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>' +
  922. '<listItem listIndent="0" listStyle="square" listType="bulleted">[3.</listItem>' +
  923. '<paragraph>Foo</paragraph>' +
  924. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.]</listItem>' +
  925. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  926. );
  927. editor.execute( 'input', { text: 'Foo' } );
  928. expect( getModelData( model ) ).to.equal(
  929. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  930. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>' +
  931. '<listItem listIndent="0" listStyle="square" listType="bulleted">Foo[]</listItem>' +
  932. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.</listItem>'
  933. );
  934. }
  935. );
  936. it(
  937. 'should not modify the the `listStyle` if lists were not merged but the content was partially removed',
  938. () => {
  939. setModelData( model,
  940. '<listItem listIndent="0" listStyle="square" listType="bulleted">111.</listItem>' +
  941. '<listItem listIndent="0" listStyle="square" listType="bulleted">222.</listItem>' +
  942. '<listItem listIndent="0" listStyle="square" listType="bulleted">[333.</listItem>' +
  943. '<paragraph>Foo</paragraph>' +
  944. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1]11.</listItem>' +
  945. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  946. );
  947. editor.execute( 'delete' );
  948. expect( getModelData( model ) ).to.equal(
  949. '<listItem listIndent="0" listStyle="square" listType="bulleted">111.</listItem>' +
  950. '<listItem listIndent="0" listStyle="square" listType="bulleted">222.</listItem>' +
  951. '<listItem listIndent="0" listStyle="circle" listType="bulleted">[]11.</listItem>' +
  952. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  953. );
  954. }
  955. );
  956. it( 'should not do anything while typing in a list item', () => {
  957. setModelData( model,
  958. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  959. '<listItem listIndent="0" listStyle="square" listType="bulleted">2.[]</listItem>' +
  960. '<listItem listIndent="0" listStyle="square" listType="bulleted">3.</listItem>' +
  961. '<paragraph></paragraph>' +
  962. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  963. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  964. );
  965. const modelChangeStub = sinon.stub( model, 'change' ).callThrough();
  966. simulateTyping( ' Foo' );
  967. // Each character calls `editor.model.change()`.
  968. expect( modelChangeStub.callCount ).to.equal( 4 );
  969. expect( getModelData( model ) ).to.equal(
  970. '<listItem listIndent="0" listStyle="square" listType="bulleted">1.</listItem>' +
  971. '<listItem listIndent="0" listStyle="square" listType="bulleted">2. Foo[]</listItem>' +
  972. '<listItem listIndent="0" listStyle="square" listType="bulleted">3.</listItem>' +
  973. '<paragraph></paragraph>' +
  974. '<listItem listIndent="0" listStyle="circle" listType="bulleted">1.</listItem>' +
  975. '<listItem listIndent="0" listStyle="circle" listType="bulleted">2.</listItem>'
  976. );
  977. } );
  978. function simulateTyping( text ) {
  979. // While typing, every character is an atomic change.
  980. text.split( '' ).forEach( character => {
  981. editor.execute( 'input', {
  982. text: character
  983. } );
  984. } );
  985. }
  986. } );
  987. } );
  988. } );