/** * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ import DocumentFragment from '../../src/view/documentfragment'; import Element from '../../src/view/element'; import Text from '../../src/view/text'; import UpcastWriter from '../../src/view/upcastwriter'; import HtmlDataProcessor from '../../src/dataprocessor/htmldataprocessor'; import ViewPosition from '../../src/view/position'; import ViewRange from '../../src/view/range'; import ViewSelection from '../../src/view/selection'; import Document from '../../src/view/document'; import { StylesProcessor } from '../../src/view/stylesmap'; describe( 'UpcastWriter', () => { let writer, view, dataprocessor, document; beforeEach( () => { document = new Document( new StylesProcessor() ); writer = new UpcastWriter( document ); dataprocessor = new HtmlDataProcessor( document ); const html = '' + '
Some underlined text
' + 'foo
fooexamplebar
' ); const span = documentFragment.getChild( 0 ).getChild( 0 ); writer.unwrapElement( span ); expect( dataprocessor.toData( documentFragment ) ).to.equal( 'fooexamplebar
' ); } ); it( 'should do nothing for elements without parent', () => { const element = new Element( document, 'p', null, 'foo' ); writer.unwrapElement( element ); expect( dataprocessor.toData( element ) ).to.equal( 'foo
' ); } ); } ); describe( 'rename', () => { it( 'should rename simple element', () => { const el = view.getChild( 0 ).getChild( 1 ); const renamed = writer.rename( 'i', el ); expect( renamed ).to.not.equal( el ); expect( renamed ).to.equal( view.getChild( 0 ).getChild( 1 ) ); expect( renamed.name ).to.equal( 'i' ); expect( view.getChild( 0 ).childCount ).to.equal( 2 ); } ); it( 'should rename direct root (DocumentFragment) child element', () => { const el = view.getChild( 1 ); const renamed = writer.rename( 'h3', el ); expect( renamed ).to.not.equal( el ); expect( renamed ).to.equal( view.getChild( 1 ) ); expect( renamed.name ).to.equal( 'h3' ); expect( view.childCount ).to.equal( 4 ); } ); it( 'should have no effect on detached element', () => { const el = new Element( document, 'h2' ); const renamed = writer.rename( 'h3', el ); expect( renamed ).to.null; expect( view.childCount ).to.equal( 4 ); } ); } ); describe( 'setAttribute', () => { it( 'should add new attribute', () => { const el = view.getChild( 0 ); writer.setAttribute( 'testAttr', 'testVal', el ); expect( el.getAttribute( 'testAttr' ) ).to.equal( 'testVal' ); } ); it( 'should update existing attribute', () => { const el = view.getChild( 1 ); writer.setAttribute( 'data-attr', 'foo', el ); expect( el.getAttribute( 'data-attr' ) ).to.equal( 'foo' ); } ); } ); describe( 'removeAttribute', () => { it( 'should remove existing attribute', () => { const el = view.getChild( 1 ); writer.removeAttribute( 'data-attr', el ); expect( el.hasAttribute( 'data-attr' ) ).to.false; } ); it( 'should have no effect if attribute does not exists', () => { const el = view.getChild( 0 ); writer.removeAttribute( 'non-existent', el ); expect( el.hasAttribute( 'non-existent' ) ).to.false; } ); } ); describe( 'addClass', () => { it( 'should add new classes if no classes', () => { const el = view.getChild( 2 ); writer.addClass( [ 'foo', 'bar' ], el ); expect( el.hasClass( 'foo' ) ).to.true; expect( el.hasClass( 'bar' ) ).to.true; expect( Array.from( el.getClassNames() ).length ).to.equal( 2 ); } ); it( 'should add new class to existing classes', () => { const el = view.getChild( 1 ); writer.addClass( 'newClass', el ); expect( el.hasClass( 'newClass' ) ).to.true; expect( Array.from( el.getClassNames() ).length ).to.equal( 3 ); } ); } ); describe( 'removeClass', () => { it( 'should remove existing class', () => { const el = view.getChild( 3 ).getChild( 0 ); writer.removeClass( 'single', el ); expect( el.hasClass( 'single' ) ).to.false; expect( Array.from( el.getClassNames() ).length ).to.equal( 0 ); } ); it( 'should remove existing class from many classes', () => { const el = view.getChild( 1 ); writer.removeClass( 'foo1', el ); expect( el.hasClass( 'foo1' ) ).to.false; expect( el.hasClass( 'bar2' ) ).to.true; expect( Array.from( el.getClassNames() ).length ).to.equal( 1 ); } ); it( 'should have no effect if there are no classes', () => { const el = view.getChild( 0 ); writer.removeClass( 'non-existent', el ); expect( el.hasClass( 'non-existent' ) ).to.false; expect( Array.from( el.getClassNames() ).length ).to.equal( 0 ); } ); } ); describe( 'setStyle', () => { it( 'should add new style', () => { const el = view.getChild( 2 ); writer.setStyle( { color: 'red', position: 'fixed' }, el ); expect( el.getStyle( 'color' ) ).to.equal( 'red' ); expect( el.getStyle( 'position' ) ).to.equal( 'fixed' ); expect( Array.from( el.getStyleNames() ).length ).to.equal( 2 ); } ); it( 'should update existing styles', () => { const el = view.getChild( 1 ); writer.setStyle( 'text-align', 'center', el ); expect( el.getStyle( 'text-align' ) ).to.equal( 'center' ); expect( Array.from( el.getStyleNames() ).length ).to.equal( 1 ); } ); } ); describe( 'removeStyle', () => { it( 'should remove existing style', () => { const el = view.getChild( 0 ); writer.removeStyle( [ 'color', 'position' ], el ); expect( el.hasStyle( 'color' ) ).to.be.false; expect( el.hasStyle( 'position' ) ).to.be.false; expect( Array.from( el.getStyleNames() ).length ).to.equal( 0 ); } ); it( 'should remove value from existing styles', () => { const el = view.getChild( 0 ); writer.removeStyle( 'position', el ); expect( el.hasStyle( 'color' ) ).to.true; expect( el.hasStyle( 'position' ) ).to.false; expect( Array.from( el.getStyleNames() ).length ).to.equal( 1 ); } ); it( 'should have no effect if styles does not exists', () => { const el = view.getChild( 2 ); writer.removeStyle( [ 'color', 'position' ], el ); expect( el.hasStyle( 'color' ) ).to.false; expect( el.hasStyle( 'position' ) ).to.false; expect( Array.from( el.getStyleNames() ).length ).to.equal( 0 ); } ); } ); describe( 'setCustomProperty', () => { it( 'should add or update custom property', () => { const el = new Element( 'span' ); writer.setCustomProperty( 'prop1', 'foo', el ); writer.setCustomProperty( 'prop2', 'bar', el ); expect( el.getCustomProperty( 'prop1' ) ).to.equal( 'foo' ); expect( el.getCustomProperty( 'prop2' ) ).to.equal( 'bar' ); expect( Array.from( el.getCustomProperties() ).length ).to.equal( 2 ); const objectProperty = { foo: 'bar' }; writer.setCustomProperty( 'prop2', objectProperty, el ); expect( el.getCustomProperty( 'prop1' ) ).to.equal( 'foo' ); expect( el.getCustomProperty( 'prop2' ) ).to.equal( objectProperty ); expect( Array.from( el.getCustomProperties() ).length ).to.equal( 2 ); } ); } ); describe( 'removeCustomProperty', () => { it( 'should remove existing custom property', () => { const el = new Element( 'p' ); writer.setCustomProperty( 'prop1', 'foo', el ); expect( el.getCustomProperty( 'prop1' ) ).to.equal( 'foo' ); expect( Array.from( el.getCustomProperties() ).length ).to.equal( 1 ); writer.removeCustomProperty( 'prop1', el ); expect( el.getCustomProperty( 'prop1' ) ).to.undefined; expect( Array.from( el.getCustomProperties() ).length ).to.equal( 0 ); } ); it( 'should have no effect if custom property does not exists', () => { const el = new Element( 'h1' ); writer.removeCustomProperty( 'prop1', el ); expect( el.getCustomProperty( 'prop1' ) ).to.undefined; expect( Array.from( el.getCustomProperties() ).length ).to.equal( 0 ); } ); } ); describe( 'createPositionAt()', () => { it( 'should return instance of Position', () => { const span = new Element( document, 'span' ); expect( writer.createPositionAt( span, 0 ) ).to.be.instanceof( ViewPosition ); } ); } ); describe( 'createPositionAfter()', () => { it( 'should return instance of Position', () => { const span = new Element( document, 'span', undefined, new Element( document, 'span' ) ); expect( writer.createPositionAfter( span.getChild( 0 ) ) ).to.be.instanceof( ViewPosition ); } ); } ); describe( 'createPositionBefore()', () => { it( 'should return instance of Position', () => { const span = new Element( document, 'span', undefined, new Element( document, 'span' ) ); expect( writer.createPositionBefore( span.getChild( 0 ) ) ).to.be.instanceof( ViewPosition ); } ); } ); describe( 'createRange()', () => { it( 'should return instance of Range', () => { expect( writer.createRange( writer.createPositionAt( new Element( document, 'span' ), 0 ) ) ).to.be.instanceof( ViewRange ); } ); } ); describe( 'createRangeIn()', () => { it( 'should return instance of Range', () => { const span = new Element( document, 'span', undefined, new Element( document, 'span' ) ); expect( writer.createRangeIn( span.getChild( 0 ) ) ).to.be.instanceof( ViewRange ); } ); } ); describe( 'createRangeOn()', () => { it( 'should return instance of Range', () => { const span = new Element( document, 'span', undefined, new Element( document, 'span' ) ); expect( writer.createRangeOn( span.getChild( 0 ) ) ).to.be.instanceof( ViewRange ); } ); } ); describe( 'createSelection()', () => { it( 'should return instance of Selection', () => { expect( writer.createSelection() ).to.be.instanceof( ViewSelection ); } ); } ); } );