123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- import { beforeEach, describe, expect, it, vi } from 'vitest';
- import { defaultPreferences } from '../src/config';
- import { PreferenceManager } from '../src/preferences';
- import { isDarkTheme } from '../src/update-css-variables';
- describe('preferences', () => {
- let preferenceManager: PreferenceManager;
- // 模拟 window.matchMedia 方法
- vi.stubGlobal(
- 'matchMedia',
- vi.fn().mockImplementation((query) => ({
- addEventListener: vi.fn(),
- addListener: vi.fn(), // Deprecated
- dispatchEvent: vi.fn(),
- matches: query === '(prefers-color-scheme: dark)',
- media: query,
- onchange: null,
- removeEventListener: vi.fn(),
- removeListener: vi.fn(), // Deprecated
- })),
- );
- beforeEach(() => {
- preferenceManager = new PreferenceManager();
- });
- it('loads default preferences if no saved preferences found', () => {
- const preferences = preferenceManager.getPreferences();
- expect(preferences).toEqual(defaultPreferences);
- });
- it('initializes preferences with overrides', async () => {
- const overrides: any = {
- app: {
- locale: 'en-US',
- },
- };
- await preferenceManager.initPreferences({
- namespace: 'testNamespace',
- overrides,
- });
- // 等待防抖动操作完成
- // await new Promise((resolve) => setTimeout(resolve, 300)); // 等待100毫秒
- const expected = {
- ...defaultPreferences,
- app: {
- ...defaultPreferences.app,
- ...overrides.app,
- },
- };
- expect(preferenceManager.getPreferences()).toEqual(expected);
- });
- it('updates theme mode correctly', () => {
- preferenceManager.updatePreferences({
- theme: {
- mode: 'light',
- },
- });
- expect(preferenceManager.getPreferences().theme.mode).toBe('light');
- });
- it('updates color modes correctly', () => {
- preferenceManager.updatePreferences({
- app: { colorGrayMode: true, colorWeakMode: true },
- });
- expect(preferenceManager.getPreferences().app.colorGrayMode).toBe(true);
- expect(preferenceManager.getPreferences().app.colorWeakMode).toBe(true);
- });
- it('resets preferences to default', () => {
- // 先更新一些偏好设置
- preferenceManager.updatePreferences({
- theme: {
- mode: 'light',
- },
- });
- // 然后重置偏好设置
- preferenceManager.resetPreferences();
- expect(preferenceManager.getPreferences()).toEqual(defaultPreferences);
- });
- it('updates isMobile correctly', () => {
- // 模拟移动端状态
- vi.stubGlobal(
- 'matchMedia',
- vi.fn().mockImplementation((query) => ({
- addEventListener: vi.fn(),
- addListener: vi.fn(),
- dispatchEvent: vi.fn(),
- matches: query === '(max-width: 768px)',
- media: query,
- onchange: null,
- removeEventListener: vi.fn(),
- removeListener: vi.fn(),
- })),
- );
- preferenceManager.updatePreferences({
- app: { isMobile: true },
- });
- expect(preferenceManager.getPreferences().app.isMobile).toBe(true);
- });
- it('updates the locale preference correctly', () => {
- preferenceManager.updatePreferences({
- app: { locale: 'en-US' },
- });
- expect(preferenceManager.getPreferences().app.locale).toBe('en-US');
- });
- it('updates the sidebar width correctly', () => {
- preferenceManager.updatePreferences({
- sidebar: { width: 200 },
- });
- expect(preferenceManager.getPreferences().sidebar.width).toBe(200);
- });
- it('updates the sidebar collapse state correctly', () => {
- preferenceManager.updatePreferences({
- sidebar: { collapsed: true },
- });
- expect(preferenceManager.getPreferences().sidebar.collapsed).toBe(true);
- });
- it('updates the navigation style type correctly', () => {
- preferenceManager.updatePreferences({
- navigation: { styleType: 'flat' },
- } as any);
- expect(preferenceManager.getPreferences().navigation.styleType).toBe(
- 'flat',
- );
- });
- it('resets preferences to default correctly', () => {
- // 先更新一些偏好设置
- preferenceManager.updatePreferences({
- app: { locale: 'en-US' },
- sidebar: { collapsed: true, width: 200 },
- theme: {
- mode: 'light',
- },
- });
- // 然后重置偏好设置
- preferenceManager.resetPreferences();
- expect(preferenceManager.getPreferences()).toEqual(defaultPreferences);
- });
- it('does not update undefined preferences', () => {
- const originalPreferences = preferenceManager.getPreferences();
- preferenceManager.updatePreferences({
- app: { nonexistentField: 'value' },
- } as any);
- expect(preferenceManager.getPreferences()).toEqual(originalPreferences);
- });
- it('reverts to default when a preference field is deleted', () => {
- preferenceManager.updatePreferences({
- app: { locale: 'en-US' },
- });
- preferenceManager.updatePreferences({
- app: { locale: undefined },
- });
- expect(preferenceManager.getPreferences().app.locale).toBe('en-US');
- });
- it('ignores updates with invalid preference value types', () => {
- const originalPreferences = preferenceManager.getPreferences();
- preferenceManager.updatePreferences({
- app: { isMobile: 'true' as unknown as boolean }, // 错误类型
- });
- expect(preferenceManager.getPreferences()).toEqual(originalPreferences);
- });
- it('merges nested preference objects correctly', () => {
- preferenceManager.updatePreferences({
- app: { name: 'New App Name' },
- });
- const expected = {
- ...defaultPreferences,
- app: {
- ...defaultPreferences.app,
- name: 'New App Name',
- },
- };
- expect(preferenceManager.getPreferences()).toEqual(expected);
- });
- it('applies updates immediately after initialization', async () => {
- const overrides: any = {
- app: {
- locale: 'en-US',
- },
- };
- await preferenceManager.initPreferences(overrides);
- preferenceManager.updatePreferences({
- theme: { mode: 'light' },
- });
- expect(preferenceManager.getPreferences().theme.mode).toBe('light');
- });
- });
- describe('isDarkTheme', () => {
- it('should return true for dark theme', () => {
- expect(isDarkTheme('dark')).toBe(true);
- });
- it('should return false for light theme', () => {
- expect(isDarkTheme('light')).toBe(false);
- });
- it('should return system preference for auto theme', () => {
- vi.spyOn(window, 'matchMedia').mockImplementation((query) => ({
- addEventListener: vi.fn(),
- addListener: vi.fn(), // Deprecated
- dispatchEvent: vi.fn(),
- matches: query === '(prefers-color-scheme: dark)',
- media: query,
- onchange: null,
- removeEventListener: vi.fn(),
- removeListener: vi.fn(), // Deprecated
- }));
- expect(isDarkTheme('auto')).toBe(true);
- expect(window.matchMedia).toHaveBeenCalledWith(
- '(prefers-color-scheme: dark)',
- );
- });
- });
|