Fix React hydration issues (#32958)

* Add more playwright axe tests to settings dialogs

* Add utility to jest setupTests to detect React hydration errors

* Iterate jest utility

* Fix axe issue heading-order

* Fix div-in-p issues

* Fix setupTests.ts

* Fix heading order

* Make types happier

* Fix hydration issues of thead containing text nodes

* Update tests

* Fix form-in-form React hydration issues

* Fix li-in-li React hydration issues

* Fix checked in form without onChange React hydration issue

* Fix styling bleeding from _common.pcss

* Update snapshots

* Fix more remaining issues

* Remove _common.pcss h2 rule altogether

* Fix test

* Update snapshots

* Iterate

* Iterate

* Update snapshots

* Simplify diff

* Test

* Update screenshots

* Update screenshot
This commit is contained in:
Michael Telatynski
2026-04-16 13:35:40 +00:00
committed by GitHub
parent d7f5546294
commit 30f442208a
62 changed files with 2652 additions and 2579 deletions
@@ -37,7 +37,6 @@ import {
import { mocked } from "jest-mock";
import userEvent from "@testing-library/user-event";
import { PushProcessor } from "matrix-js-sdk/src/pushprocessor";
import { Form } from "@vector-im/compound-web";
import Notifications from "../../../../../src/components/views/settings/Notifications";
import SettingsStore from "../../../../../src/settings/SettingsStore";
@@ -249,12 +248,7 @@ const pushRules: IPushRules = {
const flushPromises = async () => await new Promise((resolve) => window.setTimeout(resolve));
describe("<Notifications />", () => {
const getComponent = () =>
render(
<Form.Root>
<Notifications />
</Form.Root>,
);
const getComponent = () => render(<Notifications />);
// get component, wait for async data and force a render
const getComponentAndWait = async () => {
@@ -42,74 +42,74 @@ exports[`<Notifications /> main notification switches renders only enable notifi
</span>
</div>
</div>
<form
class="_root_19upo_16"
</form>
<form
class="_root_19upo_16"
>
<div
class="_inline-field_19upo_32"
>
<div
class="_inline-field_19upo_32"
class="_inline-field-control_19upo_44"
>
<div
class="_inline-field-control_19upo_44"
class="_container_udcm8_10"
>
<input
checked=""
class="_input_udcm8_24"
id="mx_SettingsFlag_testid_0"
role="switch"
type="checkbox"
/>
<div
class="_container_udcm8_10"
>
<input
checked=""
class="_input_udcm8_24"
id="mx_SettingsFlag_testid_0"
role="switch"
type="checkbox"
/>
<div
class="_ui_udcm8_34"
/>
</div>
</div>
<div
class="_inline-field-body_19upo_38"
>
<label
class="_label_19upo_59"
for="mx_SettingsFlag_testid_0"
>
Show all activity in the room list (dots or number of unread messages)
</label>
class="_ui_udcm8_34"
/>
</div>
</div>
<div
class="_inline-field_19upo_32"
class="_inline-field-body_19upo_38"
>
<label
class="_label_19upo_59"
for="mx_SettingsFlag_testid_0"
>
Show all activity in the room list (dots or number of unread messages)
</label>
</div>
</div>
<div
class="_inline-field_19upo_32"
>
<div
class="_inline-field-control_19upo_44"
>
<div
class="_inline-field-control_19upo_44"
class="_container_udcm8_10"
>
<input
checked=""
class="_input_udcm8_24"
id="mx_SettingsFlag_testid_1"
role="switch"
type="checkbox"
/>
<div
class="_container_udcm8_10"
>
<input
checked=""
class="_input_udcm8_24"
id="mx_SettingsFlag_testid_1"
role="switch"
type="checkbox"
/>
<div
class="_ui_udcm8_34"
/>
</div>
</div>
<div
class="_inline-field-body_19upo_38"
>
<label
class="_label_19upo_59"
for="mx_SettingsFlag_testid_1"
>
Only show notifications in the thread activity centre
</label>
class="_ui_udcm8_34"
/>
</div>
</div>
</form>
<div
class="_inline-field-body_19upo_38"
>
<label
class="_label_19upo_59"
for="mx_SettingsFlag_testid_1"
>
Only show notifications in the thread activity centre
</label>
</div>
</div>
</form>
</div>
`;
@@ -57,13 +57,13 @@ HTMLCollection [
class="mx_DeviceSecurityCard_description"
>
Verify your current session for enhanced secure messaging.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</p>
<div
class="mx_DeviceSecurityCard_actions"
@@ -334,13 +334,13 @@ exports[`<CurrentDeviceSection /> renders device and correct security card when
class="mx_DeviceSecurityCard_description"
>
Verify your current session for enhanced secure messaging.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</p>
<div
class="mx_DeviceSecurityCard_actions"
@@ -521,13 +521,13 @@ exports[`<CurrentDeviceSection /> renders device and correct security card when
class="mx_DeviceSecurityCard_description"
>
Verify your current session for enhanced secure messaging.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</p>
<div
class="mx_DeviceSecurityCard_actions"
@@ -37,13 +37,13 @@ exports[`<DeviceDetailHeading /> displays name edit form on rename button click
id="device-rename-description-123"
>
Please be aware that session names are also visible to people you communicate with.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</span>
</div>
<div
@@ -59,13 +59,13 @@ exports[`<DeviceDetails /> renders a verified device 1`] = `
class="mx_DeviceSecurityCard_description"
>
This session is ready for secure messaging.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</p>
</div>
</div>
@@ -175,13 +175,13 @@ exports[`<DeviceDetails /> renders device with metadata 1`] = `
class="mx_DeviceSecurityCard_description"
>
Verify or remove this session for best security and reliability.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</p>
</div>
</div>
@@ -391,13 +391,13 @@ exports[`<DeviceDetails /> renders device without metadata 1`] = `
class="mx_DeviceSecurityCard_description"
>
Verify or remove this session for best security and reliability.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</p>
</div>
</div>
@@ -34,13 +34,13 @@ exports[`<DeviceVerificationStatusCard /> renders a verified device 1`] = `
class="mx_DeviceSecurityCard_description"
>
This session is ready for secure messaging.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</p>
</div>
</div>
@@ -79,13 +79,13 @@ exports[`<DeviceVerificationStatusCard /> renders an unverifiable device 1`] = `
class="mx_DeviceSecurityCard_description"
>
This session doesn't support encryption and thus can't be verified.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</p>
</div>
</div>
@@ -124,13 +124,13 @@ exports[`<DeviceVerificationStatusCard /> renders an unverified device 1`] = `
class="mx_DeviceSecurityCard_description"
>
Verify or remove this session for best security and reliability.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</p>
<div
class="mx_DeviceSecurityCard_actions"
@@ -39,13 +39,13 @@ HTMLCollection [
>
<span>
Consider removing old sessions (90 days or older) you don't use anymore.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</span>
</p>
</div>
@@ -90,13 +90,13 @@ HTMLCollection [
>
<span>
Verify your sessions for enhanced secure messaging or remove from those you don't recognize or use anymore.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</span>
</p>
</div>
@@ -143,13 +143,13 @@ HTMLCollection [
>
<span>
For best security, remove any session that you don't recognize or use anymore.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</span>
</p>
</div>
@@ -57,13 +57,13 @@ exports[`<SecurityRecommendations /> renders both cards when user has both unver
class="mx_DeviceSecurityCard_description"
>
Verify your sessions for enhanced secure messaging or remove from those you don't recognize or use anymore.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</p>
<div
class="mx_DeviceSecurityCard_actions"
@@ -105,13 +105,13 @@ exports[`<SecurityRecommendations /> renders both cards when user has both unver
class="mx_DeviceSecurityCard_description"
>
Consider removing old sessions (90 days or older) you don't use anymore.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</p>
<div
class="mx_DeviceSecurityCard_actions"
@@ -189,13 +189,13 @@ exports[`<SecurityRecommendations /> renders inactive devices section when user
class="mx_DeviceSecurityCard_description"
>
Verify your sessions for enhanced secure messaging or remove from those you don't recognize or use anymore.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</p>
<div
class="mx_DeviceSecurityCard_actions"
@@ -237,13 +237,13 @@ exports[`<SecurityRecommendations /> renders inactive devices section when user
class="mx_DeviceSecurityCard_description"
>
Consider removing old sessions (90 days or older) you don't use anymore.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</p>
<div
class="mx_DeviceSecurityCard_actions"
@@ -321,13 +321,13 @@ exports[`<SecurityRecommendations /> renders unverified devices section when use
class="mx_DeviceSecurityCard_description"
>
Verify your sessions for enhanced secure messaging or remove from those you don't recognize or use anymore.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</p>
<div
class="mx_DeviceSecurityCard_actions"
@@ -369,13 +369,13 @@ exports[`<SecurityRecommendations /> renders unverified devices section when use
class="mx_DeviceSecurityCard_description"
>
Consider removing old sessions (90 days or older) you don't use anymore.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</p>
<div
class="mx_DeviceSecurityCard_actions"
@@ -18,7 +18,6 @@ import {
RuleId,
} from "matrix-js-sdk/src/matrix";
import React from "react";
import { Form } from "@vector-im/compound-web";
import NotificationSettings2 from "../../../../../../src/components/views/settings/notifications/NotificationSettings2";
import MatrixClientContext from "../../../../../../src/contexts/MatrixClientContext";
@@ -94,9 +93,7 @@ describe("<Notifications />", () => {
const screen = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await act(waitForUpdate);
@@ -109,9 +106,7 @@ describe("<Notifications />", () => {
const user = userEvent.setup();
const screen = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await act(async () => {
@@ -172,9 +167,7 @@ describe("<Notifications />", () => {
const user = userEvent.setup();
const screen = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await act(waitForUpdate);
@@ -190,9 +183,7 @@ describe("<Notifications />", () => {
const user = userEvent.setup();
const screen = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await act(waitForUpdate);
@@ -230,9 +221,7 @@ describe("<Notifications />", () => {
const user = userEvent.setup();
const screen = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await act(waitForUpdate);
@@ -267,9 +256,7 @@ describe("<Notifications />", () => {
const user = userEvent.setup();
const screen = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await act(waitForUpdate);
@@ -298,9 +285,7 @@ describe("<Notifications />", () => {
const user = userEvent.setup();
const screen = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await act(waitForUpdate);
@@ -325,9 +310,7 @@ describe("<Notifications />", () => {
const user = userEvent.setup();
const screen = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await act(waitForUpdate);
@@ -349,9 +332,7 @@ describe("<Notifications />", () => {
const user = userEvent.setup();
const screen = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await act(waitForUpdate);
@@ -379,9 +360,7 @@ describe("<Notifications />", () => {
const user = userEvent.setup();
const screen = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await act(waitForUpdate);
@@ -405,9 +384,7 @@ describe("<Notifications />", () => {
const user = userEvent.setup();
const screen = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await act(waitForUpdate);
@@ -429,9 +406,7 @@ describe("<Notifications />", () => {
const user = userEvent.setup();
const screen = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await act(waitForUpdate);
@@ -459,9 +434,7 @@ describe("<Notifications />", () => {
const user = userEvent.setup();
const screen = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await act(waitForUpdate);
@@ -485,9 +458,7 @@ describe("<Notifications />", () => {
const user = userEvent.setup();
const screen = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await act(waitForUpdate);
@@ -514,9 +485,7 @@ describe("<Notifications />", () => {
const user = userEvent.setup();
const screen = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await act(waitForUpdate);
@@ -535,9 +504,7 @@ describe("<Notifications />", () => {
const user = userEvent.setup();
const screen = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await act(waitForUpdate);
@@ -648,9 +615,7 @@ describe("<Notifications />", () => {
const user = userEvent.setup();
const screen = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await act(waitForUpdate);
@@ -709,9 +674,7 @@ describe("<Notifications />", () => {
const user = userEvent.setup();
const screen = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await act(waitForUpdate);
@@ -731,9 +694,7 @@ describe("<Notifications />", () => {
const { container } = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await waitForUpdate();
@@ -760,9 +721,7 @@ describe("<Notifications />", () => {
const user = userEvent.setup();
const { container } = render(
<MatrixClientContext.Provider value={cli}>
<Form.Root>
<NotificationSettings2 />
</Form.Root>
<NotificationSettings2 />
</MatrixClientContext.Provider>,
);
await waitForUpdate();
@@ -38,11 +38,11 @@ exports[`AdvancedRoomSettingsTab should render as expected 1`] = `
<span>
Internal room ID
</span>
<div
<span
class="mx_CopyableText mx_CopyableText_border"
>
!room:example.com
<div
<button
aria-label="Copy"
class="mx_AccessibleButton mx_CopyableText_copyButton"
role="button"
@@ -62,8 +62,8 @@ exports[`AdvancedRoomSettingsTab should render as expected 1`] = `
d="M8 10a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-9a2 2 0 0 1-2-2zm2 0v9h9v-9z"
/>
</svg>
</div>
</div>
</button>
</span>
</div>
</div>
</div>
@@ -186,7 +186,7 @@ exports[`<SecurityRoomSettingsTab /> join rule warns when trying to make an encr
<span>
To avoid these issues, create a
<div
<a
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
@@ -194,7 +194,7 @@ exports[`<SecurityRoomSettingsTab /> join rule warns when trying to make an encr
new public room
</div>
</a>
for the conversation you plan to have.
</span>
@@ -32,13 +32,13 @@ HTMLCollection [
class="mx_DeviceSecurityCard_description"
>
This session doesn't support encryption and thus can't be verified.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</p>
</div>
</div>,
@@ -238,13 +238,13 @@ exports[`<SessionManagerTab /> current session section renders current session s
class="mx_DeviceSecurityCard_description"
>
Your current session is ready for secure messaging.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</p>
</div>
</div>
@@ -411,13 +411,13 @@ exports[`<SessionManagerTab /> current session section renders current session s
class="mx_DeviceSecurityCard_description"
>
Verify your current session for enhanced secure messaging.
<div
<button
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
role="button"
tabindex="0"
>
Learn more
</div>
</button>
</p>
<div
class="mx_DeviceSecurityCard_actions"