From 70e0314f979226bb4a6af8ded5a06ddb6379b225 Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Fri, 15 Oct 2021 12:06:17 +0200 Subject: [PATCH] fix(core): Fix EntityHydrator when hydrating empty array relation Fixes #1153 --- packages/core/e2e/entity-hydrator.e2e-spec.ts | 19 +++++++++++++++++++ .../test-plugins/hydration-test-plugin.ts | 12 ++++++++++++ .../entity-hydrator.service.ts | 6 +++--- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/packages/core/e2e/entity-hydrator.e2e-spec.ts b/packages/core/e2e/entity-hydrator.e2e-spec.ts index 8bdfa6f786..42ea723a89 100644 --- a/packages/core/e2e/entity-hydrator.e2e-spec.ts +++ b/packages/core/e2e/entity-hydrator.e2e-spec.ts @@ -118,6 +118,19 @@ describe('Entity hydration', () => { expect(getVariantWithName(hydrateProduct, 'Laptop 15 inch 16GB').price).toBe(229900); expect(getVariantWithName(hydrateProduct, 'Laptop 15 inch 16GB').priceWithTax).toBe(275880); }); + + // https://github.com/vendure-ecommerce/vendure/issues/1153 + it('correctly handles empty array relations', async () => { + // Product T_5 has no asset defined + const { hydrateProductAsset } = await adminClient.query( + GET_HYDRATED_PRODUCT_ASSET, + { + id: 'T_5', + }, + ); + + expect(hydrateProductAsset.assets).toEqual([]); + }); }); function getVariantWithName(product: Product, name: string) { @@ -125,9 +138,15 @@ function getVariantWithName(product: Product, name: string) { } type HydrateProductQuery = { hydrateProduct: Product }; +type HydrateProductAssetQuery = { hydrateProductAsset: Product }; const GET_HYDRATED_PRODUCT = gql` query GetHydratedProduct($id: ID!) { hydrateProduct(id: $id) } `; +const GET_HYDRATED_PRODUCT_ASSET = gql` + query GetHydratedProductAsset($id: ID!) { + hydrateProductAsset(id: $id) + } +`; diff --git a/packages/core/e2e/fixtures/test-plugins/hydration-test-plugin.ts b/packages/core/e2e/fixtures/test-plugins/hydration-test-plugin.ts index eaa363d2d2..7b2a0bab63 100644 --- a/packages/core/e2e/fixtures/test-plugins/hydration-test-plugin.ts +++ b/packages/core/e2e/fixtures/test-plugins/hydration-test-plugin.ts @@ -34,6 +34,17 @@ export class TestAdminPluginResolver { }); return product; } + + // Test case for https://github.com/vendure-ecommerce/vendure/issues/1153 + @Query() + async hydrateProductAsset(@Ctx() ctx: RequestContext, @Args() args: { id: ID }) { + const product = await this.connection.getRepository(ctx, Product).findOne(args.id); + // tslint:disable-next-line:no-non-null-assertion + await this.entityHydrator.hydrate(ctx, product!, { + relations: ['assets'], + }); + return product; + } } @VendurePlugin({ @@ -43,6 +54,7 @@ export class TestAdminPluginResolver { schema: gql` extend type Query { hydrateProduct(id: ID!): JSON + hydrateProductAsset(id: ID!): JSON } `, }, diff --git a/packages/core/src/service/helpers/entity-hydrator/entity-hydrator.service.ts b/packages/core/src/service/helpers/entity-hydrator/entity-hydrator.service.ts index 9bfc75581e..69d68b4152 100644 --- a/packages/core/src/service/helpers/entity-hydrator/entity-hydrator.service.ts +++ b/packages/core/src/service/helpers/entity-hydrator/entity-hydrator.service.ts @@ -222,9 +222,9 @@ export class EntityHydrator { return currentMetadata.target as Type; } - private isTranslatable(input: any | any[]): input is Translatable { + private isTranslatable(input: T | T[] | undefined): boolean { return Array.isArray(input) - ? input[0].hasOwnProperty('translations') - : input.hasOwnProperty('translations'); + ? input[0]?.hasOwnProperty('translations') ?? false + : input?.hasOwnProperty('translations') ?? false; } }