import { Client, syncClients, expectClients } from './utils.js'; describe( 'transform', () => { let john, kate; beforeEach( () => { return Promise.all( [ Client.get( 'john' ).then( client => ( john = client ) ), Client.get( 'kate' ).then( client => ( kate = client ) ) ] ); } ); afterEach( () => { return Promise.all( [ john.destroy(), kate.destroy() ] ); } ); describe( 'move', () => { describe( 'by move', () => { it( 'elements in different paths', () => { john.setData( '[Foo]Bar' ); kate.setData( 'Foo[Bar]' ); john.move( [ 2 ] ); kate.move( [ 0 ] ); syncClients(); expectClients( 'Bar' + 'Foo' ); } ); it( 'text in same path #1', () => { john.setData( '[Foo] Bar' ); kate.setData( 'Foo [Bar]' ); john.move( [ 0, 4 ] ); kate.move( [ 0, 0 ] ); syncClients(); expectClients( 'Bar Foo' ); } ); it( 'text in same path #2', () => { john.setData( 'F[oo] Bar' ); kate.setData( 'Foo B[ar]' ); john.move( [ 0, 0 ] ); kate.move( [ 0, 4 ] ); syncClients(); expectClients( 'ooF arB' ); } ); it( 'text in same path #3', () => { john.setData( 'Foo [Bar]' ); kate.setData( 'Foo [Bar]' ); john.move( [ 0, 0 ] ); kate.move( [ 0, 0 ] ); syncClients(); expectClients( 'BarFoo ' ); } ); it( 'text in same path #4', () => { john.setData( 'F[oo] Bar' ); kate.setData( 'Foo B[ar]' ); john.move( [ 0, 6 ] ); kate.move( [ 0, 2 ] ); syncClients(); expectClients( 'Foo Bar' ); } ); it( 'text at different paths #1', () => { john.setData( 'F[oo]Bar' ); kate.setData( 'FooB[ar]' ); john.move( [ 0, 0 ] ); kate.move( [ 1, 0 ] ); syncClients(); expectClients( 'ooFarB' ); } ); it( 'text in different paths #2', () => { john.setData( '[Foo]Bar' ); kate.setData( 'Foo[Bar]' ); john.move( [ 1, 0 ] ); kate.move( [ 0, 0 ] ); syncClients(); expectClients( 'BarFoo' ); } ); it( 'text in different paths #3', () => { john.setData( 'F[oo]
Bar
' ); kate.setData( 'Foo
B[ar]
' ); john.move( [ 1, 0, 0 ] ); kate.move( [ 0, 0 ] ); syncClients(); expectClients( 'arF' + '
' + 'ooB' + '
' ); } ); it( 'text inside other client\'s range #1', () => { john.setData( 'F[oo Ba]r' ); kate.setData( 'Fo[o B]ar' ); john.move( [ 0, 0 ] ); kate.move( [ 0, 7 ] ); syncClients(); expectClients( 'oo BaFr' ); } ); it( 'text inside other client\'s range #2', () => { john.setData( 'F[oo Ba]r' ); kate.setData( 'Fo[o B]ar' ); john.move( [ 0, 0 ] ); kate.move( [ 0, 2 ] ); syncClients(); expectClients( 'oo BaFr' ); } ); it( 'text inside other client\'s range #3', () => { john.setData( 'F[oo Ba]r' ); kate.setData( '[Foo B]ar' ); john.move( [ 0, 0 ] ); kate.move( [ 0, 7 ] ); syncClients(); expectClients( 'oo BarF' ); } ); } ); describe( 'by wrap', () => { it( 'element in different path', () => { john.setData( 'F[oo]Bar' ); kate.setData( 'Foo[Bar]' ); john.move( [ 0, 0 ] ); kate.wrap( 'blockQuote' ); syncClients(); expectClients( 'ooF' + '
' + 'Bar' + '
' ); } ); it( 'element in different path #2', () => { john.setData( '[Foo]Bar' ); kate.setData( 'Foo[Bar]' ); john.move( [ 1, 0 ] ); kate.wrap( 'blockQuote' ); syncClients(); expectClients( '' + '
' + 'FooBar' + '
' ); } ); it( 'element in same path', () => { john.setData( 'F[oo]' ); kate.setData( '[Foo]' ); john.move( [ 0, 0 ] ); kate.wrap( 'blockQuote' ); syncClients(); expectClients( '
' + 'ooF' + '
' ); } ); it( 'element while moving', () => { john.setData( '[Foo]Bar' ); kate.setData( '[Foo]Bar' ); john.move( [ 2 ] ); kate.wrap( 'blockQuote' ); syncClients(); expectClients( 'Bar' + '
' + 'Foo' + '
' ); } ); it( 'intersecting wrap', () => { john.setData( 'F[oo]Bar' ); kate.setData( '[Foo]Bar' ); john.move( [ 1, 0 ] ); kate.wrap( 'div' ); syncClients(); expectClients( '
F
' + 'ooBar' ); } ); } ); describe( 'by unwrap', () => { it( 'element in different path #1', () => { john.setData( 'F[oo]
Bar
' ); kate.setData( 'Foo
[Bar]
' ); john.move( [ 0, 0 ] ); kate.unwrap(); syncClients(); expectClients( 'ooF' + 'Bar' ); } ); it( 'element in different path #2', () => { john.setData( '[Foo]
Bar
' ); kate.setData( 'Foo
[Bar]
' ); john.move( [ 1, 0, 0 ] ); kate.unwrap(); syncClients(); expectClients( '' + 'FooBar' ); } ); it( 'element in same path', () => { john.setData( '
F[oo]
' ); kate.setData( '
[Foo]
' ); john.move( [ 0, 0, 0 ] ); kate.unwrap(); syncClients(); expectClients( 'ooF' ); } ); } ); describe( 'by split', () => { it( 'text in different path #1', () => { john.setData( 'F[oo]Bar' ); kate.setData( 'FooB[]ar' ); john.move( [ 0, 0 ] ); kate.split(); syncClients(); expectClients( 'ooF' + 'B' + 'ar' ); } ); it( 'text in different path #2', () => { john.setData( '[Foo]Bar' ); kate.setData( 'FooB[]ar' ); john.move( [ 1, 1 ] ); kate.split(); syncClients(); expectClients( '' + 'BFoo' + 'ar' ); } ); it( 'text in same path', () => { john.setData( 'F[oo] Bar' ); kate.setData( 'Foo B[]ar' ); john.move( [ 0, 0 ] ); kate.split(); syncClients(); expectClients( 'ooF B' + 'ar' ); } ); it( 'text in other user\'s selection', () => { john.setData( '[Foo] Bar' ); kate.setData( 'F[]oo Bar' ); john.move( [ 0, 4 ] ); kate.split(); syncClients(); expectClients( '' + ' FooBar' ); } ); it( 'moved element', () => { john.setData( 'Foo[Bar]' ); kate.setData( 'FooBa[]r' ); john.move( [ 0 ] ); kate.split(); syncClients(); expectClients( 'Ba' + 'r' + 'Foo' ); } ); it( 'inside moved text', () => { john.setData( 'F[oo Ba]rAbc' ); kate.setData( 'Foo[] BarAbc' ); john.move( [ 1, 0 ] ); kate.split(); syncClients(); expectClients( 'F' + 'r' + 'oo BaAbc' ); } ); } ); describe( 'by remove', () => { it( 'text in same path #1', () => { john.setData( '[Foo] Bar' ); kate.setData( 'Foo [Bar]' ); john.move( [ 0, 4 ] ); kate.remove(); syncClients(); expectClients( ' Foo' ); } ); it( 'text in same path #2', () => { john.setData( 'F[oo] Bar' ); kate.setData( 'Foo B[ar]' ); john.move( [ 0, 0 ] ); kate.remove(); syncClients(); expectClients( 'ooF B' ); } ); it( 'text in same path #3', () => { john.setData( 'Foo [Bar]' ); kate.setData( 'Foo [Bar]' ); john.move( [ 0, 0 ] ); kate.remove(); syncClients(); expectClients( 'Foo ' ); } ); it( 'text at different paths #1', () => { john.setData( 'F[oo]Bar' ); kate.setData( 'FooB[ar]' ); john.move( [ 0, 0 ] ); kate.remove(); syncClients(); expectClients( 'ooFB' ); } ); it( 'text in different paths #2', () => { john.setData( '[Foo]Bar' ); kate.setData( 'Foo[Bar]' ); john.move( [ 1, 0 ] ); kate.remove(); syncClients(); expectClients( 'Foo' ); } ); it( 'text in different paths #3', () => { john.setData( 'F[oo]
Bar
' ); kate.setData( 'Foo
B[ar]
' ); john.move( [ 1, 0, 0 ] ); kate.remove(); syncClients(); expectClients( 'F' + '
' + 'ooB' + '
' ); } ); it( 'text in other user\'s selection, then undo', () => { john.setData( 'Fo[o B]ar' ); kate.setData( '[Foo B]ar' ); john.move( [ 0, 0 ] ); kate.remove(); syncClients(); john.undo(); kate.undo(); syncClients(); expectClients( 'Foo Bar' ); } ); } ); describe( 'by merge', () => { it( 'element into paragraph #1', () => { john.setData( 'F[oo]Bar' ); kate.setData( 'Foo[]Bar' ); john.move( [ 0, 0 ] ); kate.merge(); syncClients(); expectClients( 'ooFBar' ); } ); it( 'element into paragraph #2', () => { john.setData( 'FooB[ar]' ); kate.setData( 'Foo[]Bar' ); john.move( [ 0, 0 ] ); kate.merge(); syncClients(); expectClients( 'arFooB' ); } ); it( 'element into paragraph #3', () => { john.setData( 'F[oo]Bar' ); kate.setData( 'Foo[]Bar' ); john.move( [ 1, 0 ] ); kate.merge(); syncClients(); expectClients( 'FooBar' ); } ); it( 'wrapped element into wrapped paragraph #1', () => { john.setData( '
F[oo]Bar
' ); kate.setData( '
Foo[]Bar
' ); john.move( [ 0, 0, 0 ] ); kate.merge(); syncClients(); expectClients( '
ooFBar
' ); } ); it( 'wrapped element into wrapped paragraph #2', () => { john.setData( '
FooB[ar]
' ); kate.setData( '
Foo[]Bar
' ); john.move( [ 0, 0, 0 ] ); kate.merge(); syncClients(); expectClients( '
arFooB
' ); } ); it( 'wrapped element into wrapped paragraph #3', () => { john.setData( '
F[oo]Bar
' ); kate.setData( '
Foo[]Bar
' ); john.move( [ 0, 1, 0 ] ); kate.merge(); syncClients(); expectClients( '
FooBar
' ); } ); it( 'moved element', () => { john.setData( 'Foo[Bar]' ); kate.setData( 'Foo[]Bar' ); john.move( [ 0 ] ); kate.merge(); syncClients(); expectClients( 'FooBar' ); } ); it( 'moved element, then undo', () => { john.setData( 'Foo[Bar]' ); kate.setData( 'Foo[]Bar' ); john.move( [ 0 ] ); kate.merge(); syncClients(); expectClients( 'FooBar' ); john.undo(); syncClients(); expectClients( 'FooBar' ); } ); } ); describe( 'by remove attribute', () => { it( 'from element in different path', () => { john.setData( 'F[oo]Bar' ); kate.setData( 'Foo[Bar]' ); john.move( [ 1, 0 ] ); kate.removeAttribute( 'bold' ); syncClients(); expectClients( 'F' + 'ooBar' ); } ); it( 'from text in different path', () => { john.setData( 'F[oo]Bar' ); kate.setData( 'Foo[Bar]' ); john.move( [ 1, 0 ] ); kate.removeAttribute( 'bold' ); syncClients(); expectClients( 'F' + 'ooBar' ); } ); it( 'from text in same path', () => { john.setData( '[Fo]<$text bold="true">o' ); kate.setData( 'Fo<$text bold="true">[o]' ); john.move( [ 0, 3 ] ); kate.removeAttribute( 'bold' ); syncClients(); expectClients( 'oFo' ); } ); it( 'from element in same path', () => { john.setData( '[Fo]o' ); kate.setData( '[Foo]' ); john.move( [ 0, 3 ] ); kate.removeAttribute( 'bold' ); syncClients(); expectClients( 'oFo' ); } ); it( 'from text with 2 attributes in same path', () => { john.setData( '[Fo]<$text bold="true" italic="true">o' ); kate.setData( 'Fo<$text bold="true" italic="true">[o]' ); john.move( [ 0, 3 ] ); kate.removeAttribute( 'bold' ); syncClients(); expectClients( '<$text italic="true">oFo' ); } ); it( 'from text in other user\'s selection', () => { john.setData( '<$text bold="true">[Foo]' ); kate.setData( '<$text bold="true">[Foo]' ); john.move( [ 1, 0 ] ); kate.removeAttribute( 'bold' ); syncClients(); expectClients( '' + 'Foo' ); } ); } ); describe( 'by rename', () => { it( 'element in different path #1', () => { john.setData( 'FooB[ar]' ); kate.setData( '[]FooBar' ); john.move( [ 1, 0 ] ); kate.rename( 'heading1' ); syncClients(); expectClients( 'FooarB' ); } ); it( 'element in different path #2', () => { john.setData( '
Foo[Bar]
' ); kate.setData( '
[]FooBar
' ); john.move( [ 0, 0, 0 ] ); kate.rename( 'blockQuote2' ); syncClients(); expectClients( '' + 'BarFoo' + '' + '' ); } ); it( 'element in different path #3', () => { john.setData( '
[Foo]Bar
' ); kate.setData( '
[]FooBar
' ); john.move( [ 0, 1, 0 ] ); kate.rename( 'heading1' ); syncClients(); expectClients( '
' + '' + 'FooBar' + '
' ); } ); it( 'element in same path', () => { john.setData( 'Foo [Bar]' ); kate.setData( '[]Foo Bar' ); john.move( [ 0, 0 ] ); kate.rename( 'heading1' ); syncClients(); expectClients( 'BarFoo ' ); } ); } ); } ); } );