8
0
فهرست منبع

Added more tests (that simulate collaboration).

Kamil Piechaczek 7 سال پیش
والد
کامیت
01f3392434
2فایلهای تغییر یافته به همراه145 افزوده شده و 5 حذف شده
  1. 9 3
      packages/ckeditor5-media-embed/src/automediaembed.js
  2. 136 2
      packages/ckeditor5-media-embed/tests/automediaembed.js

+ 9 - 3
packages/ckeditor5-media-embed/src/automediaembed.js

@@ -11,7 +11,6 @@ import MediaEmbedEditing from './mediaembedediting';
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
 import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
 import LiveRange from '@ckeditor/ckeditor5-engine/src/model/liverange';
 import LiveRange from '@ckeditor/ckeditor5-engine/src/model/liverange';
-import Position from '@ckeditor/ckeditor5-engine/src/model/position';
 import LivePosition from '@ckeditor/ckeditor5-engine/src/model/liveposition';
 import LivePosition from '@ckeditor/ckeditor5-engine/src/model/liveposition';
 import TreeWalker from '@ckeditor/ckeditor5-engine/src/model/treewalker';
 import TreeWalker from '@ckeditor/ckeditor5-engine/src/model/treewalker';
 import Undo from '@ckeditor/ckeditor5-undo/src/undo';
 import Undo from '@ckeditor/ckeditor5-undo/src/undo';
@@ -121,7 +120,7 @@ export default class AutoMediaEmbed extends Plugin {
 		}
 		}
 
 
 		// Positions won't be available in `setTimeout` function so let's clone it.
 		// Positions won't be available in `setTimeout` function so let's clone it.
-		const positionToInsert = Position.createFromPosition( leftPosition );
+		const positionToInsert = LivePosition.createFromPosition( leftPosition );
 
 
 		// This action mustn't be executed if undo was called between pasting and auto-embedding.
 		// This action mustn't be executed if undo was called between pasting and auto-embedding.
 		this._timeoutId = global.window.setTimeout( () => {
 		this._timeoutId = global.window.setTimeout( () => {
@@ -129,8 +128,15 @@ export default class AutoMediaEmbed extends Plugin {
 				this._timeoutId = null;
 				this._timeoutId = null;
 
 
 				writer.remove( urlRange );
 				writer.remove( urlRange );
-				writer.setSelection( positionToInsert );
+
+				// Check if position where the media element should be inserted is still valid.
+				if ( positionToInsert.root.rootName !== '$graveyard' ) {
+					writer.setSelection( positionToInsert );
+				}
+
 				editor.commands.execute( 'mediaEmbed', url );
 				editor.commands.execute( 'mediaEmbed', url );
+
+				positionToInsert.detach();
 			} );
 			} );
 		}, 100 );
 		}, 100 );
 	}
 	}

+ 136 - 2
packages/ckeditor5-media-embed/tests/automediaembed.js

@@ -15,6 +15,8 @@ import List from '@ckeditor/ckeditor5-list/src/list';
 import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
 import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
 import Undo from '@ckeditor/ckeditor5-undo/src/undo';
 import Undo from '@ckeditor/ckeditor5-undo/src/undo';
 import Typing from '@ckeditor/ckeditor5-typing/src/typing';
 import Typing from '@ckeditor/ckeditor5-typing/src/typing';
+import ModelRange from '@ckeditor/ckeditor5-engine/src/model/range';
+import ModelPosition from '@ckeditor/ckeditor5-engine/src/model/position';
 import global from '@ckeditor/ckeditor5-utils/src/dom/global';
 import global from '@ckeditor/ckeditor5-utils/src/dom/global';
 import { getData, setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 import { getData, setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 
 
@@ -327,8 +329,10 @@ describe( 'AutoMediaEmbed - integration', () => {
 		} );
 		} );
 	} );
 	} );
 
 
