Skip to content

Commit 6c5e7b6

Browse files
fix(matchers): use computed styles to determine hidden-ness (ngneat#622)
* fix(matchers): also use computed styles to determine hidden-ness this catches cases like <style>#a{visibility:hidden}<style><div id="a"></div> or where css variables are used. * test: ensure elements with visible computed styles remain visible
1 parent 3a7fc53 commit 6c5e7b6

File tree

2 files changed

+29
-12
lines changed

2 files changed

+29
-12
lines changed

projects/spectator/jest/test/matchers/matchers.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ interface Dummy {
1919
<div id="classes" class="class-a class-b">Classes</div>
2020
<div id="styles" style="background-color: indianred; color: chocolate; --primary: var(--black)"></div>
2121
<custom-element style="visibility: hidden"></custom-element>
22+
<div id="computed-style"></div>
2223
`,
2324
})
2425
export class MatchersComponent {}
@@ -121,6 +122,20 @@ describe('Matchers', () => {
121122
document.querySelector('custom-element')?.shadowRoot?.querySelector("#shadow-dom")
122123
).toBeHidden();
123124
});
125+
126+
it('should detect elements whose computed styles are display: none', () => {
127+
window.getComputedStyle = () => ({ getPropertyValue: (style) => style == 'display' && 'none' });
128+
expect(document.querySelector('#computed-style')).toBeHidden();
129+
window.getComputedStyle = () => ({ getPropertyValue: (style) => style == 'display' && 'block' });
130+
expect(document.querySelector('#computed-style')).toBeVisible();
131+
});
132+
133+
it('should detect elements whose computed styles are visibility: hidden', () => {
134+
window.getComputedStyle = () => ({ getPropertyValue: (style) => style == 'visibility' && 'hidden' });
135+
expect(document.querySelector('#computed-style')).toBeHidden();
136+
window.getComputedStyle = () => ({ getPropertyValue: (style) => style == 'visibility' && 'visible' });
137+
expect(document.querySelector('#computed-style')).toBeVisible();
138+
});
124139
});
125140

126141
describe('toBePartial', () => {

projects/spectator/src/lib/matchers.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -410,11 +410,12 @@ export const toBePartial = comparator((actual, expected) => {
410410

411411
/**
412412
* Hidden elements are elements that have:
413-
* 1. Display property set to "none"
414-
* 2. Width and height set to 0 (check not applied in jest)
415-
* 3. A hidden parent element (this also hides child elements)
416-
* 4. Type equal to "hidden" (only for form elements)
417-
* 5. A "hidden" attribute
413+
* 1. Display or visibility style properties set to "none" or "hidden"
414+
* 2. Display or visibility computed styles set to "none" or "hidden"
415+
* 3. Width and height set to 0 (check not applied in jest)
416+
* 4. A hidden parent element (this also hides child elements)
417+
* 5. Type equal to "hidden" (only for form elements)
418+
* 6. A "hidden" attribute
418419
*/
419420
function isHidden(elOrSelector: HTMLElement | string): boolean {
420421
let el = $(elOrSelector)[0];
@@ -425,8 +426,8 @@ function isHidden(elOrSelector: HTMLElement | string): boolean {
425426

426427
const hiddenWhen = [
427428
(el) => !(el.offsetWidth || el.offsetHeight || el.getClientRects().length),
428-
(el) => el.style.display === 'none',
429-
(el) => el.style.visibility === 'hidden',
429+
(el) => el.style.display === 'none' || window.getComputedStyle(el).getPropertyValue?.('display') === 'none',
430+
(el) => el.style.visibility === 'hidden' || window.getComputedStyle(el).getPropertyValue?.('visibility') === 'hidden',
430431
(el) => el.type === 'hidden',
431432
(el) => el.hasAttribute('hidden'),
432433
];
@@ -454,11 +455,12 @@ function isHidden(elOrSelector: HTMLElement | string): boolean {
454455

455456
/**
456457
* Hidden elements are elements that have:
457-
* 1. Display property set to "none"
458-
* 2. Width and height set to 0
459-
* 3. A hidden parent element (this also hides child elements)
460-
* 4. Type equal to "hidden" (only for form elements)
461-
* 5. A "hidden" attribute
458+
* 1. Display or visibility style properties set to "none" or "hidden"
459+
* 2. Display or visibility computed styles set to "none" or "hidden"
460+
* 3. Width and height set to 0 (check not applied in jest)
461+
* 4. A hidden parent element (this also hides child elements)
462+
* 5. Type equal to "hidden" (only for form elements)
463+
* 6. A "hidden" attribute
462464
*
463465
* expect('div').toBeHidden();
464466
*

0 commit comments

Comments
 (0)