From 04b98fad994df2ca1957f4b2b6661bd5fce95ef0 Mon Sep 17 00:00:00 2001 From: Leandro Lourenci Date: Thu, 16 Jan 2020 20:29:06 -0300 Subject: [PATCH 1/9] Fix toBeVisible ignoring Details element --- src/__tests__/to-be-visible.js | 15 ++++++++++++++- src/to-be-visible.js | 8 +++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/__tests__/to-be-visible.js b/src/__tests__/to-be-visible.js index d3f63ded..dc94aec7 100644 --- a/src/__tests__/to-be-visible.js +++ b/src/__tests__/to-be-visible.js @@ -1,7 +1,7 @@ import {render} from './helpers/test-utils' test('.toBeVisible', () => { - const {container} = render(` + const {container, queryByTestId} = render(`

Main title

@@ -14,6 +14,14 @@ test('.toBeVisible', () => {

Hello World

+
+ Title of hidden +
Hidden details
+
+
+ Title of visible +
Visible details
+
`) @@ -32,4 +40,9 @@ test('.toBeVisible', () => { expect(() => expect(container.querySelector('p')).toBeVisible(), ).toThrowError() + + expect(queryByTestId('visible-details').querySelector('div')).toBeVisible() + // expect(queryByTestId('visible-details').querySelector('summary')).toBeVisible() + // expect(queryByTestId('hidden-details').querySelector('summary')).toBeVisible() + expect(queryByTestId('hidden-details').querySelector('div')).not.toBeVisible() }) diff --git a/src/to-be-visible.js b/src/to-be-visible.js index 44a6c907..32e39d8b 100644 --- a/src/to-be-visible.js +++ b/src/to-be-visible.js @@ -14,10 +14,16 @@ function isStyleVisible(element) { ) } +function hasElementAVisibleAttribute(element) { + return element.nodeName === 'DETAILS' + ? element.hasAttribute('open') + : !element.hasAttribute('hidden') +} + function isElementVisible(element) { return ( isStyleVisible(element) && - !element.hasAttribute('hidden') && + hasElementAVisibleAttribute(element) && (!element.parentElement || isElementVisible(element.parentElement)) ) } From 6bd600c4fc1a6815754bae9ce216db2924059574 Mon Sep 17 00:00:00 2001 From: Leandro Lourenci Date: Sat, 18 Jan 2020 18:41:55 -0300 Subject: [PATCH 2/9] Add specs for click on details --- src/__tests__/to-be-visible.js | 133 ++++++++++++++++++++++----------- 1 file changed, 88 insertions(+), 45 deletions(-) diff --git a/src/__tests__/to-be-visible.js b/src/__tests__/to-be-visible.js index dc94aec7..103f57cb 100644 --- a/src/__tests__/to-be-visible.js +++ b/src/__tests__/to-be-visible.js @@ -1,48 +1,91 @@ import {render} from './helpers/test-utils' -test('.toBeVisible', () => { - const {container, queryByTestId} = render(` -
-
-

Main title

-

Secondary title

-

Secondary title

-

Secondary title

-
Secondary title
-
- -
-

Hello World

-
-
- Title of hidden -
Hidden details
-
-
- Title of visible -
Visible details
-
-
- `) - - expect(container.querySelector('header')).toBeVisible() - expect(container.querySelector('h1')).not.toBeVisible() - expect(container.querySelector('h2')).not.toBeVisible() - expect(container.querySelector('h3')).not.toBeVisible() - expect(container.querySelector('h4')).not.toBeVisible() - expect(container.querySelector('h5')).toBeVisible() - expect(container.querySelector('button')).not.toBeVisible() - expect(container.querySelector('strong')).not.toBeVisible() - - expect(() => - expect(container.querySelector('header')).not.toBeVisible(), - ).toThrowError() - expect(() => - expect(container.querySelector('p')).toBeVisible(), - ).toThrowError() - - expect(queryByTestId('visible-details').querySelector('div')).toBeVisible() - // expect(queryByTestId('visible-details').querySelector('summary')).toBeVisible() - // expect(queryByTestId('hidden-details').querySelector('summary')).toBeVisible() - expect(queryByTestId('hidden-details').querySelector('div')).not.toBeVisible() +describe('.toBeVisible', () => { + it('returns the visibility of an element', () => { + const {container} = render(` +
+
+

Main title

+

Secondary title

+

Secondary title

+

Secondary title

+
Secondary title
+
+ +
+

Hello World

+
+
+ `) + + expect(container.querySelector('header')).toBeVisible() + expect(container.querySelector('h1')).not.toBeVisible() + expect(container.querySelector('h2')).not.toBeVisible() + expect(container.querySelector('h3')).not.toBeVisible() + expect(container.querySelector('h4')).not.toBeVisible() + expect(container.querySelector('h5')).toBeVisible() + expect(container.querySelector('button')).not.toBeVisible() + expect(container.querySelector('strong')).not.toBeVisible() + + expect(() => + expect(container.querySelector('header')).not.toBeVisible(), + ).toThrowError() + expect(() => + expect(container.querySelector('p')).toBeVisible(), + ).toThrowError() + }) + + describe('with a
element', () => { + let subject + + afterEach(() => { + subject = undefined + }) + + describe('when the details is opened', () => { + beforeEach(() => { + subject = render(` +
+ Title of visible +
Visible details
+
+ `) + }) + + it('returns true', () => { + expect(subject.container.querySelector('div')).toBeVisible() + }) + + describe('when the user clicks on the summary', () => { + beforeEach(() => subject.container.querySelector('summary').click()) + + it('returns false', () => { + expect(subject.container.querySelector('div')).not.toBeVisible() + }) + }) + }) + + describe('when the details is not opened', () => { + beforeEach(() => { + subject = render(` +
+ Title of hidden +
Hidden details
+
+ `) + }) + + it('returns false', () => { + expect(subject.container.querySelector('div')).not.toBeVisible() + }) + + describe('when the user clicks on the summary', () => { + beforeEach(() => subject.container.querySelector('summary').click()) + + it('returns true', () => { + expect(subject.container.querySelector('div')).toBeVisible() + }) + }) + }) + }) }) From 118201f54d4b6aae0d3aa89b6fe35bc062342ee8 Mon Sep 17 00:00:00 2001 From: Leandro Lourenci Date: Sun, 19 Jan 2020 11:43:52 -0300 Subject: [PATCH 3/9] Check for hidden attribute on Details element --- src/__tests__/to-be-visible.js | 15 +++++++++++++++ src/to-be-visible.js | 7 ++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/__tests__/to-be-visible.js b/src/__tests__/to-be-visible.js index 103f57cb..caa813da 100644 --- a/src/__tests__/to-be-visible.js +++ b/src/__tests__/to-be-visible.js @@ -87,5 +87,20 @@ describe('.toBeVisible', () => { }) }) }) + + describe('when the details is opened but it is hidden', () => { + beforeEach(() => { + subject = render(` + + `) + }) + + it('returns false', () => { + expect(subject.container.querySelector('div')).not.toBeVisible() + }) + }) }) }) diff --git a/src/to-be-visible.js b/src/to-be-visible.js index 32e39d8b..4aca59fe 100644 --- a/src/to-be-visible.js +++ b/src/to-be-visible.js @@ -15,9 +15,10 @@ function isStyleVisible(element) { } function hasElementAVisibleAttribute(element) { - return element.nodeName === 'DETAILS' - ? element.hasAttribute('open') - : !element.hasAttribute('hidden') + return ( + !element.hasAttribute('hidden') && + (element.nodeName === 'DETAILS' ? element.hasAttribute('open') : true) + ) } function isElementVisible(element) { From b3cdb090170ed00c9d090c28c937807651e05b81 Mon Sep 17 00:00:00 2001 From: Leandro Lourenci Date: Sun, 19 Jan 2020 17:08:57 -0300 Subject: [PATCH 4/9] Fix summary visibility --- src/__tests__/to-be-visible.js | 30 +++++++++++++++++++++++++----- src/to-be-visible.js | 12 +++++++----- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/__tests__/to-be-visible.js b/src/__tests__/to-be-visible.js index caa813da..b6953e0b 100644 --- a/src/__tests__/to-be-visible.js +++ b/src/__tests__/to-be-visible.js @@ -52,16 +52,24 @@ describe('.toBeVisible', () => { `) }) - it('returns true', () => { + it('returns true to the details content', () => { expect(subject.container.querySelector('div')).toBeVisible() }) + it('returns true to the details summary', () => { + expect(subject.container.querySelector('summary')).toBeVisible() + }) + describe('when the user clicks on the summary', () => { beforeEach(() => subject.container.querySelector('summary').click()) - it('returns false', () => { + it('returns false to the details content', () => { expect(subject.container.querySelector('div')).not.toBeVisible() }) + + it('returns true to the details summary', () => { + expect(subject.container.querySelector('summary')).toBeVisible() + }) }) }) @@ -75,16 +83,24 @@ describe('.toBeVisible', () => { `) }) - it('returns false', () => { + it('returns false to the details content', () => { expect(subject.container.querySelector('div')).not.toBeVisible() }) + it('returns true to the summary content', () => { + expect(subject.container.querySelector('summary')).toBeVisible() + }) + describe('when the user clicks on the summary', () => { beforeEach(() => subject.container.querySelector('summary').click()) - it('returns true', () => { + it('returns true to the details content', () => { expect(subject.container.querySelector('div')).toBeVisible() }) + + it('returns true to the details summary', () => { + expect(subject.container.querySelector('summary')).toBeVisible() + }) }) }) @@ -98,9 +114,13 @@ describe('.toBeVisible', () => { `) }) - it('returns false', () => { + it('returns false to the details content', () => { expect(subject.container.querySelector('div')).not.toBeVisible() }) + + it('returns false to the details summary', () => { + expect(subject.container.querySelector('summary')).not.toBeVisible() + }) }) }) }) diff --git a/src/to-be-visible.js b/src/to-be-visible.js index 4aca59fe..2d6b1472 100644 --- a/src/to-be-visible.js +++ b/src/to-be-visible.js @@ -14,18 +14,20 @@ function isStyleVisible(element) { ) } -function hasElementAVisibleAttribute(element) { +function hasElementAVisibleAttribute(element, childElement) { return ( !element.hasAttribute('hidden') && - (element.nodeName === 'DETAILS' ? element.hasAttribute('open') : true) + (element.nodeName === 'DETAILS' && childElement.nodeName !== 'SUMMARY' + ? element.hasAttribute('open') + : true) ) } -function isElementVisible(element) { +function isElementVisible(element, childElement) { return ( isStyleVisible(element) && - hasElementAVisibleAttribute(element) && - (!element.parentElement || isElementVisible(element.parentElement)) + hasElementAVisibleAttribute(element, childElement) && + (!element.parentElement || isElementVisible(element.parentElement, element)) ) } From 3a48d70071bac1fb767cc82ce4d2ea952311757d Mon Sep 17 00:00:00 2001 From: Leandro Lourenci Date: Sun, 19 Jan 2020 17:12:33 -0300 Subject: [PATCH 5/9] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 1fa48a7b..7cd134c6 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,7 @@ clear to read and to maintain. + - [Installation](#installation) - [Usage](#usage) - [Custom matchers](#custom-matchers) @@ -478,6 +479,7 @@ An element is visible if **all** the following conditions are met: - it does not have the [`hidden`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/hidden) attribute +- if `
` it has the `open` attribute #### Examples From cfc4c0594e7ed87d01cf12f67b383e32cbd92c4d Mon Sep 17 00:00:00 2001 From: Leandro Lourenci Date: Mon, 20 Jan 2020 17:16:06 -0300 Subject: [PATCH 6/9] Refactor method to get the attribute visibility --- src/to-be-visible.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/to-be-visible.js b/src/to-be-visible.js index 2d6b1472..43c6362b 100644 --- a/src/to-be-visible.js +++ b/src/to-be-visible.js @@ -14,19 +14,19 @@ function isStyleVisible(element) { ) } -function hasElementAVisibleAttribute(element, childElement) { +function isAttributeVisible(element, previousElement) { return ( !element.hasAttribute('hidden') && - (element.nodeName === 'DETAILS' && childElement.nodeName !== 'SUMMARY' + (element.nodeName === 'DETAILS' && previousElement.nodeName !== 'SUMMARY' ? element.hasAttribute('open') : true) ) } -function isElementVisible(element, childElement) { +function isElementVisible(element, previousElement) { return ( isStyleVisible(element) && - hasElementAVisibleAttribute(element, childElement) && + isAttributeVisible(element, previousElement) && (!element.parentElement || isElementVisible(element.parentElement, element)) ) } From e516b9f42904132a34f5815a63135051669d3817 Mon Sep 17 00:00:00 2001 From: Leandro Lourenci Date: Mon, 20 Jan 2020 19:50:17 -0300 Subject: [PATCH 7/9] Create contexts for nested Details --- src/__tests__/to-be-visible.js | 123 ++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 1 deletion(-) diff --git a/src/__tests__/to-be-visible.js b/src/__tests__/to-be-visible.js index b6953e0b..63f6cfd6 100644 --- a/src/__tests__/to-be-visible.js +++ b/src/__tests__/to-be-visible.js @@ -1,5 +1,6 @@ import {render} from './helpers/test-utils' +// eslint-disable-next-line max-lines-per-function describe('.toBeVisible', () => { it('returns the visibility of an element', () => { const {container} = render(` @@ -35,6 +36,7 @@ describe('.toBeVisible', () => { ).toThrowError() }) + // eslint-disable-next-line max-lines-per-function describe('with a
element', () => { let subject @@ -47,7 +49,7 @@ describe('.toBeVisible', () => { subject = render(`
Title of visible -
Visible details
+
Visible details
`) }) @@ -56,6 +58,10 @@ describe('.toBeVisible', () => { expect(subject.container.querySelector('div')).toBeVisible() }) + it('returns true to the most inner details content', () => { + expect(subject.container.querySelector('small')).toBeVisible() + }) + it('returns true to the details summary', () => { expect(subject.container.querySelector('summary')).toBeVisible() }) @@ -122,5 +128,120 @@ describe('.toBeVisible', () => { expect(subject.container.querySelector('summary')).not.toBeVisible() }) }) + + describe('when there is a nested
', () => { + describe('when the nested
is opened', () => { + beforeEach(() => { + subject = render(` +
+ Title of visible +
Outer content
+
+ Title of nested details +
Inner content
+
+
+ `) + }) + + it('returns true to the nested details content', () => { + expect( + subject.container.querySelector('details > details > div'), + ).toBeVisible() + }) + + it('returns true to the nested details summary', () => { + expect( + subject.container.querySelector('details > details > summary'), + ).toBeVisible() + }) + + it('returns true to the outer details content', () => { + expect(subject.container.querySelector('details > div')).toBeVisible() + }) + + it('returns true to the outer details summary', () => { + expect( + subject.container.querySelector('details > summary'), + ).toBeVisible() + }) + }) + + describe('when the nested
is not opened', () => { + beforeEach(() => { + subject = render(` +
+ Title of visible +
Outer content
+
+ Title of nested details +
Inner content
+
+
+ `) + }) + + it('returns false to the nested details content', () => { + expect( + subject.container.querySelector('details > details > div'), + ).not.toBeVisible() + }) + + it('returns true to the nested details summary', () => { + expect( + subject.container.querySelector('details > details > summary'), + ).toBeVisible() + }) + + it('returns true to the nested details content', () => { + expect(subject.container.querySelector('details > div')).toBeVisible() + }) + + it('returns true to the outer details summary', () => { + expect( + subject.container.querySelector('details > summary'), + ).toBeVisible() + }) + }) + + describe('when the outer
is not opened and the nested one is opened', () => { + beforeEach(() => { + subject = render(` +
+ Title of visible +
Outer content
+
+ Title of nested details +
Inner content
+
+
+ `) + }) + + it('returns false to the nested details content', () => { + expect( + subject.container.querySelector('details > details > div'), + ).not.toBeVisible() + }) + + it('returns false to the nested details summary', () => { + expect( + subject.container.querySelector('details > details > summary'), + ).not.toBeVisible() + }) + + it('returns false to the outer details content', () => { + expect( + subject.container.querySelector('details > div'), + ).not.toBeVisible() + }) + + it('returns true to the outer details summary', () => { + expect( + subject.container.querySelector('details > summary'), + ).toBeVisible() + }) + }) + }) }) }) From 568d4112b5a28270c0246c13a9010547c6a909d9 Mon Sep 17 00:00:00 2001 From: Leandro Lourenci Date: Mon, 20 Jan 2020 19:56:32 -0300 Subject: [PATCH 8/9] Apply suggestions from code review --- src/__tests__/to-be-visible.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/to-be-visible.js b/src/__tests__/to-be-visible.js index 63f6cfd6..e6282f1f 100644 --- a/src/__tests__/to-be-visible.js +++ b/src/__tests__/to-be-visible.js @@ -193,7 +193,7 @@ describe('.toBeVisible', () => { ).toBeVisible() }) - it('returns true to the nested details content', () => { + it('returns true to the outer details content', () => { expect(subject.container.querySelector('details > div')).toBeVisible() }) From c8404ff922ea76032414200af61a4434c2f144d5 Mon Sep 17 00:00:00 2001 From: Leandro Lourenci Date: Mon, 20 Jan 2020 19:58:44 -0300 Subject: [PATCH 9/9] Update src/__tests__/to-be-visible.js --- src/__tests__/to-be-visible.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/to-be-visible.js b/src/__tests__/to-be-visible.js index e6282f1f..43d47284 100644 --- a/src/__tests__/to-be-visible.js +++ b/src/__tests__/to-be-visible.js @@ -129,7 +129,7 @@ describe('.toBeVisible', () => { }) }) - describe('when there is a nested
', () => { + describe('with a nested
element', () => { describe('when the nested
is opened', () => { beforeEach(() => { subject = render(`