import { ClassicEditor } from '@ckeditor/ckeditor5-editor-classic'; import { Essentials } from '@ckeditor/ckeditor5-essentials'; import { Paragraph } from '@ckeditor/ckeditor5-paragraph'; import { Heading } from '@ckeditor/ckeditor5-heading'; import { CodeBlockEditing } from '@ckeditor/ckeditor5-code-block'; import { _setModelData as setModelData, _getModelData as getModelData, _getViewData as getViewData } from '@ckeditor/ckeditor5-engine'; import MermaidEditing from '../src/mermaidediting.js'; /* global document */ describe( 'MermaidEditing', () => { it( 'should be named', () => { expect( MermaidEditing.pluginName ).to.equal( 'MermaidEditing' ); } ); describe( 'conversion', () => { let domElement, editor, model; beforeEach( async () => { domElement = document.createElement( 'div' ); document.body.appendChild( domElement ); editor = await ClassicEditor.create( domElement, { plugins: [ Paragraph, Heading, Essentials, CodeBlockEditing, MermaidEditing ] } ); model = editor.model; } ); afterEach( () => { domElement.remove(); return editor.destroy(); } ); describe( 'conversion', () => { describe( 'upcast', () => { it( 'works correctly', () => { editor.setData( '
' +
							'flowchart TB\nA --> B\nB --> C' +
						''
					);
					expect( getModelData( model, { withoutSelection: true } ) ).to.equal(
						'' +
							''
					);
					expect( getModelData( model, { withoutSelection: true } ) ).to.equal(
						'' +
							'flowchart TB\nA --> B\nB --> C' +
						''
					);
					expect( editor.getData() ).to.equal(
						'' +
							'flowchart TB\nA --> B\nB --> C' +
						''
					);
				} );
				it( 'works correctly when empty ', () => {
					// Using editor.setData() instead of setModelData helper because of #11365.
					editor.setData(
						'' +
							''
					);
					expect( editor.getData() ).to.equal(
						'' +
							''
					);
				} );
			} );
			describe( 'editing downcast', () => {
				it( 'works correctly without displayMode attribute', () => {
					// Using editor.setData() instead of setModelData helper because of #11365.
					editor.setData(
						'' +
							'flowchart TB\nA --> B\nB --> C' +
						''
					);
					expect( getViewData( editor.editing.view, { withoutSelection: true } ) ).to.equal(
						''
					);
				} );
				it( 'works correctly with displayMode attribute', () => {
					setModelData( editor.model,
						'' +
							'flowchart TB\nA --> B\nB --> C' +
							''
						);
						const textareaView = editor.editing.view.document.getRoot().getChild( 0 ).getChild( 1 );
						domTextarea = editor.editing.view.domConverter.viewToDom( textareaView );
					} );
					it( 'is properly set during the initial conversion', () => {
						expect( domTextarea.value ).to.equal( 'flowchart TB\nA --> B\nB --> C' );
					} );
					it( 'is properly updated after model\'s attribute change', () => {
						const { model } = editor;
						const mermaidModel = model.document.getRoot().getChild( 0 );
						model.change( writer => {
							writer.setAttribute( 'source', 'abc', mermaidModel );
						} );
						expect( domTextarea.value ).to.equal( 'abc' );
					} );
					it( 'doesn\'t loop if model attribute changes to the same value', () => {
						const { model } = editor;
						const mermaidModel = model.document.getRoot().getChild( 0 );
						model.change( writer => {
							writer.setAttribute( 'source', 'flowchart TB\nA --> B\nB --> C', mermaidModel );
						} );
						expect( domTextarea.value ).to.equal( 'flowchart TB\nA --> B\nB --> C' );
					} );
				} );
				describe( 'preview div', () => {
					let domPreviewContainer, renderMermaidStub;
					beforeEach( () => {
						// Using editor.setData() instead of setModelData helper because of #11365.
						editor.setData(
							'' +
							'flowchart TB\nA --> B\nB --> C' +
							''
						);
						const previewContainerView = editor.editing.view.document.getRoot().getChild( 0 ).getChild( 2 );
						domPreviewContainer = editor.editing.view.domConverter.viewToDom( previewContainerView );
						renderMermaidStub = sinon.stub( editor.plugins.get( 'MermaidEditing' ), '_renderMermaid' );
					} );
					afterEach( () => {
						renderMermaidStub.restore();
					} );
					it( 'has proper inner text set during the initial conversion', () => {
						expect( domPreviewContainer.textContent ).to.equal( 'flowchart TB\nA --> B\nB --> C' );
					} );
					it( 'has proper inner text set after a model\'s attribute change', () => {
						const { model } = editor;
						const mermaidModel = model.document.getRoot().getChild( 0 );
						model.change( writer => {
							writer.setAttribute( 'source', 'abc', mermaidModel );
						} );
						expect( domPreviewContainer.textContent ).to.equal( 'abc' );
					} );
					it( 'calls mermaid render function after a model\'s attribute change', () => {
						const { model } = editor;
						const mermaidModel = model.document.getRoot().getChild( 0 );
						model.change( writer => {
							writer.setAttribute( 'source', 'abc', mermaidModel );
						} );
						expect( renderMermaidStub.callCount ).to.equal( 1 );
						sinon.assert.calledWithExactly( renderMermaidStub, domPreviewContainer );
					} );
				} );
			} );
			it( 'adds a editing pipeline converter that has a precedence over code block', () => {
				setModelData( editor.model, '