Skip to content

Commit c3ffd13

Browse files
committed
test(json-crdt-extensions): 💍 add Inline .str() and .pos() tests
1 parent 18d0f4c commit c3ffd13

File tree

3 files changed

+87
-23
lines changed

3 files changed

+87
-23
lines changed

src/json-crdt-extensions/peritext/block/Inline.ts

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import type {PathStep} from '../../../json-pointer';
1111
import type {Slice} from '../slice/types';
1212
import type {Peritext} from '../Peritext';
1313

14-
export type Marks = Record<string | number, unknown>;
14+
export type InlineAttributes = Record<string | number, unknown>;
1515

1616
/**
1717
* The `Inline` class represents a range of inline text within a block, which
@@ -60,14 +60,29 @@ export class Inline extends Range implements Printable {
6060
return updateNum(this.start.refresh(), this.end.refresh());
6161
}
6262

63+
/**
64+
* @returns The full text content of the inline, which is the concatenation
65+
* of all the underlying {@link ChunkSlice}s.
66+
*/
6367
public str(): string {
6468
let str = '';
6569
for (const slice of this.texts) str += slice.view();
6670
return str;
6771
}
6872

69-
public marks(): Marks {
70-
const marks: Marks = {};
73+
/**
74+
* @returns The position of the inline withing the text.
75+
*/
76+
public pos(): number {
77+
const chunkSlice = this.texts[0];
78+
if (!chunkSlice) return -1;
79+
const chunk = chunkSlice.chunk;
80+
const pos = this.rga.pos(chunk);
81+
return pos + chunkSlice.off;
82+
}
83+
84+
public attr(): InlineAttributes {
85+
const attr: InlineAttributes = {};
7186
const point = this.start as OverlayPoint;
7287
const slices: Slice[] = this.texts.length ? point.layers : point.markers;
7388
const length = slices.length;
@@ -76,8 +91,8 @@ export class Inline extends Range implements Printable {
7691
const type = slice.type as PathStep;
7792
switch (slice.behavior) {
7893
case SliceBehavior.Stack: {
79-
let dataList: unknown[] = (marks[type] as unknown[]) || (marks[type] = []);
80-
if (!Array.isArray(dataList)) dataList = marks[type] = [dataList];
94+
let dataList: unknown[] = (attr[type] as unknown[]) || (attr[type] = []);
95+
if (!Array.isArray(dataList)) dataList = attr[type] = [dataList];
8196
let data = slice.data();
8297
if (data === undefined) data = 1;
8398
dataList.push(data);
@@ -86,24 +101,16 @@ export class Inline extends Range implements Printable {
86101
case SliceBehavior.Overwrite: {
87102
let data = slice.data();
88103
if (data === undefined) data = 1;
89-
marks[type] = data;
104+
attr[type] = data;
90105
break;
91106
}
92107
case SliceBehavior.Erase: {
93-
delete marks[type];
108+
delete attr[type];
94109
break;
95110
}
96111
}
97112
}
98-
return marks;
99-
}
100-
101-
public pos(): number {
102-
const chunkSlice = this.texts[0];
103-
if (!chunkSlice) return -1;
104-
const chunk = chunkSlice.chunk;
105-
const pos = this.rga.pos(chunk);
106-
return pos + chunkSlice.off;
113+
return attr;
107114
}
108115

109116
// ---------------------------------------------------------------- Printable
@@ -116,7 +123,7 @@ export class Inline extends Range implements Printable {
116123
const range =
117124
this.start.cmp(this.end) === 0 ? startFormatted : `${startFormatted}${this.end.toString(tab, true)}`;
118125
const header = `${this.constructor.name} ${range} ${text}`;
119-
const marks = this.marks();
126+
const marks = this.attr();
120127
const markKeys = Object.keys(marks);
121128
return (
122129
header +

src/json-crdt-extensions/peritext/block/__tests__/Inline.hash.spec.ts renamed to src/json-crdt-extensions/peritext/block/__tests__/Inline.key.spec.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ describe('range hash', () => {
4040
});
4141

4242
test('computes unique hash - 4', () => {
43-
const {peritext} = setupKit();
4443
const hash1 = updateNum(
4544
updateId(0, new Timestamp(2, 7)),
4645
updateId(1, new Timestamp(2, 7)),
@@ -53,7 +52,7 @@ describe('range hash', () => {
5352
});
5453
});
5554

56-
const runPairsTests = (setup: () => Kit) => {
55+
const runKeyTests = (setup: () => Kit) => {
5756
describe('.key()', () => {
5857
test('construct unique keys for all ranges', () => {
5958
const {peritext} = setup();
@@ -88,18 +87,18 @@ const runPairsTests = (setup: () => Kit) => {
8887

8988
describe('Inline', () => {
9089
describe('lorem ipsum', () => {
91-
runPairsTests(() => setupKit('lorem ipsum dolor sit amet consectetur adipiscing elit'));
90+
runKeyTests(() => setupKit('lorem ipsum dolor sit amet consectetur adipiscing elit'));
9291
});
9392

9493
describe('numbers "0123456789", no edits', () => {
95-
runPairsTests(setupNumbersKit);
94+
runKeyTests(setupNumbersKit);
9695
});
9796

9897
describe('numbers "0123456789", with default schema and tombstones', () => {
99-
runPairsTests(setupNumbersWithTombstonesKit);
98+
runKeyTests(setupNumbersWithTombstonesKit);
10099
});
101100

102101
describe('numbers "0123456789", with default schema and tombstones and constant sid', () => {
103-
runPairsTests(() => setupNumbersWithTombstonesKit(12313123));
102+
runKeyTests(() => setupNumbersWithTombstonesKit(12313123));
104103
});
105104
});
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import {Kit, setupKit, setupNumbersKit, setupNumbersWithTombstonesKit} from '../../__tests__/setup';
2+
import {Inline} from '../Inline';
3+
4+
const runStrTests = (setup: () => Kit) => {
5+
describe('.str()', () => {
6+
test('concatenates parts of Inline correctly', () => {
7+
const {peritext} = setup();
8+
const overlay = peritext.overlay;
9+
const length = peritext.strApi().length();
10+
for (let i = 0; i < length; i++) {
11+
for (let j = 1; j <= length - i; j++) {
12+
peritext.editor.cursor.setAt(i, j);
13+
overlay.refresh();
14+
const [start, end] = [...overlay.points()];
15+
const inline = Inline.create(peritext, start, end);
16+
const str = inline.str();
17+
expect(str).toBe(peritext.strApi().view().slice(i, i + j));
18+
}
19+
}
20+
});
21+
});
22+
23+
describe('.pos()', () => {
24+
test('returns correct offset in text', () => {
25+
const {peritext} = setup();
26+
const overlay = peritext.overlay;
27+
const length = peritext.strApi().length();
28+
for (let i = 0; i < length; i++) {
29+
for (let j = 1; j <= length - i; j++) {
30+
peritext.editor.cursor.setAt(i, j);
31+
overlay.refresh();
32+
const [start, end] = [...overlay.points()];
33+
const inline = Inline.create(peritext, start, end);
34+
const pos = inline.pos();
35+
expect(pos).toBe(i);
36+
}
37+
}
38+
});
39+
});
40+
};
41+
42+
describe('Inline', () => {
43+
describe('lorem ipsum', () => {
44+
runStrTests(() => setupKit('lorem ipsum dolor sit amet'));
45+
});
46+
47+
describe('numbers "0123456789", no edits', () => {
48+
runStrTests(setupNumbersKit);
49+
});
50+
51+
describe('numbers "0123456789", with default schema and tombstones', () => {
52+
runStrTests(setupNumbersWithTombstonesKit);
53+
});
54+
55+
describe('numbers "0123456789", with default schema and tombstones and constant sid', () => {
56+
runStrTests(() => setupNumbersWithTombstonesKit(12313123));
57+
});
58+
});

0 commit comments

Comments
 (0)