mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-01 19:48:08 +00:00
# Pull Request Template ## Description This Pull Request will provide a language selector in the Profile Settings for each user, and allows them to change the UI language per agent, defaulting back to the account locale. Fixes # #678 This does PR addresses the Dashboard view but does not change the language of the agents emails ## Type of change Please delete options that are not relevant. - [X ] New feature (non-breaking change which adds functionality) ## How Has This Been Tested? 1. Go to an Agents Profile settings page 2. Select a language from the Language drop down 3. the UI will update to the new i18n locale 4. navigate through the UI to make sure the appropriate language is being used 5. Refresh the page to test that the locale persists 270 - [X] My code follows the style guidelines of this project - [X] I have performed a self-review of my code - [X] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [X] My changes generate no new warnings - [X] I have added tests that prove my fix is effective or that my feature works - [X] New and existing unit tests pass locally with my changes - [X] Any dependent changes have been merged and published in downstream modules Checklist:.724.2708 --------- Co-authored-by: Sojan Jose <sojan@pepalo.com> Co-authored-by: Pranav <pranav@chatwoot.com> Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Co-authored-by: iamsivin <iamsivin@gmail.com> Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
166 lines
5.0 KiB
JavaScript
166 lines
5.0 KiB
JavaScript
import { ref } from 'vue';
|
|
import { useFontSize } from '../useFontSize';
|
|
import { useUISettings } from 'dashboard/composables/useUISettings';
|
|
import { useAlert } from 'dashboard/composables';
|
|
import { useI18n } from 'vue-i18n';
|
|
|
|
// Mock dependencies
|
|
vi.mock('dashboard/composables/useUISettings');
|
|
vi.mock('dashboard/composables', () => ({
|
|
useAlert: vi.fn(message => message),
|
|
}));
|
|
vi.mock('vue-i18n');
|
|
|
|
// Mock requestAnimationFrame
|
|
global.requestAnimationFrame = vi.fn(cb => cb());
|
|
|
|
describe('useFontSize', () => {
|
|
const mockUISettings = ref({
|
|
font_size: '16px',
|
|
});
|
|
const mockUpdateUISettings = vi.fn().mockResolvedValue(undefined);
|
|
const mockTranslate = vi.fn(key => key);
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
|
|
// Setup mocks
|
|
useUISettings.mockReturnValue({
|
|
uiSettings: mockUISettings,
|
|
updateUISettings: mockUpdateUISettings,
|
|
});
|
|
|
|
useI18n.mockReturnValue({
|
|
t: mockTranslate,
|
|
});
|
|
|
|
// Reset DOM state
|
|
document.documentElement.style.removeProperty('font-size');
|
|
|
|
// Reset mockUISettings to default
|
|
mockUISettings.value = { font_size: '16px' };
|
|
});
|
|
|
|
it('returns fontSizeOptions with correct structure', () => {
|
|
const { fontSizeOptions } = useFontSize();
|
|
expect(fontSizeOptions.value).toHaveLength(5);
|
|
expect(fontSizeOptions.value[0]).toHaveProperty('value');
|
|
expect(fontSizeOptions.value[0]).toHaveProperty('label');
|
|
|
|
// Check specific options
|
|
expect(
|
|
fontSizeOptions.value.find(option => option.value === '16px')
|
|
).toEqual({
|
|
value: '16px',
|
|
label:
|
|
'PROFILE_SETTINGS.FORM.INTERFACE_SECTION.FONT_SIZE.OPTIONS.DEFAULT',
|
|
});
|
|
|
|
expect(
|
|
fontSizeOptions.value.find(option => option.value === '14px')
|
|
).toEqual({
|
|
value: '14px',
|
|
label:
|
|
'PROFILE_SETTINGS.FORM.INTERFACE_SECTION.FONT_SIZE.OPTIONS.SMALLER',
|
|
});
|
|
});
|
|
|
|
it('returns currentFontSize from UI settings', () => {
|
|
const { currentFontSize } = useFontSize();
|
|
expect(currentFontSize.value).toBe('16px');
|
|
|
|
mockUISettings.value.font_size = '18px';
|
|
expect(currentFontSize.value).toBe('18px');
|
|
});
|
|
|
|
it('applies font size to document root correctly based on pixel values', () => {
|
|
const { applyFontSize } = useFontSize();
|
|
|
|
applyFontSize('18px');
|
|
expect(document.documentElement.style.fontSize).toBe('18px');
|
|
|
|
applyFontSize('14px');
|
|
expect(document.documentElement.style.fontSize).toBe('14px');
|
|
|
|
applyFontSize('16px');
|
|
expect(document.documentElement.style.fontSize).toBe('16px');
|
|
});
|
|
|
|
it('updates UI settings and applies font size', async () => {
|
|
const { updateFontSize } = useFontSize();
|
|
|
|
await updateFontSize('20px');
|
|
|
|
expect(mockUpdateUISettings).toHaveBeenCalledWith({ font_size: '20px' });
|
|
expect(document.documentElement.style.fontSize).toBe('20px');
|
|
expect(useAlert).toHaveBeenCalledWith(
|
|
'PROFILE_SETTINGS.FORM.INTERFACE_SECTION.FONT_SIZE.UPDATE_SUCCESS'
|
|
);
|
|
});
|
|
|
|
it('shows error alert when update fails', async () => {
|
|
mockUpdateUISettings.mockRejectedValueOnce(new Error('Update failed'));
|
|
|
|
const { updateFontSize } = useFontSize();
|
|
await updateFontSize('20px');
|
|
|
|
expect(useAlert).toHaveBeenCalledWith(
|
|
'PROFILE_SETTINGS.FORM.INTERFACE_SECTION.FONT_SIZE.UPDATE_ERROR'
|
|
);
|
|
});
|
|
|
|
it('handles unknown font size values gracefully', () => {
|
|
const { applyFontSize } = useFontSize();
|
|
|
|
// Should not throw an error and should apply the default font size
|
|
applyFontSize('unknown-size');
|
|
expect(document.documentElement.style.fontSize).toBe('16px');
|
|
});
|
|
|
|
it('watches for UI settings changes and applies font size', async () => {
|
|
useFontSize();
|
|
|
|
// Initial font size should now be 16px instead of empty
|
|
expect(document.documentElement.style.fontSize).toBe('16px');
|
|
|
|
// Update UI settings
|
|
mockUISettings.value = { font_size: '18px' };
|
|
|
|
// Wait for next tick to let watchers fire
|
|
await Promise.resolve();
|
|
|
|
expect(document.documentElement.style.fontSize).toBe('18px');
|
|
});
|
|
|
|
it('translates font size option labels correctly', () => {
|
|
// Set up specific translation mapping
|
|
mockTranslate.mockImplementation(key => {
|
|
const translations = {
|
|
'PROFILE_SETTINGS.FORM.INTERFACE_SECTION.FONT_SIZE.OPTIONS.SMALLER':
|
|
'Smaller',
|
|
'PROFILE_SETTINGS.FORM.INTERFACE_SECTION.FONT_SIZE.OPTIONS.DEFAULT':
|
|
'Default',
|
|
};
|
|
return translations[key] || key;
|
|
});
|
|
|
|
const { fontSizeOptions } = useFontSize();
|
|
|
|
// Check that translation is applied
|
|
expect(
|
|
fontSizeOptions.value.find(option => option.value === '14px').label
|
|
).toBe('Smaller');
|
|
expect(
|
|
fontSizeOptions.value.find(option => option.value === '16px').label
|
|
).toBe('Default');
|
|
|
|
// Verify translation function was called with correct keys
|
|
expect(mockTranslate).toHaveBeenCalledWith(
|
|
'PROFILE_SETTINGS.FORM.INTERFACE_SECTION.FONT_SIZE.OPTIONS.SMALLER'
|
|
);
|
|
expect(mockTranslate).toHaveBeenCalledWith(
|
|
'PROFILE_SETTINGS.FORM.INTERFACE_SECTION.FONT_SIZE.OPTIONS.DEFAULT'
|
|
);
|
|
});
|
|
});
|