@@ -3,24 +3,159 @@ import {Peritext} from '../../Peritext';
33import { Anchor } from '../../constants' ;
44import { Editor } from '../../editor/Editor' ;
55
6- const setup = ( insert : ( editor : Editor ) => void = ( editor ) => editor . insert ( 'Hello world!' ) ) => {
6+ const setup = ( insert : ( peritext : Peritext ) => void = ( peritext ) => peritext . strApi ( ) . ins ( 0 , 'Hello world!' ) ) => {
77 const model = Model . withLogicalClock ( ) ;
88 model . api . root ( {
99 text : '' ,
1010 slices : [ ] ,
1111 } ) ;
1212 const peritext = new Peritext ( model , model . api . str ( [ 'text' ] ) . node , model . api . arr ( [ 'slices' ] ) . node ) ;
13- const editor = peritext . editor ;
14- insert ( editor ) ;
15- return { model, peritext, editor} ;
13+ insert ( peritext ) ;
14+ return { model, peritext} ;
1615} ;
1716
17+ const setupEvenDeleted = ( ) => {
18+ return setup ( ( peritext ) => {
19+ peritext . strApi ( ) . ins ( 0 , '0123456789' ) ;
20+ peritext . strApi ( ) . del ( 0 , 1 ) ;
21+ peritext . strApi ( ) . del ( 1 , 1 ) ;
22+ peritext . strApi ( ) . del ( 2 , 1 ) ;
23+ peritext . strApi ( ) . del ( 3 , 1 ) ;
24+ peritext . strApi ( ) . del ( 4 , 1 ) ;
25+ } ) ;
26+ } ;
27+
28+ describe ( 'new' , ( ) => {
29+ test ( 'creates a range from two points' , ( ) => {
30+ const { peritext} = setup ( ) ;
31+ const range = peritext . rangeAt ( 1 , 2 ) ;
32+ expect ( range . text ( ) ) . toBe ( 'el' ) ;
33+ expect ( range . start . pos ( ) ) . toBe ( 1 ) ;
34+ expect ( range . start . viewPos ( ) ) . toBe ( 1 ) ;
35+ expect ( range . start . anchor ) . toBe ( Anchor . Before ) ;
36+ expect ( range . end . pos ( ) ) . toBe ( 2 ) ;
37+ expect ( range . end . viewPos ( ) ) . toBe ( 3 ) ;
38+ expect ( range . end . anchor ) . toBe ( Anchor . After ) ;
39+ } ) ;
40+ } ) ;
41+
42+ describe ( '.from()' , ( ) => {
43+ test ( 'creates a when two points are in reverse order' , ( ) => {
44+ const { peritext} = setup ( ) ;
45+ const rangeTmp = peritext . rangeAt ( 1 , 2 ) ;
46+ const range = peritext . rangeFromPoints ( rangeTmp . end , rangeTmp . start ) ;
47+ expect ( range . text ( ) ) . toBe ( 'el' ) ;
48+ expect ( range . start . pos ( ) ) . toBe ( 1 ) ;
49+ expect ( range . start . viewPos ( ) ) . toBe ( 1 ) ;
50+ expect ( range . start . anchor ) . toBe ( Anchor . Before ) ;
51+ expect ( range . end . pos ( ) ) . toBe ( 2 ) ;
52+ expect ( range . end . viewPos ( ) ) . toBe ( 3 ) ;
53+ expect ( range . end . anchor ) . toBe ( Anchor . After ) ;
54+ } ) ;
55+ } ) ;
56+
57+ describe ( '.clone()' , ( ) => {
58+ test ( 'can clone a range' , ( ) => {
59+ const { peritext} = setup ( ) ;
60+ const range1 = peritext . rangeAt ( 2 , 3 ) ;
61+ const range2 = range1 . clone ( ) ;
62+ expect ( range2 ) . not . toBe ( range1 ) ;
63+ expect ( range1 . text ( ) ) . toBe ( range2 . text ( ) ) ;
64+ expect ( range2 . start ) . not . toBe ( range1 . start ) ;
65+ expect ( range2 . end ) . not . toBe ( range1 . end ) ;
66+ expect ( range2 . start . refresh ( ) ) . toBe ( range1 . start . refresh ( ) ) ;
67+ expect ( range2 . end . refresh ( ) ) . toBe ( range1 . end . refresh ( ) ) ;
68+ expect ( range2 . start . compare ( range1 . start ) ) . toBe ( 0 ) ;
69+ expect ( range2 . end . compare ( range1 . end ) ) . toBe ( 0 ) ;
70+ } ) ;
71+ } ) ;
72+
73+ describe ( '.isCollapsed()' , ( ) => {
74+ describe ( 'when range is collapsed' , ( ) => {
75+ test ( 'returns true at the beginning of string' , ( ) => {
76+ const { peritext} = setup ( ) ;
77+ const point = peritext . pointAtStart ( ) ;
78+ const range = peritext . range ( point , point ) ;
79+ const isCollapsed = range . isCollapsed ( ) ;
80+ expect ( isCollapsed ) . toBe ( true ) ;
81+ } ) ;
82+
83+ test ( 'returns true at the end of string' , ( ) => {
84+ const { peritext} = setup ( ) ;
85+ const point = peritext . pointAtEnd ( ) ;
86+ const range = peritext . range ( point , point ) ;
87+ const isCollapsed = range . isCollapsed ( ) ;
88+ expect ( isCollapsed ) . toBe ( true ) ;
89+ } ) ;
90+
91+ test ( 'returns true when before first character' , ( ) => {
92+ const { peritext} = setup ( ) ;
93+ const point = peritext . pointAt ( 0 , Anchor . Before ) ;
94+ const range = peritext . range ( point , point ) ;
95+ const isCollapsed = range . isCollapsed ( ) ;
96+ expect ( isCollapsed ) . toBe ( true ) ;
97+ } ) ;
98+
99+ test ( 'returns true when after last character' , ( ) => {
100+ const { peritext} = setup ( ) ;
101+ const point = peritext . pointAt ( peritext . str . length ( ) - 1 , Anchor . After ) ;
102+ const range = peritext . range ( point , point ) ;
103+ const isCollapsed = range . isCollapsed ( ) ;
104+ expect ( isCollapsed ) . toBe ( true ) ;
105+ } ) ;
106+
107+ test ( 'returns true when in the middle of plain/undeleted text' , ( ) => {
108+ const { peritext} = setup ( ) ;
109+ const point1 = peritext . pointAt ( 2 , Anchor . After ) ;
110+ const point2 = peritext . pointAt ( 3 , Anchor . Before ) ;
111+ const range1 = peritext . range ( point1 , point1 ) ;
112+ const range2 = peritext . range ( point2 , point2 ) ;
113+ expect ( range1 . isCollapsed ( ) ) . toBe ( true ) ;
114+ expect ( range2 . isCollapsed ( ) ) . toBe ( true ) ;
115+ } ) ;
116+
117+ describe ( 'when first character is deleted' , ( ) => {
118+ test ( 'returns true at the beginning of string' , ( ) => {
119+ const { peritext} = setupEvenDeleted ( ) ;
120+ const point = peritext . pointAtStart ( ) ;
121+ const range = peritext . range ( point , point ) ;
122+ const isCollapsed = range . isCollapsed ( ) ;
123+ expect ( isCollapsed ) . toBe ( true ) ;
124+ } ) ;
125+
126+ test ( 'returns true when before first character' , ( ) => {
127+ const { peritext} = setupEvenDeleted ( ) ;
128+ const point = peritext . pointAt ( 0 , Anchor . Before ) ;
129+ const range = peritext . range ( point , point ) ;
130+ const isCollapsed = range . isCollapsed ( ) ;
131+ expect ( isCollapsed ) . toBe ( true ) ;
132+ } ) ;
133+
134+ test ( 'returns true when in the middle of deleted characters' , ( ) => {
135+ const { peritext} = setupEvenDeleted ( ) ;
136+ const range = peritext . rangeAt ( 2 , 1 ) ;
137+ expect ( range . isCollapsed ( ) ) . toBe ( false ) ;
138+ peritext . strApi ( ) . del ( 1 , 3 ) ;
139+ expect ( range . isCollapsed ( ) ) . toBe ( true ) ;
140+ } ) ;
141+
142+ test ( 'returns true when whole text was deleted' , ( ) => {
143+ const { peritext} = setupEvenDeleted ( ) ;
144+ const range = peritext . rangeAt ( 1 , 3 ) ;
145+ expect ( range . isCollapsed ( ) ) . toBe ( false ) ;
146+ peritext . strApi ( ) . del ( 0 , 5 ) ;
147+ expect ( range . isCollapsed ( ) ) . toBe ( true ) ;
148+ } ) ;
149+ } ) ;
150+ } ) ;
151+ } ) ;
152+
18153describe ( '.contains()' , ( ) => {
19154 test ( 'returns true if slice is contained' , ( ) => {
20- const { peritext, editor } = setup ( ) ;
21- editor . setCursor ( 3 , 2 ) ;
22- const slice = editor . insertOverwriteSlice ( 'b' ) ;
23- editor . setCursor ( 0 ) ;
155+ const { peritext} = setup ( ) ;
156+ peritext . editor . setCursor ( 3 , 2 ) ;
157+ const slice = peritext . editor . insertOverwriteSlice ( 'b' ) ;
158+ peritext . editor . setCursor ( 0 ) ;
24159 peritext . refresh ( ) ;
25160 expect ( peritext . rangeAt ( 2 , 4 ) . contains ( slice ) ) . toBe ( true ) ;
26161 expect ( peritext . rangeAt ( 3 , 4 ) . contains ( slice ) ) . toBe ( true ) ;
@@ -29,10 +164,10 @@ describe('.contains()', () => {
29164 } ) ;
30165
31166 test ( 'returns false if slice is not contained' , ( ) => {
32- const { peritext, editor } = setup ( ) ;
33- editor . setCursor ( 3 , 2 ) ;
34- const slice = editor . insertOverwriteSlice ( 'b' ) ;
35- editor . setCursor ( 0 ) ;
167+ const { peritext} = setup ( ) ;
168+ peritext . editor . setCursor ( 3 , 2 ) ;
169+ const slice = peritext . editor . insertOverwriteSlice ( 'b' ) ;
170+ peritext . editor . setCursor ( 0 ) ;
36171 peritext . refresh ( ) ;
37172 expect ( peritext . rangeAt ( 3 , 1 ) . contains ( slice ) ) . toBe ( false ) ;
38173 expect ( peritext . rangeAt ( 2 , 1 ) . contains ( slice ) ) . toBe ( false ) ;
@@ -45,24 +180,25 @@ describe('.contains()', () => {
45180
46181describe ( '.isCollapsed()' , ( ) => {
47182 test ( 'returns true when endpoints point to the same location' , ( ) => {
48- const { editor } = setup ( ) ;
49- editor . setCursor ( 3 ) ;
50- expect ( editor . cursor . isCollapsed ( ) ) . toBe ( true ) ;
183+ const { peritext } = setup ( ) ;
184+ peritext . editor . setCursor ( 3 ) ;
185+ expect ( peritext . editor . cursor . isCollapsed ( ) ) . toBe ( true ) ;
51186 } ) ;
52187
53188 test ( 'returns true when when there is no visible content between endpoints' , ( ) => {
54- const { peritext, editor } = setup ( ) ;
189+ const { peritext} = setup ( ) ;
55190 const range = peritext . rangeAt ( 2 , 1 ) ;
56- editor . setCursor ( 2 , 1 ) ;
57- editor . delete ( ) ;
191+ peritext . editor . setCursor ( 2 , 1 ) ;
192+ peritext . editor . delete ( ) ;
58193 expect ( range . isCollapsed ( ) ) . toBe ( true ) ;
59194 } ) ;
60195} ) ;
61196
62197describe ( '.expand()' , ( ) => {
63198 const runExpandTests = ( setup2 : typeof setup ) => {
64199 test ( 'can expand anchors to include adjacent elements' , ( ) => {
65- const { editor} = setup2 ( ) ;
200+ const { peritext} = setup2 ( ) ;
201+ const editor = peritext . editor ;
66202 editor . setCursor ( 1 , 1 ) ;
67203 expect ( editor . cursor . start . pos ( ) ) . toBe ( 1 ) ;
68204 expect ( editor . cursor . start . anchor ) . toBe ( Anchor . Before ) ;
@@ -77,15 +213,15 @@ describe('.expand()', () => {
77213 } ) ;
78214
79215 test ( 'can expand anchors to contain include adjacent tombstones' , ( ) => {
80- const { peritext, editor } = setup2 ( ) ;
216+ const { peritext} = setup2 ( ) ;
81217 const tombstone1 = peritext . rangeAt ( 1 , 1 ) ;
82218 tombstone1 . expand ( ) ;
83219 const tombstone2 = peritext . rangeAt ( 3 , 1 ) ;
84220 tombstone2 . expand ( ) ;
85- editor . cursor . setRange ( tombstone1 ) ;
86- editor . delete ( ) ;
87- editor . cursor . setRange ( tombstone2 ) ;
88- editor . delete ( ) ;
221+ peritext . editor . cursor . setRange ( tombstone1 ) ;
222+ peritext . editor . delete ( ) ;
223+ peritext . editor . cursor . setRange ( tombstone2 ) ;
224+ peritext . editor . delete ( ) ;
89225 const range = peritext . rangeAt ( 1 , 1 ) ;
90226 range . expand ( ) ;
91227 expect ( range . start . pos ( ) ) . toBe ( tombstone1 . start . pos ( ) ) ;
@@ -101,7 +237,8 @@ describe('.expand()', () => {
101237
102238 describe ( 'each car is own chunk' , ( ) => {
103239 runExpandTests ( ( ) =>
104- setup ( ( editor ) => {
240+ setup ( ( peritext ) => {
241+ const editor = peritext . editor ;
105242 editor . insert ( '!' ) ;
106243 editor . setCursor ( 0 ) ;
107244 editor . insert ( 'd' ) ;
0 commit comments