@pie-lib/text-select 1.12.7 → 1.12.8-next.1639
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.json +1 -632
- package/CHANGELOG.md +178 -28
- package/NEXT.CHANGELOG.json +1 -0
- package/lib/legend.js +63 -36
- package/lib/legend.js.map +1 -1
- package/lib/token-select/index.js +3 -2
- package/lib/token-select/index.js.map +1 -1
- package/lib/token-select/token.js +113 -74
- package/lib/token-select/token.js.map +1 -1
- package/lib/tokenizer/controls.js +14 -0
- package/lib/tokenizer/controls.js.map +1 -1
- package/lib/tokenizer/token-text.js +11 -2
- package/lib/tokenizer/token-text.js.map +1 -1
- 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/legend.js +54 -36
- package/src/token-select/__tests__/__snapshots__/index.test.jsx.snap +49 -0
- package/src/token-select/__tests__/__snapshots__/token.test.jsx.snap +27 -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 +98 -72
- 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
|
@@ -2,22 +2,26 @@ import React from 'react';
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { withStyles } from '@material-ui/core/styles';
|
|
4
4
|
import classNames from 'classnames';
|
|
5
|
-
import { color } from '@pie-lib/render-ui';
|
|
6
5
|
import Check from '@material-ui/icons/Check';
|
|
7
6
|
import Close from '@material-ui/icons/Close';
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
if (useWrapper) {
|
|
11
|
-
return (
|
|
12
|
-
<span className={classNameContainer}>
|
|
13
|
-
{children}
|
|
14
|
-
<Icon className={iconClass} viewBox={'0 1 24 24'} />
|
|
15
|
-
</span>
|
|
16
|
-
);
|
|
17
|
-
}
|
|
8
|
+
import { color } from '@pie-lib/render-ui';
|
|
18
9
|
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
// we need to use a larger line height for the token to be more readable
|
|
11
|
+
const LINE_HEIGHT_MULTIPLIER = 3.2;
|
|
12
|
+
// we need a bit more space for correctness indicators
|
|
13
|
+
const CORRECTNESS_LINE_HEIGHT_MULTIPLIER = 3.4;
|
|
14
|
+
const CORRECTNESS_PADDING = 2;
|
|
15
|
+
|
|
16
|
+
const Wrapper = ({ useWrapper, children, classNameContainer, iconClass, Icon }) =>
|
|
17
|
+
useWrapper ? (
|
|
18
|
+
<span className={classNameContainer}>
|
|
19
|
+
{children}
|
|
20
|
+
<Icon className={iconClass} />
|
|
21
|
+
</span>
|
|
22
|
+
) : (
|
|
23
|
+
children
|
|
24
|
+
);
|
|
21
25
|
|
|
22
26
|
Wrapper.propTypes = {
|
|
23
27
|
useWrapper: PropTypes.bool,
|
|
@@ -38,11 +42,11 @@ export class Token extends React.Component {
|
|
|
38
42
|
static propTypes = {
|
|
39
43
|
...TokenTypes,
|
|
40
44
|
classes: PropTypes.object.isRequired,
|
|
45
|
+
text: PropTypes.string.isRequired,
|
|
41
46
|
className: PropTypes.string,
|
|
42
47
|
disabled: PropTypes.bool,
|
|
43
48
|
highlight: PropTypes.bool,
|
|
44
49
|
correct: PropTypes.bool,
|
|
45
|
-
text: PropTypes.string.isRequired,
|
|
46
50
|
};
|
|
47
51
|
|
|
48
52
|
static defaultProps = {
|
|
@@ -50,39 +54,55 @@ export class Token extends React.Component {
|
|
|
50
54
|
text: '',
|
|
51
55
|
};
|
|
52
56
|
|
|
53
|
-
|
|
57
|
+
getClassAndIconConfig = () => {
|
|
54
58
|
const {
|
|
55
|
-
text,
|
|
56
59
|
selectable,
|
|
57
60
|
selected,
|
|
58
61
|
classes,
|
|
59
62
|
className: classNameProp,
|
|
60
63
|
disabled,
|
|
61
|
-
index,
|
|
62
64
|
highlight,
|
|
63
65
|
correct,
|
|
64
66
|
animationsDisabled,
|
|
65
67
|
isMissing,
|
|
66
68
|
} = this.props;
|
|
67
69
|
const isTouchEnabled = 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0;
|
|
68
|
-
|
|
69
|
-
let className;
|
|
70
|
+
const baseClassName = Token.rootClassName;
|
|
70
71
|
let classNameContainer;
|
|
71
72
|
let Icon;
|
|
72
73
|
let iconClass;
|
|
73
74
|
|
|
74
75
|
if (correct === undefined && selected && disabled) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
76
|
+
return {
|
|
77
|
+
className: classNames(classes.token, classes.selected, classes.disabledBlack),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (correct !== undefined) {
|
|
82
|
+
const isCorrect = correct === true;
|
|
83
|
+
return {
|
|
84
|
+
className: classNames(baseClassName, classes.custom),
|
|
85
|
+
classNameContainer: classNames(isCorrect ? classes.correct : classes.incorrect, classes.commonTokenStyle),
|
|
86
|
+
Icon: isCorrect ? Check : Close,
|
|
87
|
+
iconClass: classNames(
|
|
88
|
+
classes.correctnessIndicatorIcon,
|
|
89
|
+
isCorrect ? classes.correctIcon : classes.incorrectIcon,
|
|
90
|
+
),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (isMissing) {
|
|
95
|
+
return {
|
|
96
|
+
className: classNames(baseClassName, classes.custom, classes.missing, classes.commonTokenStyle),
|
|
97
|
+
classNameContainer: classes.commonTokenStyle,
|
|
98
|
+
Icon: Close,
|
|
99
|
+
iconClass: classNames(classes.correctnessIndicatorIcon, classes.incorrectIcon),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
className: classNames(
|
|
105
|
+
baseClassName,
|
|
86
106
|
classes.token,
|
|
87
107
|
disabled && classes.disabled,
|
|
88
108
|
selectable && !disabled && !isTouchEnabled && classes.selectable,
|
|
@@ -91,11 +111,20 @@ export class Token extends React.Component {
|
|
|
91
111
|
highlight && selectable && !disabled && !selected && classes.highlight,
|
|
92
112
|
animationsDisabled && classes.print,
|
|
93
113
|
classNameProp,
|
|
94
|
-
)
|
|
95
|
-
|
|
114
|
+
),
|
|
115
|
+
classNameContainer,
|
|
116
|
+
Icon,
|
|
117
|
+
iconClass,
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
render() {
|
|
122
|
+
const { text, index, correct, isMissing } = this.props;
|
|
123
|
+
const { className, classNameContainer, Icon, iconClass } = this.getClassAndIconConfig();
|
|
124
|
+
|
|
96
125
|
return (
|
|
97
126
|
<Wrapper
|
|
98
|
-
useWrapper={correct !== undefined}
|
|
127
|
+
useWrapper={correct !== undefined || isMissing}
|
|
99
128
|
classNameContainer={classNameContainer}
|
|
100
129
|
iconClass={iconClass}
|
|
101
130
|
Icon={Icon}
|
|
@@ -115,10 +144,6 @@ export default withStyles((theme) => {
|
|
|
115
144
|
token: {
|
|
116
145
|
cursor: 'pointer',
|
|
117
146
|
textIndent: 0,
|
|
118
|
-
padding: theme.spacing.unit / 2,
|
|
119
|
-
paddingRight: 0,
|
|
120
|
-
paddingLeft: 0,
|
|
121
|
-
transition: 'background-color 100ms ease-in',
|
|
122
147
|
},
|
|
123
148
|
disabled: {
|
|
124
149
|
cursor: 'inherit',
|
|
@@ -128,72 +153,73 @@ export default withStyles((theme) => {
|
|
|
128
153
|
cursor: 'inherit',
|
|
129
154
|
},
|
|
130
155
|
disabledAndSelected: {
|
|
131
|
-
backgroundColor: color.
|
|
156
|
+
backgroundColor: color.blueGrey100(),
|
|
132
157
|
},
|
|
133
158
|
selectable: {
|
|
134
159
|
[theme.breakpoints.up(769)]: {
|
|
135
160
|
'&:hover': {
|
|
136
|
-
backgroundColor: color.
|
|
161
|
+
backgroundColor: color.blueGrey300(),
|
|
162
|
+
color: theme.palette.common.black,
|
|
137
163
|
'& > *': {
|
|
138
|
-
backgroundColor: color.
|
|
164
|
+
backgroundColor: color.blueGrey300(),
|
|
139
165
|
},
|
|
140
166
|
},
|
|
141
167
|
},
|
|
142
168
|
},
|
|
143
169
|
selected: {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
170
|
+
backgroundColor: color.blueGrey100(),
|
|
171
|
+
color: theme.palette.common.black,
|
|
172
|
+
lineHeight: `${theme.spacing.unit * LINE_HEIGHT_MULTIPLIER}px`,
|
|
173
|
+
border: `solid 2px ${color.blueGrey900()}`,
|
|
174
|
+
borderRadius: '4px',
|
|
147
175
|
'& > *': {
|
|
148
|
-
backgroundColor: color.
|
|
176
|
+
backgroundColor: color.blueGrey100(),
|
|
149
177
|
},
|
|
150
178
|
},
|
|
151
179
|
highlight: {
|
|
152
|
-
border: `dashed 2px ${color.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
marginTop: theme.spacing.unit / 2,
|
|
156
|
-
display: 'inline-block',
|
|
157
|
-
padding: theme.spacing.unit,
|
|
180
|
+
border: `dashed 2px ${color.blueGrey600()}`,
|
|
181
|
+
borderRadius: '4px',
|
|
182
|
+
lineHeight: `${theme.spacing.unit * LINE_HEIGHT_MULTIPLIER}px`,
|
|
158
183
|
},
|
|
159
184
|
print: {
|
|
160
|
-
border: `dashed 2px ${color.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
marginTop: theme.spacing.unit / 2,
|
|
164
|
-
display: 'inline-block',
|
|
165
|
-
padding: theme.spacing.unit,
|
|
185
|
+
border: `dashed 2px ${color.blueGrey600()}`,
|
|
186
|
+
borderRadius: '4px',
|
|
187
|
+
lineHeight: `${theme.spacing.unit * LINE_HEIGHT_MULTIPLIER}px`,
|
|
166
188
|
color: color.text(),
|
|
167
189
|
},
|
|
168
|
-
|
|
169
190
|
custom: {
|
|
170
191
|
display: 'initial',
|
|
171
192
|
},
|
|
193
|
+
commonTokenStyle: {
|
|
194
|
+
position: 'relative',
|
|
195
|
+
borderRadius: '4px',
|
|
196
|
+
color: theme.palette.common.black,
|
|
197
|
+
lineHeight: `${theme.spacing.unit * CORRECTNESS_LINE_HEIGHT_MULTIPLIER + CORRECTNESS_PADDING}px`,
|
|
198
|
+
padding: `${CORRECTNESS_PADDING}px`,
|
|
199
|
+
},
|
|
172
200
|
correct: {
|
|
173
|
-
|
|
174
|
-
border: `${color.correct()} solid 2px`,
|
|
175
|
-
lineHeight: `${theme.spacing.unit * 4}px`,
|
|
201
|
+
border: `${color.correctTertiary()} solid 2px`,
|
|
176
202
|
},
|
|
177
203
|
incorrect: {
|
|
178
|
-
|
|
179
|
-
border: `${color.missing()} solid 2px`,
|
|
180
|
-
lineHeight: `${theme.spacing.unit * 4}px`,
|
|
204
|
+
border: `${color.incorrectWithIcon()} solid 2px`,
|
|
181
205
|
},
|
|
182
206
|
missing: {
|
|
183
|
-
|
|
184
|
-
border: `${color.missing()} dashed 2px`,
|
|
185
|
-
textDecoration: `line-through ${color.missing()}`,
|
|
207
|
+
border: `${color.incorrectWithIcon()} dashed 2px`,
|
|
186
208
|
},
|
|
187
209
|
incorrectIcon: {
|
|
188
|
-
|
|
189
|
-
fontSize: 'larger',
|
|
190
|
-
color: color.missing(),
|
|
210
|
+
backgroundColor: color.incorrectWithIcon(),
|
|
191
211
|
},
|
|
192
|
-
|
|
193
212
|
correctIcon: {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
213
|
+
backgroundColor: color.correctTertiary(),
|
|
214
|
+
},
|
|
215
|
+
correctnessIndicatorIcon: {
|
|
216
|
+
color: color.white(),
|
|
217
|
+
position: 'absolute',
|
|
218
|
+
top: '-8px',
|
|
219
|
+
left: '-8px',
|
|
220
|
+
borderRadius: '50%',
|
|
221
|
+
fontSize: '12px',
|
|
222
|
+
padding: '2px',
|
|
197
223
|
},
|
|
198
224
|
};
|
|
199
225
|
})(Token);
|
|
@@ -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
|
+
});
|