-	describe( 'real timers', () => {
-		it( 'undo breaks the auto-media embed feature', done => {
+	describe( 'use real timers', () => {
+		const characters = Array( 10 ).fill( 1 ).map( ( x, i ) => String.fromCharCode( 65 + i ) );
+
+		it( 'undo breaks the auto-media embed feature (undo was done before auto-media embed)', done => {
 			setData( editor.model, '<paragraph>[]</paragraph>' );
 			setData( editor.model, '<paragraph>[]</paragraph>' );
 			pasteHtml( editor, 'https://www.youtube.com/watch?v=H08tGjXNHO4' );
 			pasteHtml( editor, 'https://www.youtube.com/watch?v=H08tGjXNHO4' );
 
 
@@ -371,6 +375,136 @@ describe( 'AutoMediaEmbed - integration', () => {
 				done();
 				done();
 			}, 100 );
 			}, 100 );
 		} );
 		} );
+
+		it( 'typing before pasted link during collaboration should not blow up', done => {
+			setData( editor.model, '<paragraph>[]</paragraph>' );
+
+			pasteHtml( editor, 'https://www.youtube.com/watch?v=H08tGjXNHO4' );
+
+			for ( let i = 0; i < 10; ++i ) {
+				const rootEl = editor.model.document.getRoot();
+
+				setTimeout( () => {
+					editor.model.enqueueChange( 'transparent', writer => {
+						writer.insertText( characters[ i ], new ModelPosition( rootEl, [ 0, i ] ) );
+					} );
+				}, i * 9 );
+			}
+
+			setTimeout( () => {
+				expect( getData( editor.model ) ).to.equal(
+					'<paragraph>ABCDEFGHIJ</paragraph>[<media url="https://www.youtube.com/watch?v=H08tGjXNHO4"></media>]'
+				);
+
+				done();
+			}, 100 );
+		} );
+
+		it( 'typing after pasted link during collaboration should not blow up', done => {
+			setData( editor.model, '<paragraph>[]</paragraph>' );
+
+			pasteHtml( editor, 'https://www.youtube.com/watch?v=H08tGjXNHO4' );
+
+			for ( let i = 0; i < 10; ++i ) {
+				setTimeout( () => {
+					editor.model.enqueueChange( 'transparent', writer => {
+						writer.insertText( characters[ i ], editor.model.document.selection.getFirstPosition() );
+					} );
+				}, i * 9 );
+			}
+
+			setTimeout( () => {
+				expect( getData( editor.model ) ).to.equal(
+					'<paragraph>ABCDEFGHIJ</paragraph>[<media url="https://www.youtube.com/watch?v=H08tGjXNHO4"></media>]'
+				);
+
+				done();
+			}, 100 );
+		} );
+
+		it( 'should insert the media element even if parent element where the URL was pasted has been deleted', done => {
+			setData( editor.model, '<paragraph>Foo.</paragraph><paragraph>Bar.[]</paragraph>' );
+
+			pasteHtml( editor, 'https://www.youtube.com/watch?v=H08tGjXNHO4' );
+
+			editor.model.enqueueChange( 'transparent', writer => {
+				writer.remove( ModelRange.createOn( editor.model.document.getRoot().getChild( 1 ) ) );
+			} );
+
+			setTimeout( () => {
+				expect( getData( editor.model ) ).to.equal(
+					'<paragraph>Foo.</paragraph>[<media url="https://www.youtube.com/watch?v=H08tGjXNHO4"></media>]'
+				);
+
+				done();
+			}, 100 );
+		} );
+
+		it( 'should insert the media element even if new element appeared above the pasted URL', done => {
+			setData( editor.model, '<paragraph>Foo.</paragraph><paragraph>Bar.[]</paragraph>' );
+
+			pasteHtml( editor, 'https://www.youtube.com/watch?v=H08tGjXNHO4' );
+
+			editor.model.enqueueChange( 'transparent', writer => {
+				const paragraph = writer.createElement( 'paragraph' );
+				writer.insert( paragraph, ModelPosition.createAfter( editor.model.document.getRoot().getChild( 0 ) ) );
+				writer.setSelection( paragraph, 'in' );
+			} );
+
+			setTimeout( () => {
+				for ( let i = 0; i < 10; ++i ) {
+					setTimeout( () => {
+						editor.model.enqueueChange( 'transparent', writer => {
+							writer.insertText( characters[ i ], editor.model.document.selection.getFirstPosition() );
+						} );
+					}, i * 9 );
+				}
+			} );
+
+			setTimeout( () => {
+				expect( getData( editor.model ) ).to.equal(
+					'<paragraph>Foo.</paragraph>' +
+					'<paragraph>ABCDEFGHIJ</paragraph>' +
+					'<paragraph>Bar.</paragraph>' +
+					'[<media url="https://www.youtube.com/watch?v=H08tGjXNHO4"></media>]'
+				);
+
+				done();
+			}, 100 );
+		} );
+
+		it( 'should insert the media element even if new element appeared below the pasted URL', done => {
+			setData( editor.model, '<paragraph>Foo.</paragraph><paragraph>Bar.[]</paragraph>' );
+
+			pasteHtml( editor, 'https://www.youtube.com/watch?v=H08tGjXNHO4' );
+
+			editor.model.enqueueChange( 'transparent', writer => {
+				const paragraph = writer.createElement( 'paragraph' );
+				writer.insert( paragraph, ModelPosition.createAfter( editor.model.document.getRoot().getChild( 1 ) ) );
+				writer.setSelection( paragraph, 'in' );
+			} );
+
+			setTimeout( () => {
+				for ( let i = 0; i < 10; ++i ) {
+					setTimeout( () => {
+						editor.model.enqueueChange( 'transparent', writer => {
+							writer.insertText( characters[ i ], editor.model.document.selection.getFirstPosition() );
+						} );
+					}, i * 9 );
+				}
+			} );
+
+			setTimeout( () => {
+				expect( getData( editor.model ) ).to.equal(
+					'<paragraph>Foo.</paragraph>' +
+					'<paragraph>Bar.</paragraph>' +
+					'[<media url="https://www.youtube.com/watch?v=H08tGjXNHO4"></media>]' +
+					'<paragraph>ABCDEFGHIJ</paragraph>'
+				);
+
+				done();
+			}, 100 );
+		} );
 	} );
 	} );
 
 
 	function simulateTyping( text ) {
 	function simulateTyping( text ) {