-
Notifications
You must be signed in to change notification settings - Fork 4.4k
/
Copy pathto-match-style-diff-snapshot.js
85 lines (77 loc) · 2.04 KB
/
to-match-style-diff-snapshot.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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/**
* External dependencies
*/
const snapshotDiff = require( 'snapshot-diff' );
const getStyleSheets = () =>
Array.from( document.getElementsByTagName( 'style' ) );
/**
*
* @param {Element | null} element
* @param {HTMLStyleElement[]} styleSheets
*/
const getStyleRulesForElement = ( element, styleSheets ) => {
return styleSheets.reduce( ( matchingRules, styleSheet ) => {
const found = [];
try {
Array.from( styleSheet.sheet.cssRules ).forEach( ( rule ) => {
if ( element?.matches( rule.selectorText ) ) {
found.push( rule.style );
}
} );
} catch ( e ) {}
return [ ...matchingRules, ...found ];
}, [] );
};
/*
* To clean up the style rule, we're going to pluck out the defined key/value
* pairs of the provided rule.
*
* The shape would look something like this:
*
* {
* 0: 'border-left',
* 1: 'margin-left',
* ...
* length: 2
* }
*
* The only rules we're interested in are defined with numeric keys.
* We are able to know how many are defined by looking at the `length` value.
*
* With that information, we can figure out the necessary key/value pairs
* we need for the cleaned up style rule.
*/
const cleanStyleRule = ( rule ) => {
const size = Array.from( Array( rule.length ).keys() );
const rules = size.reduce( ( acc, i ) => {
const key = rule[ i ];
const value = rule[ key ];
return { ...acc, [ key ]: value };
}, {} );
return rules;
};
/**
* @param {Element | null} received
* @param {Element | null} expected
* @param {string} testName
*/
function toMatchStyleDiffSnapshot( received, expected, testName ) {
const styleSheets = getStyleSheets();
const receivedStyles = getStyleRulesForElement( received, styleSheets ).map(
cleanStyleRule
);
const expectedStyles = getStyleRulesForElement( expected, styleSheets ).map(
cleanStyleRule
);
return snapshotDiff.toMatchDiffSnapshot.call(
this,
receivedStyles,
expectedStyles,
{
aAnnotation: 'Received styles',
bAnnotation: 'Base styles',
},
testName || ''
);
}
expect.extend( { toMatchStyleDiffSnapshot } );