diff --git a/src/__tests__/to-contain-html.js b/src/__tests__/to-contain-html.js
index 6bfd95e..259e1fd 100644
--- a/src/__tests__/to-contain-html.js
+++ b/src/__tests__/to-contain-html.js
@@ -106,7 +106,15 @@ describe('.toContainHTML', () => {
Expected:
non-existant element
>
Received:
- >
+ >
`)
})
+
+ test('ignores attribute order when comparing HTML', () => {
+ const {container} = render('link')
+ const link = container.querySelector('a')
+
+ expect(link).toContainHTML('link')
+ expect(link).toContainHTML('link')
+ })
})
diff --git a/src/to-contain-html.js b/src/to-contain-html.js
index 30158ee..fd54e70 100644
--- a/src/to-contain-html.js
+++ b/src/to-contain-html.js
@@ -1,8 +1,26 @@
import {checkHtmlElement} from './utils'
+function sortAttributes(root) {
+ const elements = [root, ...root.querySelectorAll('*')]
+ for (const el of elements) {
+ if (!el.attributes || el.attributes.length < 2) continue
+ const attrs = Array.from(el.attributes).sort((a, b) =>
+ a.name.localeCompare(b.name),
+ )
+ for (const attr of attrs) {
+ el.removeAttribute(attr.name)
+ }
+ for (const attr of attrs) {
+ el.setAttribute(attr.name, attr.value)
+ }
+ }
+}
+
function getNormalizedHtml(container, htmlText) {
const div = container.ownerDocument.createElement('div')
div.innerHTML = htmlText
+ // Sort attributes so order differences do not affect matching or messages
+ sortAttributes(div)
return div.innerHTML
}
@@ -13,8 +31,14 @@ export function toContainHTML(container, htmlText) {
throw new Error(`.toContainHTML() expects a string value, got ${htmlText}`)
}
+ const normalizedContainerHtml = getNormalizedHtml(
+ container,
+ container.outerHTML,
+ )
+ const normalizedHtmlText = getNormalizedHtml(container, htmlText)
+
return {
- pass: container.outerHTML.includes(getNormalizedHtml(container, htmlText)),
+ pass: normalizedContainerHtml.includes(normalizedHtmlText),
message: () => {
return [
this.utils.matcherHint(
@@ -24,9 +48,10 @@ export function toContainHTML(container, htmlText) {
),
'Expected:',
// eslint-disable-next-line new-cap
- ` ${this.utils.EXPECTED_COLOR(htmlText)}`,
+ ` ${this.utils.EXPECTED_COLOR(normalizedHtmlText)}`,
'Received:',
- ` ${this.utils.printReceived(container.cloneNode(true))}`,
+ // eslint-disable-next-line new-cap
+ ` ${this.utils.RECEIVED_COLOR(normalizedContainerHtml)}`,
].join('\n')
},
}