Skip to content

Commit 5f1cf80

Browse files
committed
fix(ui-test-utils): fix query by text/contents
TEST PLAN: findAll({ text: 'foo' }) should return only immediate parent element of the text cotent findAll({ contains: 'foo' }) should return all elements that contain the text findAll({ locator: '[data-foo="bar"]', text: 'foo' }) should only return an element if: <span data-foo="bar">foo</span> Change-Id: I6f1af6f563649395c026e4191f661e7f9af65a09 Reviewed-on: https://gerrit.instructure.com/165423 Tested-by: Jenkins Reviewed-by: Stephen Jensen <sejensen@instructure.com> Product-Review: Jennifer Stern <jstern@instructure.com> QA-Review: Jennifer Stern <jstern@instructure.com>
1 parent 80e54cb commit 5f1cf80

File tree

6 files changed

+79
-18
lines changed

6 files changed

+79
-18
lines changed

packages/ui-portal/src/components/Portal/__tests__/Portal.test.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@ describe('<Portal />', () => {
3232
await mount(
3333
<Portal open>Hello World</Portal>
3434
)
35-
const portal = await Portal.find({ text: 'Hello World' })
35+
const portal = await Portal.find({ contains: 'Hello World' })
3636
expect(portal.getDOMNode()).to.exist()
3737
})
3838

3939
it('should be accessible', async () => {
4040
await mount(
4141
<Portal open>Hello World</Portal>
4242
)
43-
const portal = await Portal.find({ text: 'Hello World' })
43+
const portal = await Portal.find({ contains: 'Hello World' })
4444
expect(await portal.accessible()).to.be.true()
4545
})
4646

