liststylesediting.js 37 KB

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