@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.
Files changed (35) hide show
  1. package/CHANGELOG.json +1 -632
  2. package/CHANGELOG.md +178 -28
  3. package/NEXT.CHANGELOG.json +1 -0
  4. package/lib/legend.js +63 -36
  5. package/lib/legend.js.map +1 -1
  6. package/lib/token-select/index.js +3 -2
  7. package/lib/token-select/index.js.map +1 -1
  8. package/lib/token-select/token.js +113 -74
  9. package/lib/token-select/token.js.map +1 -1
  10. package/lib/tokenizer/controls.js +14 -0
  11. package/lib/tokenizer/controls.js.map +1 -1
  12. package/lib/tokenizer/token-text.js +11 -2
  13. package/lib/tokenizer/token-text.js.map +1 -1
  14. package/package.json +8 -6
  15. package/src/__tests__/__snapshots__/text-select.test.jsx.snap +21 -0
  16. package/src/__tests__/text-select.test.jsx +34 -0
  17. package/src/__tests__/utils.test.jsx +27 -0
  18. package/src/legend.js +54 -36
  19. package/src/token-select/__tests__/__snapshots__/index.test.jsx.snap +49 -0
  20. package/src/token-select/__tests__/__snapshots__/token.test.jsx.snap +27 -0
  21. package/src/token-select/__tests__/index.test.jsx +257 -0
  22. package/src/token-select/__tests__/token.test.jsx +33 -0
  23. package/src/token-select/index.jsx +3 -1
  24. package/src/token-select/token.jsx +98 -72
  25. package/src/tokenizer/__tests__/__snapshots__/controls.test.jsx.snap +59 -0
  26. package/src/tokenizer/__tests__/__snapshots__/index.test.jsx.snap +31 -0
  27. package/src/tokenizer/__tests__/__snapshots__/token-text.test.jsx.snap +17 -0
  28. package/src/tokenizer/__tests__/builder.test.js +256 -0
  29. package/src/tokenizer/__tests__/controls.test.jsx +25 -0
  30. package/src/tokenizer/__tests__/index.test.jsx +140 -0
  31. package/src/tokenizer/__tests__/selection-utils.test.js +26 -0
  32. package/src/tokenizer/__tests__/token-text.test.jsx +136 -0
  33. package/src/tokenizer/controls.jsx +20 -1
  34. package/src/tokenizer/token-text.jsx +9 -0
  35. 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
- const Wrapper = ({ useWrapper, children, classNameContainer, iconClass, Icon }) => {
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
- return children;
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
- render() {
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
- className = classNames(classes.token, classes.selected, classes.disabledBlack);
76
- } else if (correct !== undefined) {
77
- className = classNames(Token.rootClassName, classes.custom);
78
- Icon = correct ? Check : Close;
79
- classNameContainer = correct === true ? classes.correct : classes.incorrect;
80
- iconClass = correct === true ? classes.correctIcon : classes.incorrectIcon;
81
- } else if (isMissing) {
82
- className = classNames(Token.rootClassName, classes.custom, isMissing === true && classes.missing);
83
- } else {
84
- className = classNames(
85
- Token.rootClassName,
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.secondaryLight(),
156
+ backgroundColor: color.blueGrey100(),
132
157
  },
133
158
  selectable: {
134
159
  [theme.breakpoints.up(769)]: {
135
160
  '&:hover': {
136
- backgroundColor: color.primaryLight(),
161
+ backgroundColor: color.blueGrey300(),
162
+ color: theme.palette.common.black,
137
163
  '& > *': {
138
- backgroundColor: color.primaryLight(),
164
+ backgroundColor: color.blueGrey300(),
139
165
  },
140
166
  },
141
167
  },
142
168
  },
143
169
  selected: {
144
- lineHeight: 2,
145
- marginTop: theme.spacing.unit / 2,
146
- backgroundColor: color.primaryLight(),
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.primaryLight(),
176
+ backgroundColor: color.blueGrey100(),
149
177
  },
150
178
  },
151
179
  highlight: {
152
- border: `dashed 2px ${color.disabled()}`,
153
- lineHeight: 2,
154
- boxSizing: 'border-box',
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.disabled()}`,
161
- lineHeight: 2,
162
- boxSizing: 'border-box',
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
- backgroundColor: color.correctSecondary(),
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
- backgroundColor: color.incorrectSecondary(),
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
- backgroundColor: color.incorrectSecondary(),
184
- border: `${color.missing()} dashed 2px`,
185
- textDecoration: `line-through ${color.missing()}`,
207
+ border: `${color.incorrectWithIcon()} dashed 2px`,
186
208
  },
187
209
  incorrectIcon: {
188
- verticalAlign: 'middle',
189
- fontSize: 'larger',
190
- color: color.missing(),
210
+ backgroundColor: color.incorrectWithIcon(),
191
211
  },
192
-
193
212
  correctIcon: {
194
- verticalAlign: 'middle',
195
- fontSize: 'larger',
196
- color: color.correct(),
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
+ });