@@ -102,7 +102,7 @@ describe('<Portal />', () => {
102102
</Portal>
103103
)
104104

105-
const portal = await Portal.find({ text: 'Hello World' })
105+
const portal = await Portal.find({ contains: 'Hello World' })
106106
const button = await within(portal).find('button')
107107

108108
button.keyDown('Enter')
@@ -127,7 +127,7 @@ describe('<Portal />', () => {
127127
</div>
128128
)
129129
const portal = await Portal.find({
130-
text: 'Hello World',
130+
contains: 'Hello World',
131131
timeout: 0,
132132
errorIfNotFound: false
133133
})
@@ -148,7 +148,7 @@ describe('<Portal />', () => {
148148
</div>
149149
)
150150

151-
const portal = await Portal.find({ text: 'Hello World'})
151+
const portal = await Portal.find({ contains: 'Hello World'})
152152

153153
expect(portal.getDOMNode().parentNode)
154154
.to.equal(document.getElementById('portal-mount-node'))

packages/ui-test-utils/src/utils/__tests__/queries.test.js

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ describe('find, findAll', () => {
5353
describe('by text', () => {
5454
it('can get elements by matching their text content', async () => {
5555
await mount(
56-
<div>
56+
<div data-locator="TestLocator">
5757
<span>Currently showing</span>
5858
<span>
5959
{`Step
@@ -67,17 +67,49 @@ describe('find, findAll', () => {
6767
expect(await findAll({ text: 'Step 1 of 4' })).to.have.length(1)
6868
})
6969

70+
it('can get elements by matching their nested contents', async () => {
71+
await mount(
72+
<div>
73+
<span>Currently showing</span>
74+
</div>
75+
)
76+
77+
expect(await findAll({
78+
contains: 'Currently showing'
79+
}))
80+
.to.have.length(3) // div (mount node), div, span
81+
})
82+
83+
it('should filter out non-matching results', async () => {
84+
await mount(
85+
<div data-locator="TestLocator">
86+
<span>Currently showing</span>
87+
</div>
88+
)
89+
90+
expect(await findAll({
91+
locator: '[data-locator="TestLocator"]',
92+
text: 'Foo',
93+
errorIfNotFound: false,
94+
timeout: 0
95+
})).to.have.length(0)
96+
})
97+
7098
it('can get elements by matching their text across adjacent text nodes', async () => {
71-
const textDiv = document.createElement('div')
99+
const div = document.createElement('div')
72100
const textNodeContent = ['£', '24', '.', '99']
73101
textNodeContent
74102
.map(text => document.createTextNode(text))
75-
.forEach(textNode => textDiv.appendChild(textNode))
103+
.forEach(textNode => div.appendChild(textNode))
76104

77105
const subject = await mount(<div />)
78-
subject.getDOMNode().appendChild(textDiv)
106+
subject.getDOMNode().appendChild(div)
79107

80-
expect(await findAll({ text: '£24.99' })).to.have.length(1)
108+
const nodes = await findAll({
109+
text: '£24.99'
110+
})
111+
112+
expect(nodes).to.have.length(1)
81113
})
82114

83115
it('matches case with RegExp matcher', async () => {
@@ -86,7 +118,6 @@ describe('find, findAll', () => {
86118
expect(await findAll({ text: /Step 1 of 4/, errorIfNotFound: false, timeout: 0 }))
87119
.to.have.length(0)
88120
})
89-
90121
})
91122

92123
describe('by label', () => {

packages/ui-test-utils/src/utils/filters.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@
2121
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2222
* SOFTWARE.
2323
*/
24-
import { matchElementByAttribute, matchElementByText, matchElementBySelector } from './matchers'
24+
import {
25+
matchElementByAttribute,
26+
matchElementByText,
27+
matchElementBySelector,
28+
matchElementByContents
29+
} from './matchers'
2530

2631
function filterBySelector (container, results, selector, options) {
2732
if (Array.isArray(results)) {
@@ -33,12 +38,12 @@ function filterBySelector (container, results, selector, options) {
3338
}
3439

3540
function filterByAttribute (container, results, name, value, options = {}) {
36-
return Array.isArray(results) ? results : queryAllBySelector(container, `[${name}]`)
41+
return (Array.isArray(results) ? results : queryAllBySelector(container, `[${name}]`))
3742
.filter(element => matchElementByAttribute(element, name, value, options))
3843
}
3944

4045
function filterByTitle (container, results, title, options) {
41-
return Array.isArray(results) ? results : queryAllBySelector(container, '[title], svg > title')
46+
return (Array.isArray(results) ? results : queryAllBySelector(container, '[title], svg > title'))
4247
.filter((element) => {
4348
if (matchElementBySelector(element, 'svg > title')) {
4449
return matchElementByText(element, title, options)
@@ -50,12 +55,16 @@ function filterByTitle (container, results, title, options) {
5055
})
5156
}
5257

58+
function filterByContents (container, results, elementOrString, options) {
59+
return (Array.isArray(results) ? results : queryAllBySelector(container, '*'))
60+
.filter(element => matchElementByContents(element, elementOrString, options))
61+
}
62+
5363
function filterByText (container, results, text, options) {
54-
return Array.isArray(results) ? results : queryAllBySelector(container, '*')
64+
return (Array.isArray(results) ? results : queryAllBySelector(container, '*'))
5565
.filter(element => matchElementByText(element, text, options))
5666
}
5767

58-
5968
function filterByLabelText (container, results, text, options = {}) {
6069
// aria-labelledby may not refer to a label element, so we get elements with ids too
6170
const matches = queryAllBySelector(container, 'label, [id]')
@@ -102,6 +111,7 @@ function queryAllBySelector (element = document.documentElement, selector = '*')
102111

103112
export {
104113
filterByLabelText,
114+
filterByContents,
105115
filterByText,
106116
filterByTitle,
107117
filterByAttribute,

packages/ui-test-utils/src/utils/helpers.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
* SOFTWARE.
2323
*/
2424
import runAxeCheck from '@instructure/ui-axe-check'
25-
import { fireEvent, prettyDOM, getNodeText } from 'dom-testing-library'
25+
import { fireEvent, prettyDOM } from 'dom-testing-library'
2626

2727
function typeIn (element, value) {
2828
element.value = value // eslint-disable-line no-param-reassign
@@ -34,7 +34,7 @@ function typeIn (element, value) {
3434
}
3535

3636
function text (element) {
37-
return getNodeText(element)
37+
return element.textContent
3838
}
3939

4040
function visible (element) {

packages/ui-test-utils/src/utils/matchers.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,17 @@ function matchElementByText (element, text, options = {}) {
3535
return matcher(getNodeText(element), element, text, { collapseWhitespace, trim })
3636
}
3737

38+
function matchElementByContents (element, elementOrString, options = {}) {
39+
const { exact, collapseWhitespace, trim } = options
40+
const matcher = exact ? matches : fuzzyMatches
41+
42+
if (elementOrString instanceof Element) {
43+
return element.contains(elementOrString)
44+
} else {
45+
return matcher(element.textContent, element, elementOrString, { collapseWhitespace, trim })
46+
}
47+
}
48+
3849
function matchElementByAttribute (element, name, value, options = {}) {
3950
const { exact, collapseWhitespace, trim } = options
4051
const matcher = exact ? matches : fuzzyMatches
@@ -47,6 +58,7 @@ function matchElementBySelector (element, selector) {
4758

4859
export {
4960
matchElementByText,
61+
matchElementByContents,
5062
matchElementByAttribute,
5163
matchElementBySelector
5264
}

packages/ui-test-utils/src/utils/queries.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { waitForQueryResult } from './waitForQueryResult'
3131
import {
3232
filterByLabelText,
3333
filterByText,
34+
filterByContents,
3435
filterByTitle,
3536
filterByAttribute,
3637
filterBySelector
@@ -53,6 +54,7 @@ async function findAll (...args) {
5354
css,
5455
tag,
5556
text,
57+
contains,
5658
label,
5759
title,
5860
value,
@@ -82,6 +84,10 @@ async function findAll (...args) {
8284
result = filterByText(element, result, text, options)
8385
}
8486

87+
if (contains) {
88+
result = filterByContents(element, result, contains, options)
89+
}
90+
8591
if (value) {
8692
result = filterByAttribute(element, result, 'value', value, options)
8793
}
@@ -152,6 +158,7 @@ function parseQueryArguments () {
152158
css,
153159
tag,
154160
text,
161+
contains,
155162
label,
156163
value,
157164
attribute,
@@ -163,6 +170,7 @@ function parseQueryArguments () {
163170
title,
164171
tag,
165172
text,
173+
contains,
166174
label,
167175
value,
168176
attribute

0 commit comments

Comments
 (0)