Fix bundled font or custom font not applied after theme switch (#31591)

* refactor: transform `FontWater.onAction` to switch

* fix: reload font after switching theme

Fix #26248 #31588

When a theme is swiched, `clearCustomTheme` remove all css variables.
After the styles are re-applied but the custom fonts or emoji are not
re-applied.

* test: add test for `Action.ReloadFont`

* test: add missing tests for existing actions

* test(e2e): add tests to ensure that font and emoji stay unchanged

* Revert "fix: reload font after switching theme"

This reverts commit 2b0071af21c38bf2c86780356aa39d290e9d9148.

* Revert "refactor: transform `FontWater.onAction` to switch"

This reverts commit 411915860923230cabce3ad5498fb46696a9a65e.

* Revert "test: add test for `Action.ReloadFont`"

This reverts commit 31b3b224cd2c443663a2b9bba312a4140907a8ed.

* fix: don't remove custom emoji and cpd font when clearing custom theme

Fix #26248 #31588

When a theme is swiched, `clearCustomTheme` remove all css variables.
After the styles are re-applied but the custom fonts or emoji are not
re-applied.
This fix avoid the custom font and emoji to be removed.

* test: add tests
This commit is contained in:
Florian Duros
2026-01-05 16:14:08 +00:00
committed by GitHub
parent 4bd1d4144f
commit be7be39d0f
7 changed files with 113 additions and 4 deletions
+42
View File
@@ -7,6 +7,7 @@ Please see LICENSE files in the repository root for full details.
*/
import SettingsStore from "../../src/settings/SettingsStore";
import { FontWatcher } from "../../src/settings/watchers/FontWatcher";
import { enumerateThemes, getOrderedThemes, setTheme } from "../../src/theme";
describe("theme", () => {
@@ -223,4 +224,45 @@ describe("theme", () => {
]);
});
});
describe("clearCustomTheme", () => {
beforeEach(() => {
// Reset document state
document.body.style.cssText = "";
document.head.querySelectorAll("style[title^='custom-theme-']").forEach((el) => el.remove());
});
it("should not remove font family custom properties", async () => {
// Mock theme elements
const lightTheme = {
dataset: { mxTheme: "light" },
disabled: true,
href: "fake URL",
onload: (): void => void 0,
} as unknown as HTMLStyleElement;
const removePropertySpy = jest.fn();
const styleObject = {
0: FontWatcher.FONT_FAMILY_CUSTOM_PROPERTY,
1: FontWatcher.EMOJI_FONT_FAMILY_CUSTOM_PROPERTY,
2: "--custom-color",
length: 3,
removeProperty: removePropertySpy,
};
jest.spyOn(document.body, "style", "get").mockReturnValue(styleObject as any);
jest.spyOn(document, "querySelectorAll").mockReturnValue([lightTheme] as any);
// Trigger clearCustomTheme via setTheme
await new Promise((resolve) => {
setTheme("light").then(resolve);
lightTheme.onload!({} as Event);
});
// Check that font properties were NOT removed
expect(removePropertySpy).not.toHaveBeenCalledWith(FontWatcher.FONT_FAMILY_CUSTOM_PROPERTY);
expect(removePropertySpy).not.toHaveBeenCalledWith(FontWatcher.EMOJI_FONT_FAMILY_CUSTOM_PROPERTY);
// But custom color should be removed
expect(removePropertySpy).toHaveBeenCalledWith("--custom-color");
});
});
});