@@ -497,3 +497,129 @@ describe('.prevId()', () => {
497497 expect ( p2After . prevId ( 8 ) ) . toEqual ( undefined ) ;
498498 } ) ;
499499} ) ;
500+
501+ describe ( '.rightChar()' , ( ) => {
502+ test ( 'returns the right character' , ( ) => {
503+ const model = Model . withLogicalClock ( 123456 ) ;
504+ model . api . root ( {
505+ text : 'abc' ,
506+ slices : [ ] ,
507+ } ) ;
508+ const str = model . api . str ( [ 'text' ] ) . node ;
509+ const peritext = new Peritext ( model , str , model . api . arr ( [ 'slices' ] ) . node ) ;
510+ const point0 = peritext . pointAt ( 0 ) ;
511+ const char0 = point0 . rightChar ( ) ! ;
512+ expect ( char0 . chunk . data ! . slice ( char0 . off , char0 . off + 1 ) ) . toBe ( 'a' ) ;
513+ const point1 = peritext . pointAt ( 1 ) ;
514+ const char1 = point1 . rightChar ( ) ! ;
515+ expect ( char1 . chunk . data ! . slice ( char1 . off , char1 . off + 1 ) ) . toBe ( 'b' ) ;
516+ const point2 = peritext . pointAt ( 2 ) ;
517+ const char2 = point2 . rightChar ( ) ! ;
518+ expect ( char2 . chunk . data ! . slice ( char2 . off , char2 . off + 1 ) ) . toBe ( 'c' ) ;
519+ } ) ;
520+
521+ test ( 'multi-char chunks with deletes' , ( ) => {
522+ const { peritext} = setupWithText ( ) ;
523+ const res = '012345678' ;
524+ for ( let i = 0 ; i < res . length ; i ++ ) {
525+ const point = peritext . pointAt ( i , Anchor . Before ) ;
526+ const char = point . rightChar ( ) ! ;
527+ expect ( char . view ( ) ) . toBe ( res [ i ] ) ;
528+ }
529+ for ( let i = 0 ; i < res . length - 1 ; i ++ ) {
530+ const point = peritext . pointAt ( i , Anchor . After ) ;
531+ const char = point . rightChar ( ) ! ;
532+ expect ( char . view ( ) ) . toBe ( res [ i + 1 ] ) ;
533+ }
534+ const end = peritext . pointAt ( res . length - 1 , Anchor . After ) ;
535+ expect ( end . rightChar ( ) ) . toBe ( undefined ) ;
536+ } ) ;
537+
538+ test ( 'multi-char chunks with deletes (2)' , ( ) => {
539+ const { peritext} = setupWithChunkedText ( ) ;
540+ const res = '123456789' ;
541+ for ( let i = 0 ; i < res . length ; i ++ ) {
542+ const point = peritext . pointAt ( i , Anchor . Before ) ;
543+ const char = point . rightChar ( ) ! ;
544+ expect ( char . view ( ) ) . toBe ( res [ i ] ) ;
545+ }
546+ for ( let i = 0 ; i < res . length - 1 ; i ++ ) {
547+ const point = peritext . pointAt ( i , Anchor . After ) ;
548+ const char = point . rightChar ( ) ! ;
549+ expect ( char . view ( ) ) . toBe ( res [ i + 1 ] ) ;
550+ }
551+ const end = peritext . pointAt ( res . length - 1 , Anchor . After ) ;
552+ expect ( end . rightChar ( ) ) . toBe ( undefined ) ;
553+ } ) ;
554+ } ) ;
555+
556+ describe ( '.leftChar()' , ( ) => {
557+ test ( 'returns the left character' , ( ) => {
558+ const model = Model . withLogicalClock ( 123456 ) ;
559+ model . api . root ( {
560+ text : 'abc' ,
561+ slices : [ ] ,
562+ } ) ;
563+ const str = model . api . str ( [ 'text' ] ) . node ;
564+ const peritext = new Peritext ( model , str , model . api . arr ( [ 'slices' ] ) . node ) ;
565+ model . api . str ( [ 'text' ] ) . del ( 0 , 3 ) ;
566+ model . api . str ( [ 'text' ] ) . ins ( 0 , '00a1b2c3' ) ;
567+ model . api . str ( [ 'text' ] ) . del ( 0 , 2 ) ;
568+ model . api . str ( [ 'text' ] ) . del ( 1 , 1 ) ;
569+ model . api . str ( [ 'text' ] ) . del ( 2 , 1 ) ;
570+ model . api . str ( [ 'text' ] ) . del ( 3 , 1 ) ;
571+ const point0 = peritext . pointAt ( 2 , Anchor . After ) ;
572+ const char0 = point0 . leftChar ( ) ! ;
573+ expect ( char0 . chunk . data ! . slice ( char0 . off , char0 . off + 1 ) ) . toBe ( 'c' ) ;
574+ const point1 = peritext . pointAt ( 1 , Anchor . After ) ;
575+ const char1 = point1 . leftChar ( ) ! ;
576+ expect ( char1 . chunk . data ! . slice ( char1 . off , char1 . off + 1 ) ) . toBe ( 'b' ) ;
577+ const point2 = peritext . pointAt ( 0 , Anchor . After ) ;
578+ const char2 = point2 . leftChar ( ) ! ;
579+ expect ( char2 . chunk . data ! . slice ( char2 . off , char2 . off + 1 ) ) . toBe ( 'a' ) ;
580+ } ) ;
581+
582+ test ( 'multi-char chunks with deletes' , ( ) => {
583+ const { peritext} = setupWithText ( ) ;
584+ const res = '012345678' ;
585+ const start = peritext . pointAt ( 0 , Anchor . Before ) ;
586+ expect ( start . leftChar ( ) ) . toBe ( undefined ) ;
587+ const start2 = peritext . pointAt ( 0 , Anchor . After ) ;
588+ expect ( start2 . leftChar ( ) ! . view ( ) ) . toBe ( res [ 0 ] ) ;
589+ const start3 = peritext . pointAt ( 1 , Anchor . Before ) ;
590+ const slice = start3 . leftChar ( ) ;
591+ expect ( slice ! . view ( ) ) . toBe ( res [ 0 ] ) ;
592+ for ( let i = 1 ; i < res . length ; i ++ ) {
593+ const point = peritext . pointAt ( i , Anchor . Before ) ;
594+ const char = point . leftChar ( ) ! ;
595+ expect ( char . view ( ) ) . toBe ( res [ i - 1 ] ) ;
596+ }
597+ for ( let i = 0 ; i < res . length ; i ++ ) {
598+ const point = peritext . pointAt ( i , Anchor . After ) ;
599+ const char = point . leftChar ( ) ! ;
600+ expect ( char . view ( ) ) . toBe ( res [ i ] ) ;
601+ }
602+ } ) ;
603+
604+ test ( 'multi-char chunks with deletes (2)' , ( ) => {
605+ const { peritext} = setupWithChunkedText ( ) ;
606+ const res = '123456789' ;
607+ const start = peritext . pointAt ( 0 , Anchor . Before ) ;
608+ expect ( start . leftChar ( ) ) . toBe ( undefined ) ;
609+ const start2 = peritext . pointAt ( 0 , Anchor . After ) ;
610+ expect ( start2 . leftChar ( ) ! . view ( ) ) . toBe ( res [ 0 ] ) ;
611+ const start3 = peritext . pointAt ( 1 , Anchor . Before ) ;
612+ const slice = start3 . leftChar ( ) ;
613+ expect ( slice ! . view ( ) ) . toBe ( res [ 0 ] ) ;
614+ for ( let i = 1 ; i < res . length ; i ++ ) {
615+ const point = peritext . pointAt ( i , Anchor . Before ) ;
616+ const char = point . leftChar ( ) ! ;
617+ expect ( char . view ( ) ) . toBe ( res [ i - 1 ] ) ;
618+ }
619+ for ( let i = 0 ; i < res . length ; i ++ ) {
620+ const point = peritext . pointAt ( i , Anchor . After ) ;
621+ const char = point . leftChar ( ) ! ;
622+ expect ( char . view ( ) ) . toBe ( res [ i ] ) ;
623+ }
624+ } ) ;
625+ } ) ;
0 commit comments