Skip to content

Commit 9d326ca

Browse files
author
Deepak kudi
committed
Fix nested SVG title queries
1 parent e395d5b commit 9d326ca

2 files changed

Lines changed: 51 additions & 11 deletions

File tree

src/__tests__/element-queries.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,23 @@ test('query/get title element of SVG', () => {
642642
expect(queryByTitle('Close').id).toEqual('svg-title')
643643
})
644644

645+
test('query/get nested title element of SVG graphics element', () => {
646+
const {getByTitle, queryByTitle} = render(`
647+
<div>
648+
<svg>
649+
<g>
650+
<path id="svg-path">
651+
<title>Close</title>
652+
</path>
653+
</g>
654+
</svg>
655+
</div>
656+
`)
657+
658+
expect(getByTitle('Close').id).toEqual('svg-path')
659+
expect(queryByTitle('Close').id).toEqual('svg-path')
660+
})
661+
645662
test('queryByTitle matches case with non-string matcher', () => {
646663
const {queryByTitle} = render(`<span title="1" />`)
647664
expect(queryByTitle(1)).toBeTruthy()

src/queries/title.ts

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,21 @@ import {
1414
buildQueries,
1515
} from './all-utils'
1616

17-
const isSvgTitle = (node: HTMLElement) =>
18-
node.tagName.toLowerCase() === 'title' &&
19-
node.parentElement?.tagName.toLowerCase() === 'svg'
17+
const getSvgTitleOwner = (node: HTMLElement) => {
18+
if (
19+
node.tagName.toLowerCase() !== 'title' ||
20+
node.namespaceURI !== 'http://www.w3.org/2000/svg'
21+
) {
22+
return null
23+
}
24+
25+
const parent = node.parentElement
26+
if (!parent || parent.tagName.toLowerCase() === 'svg') {
27+
return node
28+
}
29+
30+
return parent
31+
}
2032

2133
const queryAllByTitle: AllByBoundAttribute = (
2234
container,
@@ -26,14 +38,25 @@ const queryAllByTitle: AllByBoundAttribute = (
2638
checkContainerType(container)
2739
const matcher = exact ? matches : fuzzyMatches
2840
const matchNormalizer = makeNormalizer({collapseWhitespace, trim, normalizer})
29-
return Array.from(
30-
container.querySelectorAll<HTMLElement>('[title], svg > title'),
31-
).filter(
32-
node =>
33-
matcher(node.getAttribute('title'), node, text, matchNormalizer) ||
34-
(isSvgTitle(node) &&
35-
matcher(getNodeText(node), node, text, matchNormalizer)),
36-
)
41+
const results = new Set<HTMLElement>()
42+
43+
Array.from(
44+
container.querySelectorAll<HTMLElement>('[title], svg title'),
45+
).forEach(node => {
46+
if (matcher(node.getAttribute('title'), node, text, matchNormalizer)) {
47+
results.add(node)
48+
}
49+
50+
const svgTitleOwner = getSvgTitleOwner(node)
51+
if (
52+
svgTitleOwner &&
53+
matcher(getNodeText(node), svgTitleOwner, text, matchNormalizer)
54+
) {
55+
results.add(svgTitleOwner)
56+
}
57+
})
58+
59+
return Array.from(results)
3760
}
3861

3962
const getMultipleError: GetErrorFunction<[unknown]> = (c, title) =>

0 commit comments

Comments
 (0)