test(utils): add tests for updateObject util

Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
Erik Michelson 2024-02-11 22:58:48 +01:00
parent d840a6f0b1
commit f7c70ebee1
2 changed files with 56 additions and 0 deletions

View file

@ -3,12 +3,23 @@
* *
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
/**
* Takes a string-keyed object and updates it with the values of another object while ensuring that the types match.
* Keys in the new object, that are not present in the old object will be ignored.
* This is useful for updating a state object with data from an API response or local storage.
* The method operates in-place on the old object, instead of returning a new object to reduce memory usage.
*
* @param oldObject The object to update.
* @param newValues The object containing the new values.
*/
export const updateObject = <T extends Record<string, unknown>>(oldObject: T, newValues: T | null): void => { export const updateObject = <T extends Record<string, unknown>>(oldObject: T, newValues: T | null): void => {
if (typeof newValues !== 'object' || newValues === null) { if (typeof newValues !== 'object' || newValues === null) {
return return
} }
Object.keys(oldObject).forEach((key) => { Object.keys(oldObject).forEach((key) => {
if (Object.prototype.hasOwnProperty.call(newValues, key) && typeof oldObject[key] === typeof newValues[key]) { if (Object.prototype.hasOwnProperty.call(newValues, key) && typeof oldObject[key] === typeof newValues[key]) {
// TypeScript does not allow to assign a value to a key of a generic object (as it could be potentially readonly)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error // @ts-expect-error
oldObject[key] = newValues[key] oldObject[key] = newValues[key]

View file

@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { updateObject } from './update-object'
describe('updateObject', () => {
it('should not update the object if newValues is not an object', () => {
const oldObject = { a: 1, b: 2 }
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
updateObject(oldObject, 'abc')
expect(oldObject).toEqual({ a: 1, b: 2 })
})
it('should not update the object if newValues is null', () => {
const oldObject = { a: 1, b: 2 }
updateObject(oldObject, null)
expect(oldObject).toEqual({ a: 1, b: 2 })
})
it('should update the object with the new values', () => {
const oldObject = { a: 1, b: 2 }
const newValues = { a: 3, b: 4 }
updateObject(oldObject, newValues)
expect(oldObject).toEqual({ a: 3, b: 4 })
})
it('should ignore keys that are not present in the old object', () => {
const oldObject = { a: 1, b: 2 }
const newValues = { a: 3, b: 4, c: 5 }
updateObject(oldObject, newValues)
expect(oldObject).toEqual({ a: 3, b: 4 })
})
it('should ignore keys with different types', () => {
const oldObject = { a: 1, b: 2 }
const newValues = { a: '3', b: 4 }
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
updateObject(oldObject, newValues)
expect(oldObject).toEqual({ a: 1, b: 4 })
})
})