-
Notifications
You must be signed in to change notification settings - Fork 44
/
to-have-text-content.js
55 lines (49 loc) 路 1.76 KB
/
to-have-text-content.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import { matcherHint } from 'jest-matcher-utils';
import { compose, defaultTo, is, join, map, path, filter } from 'ramda';
import { checkReactElement, getMessage, matches, normalize } from './utils';
function getText(child, currentValue = '') {
let value = currentValue;
if (!child) {
return value;
} else if (Array.isArray(child)) {
return child.reduce((acc, element) => acc + getText(path(['props', 'children'], element)), '');
} else if (typeof child === 'object') {
return getText(path(['props', 'children'], child), value);
} else {
return `${value}${child}`;
}
}
export function toHaveTextContent(element, checkWith) {
checkReactElement(element, toHaveTextContent, this);
// step 9: enjoy your text content 鈽猴笍
const textContent = compose(
// step 8: strip out extra whitespace
normalize,
// step 7: join the resulting array
join(''),
// step 6: filter out values hidden by React
filter(child => typeof child === 'string' || typeof child === 'number'),
// step 5: map the array to get text content
map(child => (typeof child === 'object' ? getText(child) : child)),
// step 4: make sure non-array children end up in an array
child => (is(Array, child) ? child : [child]),
// step 3: default to an array
defaultTo([]),
// step 2: drill down to the children
path(['props', 'children']),
// step 1: get the element
)(element);
return {
pass: matches(textContent, checkWith),
message: () => {
const to = this.isNot ? 'not to' : 'to';
return getMessage(
matcherHint(`${this.isNot ? '.not' : ''}.toHaveTextContent`, 'element', ''),
`Expected element ${to} have text content`,
checkWith,
'Received',
textContent,
);
},
};
}