@pie-lib/text-select 1.12.8 → 1.13.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -61
- package/NEXT.CHANGELOG.json +1 -0
- package/package.json +8 -6
- package/src/__tests__/__snapshots__/text-select.test.jsx.snap +21 -0
- package/src/__tests__/text-select.test.jsx +34 -0
- package/src/__tests__/utils.test.jsx +27 -0
- package/src/index.js +2 -1
- package/src/token-select/__tests__/__snapshots__/index.test.jsx.snap +49 -0
- package/src/token-select/__tests__/__snapshots__/token.test.jsx.snap +31 -0
- package/src/token-select/__tests__/index.test.jsx +257 -0
- package/src/token-select/__tests__/token.test.jsx +33 -0
- package/src/token-select/index.jsx +3 -1
- package/src/token-select/token.jsx +11 -20
- package/src/tokenizer/__tests__/__snapshots__/controls.test.jsx.snap +59 -0
- package/src/tokenizer/__tests__/__snapshots__/index.test.jsx.snap +31 -0
- package/src/tokenizer/__tests__/__snapshots__/token-text.test.jsx.snap +17 -0
- package/src/tokenizer/__tests__/builder.test.js +256 -0
- package/src/tokenizer/__tests__/controls.test.jsx +25 -0
- package/src/tokenizer/__tests__/index.test.jsx +140 -0
- package/src/tokenizer/__tests__/selection-utils.test.js +26 -0
- package/src/tokenizer/__tests__/token-text.test.jsx +136 -0
- package/src/tokenizer/controls.jsx +20 -1
- package/src/tokenizer/token-text.jsx +9 -0
- package/README.md +0 -3
- package/lib/index.js +0 -68
- package/lib/index.js.map +0 -1
- package/lib/legend.js +0 -99
- package/lib/legend.js.map +0 -1
- package/lib/text-select.js +0 -138
- package/lib/text-select.js.map +0 -1
- package/lib/token-select/index.js +0 -249
- package/lib/token-select/index.js.map +0 -1
- package/lib/token-select/token.js +0 -237
- package/lib/token-select/token.js.map +0 -1
- package/lib/tokenizer/builder.js +0 -311
- package/lib/tokenizer/builder.js.map +0 -1
- package/lib/tokenizer/controls.js +0 -123
- package/lib/tokenizer/controls.js.map +0 -1
- package/lib/tokenizer/index.js +0 -205
- package/lib/tokenizer/index.js.map +0 -1
- package/lib/tokenizer/selection-utils.js +0 -65
- package/lib/tokenizer/selection-utils.js.map +0 -1
- package/lib/tokenizer/token-text.js +0 -200
- package/lib/tokenizer/token-text.js.map +0 -1
- package/lib/utils.js +0 -67
- package/lib/utils.js.map +0 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Token } from '../token';
|
|
2
|
+
import { shallow } from 'enzyme';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
describe('token', () => {
|
|
6
|
+
describe('snapshot', () => {
|
|
7
|
+
it('renders', () => {
|
|
8
|
+
const w = shallow(
|
|
9
|
+
<Token
|
|
10
|
+
classes={{
|
|
11
|
+
token: 'token',
|
|
12
|
+
selectable: 'selectable',
|
|
13
|
+
}}
|
|
14
|
+
text={'foo bar'}
|
|
15
|
+
/>,
|
|
16
|
+
);
|
|
17
|
+
expect(w).toMatchSnapshot();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('renders with brs', () => {
|
|
21
|
+
const w = shallow(
|
|
22
|
+
<Token
|
|
23
|
+
classes={{
|
|
24
|
+
token: 'token',
|
|
25
|
+
selectable: 'selectable',
|
|
26
|
+
}}
|
|
27
|
+
text={'foo \nbar'}
|
|
28
|
+
/>,
|
|
29
|
+
);
|
|
30
|
+
expect(w).toMatchSnapshot();
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -58,7 +58,9 @@ export class TokenSelect extends React.Component {
|
|
|
58
58
|
const targetedTokenIndex = targetSpanWrapper && targetSpanWrapper.dataset && targetSpanWrapper.dataset.indexkey;
|
|
59
59
|
const t = targetedTokenIndex && tokensCloned[targetedTokenIndex];
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
// don't toggle if we are in print mode, token correctness is defined or if it's missing
|
|
62
|
+
// (missing means that it was evaluated as correct and not selected)
|
|
63
|
+
if (t && t.correct === undefined && !animationsDisabled && !t.isMissing) {
|
|
62
64
|
const { onChange, maxNoOfSelections } = this.props;
|
|
63
65
|
const selected = !t.selected;
|
|
64
66
|
|
|
@@ -115,10 +115,6 @@ export default withStyles((theme) => {
|
|
|
115
115
|
token: {
|
|
116
116
|
cursor: 'pointer',
|
|
117
117
|
textIndent: 0,
|
|
118
|
-
padding: theme.spacing.unit / 2,
|
|
119
|
-
paddingRight: 0,
|
|
120
|
-
paddingLeft: 0,
|
|
121
|
-
transition: 'background-color 100ms ease-in',
|
|
122
118
|
},
|
|
123
119
|
disabled: {
|
|
124
120
|
cursor: 'inherit',
|
|
@@ -134,6 +130,7 @@ export default withStyles((theme) => {
|
|
|
134
130
|
[theme.breakpoints.up(769)]: {
|
|
135
131
|
'&:hover': {
|
|
136
132
|
backgroundColor: color.primaryLight(),
|
|
133
|
+
color: theme.palette.common.black,
|
|
137
134
|
'& > *': {
|
|
138
135
|
backgroundColor: color.primaryLight(),
|
|
139
136
|
},
|
|
@@ -141,47 +138,42 @@ export default withStyles((theme) => {
|
|
|
141
138
|
},
|
|
142
139
|
},
|
|
143
140
|
selected: {
|
|
144
|
-
lineHeight: 2,
|
|
145
|
-
marginTop: theme.spacing.unit / 2,
|
|
146
141
|
backgroundColor: color.primaryLight(),
|
|
142
|
+
color: theme.palette.common.black,
|
|
143
|
+
lineHeight: `${theme.spacing.unit * 3}px`,
|
|
147
144
|
'& > *': {
|
|
148
145
|
backgroundColor: color.primaryLight(),
|
|
149
146
|
},
|
|
150
147
|
},
|
|
151
148
|
highlight: {
|
|
152
149
|
border: `dashed 2px ${color.disabled()}`,
|
|
153
|
-
lineHeight:
|
|
154
|
-
boxSizing: 'border-box',
|
|
155
|
-
marginTop: theme.spacing.unit / 2,
|
|
156
|
-
display: 'inline-block',
|
|
157
|
-
padding: theme.spacing.unit,
|
|
150
|
+
lineHeight: `${theme.spacing.unit * 3}px`,
|
|
158
151
|
},
|
|
159
152
|
print: {
|
|
160
153
|
border: `dashed 2px ${color.disabled()}`,
|
|
161
|
-
lineHeight:
|
|
162
|
-
boxSizing: 'border-box',
|
|
163
|
-
marginTop: theme.spacing.unit / 2,
|
|
164
|
-
display: 'inline-block',
|
|
165
|
-
padding: theme.spacing.unit,
|
|
154
|
+
lineHeight: `${theme.spacing.unit * 3}px`,
|
|
166
155
|
color: color.text(),
|
|
167
156
|
},
|
|
168
|
-
|
|
169
157
|
custom: {
|
|
170
158
|
display: 'initial',
|
|
171
159
|
},
|
|
172
160
|
correct: {
|
|
173
161
|
backgroundColor: color.correctSecondary(),
|
|
174
162
|
border: `${color.correct()} solid 2px`,
|
|
175
|
-
|
|
163
|
+
color: theme.palette.common.black,
|
|
164
|
+
lineHeight: `${theme.spacing.unit * 3}px`,
|
|
176
165
|
},
|
|
177
166
|
incorrect: {
|
|
178
167
|
backgroundColor: color.incorrectSecondary(),
|
|
179
168
|
border: `${color.missing()} solid 2px`,
|
|
180
|
-
|
|
169
|
+
color: theme.palette.common.black,
|
|
170
|
+
lineHeight: `${theme.spacing.unit * 3}px`,
|
|
181
171
|
},
|
|
182
172
|
missing: {
|
|
183
173
|
backgroundColor: color.incorrectSecondary(),
|
|
184
174
|
border: `${color.missing()} dashed 2px`,
|
|
175
|
+
color: theme.palette.common.black,
|
|
176
|
+
lineHeight: `${theme.spacing.unit * 3}px`,
|
|
185
177
|
textDecoration: `line-through ${color.missing()}`,
|
|
186
178
|
},
|
|
187
179
|
incorrectIcon: {
|
|
@@ -189,7 +181,6 @@ export default withStyles((theme) => {
|
|
|
189
181
|
fontSize: 'larger',
|
|
190
182
|
color: color.missing(),
|
|
191
183
|
},
|
|
192
|
-
|
|
193
184
|
correctIcon: {
|
|
194
185
|
verticalAlign: 'middle',
|
|
195
186
|
fontSize: 'larger',
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`controls snapshot renders 1`] = `
|
|
4
|
+
<div>
|
|
5
|
+
<div>
|
|
6
|
+
<WithStyles(Button)
|
|
7
|
+
className="button"
|
|
8
|
+
color="primary"
|
|
9
|
+
disabled={false}
|
|
10
|
+
onClick={[MockFunction]}
|
|
11
|
+
size="small"
|
|
12
|
+
>
|
|
13
|
+
Words
|
|
14
|
+
</WithStyles(Button)>
|
|
15
|
+
<WithStyles(Button)
|
|
16
|
+
className="button"
|
|
17
|
+
color="primary"
|
|
18
|
+
disabled={false}
|
|
19
|
+
onClick={[MockFunction]}
|
|
20
|
+
size="small"
|
|
21
|
+
>
|
|
22
|
+
Sentences
|
|
23
|
+
</WithStyles(Button)>
|
|
24
|
+
<WithStyles(Button)
|
|
25
|
+
className="button"
|
|
26
|
+
color="primary"
|
|
27
|
+
disabled={false}
|
|
28
|
+
onClick={[MockFunction]}
|
|
29
|
+
size="small"
|
|
30
|
+
>
|
|
31
|
+
Paragraphs
|
|
32
|
+
</WithStyles(Button)>
|
|
33
|
+
<WithStyles(Button)
|
|
34
|
+
className="button"
|
|
35
|
+
color="secondary"
|
|
36
|
+
disabled={false}
|
|
37
|
+
onClick={[MockFunction]}
|
|
38
|
+
size="small"
|
|
39
|
+
>
|
|
40
|
+
Clear
|
|
41
|
+
</WithStyles(Button)>
|
|
42
|
+
</div>
|
|
43
|
+
<WithStyles(WithFormControlContext(FormControlLabel))
|
|
44
|
+
control={
|
|
45
|
+
<WithStyles(Switch)
|
|
46
|
+
checked={false}
|
|
47
|
+
classes={
|
|
48
|
+
Object {
|
|
49
|
+
"bar": "",
|
|
50
|
+
"checked": undefined,
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
onChange={[MockFunction]}
|
|
54
|
+
/>
|
|
55
|
+
}
|
|
56
|
+
label="Set correct answers"
|
|
57
|
+
/>
|
|
58
|
+
</div>
|
|
59
|
+
`;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`tokenizer snapshot renders 1`] = `
|
|
4
|
+
<div
|
|
5
|
+
className=""
|
|
6
|
+
>
|
|
7
|
+
<WithStyles(Controls)
|
|
8
|
+
onClear={[Function]}
|
|
9
|
+
onParagraphs={[Function]}
|
|
10
|
+
onSentences={[Function]}
|
|
11
|
+
onToggleCorrectMode={[Function]}
|
|
12
|
+
onWords={[Function]}
|
|
13
|
+
setCorrectMode={false}
|
|
14
|
+
/>
|
|
15
|
+
<TokenText
|
|
16
|
+
className=""
|
|
17
|
+
onSelectToken={[Function]}
|
|
18
|
+
onTokenClick={[Function]}
|
|
19
|
+
text="foo"
|
|
20
|
+
tokens={
|
|
21
|
+
Array [
|
|
22
|
+
Object {
|
|
23
|
+
"end": 1,
|
|
24
|
+
"start": 0,
|
|
25
|
+
"text": "f",
|
|
26
|
+
},
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
/>
|
|
30
|
+
</div>
|
|
31
|
+
`;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`token-text snapshot renders 1`] = `
|
|
4
|
+
<div
|
|
5
|
+
onClick={[Function]}
|
|
6
|
+
>
|
|
7
|
+
<WithStyles(Component)
|
|
8
|
+
end={13}
|
|
9
|
+
key="0"
|
|
10
|
+
onClick={[Function]}
|
|
11
|
+
predefined={true}
|
|
12
|
+
start={0}
|
|
13
|
+
text="lorem
|
|
14
|
+
foo bar"
|
|
15
|
+
/>
|
|
16
|
+
</div>
|
|
17
|
+
`;
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { normalize, sentences, words, paragraphs, sort, intersection } from '../builder';
|
|
2
|
+
|
|
3
|
+
const token = (start, end, text) => ({ start, end, text });
|
|
4
|
+
|
|
5
|
+
const selection = (start, end) => ({ start, end });
|
|
6
|
+
|
|
7
|
+
const o = (strings, ...exp) => {
|
|
8
|
+
return strings.reduce((acc, v, index) => {
|
|
9
|
+
const e = exp[index];
|
|
10
|
+
const s = typeof e === 'object' ? JSON.stringify(e) : e;
|
|
11
|
+
return `${acc}${v}${s || ''}`;
|
|
12
|
+
}, '');
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
describe('builder', () => {
|
|
16
|
+
describe('intersection', () => {
|
|
17
|
+
const assert = (selection, tokens, expected) => {
|
|
18
|
+
it(o`${selection}, ${tokens} => ${expected}`, () => {
|
|
19
|
+
const received = intersection(selection, tokens);
|
|
20
|
+
expect(received.results).toEqual(expected);
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
assert(selection(2, 3), [token(0, 1)], []);
|
|
25
|
+
assert(selection(1, 2), [token(0, 1)], []);
|
|
26
|
+
assert(selection(0, 1), [token(0, 1)], [{ token: token(0, 1), type: 'exact-fit' }]);
|
|
27
|
+
assert(selection(0, 2), [token(0, 1)], [{ token: token(0, 1), type: 'within-selection' }]);
|
|
28
|
+
assert(selection(0, 2), [token(1, 2)], [{ token: token(1, 2), type: 'within-selection' }]);
|
|
29
|
+
assert(
|
|
30
|
+
selection(0, 10),
|
|
31
|
+
[token(1, 2), token(2, 3)],
|
|
32
|
+
[
|
|
33
|
+
{ token: token(1, 2), type: 'within-selection' },
|
|
34
|
+
{ token: token(2, 3), type: 'within-selection' },
|
|
35
|
+
],
|
|
36
|
+
);
|
|
37
|
+
assert(
|
|
38
|
+
selection(0, 10),
|
|
39
|
+
[token(1, 2), token(2, 11)],
|
|
40
|
+
[
|
|
41
|
+
{ token: token(1, 2), type: 'within-selection' },
|
|
42
|
+
{ token: token(2, 11), type: 'overlap' },
|
|
43
|
+
],
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('sort', () => {
|
|
48
|
+
it('sorts', () => {
|
|
49
|
+
const out = sort([token(1, 2), token(0, 1)]);
|
|
50
|
+
expect(out).toEqual([token(0, 1), token(1, 2)]);
|
|
51
|
+
});
|
|
52
|
+
it('sorts', () => {
|
|
53
|
+
const out = sort([token(0, 1), token(1, 2)]);
|
|
54
|
+
expect(out).toEqual([token(0, 1), token(1, 2)]);
|
|
55
|
+
});
|
|
56
|
+
xit('sorts', () => {
|
|
57
|
+
expect(() => sort([token(0, 2), token(1, 2)])).toThrow(Error);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe('normalize', () => {
|
|
61
|
+
const assert = (input, tokens, expected) => {
|
|
62
|
+
it(`${input} + ${JSON.stringify(tokens)} -> ${JSON.stringify(expected)}`, () => {
|
|
63
|
+
const out = normalize(input, tokens);
|
|
64
|
+
expect(out).toEqual(expected);
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
assert(
|
|
68
|
+
null,
|
|
69
|
+
[],
|
|
70
|
+
[
|
|
71
|
+
{
|
|
72
|
+
text: '',
|
|
73
|
+
start: 0,
|
|
74
|
+
end: 0,
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
);
|
|
78
|
+
assert(
|
|
79
|
+
'abcde',
|
|
80
|
+
[
|
|
81
|
+
{ text: 'b', start: 1, end: 2 },
|
|
82
|
+
{ text: 'd', start: 3, end: 4 },
|
|
83
|
+
],
|
|
84
|
+
[
|
|
85
|
+
{ text: 'a', start: 0, end: 1 },
|
|
86
|
+
{ text: 'b', start: 1, end: 2, predefined: true },
|
|
87
|
+
{ text: 'c', start: 2, end: 3 },
|
|
88
|
+
{ text: 'd', start: 3, end: 4, predefined: true },
|
|
89
|
+
{ text: 'e', start: 4, end: 5 },
|
|
90
|
+
],
|
|
91
|
+
);
|
|
92
|
+
assert(
|
|
93
|
+
'abc',
|
|
94
|
+
[{ text: 'c', start: 2, end: 3 }],
|
|
95
|
+
[
|
|
96
|
+
{ text: 'ab', start: 0, end: 2 },
|
|
97
|
+
{ text: 'c', start: 2, end: 3, predefined: true },
|
|
98
|
+
],
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
assert(
|
|
102
|
+
'abc',
|
|
103
|
+
[
|
|
104
|
+
{ text: 'c', start: 2, end: 3 },
|
|
105
|
+
{ text: 'b', start: 1, end: 2 },
|
|
106
|
+
],
|
|
107
|
+
[
|
|
108
|
+
{ text: 'a', start: 0, end: 1 },
|
|
109
|
+
{ text: 'b', start: 1, end: 2, predefined: true },
|
|
110
|
+
{ text: 'c', start: 2, end: 3, predefined: true },
|
|
111
|
+
],
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
assert(
|
|
115
|
+
'abc',
|
|
116
|
+
[{ text: 'a', start: 0, end: 1 }],
|
|
117
|
+
[
|
|
118
|
+
{ text: 'a', start: 0, end: 1, predefined: true },
|
|
119
|
+
{ text: 'bc', start: 1, end: 3 },
|
|
120
|
+
],
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
assert(
|
|
124
|
+
'abcd',
|
|
125
|
+
[
|
|
126
|
+
{ text: 'b', start: 1, end: 2 },
|
|
127
|
+
{ text: 'c', start: 2, end: 3 },
|
|
128
|
+
{ text: 'd', start: 3, end: 4 },
|
|
129
|
+
],
|
|
130
|
+
[
|
|
131
|
+
{ text: 'a', start: 0, end: 1 },
|
|
132
|
+
{ text: 'b', start: 1, end: 2, predefined: true },
|
|
133
|
+
{ text: 'c', start: 2, end: 3, predefined: true },
|
|
134
|
+
{ text: 'd', start: 3, end: 4, predefined: true },
|
|
135
|
+
],
|
|
136
|
+
);
|
|
137
|
+
assert(
|
|
138
|
+
'abcde',
|
|
139
|
+
[
|
|
140
|
+
{ text: 'b', start: 1, end: 2 },
|
|
141
|
+
{ text: 'c', start: 2, end: 3 },
|
|
142
|
+
{ text: 'd', start: 3, end: 4 },
|
|
143
|
+
],
|
|
144
|
+
[
|
|
145
|
+
{ text: 'a', start: 0, end: 1 },
|
|
146
|
+
{ text: 'b', start: 1, end: 2, predefined: true },
|
|
147
|
+
{ text: 'c', start: 2, end: 3, predefined: true },
|
|
148
|
+
{ text: 'd', start: 3, end: 4, predefined: true },
|
|
149
|
+
{ text: 'e', start: 4, end: 5 },
|
|
150
|
+
],
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
// same token defined multiple times
|
|
154
|
+
assert(
|
|
155
|
+
'abcde',
|
|
156
|
+
[
|
|
157
|
+
{ text: 'c', start: 2, end: 3 },
|
|
158
|
+
{ text: 'b', start: 1, end: 2 },
|
|
159
|
+
{ text: 'c', start: 2, end: 3 },
|
|
160
|
+
{ text: 'd', start: 3, end: 4 },
|
|
161
|
+
{ text: 'c', start: 2, end: 3 },
|
|
162
|
+
],
|
|
163
|
+
[
|
|
164
|
+
{ text: 'a', start: 0, end: 1 },
|
|
165
|
+
{ text: 'b', start: 1, end: 2, predefined: true },
|
|
166
|
+
{ text: 'c', start: 2, end: 3, predefined: true },
|
|
167
|
+
{ text: 'd', start: 3, end: 4, predefined: true },
|
|
168
|
+
{ text: 'e', start: 4, end: 5 },
|
|
169
|
+
],
|
|
170
|
+
);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe('words', () => {
|
|
174
|
+
it('works', () => {
|
|
175
|
+
const out = words('foo. bar');
|
|
176
|
+
expect(out).toEqual([
|
|
177
|
+
{
|
|
178
|
+
text: 'foo.',
|
|
179
|
+
start: 0,
|
|
180
|
+
end: 4,
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
text: 'bar',
|
|
184
|
+
start: 5,
|
|
185
|
+
end: 8,
|
|
186
|
+
},
|
|
187
|
+
]);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
describe('sentences', () => {
|
|
192
|
+
it('foobar', () => {
|
|
193
|
+
const text = 'This is foo. This is bar.';
|
|
194
|
+
const out = sentences(text);
|
|
195
|
+
expect(out[0]).toEqual({ text: 'This is foo.', start: 0, end: 12 });
|
|
196
|
+
expect(out[1]).toEqual({ text: 'This is bar.', start: 13, end: 25 });
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('works', () => {
|
|
200
|
+
const text =
|
|
201
|
+
'On Jan. 20, former Sen. Barack Obama became the 44th President of the USA. Millions attended the Inauguration.';
|
|
202
|
+
|
|
203
|
+
const out = sentences(text);
|
|
204
|
+
expect(out.length).toEqual(2);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('works for sentences separated by \n', () => {
|
|
208
|
+
const text = 'This is foo\nThis is bar';
|
|
209
|
+
const out = sentences(text);
|
|
210
|
+
expect(out[0]).toEqual({ text: 'This is foo', start: 0, end: 11 });
|
|
211
|
+
expect(out[1]).toEqual({ text: 'This is bar', start: 12, end: 23 });
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('works for sentences ending in one-character-words', () => {
|
|
215
|
+
const text =
|
|
216
|
+
"This is Sentence 1. This is Sentence 2. This is Sentence 3. This is Sentence 4. Dr. A. said he'll call in 5.";
|
|
217
|
+
|
|
218
|
+
const out = sentences(text);
|
|
219
|
+
|
|
220
|
+
expect(out.length).toEqual(5);
|
|
221
|
+
|
|
222
|
+
expect(out).toEqual([
|
|
223
|
+
{ text: 'This is Sentence 1.', start: 0, end: 19 },
|
|
224
|
+
{ text: 'This is Sentence 2.', start: 20, end: 39 },
|
|
225
|
+
{ text: 'This is Sentence 3.', start: 40, end: 59 },
|
|
226
|
+
{ text: 'This is Sentence 4.', start: 60, end: 79 },
|
|
227
|
+
{ text: "Dr. A. said he'll call in 5.", start: 80, end: 108 },
|
|
228
|
+
]);
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
describe('paragraphs', () => {
|
|
233
|
+
it('foobar', () => {
|
|
234
|
+
const text = 'This is foo. This is bar.\nThis is foobar. This is barfoo.';
|
|
235
|
+
const out = paragraphs(text);
|
|
236
|
+
expect(out[0]).toEqual({
|
|
237
|
+
text: 'This is foo. This is bar.',
|
|
238
|
+
start: 0,
|
|
239
|
+
end: 25,
|
|
240
|
+
});
|
|
241
|
+
expect(out[1]).toEqual({
|
|
242
|
+
text: 'This is foobar. This is barfoo.',
|
|
243
|
+
start: 26,
|
|
244
|
+
end: 57,
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
it('works', () => {
|
|
248
|
+
const text =
|
|
249
|
+
'On Jan. 20, former Sen. Barack Obama became the 44th President of the USA. Millions attended the Inauguration.' +
|
|
250
|
+
'\\ndadadadadadadadada.';
|
|
251
|
+
|
|
252
|
+
const out = paragraphs(text);
|
|
253
|
+
expect(out.length).toEqual(1);
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Controls } from '../controls';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { shallow, configure } from 'enzyme';
|
|
4
|
+
import Adapter from 'enzyme-adapter-react-16';
|
|
5
|
+
|
|
6
|
+
configure({ adapter: new Adapter() });
|
|
7
|
+
|
|
8
|
+
describe('controls', () => {
|
|
9
|
+
describe('snapshot', () => {
|
|
10
|
+
it('renders', () => {
|
|
11
|
+
const w = shallow(
|
|
12
|
+
<Controls
|
|
13
|
+
classes={{ button: 'button' }}
|
|
14
|
+
onClear={jest.fn()}
|
|
15
|
+
onWords={jest.fn()}
|
|
16
|
+
onSentences={jest.fn()}
|
|
17
|
+
onParagraphs={jest.fn()}
|
|
18
|
+
setCorrectMode={false}
|
|
19
|
+
onToggleCorrectMode={jest.fn()}
|
|
20
|
+
/>,
|
|
21
|
+
);
|
|
22
|
+
expect(w).toMatchSnapshot();
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { Tokenizer } from '../index';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { shallow } from 'enzyme';
|
|
4
|
+
import { words, sentences, paragraphs } from '../builder';
|
|
5
|
+
|
|
6
|
+
const tokens = () => [
|
|
7
|
+
{
|
|
8
|
+
start: 0,
|
|
9
|
+
end: 1,
|
|
10
|
+
text: 'f',
|
|
11
|
+
},
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
const eff = () => tokens()[0];
|
|
15
|
+
|
|
16
|
+
jest.mock('../builder', () => ({
|
|
17
|
+
words: jest.fn().mockReturnValue([{ start: 0, end: 3, text: 'foo' }]),
|
|
18
|
+
sentences: jest.fn().mockReturnValue([{ start: 0, end: 3, text: 'foo' }]),
|
|
19
|
+
paragraphs: jest.fn().mockReturnValue([{ start: 0, end: 3, text: 'foo' }]),
|
|
20
|
+
}));
|
|
21
|
+
describe('tokenizer', () => {
|
|
22
|
+
describe('snapshot', () => {
|
|
23
|
+
it('renders', () => {
|
|
24
|
+
const w = shallow(<Tokenizer text="foo" classes={{}} onChange={jest.fn()} tokens={tokens()} />);
|
|
25
|
+
expect(w).toMatchSnapshot();
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe('logic', () => {
|
|
30
|
+
let w;
|
|
31
|
+
let onChange;
|
|
32
|
+
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
onChange = jest.fn();
|
|
35
|
+
w = shallow(<Tokenizer text="foo" classes={{}} onChange={onChange} tokens={tokens()} />);
|
|
36
|
+
});
|
|
37
|
+
describe('tokenIndex', () => {
|
|
38
|
+
it('returns 0', () => {
|
|
39
|
+
const index = w.instance().tokenIndex(eff());
|
|
40
|
+
expect(index).toEqual(0);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('returns -1', () => {
|
|
44
|
+
const index = w.instance().tokenIndex({ start: 2, end: 3, text: 'f' });
|
|
45
|
+
expect(index).toEqual(-1);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('tokenClick', () => {
|
|
50
|
+
let i;
|
|
51
|
+
|
|
52
|
+
beforeEach(() => {
|
|
53
|
+
i = w.instance();
|
|
54
|
+
i.setCorrect = jest.fn();
|
|
55
|
+
i.removeToken = jest.fn();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('calls removeToken if setCorrectMode == false', () => {
|
|
59
|
+
i.tokenClick(eff());
|
|
60
|
+
expect(i.setCorrect).not.toBeCalled();
|
|
61
|
+
expect(i.removeToken).toBeCalled();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('calls setCorrect if setCorrectMode == true', () => {
|
|
65
|
+
i.setState({ setCorrectMode: true });
|
|
66
|
+
i.tokenClick(eff());
|
|
67
|
+
expect(i.setCorrect).toBeCalled();
|
|
68
|
+
expect(i.removeToken).not.toBeCalled();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
describe('selectToken', () => {
|
|
73
|
+
it('calls onChange', () => {
|
|
74
|
+
w.instance().selectToken({ start: 1, end: 3, text: 'oo' }, [{ start: 0, end: 1, text: 'f' }]);
|
|
75
|
+
expect(onChange).toBeCalledWith([{ start: 1, end: 3, text: 'oo' }], '');
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
describe('buildParagraphsTokens', () => {
|
|
80
|
+
it('calls paragraphs', () => {
|
|
81
|
+
w.instance().buildTokens('paragraph', paragraphs);
|
|
82
|
+
expect(paragraphs).toBeCalledWith('foo');
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe('buildSentenceTokens', () => {
|
|
87
|
+
it('calls sentences', () => {
|
|
88
|
+
w.instance().buildTokens('sentence', sentences);
|
|
89
|
+
expect(sentences).toBeCalledWith('foo');
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
describe('buildWordTokens', () => {
|
|
94
|
+
it('calls words', () => {
|
|
95
|
+
w.instance().buildTokens('word', words);
|
|
96
|
+
expect(words).toBeCalledWith('foo');
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe('clear', () => {
|
|
101
|
+
it('calls onChange with an empty array', () => {
|
|
102
|
+
w.instance().clear();
|
|
103
|
+
expect(onChange).toBeCalledWith([], '');
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
describe('toggleCorrectMode', () => {
|
|
108
|
+
it('set state', () => {
|
|
109
|
+
w.setState({ setCorrectMode: true });
|
|
110
|
+
w.instance().toggleCorrectMode();
|
|
111
|
+
expect(w.state('setCorrectMode')).toEqual(false);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('setCorrect', () => {
|
|
116
|
+
it('calls onChange', () => {
|
|
117
|
+
w.instance().setCorrect({ start: 0, end: 1, text: 'f' });
|
|
118
|
+
expect(onChange).toBeCalledWith([{ start: 0, end: 1, text: 'f', correct: true }], '');
|
|
119
|
+
});
|
|
120
|
+
it('calls onChange w/ correct: false', () => {
|
|
121
|
+
w.setProps({
|
|
122
|
+
tokens: [{ start: 0, end: 1, text: 'f', correct: true }],
|
|
123
|
+
});
|
|
124
|
+
w.instance().setCorrect({ start: 0, end: 1, text: 'f' });
|
|
125
|
+
expect(onChange).toBeCalledWith([{ start: 0, end: 1, text: 'f', correct: false }], '');
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe('removeToken', () => {
|
|
130
|
+
it('calls onChange', () => {
|
|
131
|
+
w.instance().removeToken({ start: 0, end: 1, text: 'f' });
|
|
132
|
+
expect(onChange).toBeCalledWith([], '');
|
|
133
|
+
});
|
|
134
|
+
it('does not call onChange if it cant find the token', () => {
|
|
135
|
+
w.instance().removeToken({ start: 2, end: 3, text: 'a' });
|
|
136
|
+
expect(onChange).not.toBeCalled();
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { clearSelection, getCaretCharacterOffsetWithin } from '../selection-utils';
|
|
2
|
+
|
|
3
|
+
describe('selection-utils', () => {
|
|
4
|
+
let selection;
|
|
5
|
+
let range;
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
selection = {
|
|
8
|
+
removeAllRanges: jest.fn(),
|
|
9
|
+
addRange: jest.fn(),
|
|
10
|
+
getRangeAt: jest.fn().mockReturnValue(range),
|
|
11
|
+
};
|
|
12
|
+
global.document.getSelection = jest.fn().mockReturnValue(selection);
|
|
13
|
+
global.document.createRange = jest.fn();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe('clearSelection', () => {
|
|
17
|
+
it('calls removeAllRanges', () => {
|
|
18
|
+
clearSelection();
|
|
19
|
+
expect(selection.removeAllRanges).toBeCalled();
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
xdescribe('getCaretCharacterOffsetWithin', () => {
|
|
24
|
+
it('TODO', () => {});
|
|
25
|
+
});
|
|
26
|
+
});
|