Skip to content

Commit c6614d9

Browse files
committed
test(json-crdt-extensions): šŸ’ add .findContained() and .findOverlapping() overlay tests
1 parent 6676486 commit c6614d9

File tree

4 files changed

+162
-4
lines changed

4 files changed

+162
-4
lines changed

ā€Žsrc/json-crdt-extensions/peritext/overlay/MarkerOverlayPoint.tsā€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type {MarkerSlice} from '../slice/MarkerSlice';
88

99
export class MarkerOverlayPoint<T = string> extends OverlayPoint<T> {
1010
/**
11-
* Hash value of the preceding text contents, up until the next marker.
11+
* Hash value of the following text contents, up until the next marker.
1212
*/
1313
public textHash: number = 0;
1414

ā€Žsrc/json-crdt-extensions/peritext/overlay/Overlay.tsā€Ž

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ export class Overlay<T = string> implements Printable, Stateful {
118118
}
119119
return;
120120
}
121-
121+
122+
/** @todo Rename to `chunks()`. */
122123
public chunkSlices0(
123124
chunk: Chunk<T> | undefined,
124125
p1: Point<T>,
@@ -245,6 +246,14 @@ export class Overlay<T = string> implements Printable, Stateful {
245246
return new UndefEndIter(this.tuples0(after));
246247
}
247248

249+
/**
250+
* Finds all slices that are contained within the given range. A slice is
251+
* considered contained if its start and end points are within the range,
252+
* inclusive (uses {@link Range#contains} method to check containment).
253+
*
254+
* @param range The range to search for contained slices.
255+
* @returns A set of slices that are contained within the given range.
256+
*/
248257
public findContained(range: Range<T>): Set<Slice<T>> {
249258
const result = new Set<Slice<T>>();
250259
let point = this.getOrNextLower(range.start);
@@ -265,6 +274,14 @@ export class Overlay<T = string> implements Printable, Stateful {
265274
return result;
266275
}
267276

277+
/**
278+
* Finds all slices that overlap with the given range. A slice is considered
279+
* overlapping if its start or end point is within the range, inclusive
280+
* (uses {@link Range#containsPoint} method to check overlap).
281+
*
282+
* @param range The range to search for overlapping slices.
283+
* @returns A set of slices that overlap with the given range.
284+
*/
268285
public findOverlapping(range: Range<T>): Set<Slice<T>> {
269286
const result = new Set<Slice<T>>();
270287
let point = this.getOrNextLower(range.start);
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import {Kit, setupHelloWorldKit, setupHelloWorldWithFewEditsKit} from '../../__tests__/setup';
2+
3+
const runFindContainedTests = (setup: () => Kit) => {
4+
describe('.findContained()', () => {
5+
test('returns empty set by default', () => {
6+
const {peritext} = setup();
7+
peritext.overlay.refresh();
8+
const slices = peritext.overlay.findContained(peritext.rangeAt(3, 4));
9+
expect(slices.size).toBe(0);
10+
});
11+
12+
test('returns a single contained slice', () => {
13+
const {peritext, editor} = setup();
14+
editor.cursor.setAt(3, 2);
15+
editor.saved.insStack('em');
16+
editor.cursor.setAt(0);
17+
peritext.overlay.refresh();
18+
const slices = peritext.overlay.findContained(peritext.rangeAt(3, 4));
19+
expect(slices.size).toBe(1);
20+
});
21+
22+
test('returns two contained slice', () => {
23+
const {peritext, editor} = setup();
24+
editor.cursor.setAt(3, 1);
25+
editor.saved.insStack('em');
26+
editor.cursor.setAt(5, 2);
27+
editor.saved.insStack('bold');
28+
editor.cursor.setAt(0);
29+
peritext.overlay.refresh();
30+
const slices = peritext.overlay.findContained(peritext.rangeAt(2, 8));
31+
expect(slices.size).toBe(2);
32+
});
33+
34+
test('does not return overlapping slice', () => {
35+
const {peritext, editor} = setup();
36+
editor.cursor.setAt(3, 4);
37+
editor.saved.insStack('em');
38+
editor.cursor.setAt(5, 2);
39+
editor.saved.insStack('bold');
40+
editor.cursor.setAt(0);
41+
peritext.overlay.refresh();
42+
const slices = peritext.overlay.findContained(peritext.rangeAt(4, 8));
43+
expect(slices.size).toBe(1);
44+
});
45+
46+
test('returns split blocks', () => {
47+
const {peritext, editor} = setup();
48+
editor.cursor.setAt(3, 4);
49+
editor.saved.insStack('em');
50+
editor.cursor.setAt(5, 2);
51+
editor.saved.insStack('bold');
52+
editor.cursor.setAt(8);
53+
editor.saved.insMarker('p');
54+
editor.cursor.setAt(0);
55+
peritext.overlay.refresh();
56+
const slices = peritext.overlay.findContained(peritext.rangeAt(4, 8));
57+
expect(slices.size).toBe(2);
58+
});
59+
});
60+
};
61+
62+
const runFindOverlappingTests = (setup: () => Kit) => {
63+
describe('.findOverlapping()', () => {
64+
test('returns empty set by default', () => {
65+
const {peritext} = setup();
66+
peritext.overlay.refresh();
67+
const slices = peritext.overlay.findOverlapping(peritext.rangeAt(3, 4));
68+
expect(slices.size).toBe(0);
69+
});
70+
71+
test('returns a single contained slice', () => {
72+
const {peritext, editor} = setup();
73+
editor.cursor.setAt(3, 2);
74+
editor.saved.insStack('em');
75+
editor.cursor.setAt(0);
76+
peritext.overlay.refresh();
77+
const slices = peritext.overlay.findOverlapping(peritext.rangeAt(3, 4));
78+
expect(slices.size).toBe(1);
79+
});
80+
81+
test('returns two contained slice', () => {
82+
const {peritext, editor} = setup();
83+
editor.cursor.setAt(3, 1);
84+
editor.saved.insStack('em');
85+
editor.cursor.setAt(5, 2);
86+
editor.saved.insStack('bold');
87+
editor.cursor.setAt(0);
88+
peritext.overlay.refresh();
89+
const slices = peritext.overlay.findOverlapping(peritext.rangeAt(2, 8));
90+
expect(slices.size).toBe(2);
91+
});
92+
93+
test('returns overlapping slices', () => {
94+
const {peritext, editor} = setup();
95+
editor.cursor.setAt(3, 4);
96+
editor.saved.insStack('em');
97+
editor.cursor.setAt(5, 2);
98+
editor.saved.insStack('bold');
99+
editor.cursor.setAt(0);
100+
peritext.overlay.refresh();
101+
const slices = peritext.overlay.findOverlapping(peritext.rangeAt(4, 8));
102+
expect(slices.size).toBe(2);
103+
});
104+
105+
test('returns overlapping slices from both ends', () => {
106+
const {peritext, editor} = setup();
107+
editor.cursor.setAt(3, 2);
108+
editor.saved.insStack('em');
109+
editor.cursor.setAt(8, 2);
110+
editor.saved.insStack('bold');
111+
editor.cursor.setAt(0);
112+
peritext.overlay.refresh();
113+
const slices = peritext.overlay.findOverlapping(peritext.rangeAt(4, 5));
114+
expect(slices.size).toBe(2);
115+
});
116+
117+
test('returns split blocks', () => {
118+
const {peritext, editor} = setup();
119+
editor.cursor.setAt(3, 4);
120+
editor.saved.insStack('em');
121+
editor.cursor.setAt(5, 2);
122+
editor.saved.insStack('bold');
123+
editor.cursor.setAt(8);
124+
editor.saved.insMarker('p');
125+
editor.cursor.setAt(0);
126+
peritext.overlay.refresh();
127+
const slices = peritext.overlay.findOverlapping(peritext.rangeAt(4, 8));
128+
expect(slices.size).toBe(3);
129+
});
130+
});
131+
};
132+
133+
describe('text "hello world", no edits', () => {
134+
runFindContainedTests(setupHelloWorldKit);
135+
runFindOverlappingTests(setupHelloWorldKit);
136+
});
137+
138+
describe('text "hello world", with few edits', () => {
139+
runFindContainedTests(setupHelloWorldWithFewEditsKit);
140+
runFindOverlappingTests(setupHelloWorldWithFewEditsKit);
141+
});

ā€Žsrc/json-crdt-extensions/peritext/overlay/__tests__/Overlay.tuples.spec.tsā€Ž

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,10 @@ const runPairsTests = (setup: () => Kit) => {
152152
});
153153
};
154154

155-
describe('numbers "hello world", no edits', () => {
155+
describe('text "hello world", no edits', () => {
156156
runPairsTests(setupHelloWorldKit);
157157
});
158158

159-
describe('numbers "hello world", with default schema and tombstones', () => {
159+
describe('text "hello world", with few edits', () => {
160160
runPairsTests(setupHelloWorldWithFewEditsKit);
161161
});

0 commit comments

Comments
Ā (0)