Skip to content

Commit dd2ec8c

Browse files
authored
fix: dom-utils onChild calling handler for elements outside the parent (@fehmer) (monkeytypegame#7279)
1 parent bd3cd75 commit dd2ec8c

File tree

2 files changed

+30
-5
lines changed

2 files changed

+30
-5
lines changed

frontend/__tests__/utils/dom.jsdom-spec.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
import { describe, it, expect, vi, beforeEach } from "vitest";
22
import { screen } from "@testing-library/dom";
33
import { userEvent } from "@testing-library/user-event";
4-
import { qs } from "../../src/ts/utils/dom";
4+
import { ElementWithUtils, qsr } from "../../src/ts/utils/dom";
55

66
describe("dom", () => {
77
describe("ElementWithUtils", () => {
88
describe("onChild", () => {
99
const handler = vi.fn();
1010

11-
function registerOnChild(event: string, selector: string): void {
12-
const parent = qs("#parent");
11+
function registerOnChild(
12+
event: string,
13+
selector: string,
14+
options?: {
15+
parent?: ElementWithUtils;
16+
},
17+
): void {
18+
const parent = options?.parent ?? qsr("#parent");
1319
parent?.onChild(event, selector, (e) =>
1420
handler({
1521
target: e.target,
@@ -33,7 +39,10 @@ describe("dom", () => {
3339
<div id="inner1" class="inner">test</div>
3440
<div id="inner2" data-testid="inner2" class="inner">
3541
test
36-
<button id="button" data-testid="button">click</button>
42+
<button id="button" data-testid="button">
43+
click me
44+
<i id="icon" data-testid="icon">test</i>
45+
</button>
3746
</div>
3847
</div>
3948
<div id="mid2" class="middle">
@@ -57,6 +66,18 @@ describe("dom", () => {
5766
expect(handler).not.toHaveBeenCalled();
5867
});
5968

69+
it("should not fire when selector doesnt match", async () => {
70+
//GIVEN
71+
const buttonEl = qsr("#button");
72+
registerOnChild("click", "div", { parent: buttonEl });
73+
74+
//WHEN
75+
await userEvent.click(screen.getByTestId("icon"));
76+
77+
//THEN
78+
expect(handler).not.toHaveBeenCalled();
79+
});
80+
6081
it("should fire when selector is clicked", async () => {
6182
//GIVEN
6283
registerOnChild("click", "div");

frontend/src/ts/utils/dom.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,11 @@ export class ElementWithUtils<T extends HTMLElement = HTMLElement> {
311311

312312
let childTarget = target.closest(selector);
313313
//bubble up until no match found or the parent element is reached
314-
while (childTarget !== null && childTarget !== this.native) {
314+
while (
315+
childTarget !== null &&
316+
childTarget !== this.native && //stop on parent
317+
this.native.contains(childTarget) //stop above parent
318+
) {
315319
if (typeof handler === "function") {
316320
handler.call(
317321
childTarget as HTMLElement,

0 commit comments

Comments
 (0)