- Introduced a new `pageLayout` field in the user settings schema to allow for top-level layout configurations. - Refactored the user settings manager to handle `pageLayout` separately from default settings, ensuring proper data structure during updates. - Updated normalization functions to accommodate the new `pageLayout` field, enhancing the overall user settings management. - Added tests to verify the correct handling of `pageLayout` updates, ensuring that it is written at the top level and not under defaults.
147 lines
3.6 KiB
JavaScript
147 lines
3.6 KiB
JavaScript
import { jest } from '@jest/globals';
|
|
|
|
const findOne = jest.fn();
|
|
const findOneAndUpdate = jest.fn();
|
|
|
|
jest.unstable_mockModule(
|
|
'../database/schemas/misc/usersettings.schema.js',
|
|
() => ({
|
|
userSettingsModel: {
|
|
findOne,
|
|
findOneAndUpdate
|
|
}
|
|
})
|
|
);
|
|
|
|
const { UserSettingsManager, createEmptySettings, isSafeSettingsKey } =
|
|
await import('./usersettingsmanager.js');
|
|
|
|
const queryResult = value => ({
|
|
select: jest.fn().mockReturnValue({
|
|
lean: jest.fn().mockResolvedValue(value)
|
|
})
|
|
});
|
|
|
|
describe('UserSettingsManager', () => {
|
|
let manager;
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
manager = new UserSettingsManager({
|
|
authenticated: true,
|
|
user: { _id: 'user-id' }
|
|
});
|
|
});
|
|
|
|
it('returns empty defaults when the user has no settings document', async () => {
|
|
findOne.mockReturnValue(queryResult(null));
|
|
|
|
await expect(manager.getUserSettings()).resolves.toEqual(
|
|
createEmptySettings()
|
|
);
|
|
expect(findOne).toHaveBeenCalledWith({ user: 'user-id' });
|
|
});
|
|
|
|
it('atomically upserts only the requested category and key', async () => {
|
|
const defaults = {
|
|
...createEmptySettings(),
|
|
viewMode: { payments: 'cards' }
|
|
};
|
|
findOneAndUpdate.mockReturnValue(queryResult({ defaults }));
|
|
|
|
await expect(
|
|
manager.updateUserSettings({
|
|
category: 'viewMode',
|
|
key: 'payments',
|
|
value: 'cards'
|
|
})
|
|
).resolves.toEqual(defaults);
|
|
|
|
expect(findOneAndUpdate).toHaveBeenCalledWith(
|
|
{ user: 'user-id' },
|
|
expect.objectContaining({
|
|
$set: expect.objectContaining({
|
|
'defaults.viewMode.payments': 'cards'
|
|
}),
|
|
$setOnInsert: expect.objectContaining({ user: 'user-id' })
|
|
}),
|
|
{
|
|
new: true,
|
|
upsert: true,
|
|
setDefaultsOnInsert: true
|
|
}
|
|
);
|
|
});
|
|
|
|
it('writes pageLayout at the top level, not under defaults', async () => {
|
|
const pageLayout = {
|
|
InventoryOverview: {
|
|
sectionOrder: ['partStockStats'],
|
|
statsOrder: {}
|
|
}
|
|
};
|
|
findOneAndUpdate.mockReturnValue(
|
|
queryResult({
|
|
defaults: createEmptySettings(),
|
|
pageLayout
|
|
})
|
|
);
|
|
|
|
await expect(
|
|
manager.updateUserSettings({
|
|
category: 'pageLayout',
|
|
key: 'InventoryOverview',
|
|
value: pageLayout.InventoryOverview
|
|
})
|
|
).resolves.toEqual({
|
|
...createEmptySettings(),
|
|
pageLayout
|
|
});
|
|
|
|
expect(findOneAndUpdate).toHaveBeenCalledWith(
|
|
{ user: 'user-id' },
|
|
expect.objectContaining({
|
|
$set: expect.objectContaining({
|
|
'pageLayout.InventoryOverview': pageLayout.InventoryOverview
|
|
})
|
|
}),
|
|
expect.anything()
|
|
);
|
|
expect(findOneAndUpdate.mock.calls[0][1].$set).not.toHaveProperty(
|
|
'defaults.pageLayout.InventoryOverview'
|
|
);
|
|
});
|
|
|
|
it('rejects invalid categories and unsafe keys', async () => {
|
|
await expect(
|
|
manager.updateUserSettings({
|
|
category: 'unknown',
|
|
key: 'payments',
|
|
value: true
|
|
})
|
|
).rejects.toThrow('Invalid user settings category');
|
|
|
|
await expect(
|
|
manager.updateUserSettings({
|
|
category: 'viewMode',
|
|
key: 'payments.value',
|
|
value: true
|
|
})
|
|
).rejects.toThrow('Invalid user settings key');
|
|
|
|
expect(isSafeSettingsKey('$payments')).toBe(false);
|
|
expect(findOneAndUpdate).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('rejects unauthenticated access', async () => {
|
|
manager = new UserSettingsManager({
|
|
authenticated: false,
|
|
user: { _id: 'user-id' }
|
|
});
|
|
|
|
await expect(manager.getUserSettings()).rejects.toThrow(
|
|
'User is not authenticated'
|
|
);
|
|
});
|
|
});
|