integration.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  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. /* global document */
  6. import BlockQuote from '../src/blockquote';
  7. import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
  8. import Image from '@ckeditor/ckeditor5-image/src/image';
  9. import ImageCaption from '@ckeditor/ckeditor5-image/src/imagecaption';
  10. import List from '@ckeditor/ckeditor5-list/src/list';
  11. import Enter from '@ckeditor/ckeditor5-enter/src/enter';
  12. import Delete from '@ckeditor/ckeditor5-typing/src/delete';
  13. import Heading from '@ckeditor/ckeditor5-heading/src/heading';
  14. import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
  15. import Table from '@ckeditor/ckeditor5-table/src/table';
  16. import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
  17. import {
  18. parse as parseModel,
  19. getData as getModelData,
  20. setData as setModelData
  21. } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
  22. describe( 'BlockQuote integration', () => {
  23. let editor, model, element, viewDocument;
  24. beforeEach( () => {
  25. element = document.createElement( 'div' );
  26. document.body.appendChild( element );
  27. return ClassicTestEditor
  28. .create( element, {
  29. plugins: [ BlockQuote, Paragraph, Bold, Image, ImageCaption, List, Enter, Delete, Heading, Table ]
  30. } )
  31. .then( newEditor => {
  32. editor = newEditor;
  33. model = editor.model;
  34. viewDocument = editor.editing.view.document;
  35. } );
  36. } );
  37. afterEach( () => {
  38. element.remove();
  39. return editor.destroy();
  40. } );
  41. describe( 'enter key support', () => {
  42. function fakeEventData() {
  43. return {
  44. preventDefault: sinon.spy()
  45. };
  46. }
  47. it( 'does nothing if selection is in an empty block but not in a block quote', () => {
  48. const data = fakeEventData();
  49. const execSpy = sinon.spy( editor, 'execute' );
  50. setModelData( model, '<paragraph>x</paragraph><paragraph>[]</paragraph><paragraph>x</paragraph>' );
  51. viewDocument.fire( 'enter', data );
  52. // Only enter command should be executed.
  53. expect( data.preventDefault.called ).to.be.true;
  54. expect( execSpy.calledOnce ).to.be.true;
  55. expect( execSpy.args[ 0 ][ 0 ] ).to.equal( 'enter' );
  56. } );
  57. it( 'does nothing if selection is in a non-empty block (at the end) in a block quote', () => {
  58. const data = fakeEventData();
  59. const execSpy = sinon.spy( editor, 'execute' );
  60. setModelData( model, '<blockQuote><paragraph>xx[]</paragraph></blockQuote>' );
  61. viewDocument.fire( 'enter', data );
  62. // Only enter command should be executed.
  63. expect( data.preventDefault.called ).to.be.true;
  64. expect( execSpy.calledOnce ).to.be.true;
  65. expect( execSpy.args[ 0 ][ 0 ] ).to.equal( 'enter' );
  66. } );
  67. it( 'does nothing if selection is in a non-empty block (at the beginning) in a block quote', () => {
  68. const data = fakeEventData();
  69. const execSpy = sinon.spy( editor, 'execute' );
  70. setModelData( model, '<blockQuote><paragraph>[]xx</paragraph></blockQuote>' );
  71. viewDocument.fire( 'enter', data );
  72. // Only enter command should be executed.
  73. expect( data.preventDefault.called ).to.be.true;
  74. expect( execSpy.calledOnce ).to.be.true;
  75. expect( execSpy.args[ 0 ][ 0 ] ).to.equal( 'enter' );
  76. } );
  77. it( 'does nothing if selection is not collapsed', () => {
  78. const data = fakeEventData();
  79. const execSpy = sinon.spy( editor, 'execute' );
  80. setModelData( model, '<blockQuote><paragraph>[</paragraph><paragraph>]</paragraph></blockQuote>' );
  81. viewDocument.fire( 'enter', data );
  82. // Only enter command should be executed.
  83. expect( data.preventDefault.called ).to.be.true;
  84. expect( execSpy.calledOnce ).to.be.true;
  85. expect( execSpy.args[ 0 ][ 0 ] ).to.equal( 'enter' );
  86. } );
  87. it( 'does not interfere with a similar handler in the list feature', () => {
  88. const data = fakeEventData();
  89. setModelData( model,
  90. '<paragraph>x</paragraph>' +
  91. '<blockQuote>' +
  92. '<listItem listIndent="0" listType="bulleted">a</listItem>' +
  93. '<listItem listIndent="0" listType="bulleted">[]</listItem>' +
  94. '</blockQuote>' +
  95. '<paragraph>x</paragraph>'
  96. );
  97. viewDocument.fire( 'enter', data );
  98. expect( data.preventDefault.called ).to.be.true;
  99. expect( getModelData( model ) ).to.equal(
  100. '<paragraph>x</paragraph>' +
  101. '<blockQuote>' +
  102. '<listItem listIndent="0" listType="bulleted">a</listItem>' +
  103. '<paragraph>[]</paragraph>' +
  104. '</blockQuote>' +
  105. '<paragraph>x</paragraph>'
  106. );
  107. } );
  108. it( 'escapes block quote if selection is in an empty block in an empty block quote', () => {
  109. const data = fakeEventData();
  110. const execSpy = sinon.spy( editor, 'execute' );
  111. setModelData( model, '<paragraph>x</paragraph><blockQuote><paragraph>[]</paragraph></blockQuote><paragraph>x</paragraph>' );
  112. viewDocument.fire( 'enter', data );
  113. expect( data.preventDefault.called ).to.be.true;
  114. expect( execSpy.calledOnce ).to.be.true;
  115. expect( execSpy.args[ 0 ][ 0 ] ).to.equal( 'blockQuote' );
  116. expect( getModelData( model ) ).to.equal( '<paragraph>x</paragraph><paragraph>[]</paragraph><paragraph>x</paragraph>' );
  117. } );
  118. it( 'escapes block quote if selection is in an empty block in the middle of a block quote', () => {
  119. const data = fakeEventData();
  120. const execSpy = sinon.spy( editor, 'execute' );
  121. setModelData( model,
  122. '<paragraph>x</paragraph>' +
  123. '<blockQuote><paragraph>a</paragraph><paragraph>[]</paragraph><paragraph>b</paragraph></blockQuote>' +
  124. '<paragraph>x</paragraph>'
  125. );
  126. viewDocument.fire( 'enter', data );
  127. expect( data.preventDefault.called ).to.be.true;
  128. expect( execSpy.calledOnce ).to.be.true;
  129. expect( execSpy.args[ 0 ][ 0 ] ).to.equal( 'blockQuote' );
  130. expect( getModelData( model ) ).to.equal(
  131. '<paragraph>x</paragraph>' +
  132. '<blockQuote><paragraph>a</paragraph></blockQuote>' +
  133. '<paragraph>[]</paragraph>' +
  134. '<blockQuote><paragraph>b</paragraph></blockQuote>' +
  135. '<paragraph>x</paragraph>'
  136. );
  137. } );
  138. it( 'escapes block quote if selection is in an empty block at the end of a block quote', () => {
  139. const data = fakeEventData();
  140. const execSpy = sinon.spy( editor, 'execute' );
  141. setModelData( model,
  142. '<paragraph>x</paragraph>' +
  143. '<blockQuote><paragraph>a</paragraph><paragraph>[]</paragraph></blockQuote>' +
  144. '<paragraph>x</paragraph>'
  145. );
  146. viewDocument.fire( 'enter', data );
  147. expect( data.preventDefault.called ).to.be.true;
  148. expect( execSpy.calledOnce ).to.be.true;
  149. expect( execSpy.args[ 0 ][ 0 ] ).to.equal( 'blockQuote' );
  150. expect( getModelData( model ) ).to.equal(
  151. '<paragraph>x</paragraph>' +
  152. '<blockQuote><paragraph>a</paragraph></blockQuote>' +
  153. '<paragraph>[]</paragraph>' +
  154. '<paragraph>x</paragraph>'
  155. );
  156. } );
  157. it( 'scrolls the view document to the selection after the command is executed', () => {
  158. const data = fakeEventData();
  159. const execSpy = sinon.spy( editor, 'execute' );
  160. const scrollSpy = sinon.stub( editor.editing.view, 'scrollToTheSelection' );
  161. setModelData( model,
  162. '<paragraph>x</paragraph>' +
  163. '<blockQuote><paragraph>a</paragraph><paragraph>[]</paragraph></blockQuote>' +
  164. '<paragraph>x</paragraph>'
  165. );
  166. viewDocument.fire( 'enter', data );
  167. sinon.assert.calledOnce( scrollSpy );
  168. sinon.assert.callOrder( execSpy, scrollSpy );
  169. } );
  170. } );
  171. describe( 'backspace key support', () => {
  172. function fakeEventData() {
  173. return {
  174. preventDefault: sinon.spy(),
  175. direction: 'backward',
  176. unit: 'character'
  177. };
  178. }
  179. it( 'merges paragraph into paragraph in the quote', () => {
  180. const data = fakeEventData();
  181. setModelData( model,
  182. '<blockQuote><paragraph>a</paragraph><paragraph>b</paragraph></blockQuote>' +
  183. '<paragraph>[]c</paragraph>' +
  184. '<paragraph>d</paragraph>'
  185. );
  186. viewDocument.fire( 'delete', data );
  187. expect( getModelData( model ) ).to.equal(
  188. '<blockQuote><paragraph>a</paragraph><paragraph>b[]c</paragraph></blockQuote>' +
  189. '<paragraph>d</paragraph>'
  190. );
  191. } );
  192. it( 'merges paragraph from a quote into a paragraph before quote', () => {
  193. const data = fakeEventData();
  194. setModelData( model,
  195. '<paragraph>x</paragraph>' +
  196. '<blockQuote><paragraph>[]a</paragraph><paragraph>b</paragraph></blockQuote>' +
  197. '<paragraph>y</paragraph>'
  198. );
  199. viewDocument.fire( 'delete', data );
  200. expect( getModelData( model ) ).to.equal(
  201. '<paragraph>x[]a</paragraph>' +
  202. '<blockQuote><paragraph>b</paragraph></blockQuote>' +
  203. '<paragraph>y</paragraph>'
  204. );
  205. } );
  206. it( 'merges two quotes', () => {
  207. const data = fakeEventData();
  208. setModelData( model,
  209. '<paragraph>x</paragraph>' +
  210. '<blockQuote><paragraph>a</paragraph><paragraph>b</paragraph></blockQuote>' +
  211. '<blockQuote><paragraph>[]c</paragraph><paragraph>d</paragraph></blockQuote>' +
  212. '<paragraph>y</paragraph>'
  213. );
  214. viewDocument.fire( 'delete', data );
  215. expect( getModelData( model ) ).to.equal(
  216. '<paragraph>x</paragraph>' +
  217. '<blockQuote><paragraph>a</paragraph><paragraph>b[]c</paragraph><paragraph>d</paragraph></blockQuote>' +
  218. '<paragraph>y</paragraph>'
  219. );
  220. } );
  221. it( 'removes empty quote when merging into another quote', () => {
  222. const data = fakeEventData();
  223. setModelData( model,
  224. '<paragraph>x</paragraph>' +
  225. '<blockQuote><paragraph>a</paragraph></blockQuote>' +
  226. '<blockQuote><paragraph>[]</paragraph></blockQuote>' +
  227. '<paragraph>y</paragraph>'
  228. );
  229. viewDocument.fire( 'delete', data );
  230. expect( getModelData( model ) ).to.equal(
  231. '<paragraph>x</paragraph>' +
  232. '<blockQuote><paragraph>a[]</paragraph></blockQuote>' +
  233. '<paragraph>y</paragraph>'
  234. );
  235. } );
  236. it( 'removes empty quote when merging into a paragraph', () => {
  237. const data = fakeEventData();
  238. setModelData( model,
  239. '<paragraph>x</paragraph>' +
  240. '<blockQuote><paragraph>[]</paragraph></blockQuote>' +
  241. '<paragraph>y</paragraph>'
  242. );
  243. viewDocument.fire( 'delete', data );
  244. expect( getModelData( model ) ).to.equal(
  245. '<paragraph>x[]</paragraph>' +
  246. '<paragraph>y</paragraph>'
  247. );
  248. } );
  249. } );
  250. // Historically, due to problems with schema, images were not quotable.
  251. // These tests were left here to confirm that after schema was fixed, images are properly quotable.
  252. describe( 'compatibility with images', () => {
  253. it( 'quotes a simple image', () => {
  254. const element = document.createElement( 'div' );
  255. document.body.appendChild( element );
  256. // We can't load ImageCaption in this test because it adds <caption> to all images automatically.
  257. return ClassicTestEditor
  258. .create( element, {
  259. plugins: [ BlockQuote, Paragraph, Image ]
  260. } )
  261. .then( editor => {
  262. setModelData( editor.model,
  263. '<paragraph>fo[o</paragraph>' +
  264. '<image src="/assets/sample.png"></image>' +
  265. '<paragraph>b]ar</paragraph>'
  266. );
  267. editor.execute( 'blockQuote' );
  268. expect( getModelData( editor.model ) ).to.equal(
  269. '<blockQuote>' +
  270. '<paragraph>fo[o</paragraph>' +
  271. '<image src="/assets/sample.png"></image>' +
  272. '<paragraph>b]ar</paragraph>' +
  273. '</blockQuote>'
  274. );
  275. element.remove();
  276. return editor.destroy();
  277. } );
  278. } );
  279. it( 'quotes an image with caption', () => {
  280. setModelData( model,
  281. '<paragraph>fo[o</paragraph>' +
  282. '<image src="/assets/sample.png">' +
  283. '<caption>xxx</caption>' +
  284. '</image>' +
  285. '<paragraph>b]ar</paragraph>'
  286. );
  287. editor.execute( 'blockQuote' );
  288. expect( getModelData( model ) ).to.equal(
  289. '<blockQuote>' +
  290. '<paragraph>fo[o</paragraph>' +
  291. '<image src="/assets/sample.png">' +
  292. '<caption>xxx</caption>' +
  293. '</image>' +
  294. '<paragraph>b]ar</paragraph>' +
  295. '</blockQuote>'
  296. );
  297. } );
  298. it( 'adds an image to an existing quote', () => {
  299. setModelData( model,
  300. '<paragraph>fo[o</paragraph>' +
  301. '<image src="/assets/sample.png">' +
  302. '<caption>xxx</caption>' +
  303. '</image>' +
  304. '<blockQuote><paragraph>b]ar</paragraph></blockQuote>'
  305. );
  306. editor.execute( 'blockQuote' );
  307. // Selection incorrectly trimmed.
  308. expect( getModelData( model ) ).to.equal(
  309. '<blockQuote>' +
  310. '<paragraph>foo</paragraph>' +
  311. '<image src="/assets/sample.png">' +
  312. '<caption>xxx</caption>' +
  313. '</image>' +
  314. '<paragraph>[b]ar</paragraph>' +
  315. '</blockQuote>'
  316. );
  317. } );
  318. it( 'wraps paragraph+image', () => {
  319. setModelData( model,
  320. '<paragraph>[foo</paragraph><image><caption>foo</caption></image>]'
  321. );
  322. editor.execute( 'blockQuote' );
  323. expect( getModelData( model ) ).to.equal(
  324. '<blockQuote><paragraph>[foo</paragraph><image><caption>foo</caption></image>]</blockQuote>'
  325. );
  326. } );
  327. it( 'unwraps paragraph+image', () => {
  328. setModelData( model,
  329. '<blockQuote><paragraph>[foo</paragraph><image><caption>foo</caption></image>]</blockQuote>'
  330. );
  331. editor.execute( 'blockQuote' );
  332. expect( getModelData( model ) ).to.equal(
  333. '<paragraph>[foo</paragraph><image><caption>foo</caption></image>]'
  334. );
  335. } );
  336. it( 'wraps image+paragraph', () => {
  337. setModelData( model,
  338. '[<image><caption>foo</caption></image><paragraph>foo]</paragraph>'
  339. );
  340. editor.execute( 'blockQuote' );
  341. expect( getModelData( model ) ).to.equal(
  342. '<blockQuote>[<image><caption>foo</caption></image><paragraph>foo]</paragraph></blockQuote>'
  343. );
  344. } );
  345. it( 'unwraps image+paragraph', () => {
  346. setModelData( model,
  347. '[<image><caption>foo</caption></image><paragraph>foo]</paragraph>'
  348. );
  349. editor.execute( 'blockQuote' );
  350. expect( getModelData( model ) ).to.equal(
  351. '<blockQuote>[<image><caption>foo</caption></image><paragraph>foo]</paragraph></blockQuote>'
  352. );
  353. } );
  354. } );
  355. // When blockQuote with a paragraph was pasted into a list item, the item contained the paragraph. It was invalid.
  356. // There is a test which checks whether blockQuote will split the list items instead of merging with.
  357. describe( 'compatibility with lists', () => {
  358. it( 'does not merge the paragraph with list item', () => {
  359. setModelData( model, '<listItem listIndent="0" listType="bulleted">fo[]o</listItem>' );
  360. const df = parseModel(
  361. '<blockQuote><paragraph>xxx</paragraph></blockQuote><heading1>yyy</heading1>',
  362. model.schema
  363. );
  364. model.insertContent( df, model.document.selection );
  365. expect( getModelData( model ) ).to.equal(
  366. '<listItem listIndent="0" listType="bulleted">fo</listItem>' +
  367. '<blockQuote>' +
  368. '<paragraph>xxx</paragraph>' +
  369. '</blockQuote>' +
  370. '<heading1>yyy[]o</heading1>'
  371. );
  372. } );
  373. } );
  374. describe( 'compatibility with tables', () => {
  375. it( 'wraps whole table', () => {
  376. setModelData( model, '[<table><tableRow><tableCell><paragraph>foo</paragraph></tableCell></tableRow></table>]' );
  377. editor.execute( 'blockQuote' );
  378. expect( getModelData( model ) ).to.equal(
  379. '<blockQuote>[<table><tableRow><tableCell><paragraph>foo</paragraph></tableCell></tableRow></table>]</blockQuote>'
  380. );
  381. } );
  382. it( 'unwraps whole table', () => {
  383. setModelData(
  384. model,
  385. '<blockQuote>[<table><tableRow><tableCell><paragraph>foo</paragraph></tableCell></tableRow></table>]</blockQuote>'
  386. );
  387. editor.execute( 'blockQuote' );
  388. expect( getModelData( model ) ).to.equal(
  389. '[<table><tableRow><tableCell><paragraph>foo</paragraph></tableCell></tableRow></table>]'
  390. );
  391. } );
  392. it( 'wraps paragraph in table cell', () => {
  393. setModelData( model, '<table><tableRow><tableCell><paragraph>[]foo</paragraph></tableCell></tableRow></table>' );
  394. editor.execute( 'blockQuote' );
  395. expect( getModelData( model ) ).to.equal(
  396. '<table><tableRow><tableCell><blockQuote><paragraph>[]foo</paragraph></blockQuote></tableCell></tableRow></table>'
  397. );
  398. } );
  399. it( 'unwraps paragraph in table cell', () => {
  400. setModelData(
  401. model,
  402. '<table><tableRow><tableCell><blockQuote><paragraph>[]foo</paragraph></blockQuote></tableCell></tableRow></table>'
  403. );
  404. editor.execute( 'blockQuote' );
  405. expect( getModelData( model ) ).to.equal(
  406. '<table><tableRow><tableCell><paragraph>[]foo</paragraph></tableCell></tableRow></table>'
  407. );
  408. } );
  409. it( 'wraps image in table cell', () => {
  410. setModelData( model,
  411. '<table>' +
  412. '<tableRow>' +
  413. '<tableCell>[<image><caption>foo</caption></image>]</tableCell>' +
  414. ' </tableRow>' +
  415. '</table>'
  416. );
  417. editor.execute( 'blockQuote' );
  418. expect( getModelData( model ) ).to.equal(
  419. '<table>' +
  420. '<tableRow>' +
  421. '<tableCell><blockQuote>[<image><caption>foo</caption></image>]</blockQuote></tableCell>' +
  422. '</tableRow>' +
  423. '</table>'
  424. );
  425. } );
  426. it( 'unwraps image in table cell', () => {
  427. setModelData( model,
  428. '<table>' +
  429. '<tableRow>' +
  430. '<tableCell><blockQuote>[<image><caption>foo</caption></image>]</blockQuote></tableCell>' +
  431. '</tableRow>' +
  432. '</table>'
  433. );
  434. editor.execute( 'blockQuote' );
  435. expect( getModelData( model ) ).to.equal(
  436. '<table>' +
  437. '<tableRow>' +
  438. '<tableCell>[<image><caption>foo</caption></image>]</tableCell>' +
  439. '</tableRow>' +
  440. '</table>'
  441. );
  442. } );
  443. it( 'wraps paragraph+image in table cell', () => {
  444. setModelData( model,
  445. '<table>' +
  446. '<tableRow>' +
  447. '<tableCell><paragraph>[foo</paragraph><image><caption>foo</caption></image>]</tableCell>' +
  448. '</tableRow>' +
  449. '</table>'
  450. );
  451. editor.execute( 'blockQuote' );
  452. expect( getModelData( model ) ).to.equal(
  453. '<table>' +
  454. '<tableRow>' +
  455. '<tableCell>' +
  456. '<blockQuote><paragraph>[foo</paragraph><image><caption>foo</caption></image>]</blockQuote>' +
  457. '</tableCell>' +
  458. '</tableRow>' +
  459. '</table>'
  460. );
  461. } );
  462. it( 'unwraps paragraph+image in table cell', () => {
  463. setModelData( model,
  464. '<table>' +
  465. '<tableRow>' +
  466. '<tableCell>' +
  467. '<blockQuote><paragraph>[foo</paragraph><image><caption>foo</caption></image>]</blockQuote>' +
  468. '</tableCell>' +
  469. '</tableRow>' +
  470. '</table>'
  471. );
  472. editor.execute( 'blockQuote' );
  473. expect( getModelData( model ) ).to.equal(
  474. '<table>' +
  475. '<tableRow>' +
  476. '<tableCell><paragraph>[foo</paragraph><image><caption>foo</caption></image>]</tableCell>' +
  477. '</tableRow>' +
  478. '</table>'
  479. );
  480. } );
  481. it( 'wraps image+paragraph in table cell', () => {
  482. setModelData( model,
  483. '<table>' +
  484. '<tableRow>' +
  485. '<tableCell>[<image><caption>foo</caption></image><paragraph>foo]</paragraph></tableCell>' +
  486. '</tableRow>' +
  487. '</table>'
  488. );
  489. editor.execute( 'blockQuote' );
  490. expect( getModelData( model ) ).to.equal(
  491. '<table>' +
  492. '<tableRow>' +
  493. '<tableCell>' +
  494. '<blockQuote>[<image><caption>foo</caption></image><paragraph>foo]</paragraph></blockQuote>' +
  495. '</tableCell>' +
  496. '</tableRow>' +
  497. '</table>'
  498. );
  499. } );
  500. it( 'unwraps image+paragraph in table cell', () => {
  501. setModelData( model,
  502. '<table>' +
  503. '<tableRow>' +
  504. '<tableCell>[<image><caption>foo</caption></image><paragraph>foo]</paragraph></tableCell>' +
  505. '</tableRow>' +
  506. '</table>'
  507. );
  508. editor.execute( 'blockQuote' );
  509. expect( getModelData( model ) ).to.equal(
  510. '<table>' +
  511. '<tableRow>' +
  512. '<tableCell>' +
  513. '<blockQuote>[<image><caption>foo</caption></image><paragraph>foo]</paragraph></blockQuote>' +
  514. '</tableCell>' +
  515. '</tableRow>' +
  516. '</table>'
  517. );
  518. } );
  519. } );
  520. describe( 'autoparagraphing', () => {
  521. it( 'text in block quote in div', () => {
  522. const data =
  523. '<blockquote>' +
  524. '<div>foo<strong>bar</strong></div>' +
  525. '</blockquote>' +
  526. 'xyz';
  527. editor.setData( data );
  528. expect( editor.getData() ).to.equal(
  529. '<blockquote>' +
  530. '<p>foo<strong>bar</strong></p>' +
  531. '</blockquote>' +
  532. '<p>xyz</p>'
  533. );
  534. } );
  535. it( 'text directly in block quote', () => {
  536. const data =
  537. '<blockquote>' +
  538. 'foo<strong>bar</strong>' +
  539. '</blockquote>' +
  540. 'xyz';
  541. editor.setData( data );
  542. expect( editor.getData() ).to.equal(
  543. '<blockquote>' +
  544. '<p>foo<strong>bar</strong></p>' +
  545. '</blockquote>' +
  546. '<p>xyz</p>'
  547. );
  548. } );
  549. it( 'text after block quote in div', () => {
  550. const data =
  551. '<blockquote>' +
  552. 'foo<strong>bar</strong>' +
  553. '</blockquote>' +
  554. '<div>xyz</div>';
  555. editor.setData( data );
  556. expect( editor.getData() ).to.equal(
  557. '<blockquote>' +
  558. '<p>foo<strong>bar</strong></p>' +
  559. '</blockquote>' +
  560. '<p>xyz</p>'
  561. );
  562. } );
  563. it( 'text inside block quote in and after div', () => {
  564. const data =
  565. '<blockquote>' +
  566. '<div>foo</div><strong>bar</strong>' +
  567. '</blockquote>' +
  568. 'xyz';
  569. editor.setData( data );
  570. expect( editor.getData() ).to.equal(
  571. '<blockquote>' +
  572. '<p>foo</p><p><strong>bar</strong></p>' +
  573. '</blockquote>' +
  574. '<p>xyz</p>'
  575. );
  576. } );
  577. it( 'text inside block quote in div split by heading', () => {
  578. const data =
  579. '<blockquote>' +
  580. '<div>foo<h2>bar</h2><strong>baz</strong></div>' +
  581. '</blockquote>' +
  582. 'xyz';
  583. editor.setData( data );
  584. expect( editor.getData() ).to.equal(
  585. '<blockquote>' +
  586. '<p>foo</p><h2>bar</h2><p><strong>baz</strong></p>' +
  587. '</blockquote>' +
  588. '<p>xyz</p>'
  589. );
  590. } );
  591. } );
  592. } );