diff --git a/packages/devextreme/js/__internal/ui/themes.ts b/packages/devextreme/js/__internal/ui/themes.ts index 0bba28d28db5..537b6e7f29a9 100644 --- a/packages/devextreme/js/__internal/ui/themes.ts +++ b/packages/devextreme/js/__internal/ui/themes.ts @@ -50,6 +50,9 @@ function readThemeMarker(): string | null { let result: string; try { + if (!window?.getComputedStyle) { + return null; + } result = window.getComputedStyle(element.get(0)).fontFamily; if (!result) { return null; diff --git a/packages/devextreme/testing/tests/DevExpress.ui/themes.tests.js b/packages/devextreme/testing/tests/DevExpress.ui/themes.tests.js index 6e36c92a7ebd..3e98fd22e59e 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui/themes.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui/themes.tests.js @@ -825,3 +825,39 @@ QUnit.module('initialized method', (hooks) => { }); }); }); + +QUnit.module('readThemeMarker error handling', () => { + test('readThemeMarker returns null when getComputedStyle throws an error', function(assert) { + const done = assert.async(); + const originalGetComputedStyle = window.getComputedStyle; + window.getComputedStyle = undefined; + + try { + themes.resetTheme(); + const value = themes.current(); + assert.strictEqual(value, null, 'current() returns null on getComputedStyle being undefined'); + } finally { + window.getComputedStyle = originalGetComputedStyle; + done(); + } + }); + + test('waitForThemeLoad resolves even if getComputedStyle continuously throws', function(assert) { + const done = assert.async(); + const originalGetComputedStyle = window.getComputedStyle; + window.getComputedStyle = undefined; + + const TEST_TIMEOUT = 30; + themes.resetTheme(); + themes.setDefaultTimeout(TEST_TIMEOUT); + + themes.ready(() => { + assert.strictEqual(themes.current(), null, 'theme remains null after timeout'); + window.getComputedStyle = originalGetComputedStyle; + themes.setDefaultTimeout(defaultTimeout); + done(); + }); + + themes.waitForThemeLoad('some.nonexistent.theme'); + }); +});