fix: handle localStorage availability in ThemeService and update tests accordingly
This commit is contained in:
1 parent
c10a79d5fb
commit
38414e8656
2 files changed
+21
-2
No files matched your search
@@ -5,6 +5,8 @@ import { ThemeService } from './theme.service';
|
|||||||
describe('ThemeService', () => {
|
describe('ThemeService', () => {
|
||||||
beforeEach(() => localStorage.clear());
|
beforeEach(() => localStorage.clear());
|
||||||
|
|
||||||
|
afterEach(() => vi.unstubAllGlobals());
|
||||||
|
|
||||||
it('defaults to the operating-system preference', () => {
|
it('defaults to the operating-system preference', () => {
|
||||||
vi.stubGlobal(
|
vi.stubGlobal(
|
||||||
'matchMedia',
|
'matchMedia',
|
||||||
@@ -34,4 +36,20 @@ describe('ThemeService', () => {
|
|||||||
expect(document.documentElement.dataset['themePreference']).toBe('light');
|
expect(document.documentElement.dataset['themePreference']).toBe('light');
|
||||||
expect(listener).toHaveBeenCalledWith('change', expect.any(Function));
|
expect(listener).toHaveBeenCalledWith('change', expect.any(Function));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('works when browser storage is unavailable', () => {
|
||||||
|
vi.stubGlobal('localStorage', undefined);
|
||||||
|
vi.stubGlobal(
|
||||||
|
'matchMedia',
|
||||||
|
vi.fn(() => ({ matches: false, addEventListener: vi.fn() })),
|
||||||
|
);
|
||||||
|
|
||||||
|
const service = TestBed.inject(ThemeService);
|
||||||
|
TestBed.tick();
|
||||||
|
|
||||||
|
expect(service.preference()).toBe('system');
|
||||||
|
service.setPreference('dark');
|
||||||
|
TestBed.tick();
|
||||||
|
expect(document.documentElement.dataset['theme']).toBe('dark');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
@@ -8,6 +8,7 @@ const THEME_STORAGE_KEY = 'lmnp-theme';
|
|||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class ThemeService {
|
export class ThemeService {
|
||||||
private readonly document = inject(DOCUMENT);
|
private readonly document = inject(DOCUMENT);
|
||||||
|
private readonly storage = typeof localStorage === 'undefined' ? null : localStorage;
|
||||||
private readonly colorSchemeQuery =
|
private readonly colorSchemeQuery =
|
||||||
typeof window.matchMedia === 'function'
|
typeof window.matchMedia === 'function'
|
||||||
? window.matchMedia('(prefers-color-scheme: dark)')
|
? window.matchMedia('(prefers-color-scheme: dark)')
|
||||||
@@ -26,7 +27,7 @@ export class ThemeService {
|
|||||||
const resolvedTheme =
|
const resolvedTheme =
|
||||||
preference === 'system' ? (this.systemUsesDark() ? 'dark' : 'light') : preference;
|
preference === 'system' ? (this.systemUsesDark() ? 'dark' : 'light') : preference;
|
||||||
|
|
||||||
localStorage.setItem(THEME_STORAGE_KEY, preference);
|
this.storage?.setItem(THEME_STORAGE_KEY, preference);
|
||||||
this.document.documentElement.dataset['theme'] = resolvedTheme;
|
this.document.documentElement.dataset['theme'] = resolvedTheme;
|
||||||
this.document.documentElement.dataset['themePreference'] = preference;
|
this.document.documentElement.dataset['themePreference'] = preference;
|
||||||
});
|
});
|
||||||
@@ -37,7 +38,7 @@ export class ThemeService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readPreference(): ThemePreference {
|
private readPreference(): ThemePreference {
|
||||||
const storedPreference = localStorage.getItem(THEME_STORAGE_KEY);
|
const storedPreference = this.storage?.getItem(THEME_STORAGE_KEY);
|
||||||
return storedPreference === 'dark' || storedPreference === 'system'
|
return storedPreference === 'dark' || storedPreference === 'system'
|
||||||
? storedPreference
|
? storedPreference
|
||||||
: 'system';
|
: 'system';
|
||||||
|
|||||||
Reference in new issue
Block a user