Skip to content

Commit

Permalink
feat(shadow-dom): getClosestElement to traverse up the shadow root …
Browse files Browse the repository at this point in the history
…host
  • Loading branch information
AriPerkkio committed Feb 12, 2022
1 parent 485a736 commit 7aa5557
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 3 deletions.
15 changes: 15 additions & 0 deletions src/queries.ts
Expand Up @@ -22,3 +22,18 @@ export function closest(

return null;
}

/**
* `Node.parentNode` as method which traverses tree up when `ShadowRoot` is encountered
*/
export function getParentNode(node: Node): Node['parentNode'] {
if (node.parentNode || !getConfig().includeShadowDom) {
return node.parentNode;
}

if (isShadowRoot(node)) {
return node.host;
}

return null;
}
6 changes: 4 additions & 2 deletions src/utils.ts
Expand Up @@ -41,8 +41,10 @@ export function getClosestElement(node: Node): Element | null {
return node;
}

if (node.parentNode) {
return getClosestElement(node.parentNode);
const parentNode = queries.getParentNode(node);

if (parentNode) {
return getClosestElement(parentNode);
}

return null;
Expand Down
53 changes: 52 additions & 1 deletion test/utils.test.ts
@@ -1,7 +1,58 @@
import { configure } from '../src/config';
import { getTextContent, isInDOM } from '../src/utils';
import { getClosestElement, getTextContent, isInDOM } from '../src/utils';
import { appendToRoot } from './utils';

describe('getClosestElement', () => {
test('returns itself when element', () => {
const element = document.createElement('div');

expect(getClosestElement(element)).toBe(element);
});

test('returns parent element of text node', () => {
const element = document.createElement('div');
const text = document.createTextNode('Hello world');
element.appendChild(text);

expect(getClosestElement(text)).toBe(element);
});

test('returns null when node has no parent', () => {
const text = document.createTextNode('Hello world');

expect(getClosestElement(text)).toBe(null);
});

test('returns null when node has parentless node as parent', () => {
const parentNode = { parentNode: null } as Node;
const text = { parentNode } as Node;

expect(getClosestElement(text)).toBe(null);
});

test('returns parent of element inside shadow root', () => {
configure({ includeShadowDom: true });

const text = document.createTextNode('Hello world');
const root = document.createElement('div');

root.attachShadow({ mode: 'open' }).appendChild(text);

expect(getClosestElement(text)).toBe(root);
});

test('does not traverse shadow dom when config.includeShadowDom is false', () => {
configure({ includeShadowDom: false });

const text = document.createTextNode('Hello world');
const root = document.createElement('div');

root.attachShadow({ mode: 'open' }).appendChild(text);

expect(getClosestElement(text)).toBe(null);
});
});

describe('getTextContent', () => {
let root: HTMLElement;

Expand Down

0 comments on commit 7aa5557

Please sign in to comment.