import { assert } from "chai"; import { getFallbackSelector } from "../src/selector-fallback.js"; import { testMultiSelector, testSelector } from "../src/utilities-dom.js"; describe("selector - fallback", function () { let root: Element; beforeEach(function () { root = document.body.appendChild(document.createElement("div")); }); afterEach(function () { root.parentNode.removeChild(root); }); it("should produce simple selector", () => { root.innerHTML = "
"; const needleElement = root.firstElementChild; const result = getFallbackSelector([needleElement]); assert.ok(testSelector([needleElement], result, root)); }); it("should produce nested selector", () => { root.innerHTML = "
"; const needleElement = root.firstElementChild.firstElementChild.firstElementChild; const result = getFallbackSelector([needleElement]); assert.ok(testSelector([needleElement], result, root)); }); it("should produce selector beside similar elements", () => { root.innerHTML = "
"; const needleElement = root.firstElementChild; const result = getFallbackSelector([needleElement]); assert.ok(testSelector([needleElement], result, root)); }); // https://developer.mozilla.org/en-US/docs/Web/API/element/querySelector#the_entire_hierarchy_counts it("should consider entire hierarchy", () => { root.innerHTML = `
haystack
needle
this should not match
`; const haystackElement = root.firstElementChild.firstElementChild; const needleElement = root.firstElementChild.firstElementChild.firstElementChild; const result = getFallbackSelector([needleElement]); assert.ok(testSelector([needleElement], result, haystackElement)); }); it("should produce selector for multiple elements", () => { root.innerHTML = `
`; const needleElements = [...root.querySelectorAll("div")]; const result = getFallbackSelector(needleElements); needleElements.forEach((element) => { assert.ok(testMultiSelector(element, result, root)); }); }); it("should use :scope when the root option is set", () => { root.innerHTML = `
root
needle
`; const rootElement = root.firstElementChild; const needleElement = rootElement.firstElementChild.firstElementChild; const result = getFallbackSelector([needleElement], rootElement); assert.ok(testSelector([needleElement], result, rootElement)); assert.equal(result, ":scope > :nth-child(1) > :nth-child(1)"); }); it("should generate correct nth-child path for nested elements", () => { root.innerHTML = `
`; const targetElement = root.querySelector("span"); const result = getFallbackSelector([targetElement], root); assert.ok(testSelector([targetElement], result, root)); assert.equal(result, ":scope > :nth-child(1) > :nth-child(3) > :nth-child(1)"); }); it("should work with elements in iframe", () => { const iframe = document.createElement("iframe"); iframe.style.display = "none"; document.body.appendChild(iframe); const iframeDoc = iframe.contentDocument; iframeDoc.body.innerHTML = `
`; const container = iframeDoc.body; const targetElement = iframeDoc.querySelector("span"); const result = getFallbackSelector([targetElement], container); document.body.removeChild(iframe); assert.ok(testSelector([targetElement], result, container)); assert.equal(result, ":scope > :nth-child(1) > :nth-child(2)"); }); });