import { strict as assert } from "assert" ; import { createInsertSegmentOp , createRemoveRangeOp } from "../opBuilder" ; import { TextSegment } from "../textSegment" ; import { TestClient } from "./testClient" ; describe ( "MergeTree.markRangeRemoved" , ( ) => { let client ; beforeEach ( ( ) => { client = new TestClient ( ) ; client . startOrUpdateCollaboration ( "local" ) ; for ( const char of "hello world" ) { client . applyMsg ( client . makeOpMessage ( client . insertTextLocal ( client . getLength ( ) , char ) , client . getCurrentSeq ( ) + 1 ) ) ; } assert . equal ( client . getText ( ) , "hello world" ) ; } ) ; it ( "local remove followed by local insert" , ( ) => { client . removeRangeLocal ( 0 , client . getLength ( ) ) ; assert . equal ( client . getText ( ) , "" ) ; client . insertTextLocal ( 0 , "text" ) ; assert . equal ( client . getText ( ) , "text" ) ; } ) ; it ( "local insert followed by local remove" , ( ) => { client . insertTextLocal ( 0 , "text" ) ; assert . equal ( client . getText ( ) , "texthello world" ) ; client . removeRangeLocal ( 0 , client . getLength ( ) ) ; assert . equal ( client . getText ( ) , "" ) ; } ) ; it ( "remote remove followed by local insert" , ( ) => { client . applyMsg ( client . makeOpMessage ( createRemoveRangeOp ( 0 , client . getLength ( ) ) , client . mergeTree . collabWindow . currentSeq + 1 , client . mergeTree . collabWindow . currentSeq , "remote" ) ) ; assert . equal ( client . getText ( ) , "" ) ; client . insertTextLocal ( 0 , "text" ) ; assert . equal ( client . getText ( ) , "text" ) ; } ) ; it ( "local remove followed by remote insert" , ( ) => { client . removeRangeLocal ( 0 , client . getLength ( ) ) ; assert . equal ( client . getText ( ) , "" ) ; client . applyMsg ( client . makeOpMessage ( createInsertSegmentOp ( 0 , TextSegment . make ( "text" ) ) , client . mergeTree . collabWindow . currentSeq + 1 , client . mergeTree . collabWindow . currentSeq , "remote" ) ) ; assert . equal ( client . getText ( ) , "text" ) ; } ) ; it ( "remote remove followed by remote insert" , ( ) => { const removeMsg = client . makeOpMessage ( createRemoveRangeOp ( 0 , client . getLength ( ) ) , client . mergeTree . collabWindow . currentSeq + 1 , client . mergeTree . collabWindow . currentSeq , "remote2" ) ; const insertMsg = client . makeOpMessage ( createInsertSegmentOp ( 0 , TextSegment . make ( "text" ) ) , client . mergeTree . collabWindow . currentSeq + 2 , client . mergeTree . collabWindow . currentSeq , "remote" ) ; client . applyMsg ( removeMsg ) ; client . applyMsg ( insertMsg ) ; assert . equal ( client . getText ( ) , "text" ) ; } ) ; it ( "remote insert followed by remote remove" , ( ) => { const insertMsg = client . makeOpMessage ( createInsertSegmentOp ( 0 , TextSegment . make ( "text" ) ) , client . mergeTree . collabWindow . currentSeq + 1 , client . mergeTree . collabWindow . currentSeq , "remote" ) ; const removeMsg = client . makeOpMessage ( createRemoveRangeOp ( 0 , client . getLength ( ) ) , client . mergeTree . collabWindow . currentSeq + 2 , client . mergeTree . collabWindow . currentSeq , "remote2" ) ; client . applyMsg ( insertMsg ) ; client . applyMsg ( removeMsg ) ; assert . equal ( client . getText ( ) , "text" ) ; } ) ; it ( "local and remote clients race to insert at position of removed segment" , ( ) => { const expected = new TestClient ( ) ; expected . startOrUpdateCollaboration ( "3" ) ; { let seq = 0 ; expected . insertTextRemote ( 0 , "a" , undefined , ++ seq , 0 , "1" ) ; expected . removeRangeRemote ( 0 , 1 , ++ seq , 0 , "1" ) ; const refSeqAt2 = expected . getCurrentSeq ( ) ; expected . insertTextRemote ( 0 , "X" , undefined , ++ seq , 0 , "2" ) ; expected . insertTextRemote ( 0 , "c" , undefined , ++ seq , refSeqAt2 , "1" ) ; } const actual = new TestClient ( ) ; actual . startOrUpdateCollaboration ( "1" ) ; { let seq = 0 ; const op1 = actual . insertTextLocal ( 0 , "a" ) ; const op2 = actual . removeRangeLocal ( 0 , 1 ) ; actual . applyMsg ( actual . makeOpMessage ( op1 , ++ seq , 0 ) ) ; actual . applyMsg ( actual . makeOpMessage ( op2 , ++ seq , 0 ) ) ; const refSeqAt2 = actual . getCurrentSeq ( ) ; const op4 = actual . insertTextLocal ( 0 , "c" ) ; actual . insertTextRemote ( 0 , "X" , undefined , ++ seq , 0 , "2" ) ; actual . applyMsg ( actual . makeOpMessage ( op4 , ++ seq , refSeqAt2 ) ) ; } assert . equal ( actual . getText ( ) , expected . getText ( ) ) ; } ) ; } ) ;