From 8d5545969a6d8573d5bd7b02843619c3f112f53d Mon Sep 17 00:00:00 2001 From: Ari Perkkio Date: Wed, 3 Mar 2021 20:06:28 +0200 Subject: [PATCH] fix: detect appended text nodes --- src/to-be-announced.ts | 13 ++++++------- src/utils.ts | 24 ++++++++++++++++-------- test/to-be-announced.dom.test.ts | 8 ++++++++ 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/to-be-announced.ts b/src/to-be-announced.ts index 8b1c15a..db92d29 100644 --- a/src/to-be-announced.ts +++ b/src/to-be-announced.ts @@ -1,4 +1,5 @@ import { + getClosestElement, getParentLiveRegion, isElement, isInDOM, @@ -34,7 +35,10 @@ const incorrectlyUsedStatusMessages: string[] = []; * - `textContent` of live region should have changed */ function updateAnnouncements(node: Node) { - const parentLiveRegion = getParentLiveRegion(node); + const element = getClosestElement(node); + if (!element) return; + + const parentLiveRegion = getParentLiveRegion(element); if (parentLiveRegion) { const politenessSetting = resolvePolitenessSetting(parentLiveRegion); @@ -85,12 +89,7 @@ function onTextContentChange(this: Node) { // https://github.com/facebook/react/blob/9198a5cec0936a21a5ba194a22fcbac03eba5d1d/packages/react-dom/src/client/setTextContent.js#L12-L35 function onNodeValueChange(this: Node) { - // This should be a TEXT_NODE - const element = isElement(this) ? this : this.parentElement; - - if (element) { - updateAnnouncements(element); - } + updateAnnouncements(this); } function onAppendChild(newChild: Node) { diff --git a/src/utils.ts b/src/utils.ts index 056ae98..84842ab 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -16,8 +16,20 @@ export const LIVE_REGION_QUERY = [ // '[role="timer"]', ].join(', '); -export function isElement(node: Node): node is Element { - return node && 'closest' in node; +export function isElement(node: Node | null): node is Element { + return node != null && 'closest' in node; +} + +export function getClosestElement(node: Node): Element | null { + if (isElement(node)) { + return node; + } + + if (node.parentNode) { + return getClosestElement(node.parentNode); + } + + return null; } export function isLiveRegionAttribute( @@ -33,12 +45,8 @@ export function isInDOM(node: Node): boolean { return isElement(node) && node.closest('html') != null; } -export function getParentLiveRegion(node: Node): Element | null { - if (isElement(node)) { - return node.closest(LIVE_REGION_QUERY); - } - - return null; +export function getParentLiveRegion(element: Element): Element | null { + return element.closest(LIVE_REGION_QUERY); } function isPolitenessSetting( diff --git a/test/to-be-announced.dom.test.ts b/test/to-be-announced.dom.test.ts index d592d94..20c02aa 100644 --- a/test/to-be-announced.dom.test.ts +++ b/test/to-be-announced.dom.test.ts @@ -70,6 +70,14 @@ import { appendToRoot, Tag } from './utils'; expect('First').not.toBeAnnounced(); expect('Second').toBeAnnounced(); }); + + test('should announce when text node is appended into existing container', () => { + appendToRoot(element); + + element.appendChild(document.createTextNode('Hello world')); + + expect('Hello world').toBeAnnounced(); + }); }); });