diff --git a/src/hooks/usePermalink.ts b/src/hooks/usePermalink.ts index a6b19d7de7..87a9c19244 100644 --- a/src/hooks/usePermalink.ts +++ b/src/hooks/usePermalink.ts @@ -167,6 +167,7 @@ export const usePermalink: (args: Args) => HookResult = ({ room, type: argType, text = member.name || resourceId; onClick = (e: ButtonEvent): void => { e.preventDefault(); + e.stopPropagation(); dis.dispatch({ action: Action.ViewUser, member: member, diff --git a/test/components/views/elements/Pill-test.tsx b/test/components/views/elements/Pill-test.tsx index 72c68e117c..2937352468 100644 --- a/test/components/views/elements/Pill-test.tsx +++ b/test/components/views/elements/Pill-test.tsx @@ -31,6 +31,7 @@ import { } from "../../../test-utils"; import DMRoomMap from "../../../../src/utils/DMRoomMap"; import { Action } from "../../../../src/dispatcher/actions"; +import { ButtonEvent } from "../../../../src/components/views/elements/AccessibleButton"; describe("<Pill>", () => { let client: Mocked<MatrixClient>; @@ -43,6 +44,7 @@ describe("<Pill>", () => { const user1Id = "@user1:example.com"; const user2Id = "@user2:example.com"; let renderResult: RenderResult; + let pillParentClickHandler: (e: ButtonEvent) => void; const renderPill = (props: PillProps): void => { const withDefault = { @@ -50,7 +52,12 @@ describe("<Pill>", () => { shouldShowPillAvatar: true, ...props, } as PillProps; - renderResult = render(<Pill {...withDefault} />); + // wrap Pill with a div to allow testing of event bubbling + renderResult = render( + <div onClick={pillParentClickHandler}> + <Pill {...withDefault} /> + </div>, + ); }; filterConsole( @@ -88,6 +95,7 @@ describe("<Pill>", () => { }); jest.spyOn(dis, "dispatch"); + pillParentClickHandler = jest.fn(); }); describe("when rendering a pill for a room", () => { @@ -168,11 +176,13 @@ describe("<Pill>", () => { await userEvent.click(screen.getByText("User 1")); }); - it("should dipsatch a view user action", () => { + it("should dipsatch a view user action and prevent event bubbling", () => { expect(dis.dispatch).toHaveBeenCalledWith({ action: Action.ViewUser, member: room1.getMember(user1Id), }); + + expect(pillParentClickHandler).not.toHaveBeenCalled(); }); }); }); @@ -195,7 +205,11 @@ describe("<Pill>", () => { renderPill({ url: permalinkPrefix, }); - expect(renderResult.asFragment()).toMatchInlineSnapshot(`<DocumentFragment />`); + expect(renderResult.asFragment()).toMatchInlineSnapshot(` + <DocumentFragment> + <div /> + </DocumentFragment> + `); }); it("should not render an avatar or link when called with inMessage = false and shouldShowPillAvatar = false", () => { diff --git a/test/components/views/elements/__snapshots__/Pill-test.tsx.snap b/test/components/views/elements/__snapshots__/Pill-test.tsx.snap index ea973e3686..d9e5810864 100644 --- a/test/components/views/elements/__snapshots__/Pill-test.tsx.snap +++ b/test/components/views/elements/__snapshots__/Pill-test.tsx.snap @@ -1,246 +1,264 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`<Pill> should not render a non-permalink 1`] = `<DocumentFragment />`; +exports[`<Pill> should not render a non-permalink 1`] = ` +<DocumentFragment> + <div /> +</DocumentFragment> +`; exports[`<Pill> should not render an avatar or link when called with inMessage = false and shouldShowPillAvatar = false 1`] = ` <DocumentFragment> - <bdi> - <span - class="mx_Pill mx_RoomPill" - > + <div> + <bdi> <span - class="mx_Pill_linkText" + class="mx_Pill mx_RoomPill" > - Room 1 + <span + class="mx_Pill_linkText" + > + Room 1 + </span> </span> - </span> - </bdi> + </bdi> + </div> </DocumentFragment> `; exports[`<Pill> should render the expected pill for @room 1`] = ` <DocumentFragment> - <bdi> - <span - class="mx_Pill mx_AtRoomPill" - > + <div> + <bdi> <span - aria-hidden="true" - class="mx_BaseAvatar" - role="presentation" + class="mx_Pill mx_AtRoomPill" > <span aria-hidden="true" - class="mx_BaseAvatar_initial" - style="font-size: 10.4px; width: 16px; line-height: 16px;" + class="mx_BaseAvatar" + role="presentation" > - R + <span + aria-hidden="true" + class="mx_BaseAvatar_initial" + style="font-size: 10.4px; width: 16px; line-height: 16px;" + > + R + </span> + <img + alt="" + aria-hidden="true" + class="mx_BaseAvatar_image" + data-testid="avatar-img" + src="data:image/png;base64,00" + style="width: 16px; height: 16px;" + /> + </span> + <span + class="mx_Pill_linkText" + > + @room </span> - <img - alt="" - aria-hidden="true" - class="mx_BaseAvatar_image" - data-testid="avatar-img" - src="data:image/png;base64,00" - style="width: 16px; height: 16px;" - /> </span> - <span - class="mx_Pill_linkText" - > - @room - </span> - </span> - </bdi> + </bdi> + </div> </DocumentFragment> `; exports[`<Pill> should render the expected pill for a room alias 1`] = ` <DocumentFragment> - <bdi> - <a - class="mx_Pill mx_RoomPill" - href="https://matrix.to/#/#room1:example.com" - > - <span - aria-hidden="true" - class="mx_BaseAvatar" - role="presentation" + <div> + <bdi> + <a + class="mx_Pill mx_RoomPill" + href="https://matrix.to/#/#room1:example.com" > <span aria-hidden="true" - class="mx_BaseAvatar_initial" - style="font-size: 10.4px; width: 16px; line-height: 16px;" + class="mx_BaseAvatar" + role="presentation" > - R + <span + aria-hidden="true" + class="mx_BaseAvatar_initial" + style="font-size: 10.4px; width: 16px; line-height: 16px;" + > + R + </span> + <img + alt="" + aria-hidden="true" + class="mx_BaseAvatar_image" + data-testid="avatar-img" + src="data:image/png;base64,00" + style="width: 16px; height: 16px;" + /> </span> - <img - alt="" - aria-hidden="true" - class="mx_BaseAvatar_image" - data-testid="avatar-img" - src="data:image/png;base64,00" - style="width: 16px; height: 16px;" - /> - </span> - <span - class="mx_Pill_linkText" - > - Room 1 - </span> - </a> - </bdi> + <span + class="mx_Pill_linkText" + > + Room 1 + </span> + </a> + </bdi> + </div> </DocumentFragment> `; exports[`<Pill> should render the expected pill for a space 1`] = ` <DocumentFragment> - <bdi> - <a - class="mx_Pill mx_RoomPill" - href="https://matrix.to/#/!space1:example.com" - > - <span - aria-hidden="true" - class="mx_BaseAvatar" - role="presentation" + <div> + <bdi> + <a + class="mx_Pill mx_RoomPill" + href="https://matrix.to/#/!space1:example.com" > <span aria-hidden="true" - class="mx_BaseAvatar_initial" - style="font-size: 10.4px; width: 16px; line-height: 16px;" + class="mx_BaseAvatar" + role="presentation" > - S + <span + aria-hidden="true" + class="mx_BaseAvatar_initial" + style="font-size: 10.4px; width: 16px; line-height: 16px;" + > + S + </span> + <img + alt="" + aria-hidden="true" + class="mx_BaseAvatar_image" + data-testid="avatar-img" + src="data:image/png;base64,00" + style="width: 16px; height: 16px;" + /> </span> - <img - alt="" - aria-hidden="true" - class="mx_BaseAvatar_image" - data-testid="avatar-img" - src="data:image/png;base64,00" - style="width: 16px; height: 16px;" - /> - </span> - <span - class="mx_Pill_linkText" - > - Space 1 - </span> - </a> - </bdi> + <span + class="mx_Pill_linkText" + > + Space 1 + </span> + </a> + </bdi> + </div> </DocumentFragment> `; exports[`<Pill> should render the expected pill for a user not in the room 1`] = ` <DocumentFragment> - <bdi> - <a - class="mx_Pill mx_UserPill" - href="https://matrix.to/#/@user2:example.com" - > - <span - aria-hidden="true" - class="mx_BaseAvatar" - role="presentation" + <div> + <bdi> + <a + class="mx_Pill mx_UserPill" + href="https://matrix.to/#/@user2:example.com" > <span aria-hidden="true" - class="mx_BaseAvatar_initial" - style="font-size: 10.4px; width: 16px; line-height: 16px;" + class="mx_BaseAvatar" + role="presentation" > - U + <span + aria-hidden="true" + class="mx_BaseAvatar_initial" + style="font-size: 10.4px; width: 16px; line-height: 16px;" + > + U + </span> + <img + alt="" + aria-hidden="true" + class="mx_BaseAvatar_image" + data-testid="avatar-img" + src="data:image/png;base64,00" + style="width: 16px; height: 16px;" + /> </span> - <img - alt="" - aria-hidden="true" - class="mx_BaseAvatar_image" - data-testid="avatar-img" - src="data:image/png;base64,00" - style="width: 16px; height: 16px;" - /> - </span> - <span - class="mx_Pill_linkText" - > - User 2 - </span> - </a> - </bdi> + <span + class="mx_Pill_linkText" + > + User 2 + </span> + </a> + </bdi> + </div> </DocumentFragment> `; exports[`<Pill> when rendering a pill for a room should render the expected pill 1`] = ` <DocumentFragment> - <bdi> - <a - class="mx_Pill mx_RoomPill" - href="https://matrix.to/#/!room1:example.com" - > - <span - aria-hidden="true" - class="mx_BaseAvatar" - role="presentation" + <div> + <bdi> + <a + class="mx_Pill mx_RoomPill" + href="https://matrix.to/#/!room1:example.com" > <span aria-hidden="true" - class="mx_BaseAvatar_initial" - style="font-size: 10.4px; width: 16px; line-height: 16px;" + class="mx_BaseAvatar" + role="presentation" > - R + <span + aria-hidden="true" + class="mx_BaseAvatar_initial" + style="font-size: 10.4px; width: 16px; line-height: 16px;" + > + R + </span> + <img + alt="" + aria-hidden="true" + class="mx_BaseAvatar_image" + data-testid="avatar-img" + src="data:image/png;base64,00" + style="width: 16px; height: 16px;" + /> </span> - <img - alt="" - aria-hidden="true" - class="mx_BaseAvatar_image" - data-testid="avatar-img" - src="data:image/png;base64,00" - style="width: 16px; height: 16px;" - /> - </span> - <span - class="mx_Pill_linkText" - > - Room 1 - </span> - </a> - </bdi> + <span + class="mx_Pill_linkText" + > + Room 1 + </span> + </a> + </bdi> + </div> </DocumentFragment> `; exports[`<Pill> when rendering a pill for a user in the room should render as expected 1`] = ` <DocumentFragment> - <bdi> - <a - class="mx_Pill mx_UserPill" - href="https://matrix.to/#/@user1:example.com" - > - <span - aria-hidden="true" - class="mx_BaseAvatar" - role="presentation" + <div> + <bdi> + <a + class="mx_Pill mx_UserPill" + href="https://matrix.to/#/@user1:example.com" > <span aria-hidden="true" - class="mx_BaseAvatar_initial" - style="font-size: 10.4px; width: 16px; line-height: 16px;" + class="mx_BaseAvatar" + role="presentation" > - U + <span + aria-hidden="true" + class="mx_BaseAvatar_initial" + style="font-size: 10.4px; width: 16px; line-height: 16px;" + > + U + </span> + <img + alt="" + aria-hidden="true" + class="mx_BaseAvatar_image" + data-testid="avatar-img" + src="data:image/png;base64,00" + style="width: 16px; height: 16px;" + /> </span> - <img - alt="" - aria-hidden="true" - class="mx_BaseAvatar_image" - data-testid="avatar-img" - src="data:image/png;base64,00" - style="width: 16px; height: 16px;" - /> - </span> - <span - class="mx_Pill_linkText" - > - User 1 - </span> - </a> - </bdi> + <span + class="mx_Pill_linkText" + > + User 1 + </span> + </a> + </bdi> + </div> </DocumentFragment> `;