From a2b88ae99ba0ab9470d49752c35297dc22e56add Mon Sep 17 00:00:00 2001 From: Ryan Huellen Date: Sat, 23 Nov 2024 23:50:44 -0600 Subject: [PATCH] test: full coverage on deserializer --- .../deserializeResourceObject.test.ts | 42 ++++++++++--------- .../serializeResourceLinkage.test.ts | 8 ++-- src/serializers/deserializeResourceObject.ts | 34 ++++++++------- src/serializers/serializeResourceLinkage.ts | 4 +- 4 files changed, 46 insertions(+), 42 deletions(-) diff --git a/__tests__/serializers/deserializeResourceObject.test.ts b/__tests__/serializers/deserializeResourceObject.test.ts index 98a3077..a03238f 100644 --- a/__tests__/serializers/deserializeResourceObject.test.ts +++ b/__tests__/serializers/deserializeResourceObject.test.ts @@ -20,27 +20,29 @@ describe('`deserializeResourceObject`', () => { chance = new Chance(); }); - it('should throw an error if the type of the resource object does not match the expected type', () => { - const expectedType = chance.string(); - - getMetadataBySymbolMocked.mockImplementation((_, symbol) => { - if (symbol === resourceSymbol) { - return expectedType; - } + describe('`type`', () => { + it('should throw an error if the type of the resource object does not match the expected type', () => { + const expectedType = chance.string(); + + getMetadataBySymbolMocked.mockImplementation((_, symbol) => { + if (symbol === resourceSymbol) { + return expectedType; + } + }); + + const resourceObject = { + type: chance.string(), + id: chance.string(), + }; + + class SomeResource {} + + expect(() => + deserializeResourceObject(resourceObject, SomeResource), + ).toThrow( + `Failed to deserialize resource object because the type ${resourceObject.type} does not match the expected type ${expectedType}.`, + ); }); - - const resourceObject = { - type: chance.string(), - id: chance.string(), - }; - - class SomeResource {} - - expect(() => - deserializeResourceObject(resourceObject, SomeResource), - ).toThrow( - `Failed to deserialize resource object because the type ${resourceObject.type} does not match the expected type ${expectedType}.`, - ); }); it('should deserialize a resource object into a class instance', () => { diff --git a/__tests__/serializers/serializeResourceLinkage.test.ts b/__tests__/serializers/serializeResourceLinkage.test.ts index e0c95bd..e86ecec 100644 --- a/__tests__/serializers/serializeResourceLinkage.test.ts +++ b/__tests__/serializers/serializeResourceLinkage.test.ts @@ -45,7 +45,7 @@ describe('`serializeResourceLinkage`', () => { ); }); - it('should throw an error if some element in the array does not have an id field', () => { + it('should throw an error if some element in the array does not have an id', () => { const classInstances = [ { a: 'a', @@ -61,7 +61,7 @@ describe('`serializeResourceLinkage`', () => { collectMocked.mockImplementation(() => undefined); expect(() => serializeResourceLinkage(classInstances)).toThrow( - 'Failed to serialize relationship object because the provided class instance does not have an id field.', + 'Failed to serialize relationship object because the provided class instance does not have an id.', ); }); @@ -119,7 +119,7 @@ describe('`serializeResourceLinkage`', () => { ); }); - it('should throw an error if the class instance does not have an id field', () => { + it('should throw an error if the class instance does not have an id', () => { const classInstance = { a: 'a', }; @@ -133,7 +133,7 @@ describe('`serializeResourceLinkage`', () => { collectMocked.mockImplementation(() => undefined); expect(() => serializeResourceLinkage(classInstance)).toThrow( - 'Failed to serialize relationship object because the provided class instance does not have an id field.', + 'Failed to serialize relationship object because the provided class instance does not have an id.', ); }); diff --git a/src/serializers/deserializeResourceObject.ts b/src/serializers/deserializeResourceObject.ts index 9bf4164..014253e 100644 --- a/src/serializers/deserializeResourceObject.ts +++ b/src/serializers/deserializeResourceObject.ts @@ -13,7 +13,8 @@ export const deserializeResourceObject = < T extends JSONAPIResourceObject = JSONAPIResourceObject, >( resourceObject: T, - { prototype }: new () => C, + // biome-ignore lint/suspicious/noExplicitAny: `any` is required to support all class constructors. + { prototype }: new (..._: any[]) => C, ): C => { const classInstance = Object.create(prototype); @@ -28,7 +29,7 @@ export const deserializeResourceObject = < const id = getMetadataBySymbol(classInstance, idSymbol); if (id !== undefined) { - classInstance[id] = resourceObject.id ?? null; + classInstance[id] = resourceObject.id; } if (resourceObject.attributes !== undefined) { @@ -39,7 +40,7 @@ export const deserializeResourceObject = < if (attributes !== undefined) { for (const attribute of attributes) { - classInstance[attribute] = resourceObject.attributes[attribute] ?? null; + classInstance[attribute] = resourceObject.attributes[attribute]; } } } @@ -49,7 +50,7 @@ export const deserializeResourceObject = < if (links !== undefined) { for (const link of links) { - classInstance[link] = resourceObject.links[link] ?? null; + classInstance[link] = resourceObject.links[link]; } } } @@ -59,26 +60,27 @@ export const deserializeResourceObject = < if (metas !== undefined) { for (const meta of metas) { - classInstance[meta] = resourceObject.meta[meta] ?? null; + classInstance[meta] = resourceObject.meta[meta]; } } } if (resourceObject.relationships !== undefined) { - const relationshipTuples = - getMetadataBySymbol<[string, string][]>( - classInstance, - relationshipsSymbol, - ) ?? []; + const relationshipTuples = getMetadataBySymbol<[string, string][]>( + classInstance, + relationshipsSymbol, + ); - for (const [key] of relationshipTuples) { - const relationship = resourceObject.relationships[key]; + if (relationshipTuples !== undefined) { + for (const [key] of relationshipTuples) { + const relationship = resourceObject.relationships[key]; - if (relationship !== undefined) { - const resourceLinkage = relationship.data; + if (relationship !== undefined) { + const resourceLinkage = relationship.data; - if (resourceLinkage !== undefined) { - classInstance[key] = resourceLinkage ?? null; + if (resourceLinkage !== undefined) { + classInstance[key] = resourceLinkage; + } } } } diff --git a/src/serializers/serializeResourceLinkage.ts b/src/serializers/serializeResourceLinkage.ts index dac82d1..4d6cd3b 100644 --- a/src/serializers/serializeResourceLinkage.ts +++ b/src/serializers/serializeResourceLinkage.ts @@ -29,7 +29,7 @@ export const serializeResourceLinkage = ( if (id === undefined) { throw new Error( - 'Failed to serialize relationship object because the provided class instance does not have an id field.', + 'Failed to serialize relationship object because the provided class instance does not have an id.', ); } @@ -52,7 +52,7 @@ export const serializeResourceLinkage = ( if (id === undefined) { throw new Error( - 'Failed to serialize relationship object because the provided class instance does not have an id field.', + 'Failed to serialize relationship object because the provided class instance does not have an id.', ); }