feat: add some test case
This commit is contained in:
@@ -45,7 +45,6 @@ const defaultPreferences: Preferences = {
|
||||
split: true,
|
||||
styleType: 'rounded',
|
||||
},
|
||||
|
||||
shortcutKeys: { enable: true },
|
||||
sidebar: {
|
||||
collapse: false,
|
||||
@@ -56,17 +55,14 @@ const defaultPreferences: Preferences = {
|
||||
hidden: false,
|
||||
width: 240,
|
||||
},
|
||||
|
||||
tabbar: {
|
||||
enable: true,
|
||||
keepAlive: true,
|
||||
showIcon: true,
|
||||
},
|
||||
|
||||
theme: {
|
||||
colorPrimary: 'hsl(211 91% 39%)',
|
||||
},
|
||||
|
||||
transition: {
|
||||
enable: true,
|
||||
name: 'fade-slide',
|
||||
|
268
packages/@vben-core/forward/preferences/src/preferences.test.ts
Normal file
268
packages/@vben-core/forward/preferences/src/preferences.test.ts
Normal file
@@ -0,0 +1,268 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { defaultPreferences } from './config';
|
||||
import { PreferenceManager, isDarkTheme } from './preferences';
|
||||
|
||||
describe('preferences', () => {
|
||||
let preferenceManager: PreferenceManager;
|
||||
vi.mock('@vben-core/cache', () => {
|
||||
return {
|
||||
StorageManager: vi.fn().mockImplementation(() => {
|
||||
return {
|
||||
getItem: vi.fn(),
|
||||
removeItem: vi.fn(),
|
||||
setItem: vi.fn(),
|
||||
};
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
// 模拟 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('initPreferences should initialize preferences with overrides and namespace', async () => {
|
||||
const overrides = { theme: { colorPrimary: 'hsl(211 91% 39%)' } };
|
||||
const namespace = 'testNamespace';
|
||||
|
||||
await preferenceManager.initPreferences({ namespace, overrides });
|
||||
|
||||
expect(preferenceManager.getPreferences().theme.colorPrimary).toBe(
|
||||
overrides.theme.colorPrimary,
|
||||
);
|
||||
});
|
||||
|
||||
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',
|
||||
themeMode: 'light',
|
||||
},
|
||||
};
|
||||
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({
|
||||
app: { themeMode: 'light' },
|
||||
});
|
||||
|
||||
expect(preferenceManager.getPreferences().app.themeMode).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({
|
||||
app: { themeMode: '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: { collapse: true },
|
||||
});
|
||||
|
||||
expect(preferenceManager.getPreferences().sidebar.collapse).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', themeMode: 'light' },
|
||||
sidebar: { collapse: true, width: 200 },
|
||||
});
|
||||
|
||||
// 然后重置偏好设置
|
||||
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({
|
||||
app: { themeMode: 'light' },
|
||||
});
|
||||
|
||||
expect(preferenceManager.getPreferences().app.themeMode).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)',
|
||||
);
|
||||
});
|
||||
});
|
@@ -85,15 +85,21 @@ class PreferenceManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从缓存中加载偏好设置。如果缓存中没有找到对应的偏好设置,则返回默认偏好设置。
|
||||
*/
|
||||
private loadCachedPreferences() {
|
||||
return this.cache?.getItem(STORAGE_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载偏好设置
|
||||
* 从缓存中加载偏好设置。如果缓存中没有找到对应的偏好设置,则返回默认偏好设置。
|
||||
* @returns {Preferences} 加载的偏好设置
|
||||
*/
|
||||
private loadPreferences(): Preferences {
|
||||
const savedPreferences = this.cache?.getItem(STORAGE_KEY);
|
||||
return savedPreferences || { ...defaultPreferences };
|
||||
private loadPreferences(): Preferences | null {
|
||||
return this.loadCachedPreferences() || { ...defaultPreferences };
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听状态和系统偏好设置的变化。
|
||||
*/
|
||||
@@ -239,7 +245,7 @@ class PreferenceManager {
|
||||
this.initialPreferences = merge({}, overrides, defaultPreferences);
|
||||
|
||||
// 加载并合并当前存储的偏好设置
|
||||
const mergedPreference = merge({}, this.loadPreferences(), overrides);
|
||||
const mergedPreference = merge({}, this.loadCachedPreferences(), overrides);
|
||||
|
||||
// 更新偏好设置
|
||||
this.updatePreferences(mergedPreference);
|
||||
@@ -274,9 +280,10 @@ class PreferenceManager {
|
||||
* @param updates - 要更新的偏好设置
|
||||
*/
|
||||
public updatePreferences(updates: DeepPartial<Preferences>) {
|
||||
const mergedState = merge(updates, markRaw(this.state));
|
||||
const mergedState = merge({}, updates, markRaw(this.state));
|
||||
|
||||
Object.assign(this.state, mergedState);
|
||||
|
||||
Object.assign(this.flattenedState, flattenObject(this.state));
|
||||
|
||||
// 根据更新的键值执行相应的操作
|
||||
@@ -286,4 +293,4 @@ class PreferenceManager {
|
||||
}
|
||||
|
||||
const preferencesManager = new PreferenceManager();
|
||||
export { isDarkTheme, preferencesManager };
|
||||
export { PreferenceManager, isDarkTheme, preferencesManager };
|
||||
|
Reference in New Issue
Block a user