htmldataprocessor.js 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /**
  2. * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* bender-tags: browser-only */
  6. 'use strict';
  7. import HtmlDataProcessor from '/ckeditor5/engine/dataprocessor/htmldataprocessor.js';
  8. import xssTemplates from '/tests/engine/dataprocessor/_utils/xsstemplates.js';
  9. describe( 'HtmlDataProcessor', () => {
  10. const dataProcessor = new HtmlDataProcessor();
  11. describe( 'toDom', () => {
  12. it( 'should return empty DocumentFragment when empty string is passed', () => {
  13. const fragment = dataProcessor.toDom( '' );
  14. expect( fragment ).to.be.an.instanceOf( DocumentFragment );
  15. expect( fragment.childNodes.length ).to.equal( 0 );
  16. } );
  17. it( 'should convert HTML to DocumentFragment with single text node', () => {
  18. const fragment = dataProcessor.toDom( 'foo bar' );
  19. expect( fragment.childNodes.length ).to.equal( 1 );
  20. expect( fragment.childNodes[ 0 ].nodeType ).to.equal( Node.TEXT_NODE );
  21. expect( fragment.childNodes[ 0 ].textContent ).to.equal( 'foo bar' );
  22. } );
  23. it( 'should convert HTML to DocumentFragment with multiple child nodes', () => {
  24. const fragment = dataProcessor.toDom( '<p>foo</p><p>bar</p>' );
  25. expect( fragment.childNodes.length ).to.equal( 2 );
  26. expect( fragment.childNodes[ 0 ].nodeType ).to.equal( Node.ELEMENT_NODE );
  27. expect( fragment.childNodes[ 0 ].textContent ).to.equal( 'foo' );
  28. expect( fragment.childNodes[ 1 ].nodeType ).to.equal( Node.ELEMENT_NODE );
  29. expect( fragment.childNodes[ 1 ].textContent ).to.equal( 'bar' );
  30. } );
  31. it( 'should return only elements inside body tag', () => {
  32. const fragment = dataProcessor.toDom( '<html><head></head><body><p>foo</p></body></html>' );
  33. expect( fragment.childNodes.length ).to.equal( 1 );
  34. expect( fragment.childNodes[ 0 ].textContent ).to.equal( 'foo' );
  35. expect( fragment.childNodes[ 0 ].tagName.toLowerCase() ).to.equal( 'p' );
  36. } );
  37. it( 'should not add any additional nodes', () => {
  38. const fragment = dataProcessor.toDom( 'foo <b>bar</b> text' );
  39. expect( fragment.childNodes.length ).to.equal( 3 );
  40. expect( fragment.childNodes[ 0 ].nodeType ).to.equal( Node.TEXT_NODE );
  41. expect( fragment.childNodes[ 0 ].textContent ).to.equal( 'foo ' );
  42. expect( fragment.childNodes[ 1 ].nodeType ).to.equal( Node.ELEMENT_NODE );
  43. expect( fragment.childNodes[ 1 ].innerHTML ).to.equal( 'bar' );
  44. expect( fragment.childNodes[ 2 ].nodeType ).to.equal( Node.TEXT_NODE );
  45. expect( fragment.childNodes[ 2 ].textContent ).to.equal( ' text' );
  46. } );
  47. // Test against XSS attacks.
  48. for ( let name in xssTemplates ) {
  49. const input = xssTemplates[ name ].replace( /%xss%/g, 'testXss()' );
  50. it( 'should prevent XSS attacks: ' + name, ( done ) => {
  51. window.testXss = sinon.spy();
  52. dataProcessor.toDom( input );
  53. setTimeout( () => {
  54. sinon.assert.notCalled( window.testXss );
  55. done();
  56. }, 10 );
  57. } );
  58. }
  59. } );
  60. describe( 'toData', () => {
  61. it( 'should use HtmlWriter', () => {
  62. const spy = sinon.spy( dataProcessor._htmlWriter, 'getHtml' );
  63. const fragment = document.createDocumentFragment();
  64. const paragraph = document.createElement( 'p' );
  65. fragment.appendChild( paragraph );
  66. dataProcessor.toData( fragment );
  67. spy.restore();
  68. sinon.assert.calledWithExactly( spy, fragment );
  69. } );
  70. } );
  71. } );