From f7c70ebee1a578e619ad895615d77ebd146c0375 Mon Sep 17 00:00:00 2001 From: Erik Michelson Date: Sun, 11 Feb 2024 22:58:48 +0100 Subject: [PATCH] test(utils): add tests for updateObject util Signed-off-by: Erik Michelson --- frontend/src/utils/update-object.ts | 11 ++++++ frontend/src/utils/update-objects.spec.ts | 45 +++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 frontend/src/utils/update-objects.spec.ts diff --git a/frontend/src/utils/update-object.ts b/frontend/src/utils/update-object.ts index 5ea80f435..663290bc3 100644 --- a/frontend/src/utils/update-object.ts +++ b/frontend/src/utils/update-object.ts @@ -3,12 +3,23 @@ * * 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 = >(oldObject: T, newValues: T | null): void => { if (typeof newValues !== 'object' || newValues === null) { return } Object.keys(oldObject).forEach((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 // @ts-expect-error oldObject[key] = newValues[key] diff --git a/frontend/src/utils/update-objects.spec.ts b/frontend/src/utils/update-objects.spec.ts new file mode 100644 index 000000000..c9aca5cc6 --- /dev/null +++ b/frontend/src/utils/update-objects.spec.ts @@ -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 }) + }) +})