瀏覽代碼

fix(core): Correctly persist relation custom fields on Zone entity (#3951)

Ahmed Elhor 2 月之前
父節點
當前提交
c68120a4e7
共有 2 個文件被更改,包括 166 次插入3 次删除
  1. 162 3
      packages/core/e2e/zone.e2e-spec.ts
  2. 4 0
      packages/core/src/service/services/zone.service.ts

+ 162 - 3
packages/core/e2e/zone.e2e-spec.ts

@@ -1,20 +1,33 @@
+import { Facet, LanguageCode, mergeConfig } from '@vendure/core';
 import { createTestEnvironment } from '@vendure/testing';
 import { createTestEnvironment } from '@vendure/testing';
 import gql from 'graphql-tag';
 import gql from 'graphql-tag';
 import path from 'path';
 import path from 'path';
 import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 import { afterAll, beforeAll, describe, expect, it } from 'vitest';
 
 
 import { initialData } from '../../../e2e-common/e2e-initial-data';
 import { initialData } from '../../../e2e-common/e2e-initial-data';
-import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
+import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config';
 
 
 import { ZONE_FRAGMENT } from './graphql/fragments';
 import { ZONE_FRAGMENT } from './graphql/fragments';
 import * as Codegen from './graphql/generated-e2e-admin-types';
 import * as Codegen from './graphql/generated-e2e-admin-types';
 import { DeletionResult } from './graphql/generated-e2e-admin-types';
 import { DeletionResult } from './graphql/generated-e2e-admin-types';
 import { GET_COUNTRY_LIST, UPDATE_CHANNEL } from './graphql/shared-definitions';
 import { GET_COUNTRY_LIST, UPDATE_CHANNEL } from './graphql/shared-definitions';
-
+// import { Facet, LanguageCode } from '../src';
 /* eslint-disable @typescript-eslint/no-non-null-assertion */
 /* eslint-disable @typescript-eslint/no-non-null-assertion */
 
 
 describe('Zone resolver', () => {
 describe('Zone resolver', () => {
-    const { server, adminClient } = createTestEnvironment(testConfig());
+    const { server, adminClient } = createTestEnvironment(
+        mergeConfig(testConfig(), {
+            customFields: {
+                Zone: [
+                    {
+                        name: 'relatedFacet',
+                        type: 'relation',
+                        entity: Facet,
+                    },
+                ],
+            },
+        }),
+    );
     let countries: Codegen.GetCountryListQuery['countries']['items'];
     let countries: Codegen.GetCountryListQuery['countries']['items'];
     let zones: Array<{ id: string; name: string }>;
     let zones: Array<{ id: string; name: string }>;
     let oceania: { id: string; name: string };
     let oceania: { id: string; name: string };
@@ -215,8 +228,154 @@ describe('Zone resolver', () => {
             expect(result2.zones.items.find(c => c.id === oceania.id)).not.toBeUndefined();
             expect(result2.zones.items.find(c => c.id === oceania.id)).not.toBeUndefined();
         });
         });
     });
     });
+
+    describe('Zone custom fields', () => {
+        let testFacet: Codegen.CreateFacetMutation['createFacet'];
+        // Create a target entity (Facet) to link the Zone to
+        it('create a target Facet', async () => {
+            const result = await adminClient.query<
+                Codegen.CreateFacetMutation,
+                Codegen.CreateFacetMutationVariables
+            >(CREATE_FACET_WITH_VALUE, {
+                input: {
+                    code: 'test-relation-facet',
+                    isPrivate: false,
+                    translations: [{ languageCode: LanguageCode.en, name: 'Test Relation Facet' }],
+                },
+            });
+
+            testFacet = result.createFacet;
+            expect(testFacet.name).toBe('Test Relation Facet');
+        });
+
+        // Test createZone with a custom relation field
+        it('createZone persists custom relation field', async () => {
+            const input: Codegen.CreateZoneInput = {
+                name: 'Zone with Custom Relation',
+                memberIds: [],
+                customFields: {
+                    relatedFacetId: testFacet.id,
+                },
+            };
+
+            const result = await adminClient.query<
+                CreateZoneMutationWithCF,
+                Codegen.CreateZoneMutationVariables
+            >(CREATE_ZONE_WITH_CF, { input });
+
+            //  Verify the return value
+            expect(result.createZone.customFields.relatedFacet.id).toBe(testFacet.id);
+            //  Verify by querying it again from the database
+            const result2 = await adminClient.query<GetZoneQueryWithCF, Codegen.GetZoneQueryVariables>(
+                GET_ZONE_WITH_CUSTOM_FIELDS,
+                { id: result.createZone.id },
+            );
+            expect(result2.zone.customFields.relatedFacet.id).toBe(testFacet.id);
+        });
+
+        // Test updateZone with a custom relation field
+        it('updateZone persists custom relation field', async () => {
+            const result = await adminClient.query<
+                UpdateZoneMutationWithCF,
+                Codegen.UpdateZoneMutationVariables
+            >(UPDATE_ZONE_WITH_CF, {
+                input: {
+                    id: zones[1].id,
+                    customFields: {
+                        relatedFacetId: testFacet.id,
+                    },
+                },
+            });
+
+            // Verify the return value
+            expect(result.updateZone.customFields.relatedFacet.id).toBe(testFacet.id);
+
+            // Verify by querying it again from the database
+            const result2 = await adminClient.query<GetZoneQueryWithCF, Codegen.GetZoneQueryVariables>(
+                GET_ZONE_WITH_CUSTOM_FIELDS,
+                { id: zones[1].id },
+            );
+            expect(result2.zone.customFields.relatedFacet.id).toBe(testFacet.id);
+        });
+    });
 });
 });
 
 
+type ZoneWithCustomFields = Omit<Codegen.Zone, 'customFields'> & {
+    customFields: {
+        relatedFacet: {
+            id: string;
+        };
+    };
+};
+
+type CreateZoneMutationWithCF = Omit<Codegen.CreateZoneMutation, 'createZone'> & {
+    createZone: ZoneWithCustomFields;
+};
+
+type UpdateZoneMutationWithCF = Omit<Codegen.UpdateZoneMutation, 'updateZone'> & {
+    updateZone: ZoneWithCustomFields;
+};
+
+type GetZoneQueryWithCF = Omit<Codegen.GetZoneQuery, 'zone'> & {
+    zone: ZoneWithCustomFields;
+};
+
+const CREATE_FACET_WITH_VALUE = gql`
+    mutation CreateFacetWithValue($input: CreateFacetInput!) {
+        createFacet(input: $input) {
+            id
+            name
+        }
+    }
+`;
+
+// A new fragment to include the custom fields
+const ZONE_CUSTOM_FIELDS_FRAGMENT = gql`
+    fragment ZoneCustomFields on Zone {
+        customFields {
+            relatedFacet {
+                id
+            }
+        }
+    }
+`;
+
+// A new mutation to create a Zone with custom fields
+const CREATE_ZONE_WITH_CF = gql`
+    mutation CreateZoneWithCF($input: CreateZoneInput!) {
+        createZone(input: $input) {
+            ...Zone
+            ...ZoneCustomFields
+        }
+    }
+    ${ZONE_FRAGMENT}
+    ${ZONE_CUSTOM_FIELDS_FRAGMENT}
+`;
+
+// A new mutation to update a Zone with custom fields
+const UPDATE_ZONE_WITH_CF = gql`
+    mutation UpdateZoneWithCF($input: UpdateZoneInput!) {
+        updateZone(input: $input) {
+            ...Zone
+            ...ZoneCustomFields
+        }
+    }
+    ${ZONE_FRAGMENT}
+    ${ZONE_CUSTOM_FIELDS_FRAGMENT}
+`;
+
+// A new query to fetch the Zone with its custom fields
+const GET_ZONE_WITH_CUSTOM_FIELDS = gql`
+    query GetZoneWithCustomFields($id: ID!) {
+        zone(id: $id) {
+            ...Zone
+            ...ZoneCustomFields
+        }
+    }
+    ${ZONE_FRAGMENT}
+    ${ZONE_CUSTOM_FIELDS_FRAGMENT}
+`;
+
 const DELETE_ZONE = gql`
 const DELETE_ZONE = gql`
     mutation DeleteZone($id: ID!) {
     mutation DeleteZone($id: ID!) {
         deleteZone(id: $id) {
         deleteZone(id: $id) {

+ 4 - 0
packages/core/src/service/services/zone.service.ts

@@ -24,6 +24,7 @@ import { Zone } from '../../entity/zone/zone.entity';
 import { EventBus } from '../../event-bus';
 import { EventBus } from '../../event-bus';
 import { ZoneEvent } from '../../event-bus/events/zone-event';
 import { ZoneEvent } from '../../event-bus/events/zone-event';
 import { ZoneMembersEvent } from '../../event-bus/events/zone-members-event';
 import { ZoneMembersEvent } from '../../event-bus/events/zone-members-event';
+import { CustomFieldRelationService } from '../helpers/custom-field-relation/custom-field-relation.service';
 import { ListQueryBuilder } from '../helpers/list-query-builder/list-query-builder';
 import { ListQueryBuilder } from '../helpers/list-query-builder/list-query-builder';
 import { TranslatorService } from '../helpers/translator/translator.service';
 import { TranslatorService } from '../helpers/translator/translator.service';
 import { patchEntity } from '../helpers/utils/patch-entity';
 import { patchEntity } from '../helpers/utils/patch-entity';
@@ -47,6 +48,7 @@ export class ZoneService {
         private eventBus: EventBus,
         private eventBus: EventBus,
         private translator: TranslatorService,
         private translator: TranslatorService,
         private listQueryBuilder: ListQueryBuilder,
         private listQueryBuilder: ListQueryBuilder,
+        private customFieldRelationService: CustomFieldRelationService,
     ) {}
     ) {}
 
 
     /** @internal */
     /** @internal */
@@ -121,6 +123,7 @@ export class ZoneService {
             zone.members = await this.getCountriesFromIds(ctx, input.memberIds);
             zone.members = await this.getCountriesFromIds(ctx, input.memberIds);
         }
         }
         const newZone = await this.connection.getRepository(ctx, Zone).save(zone);
         const newZone = await this.connection.getRepository(ctx, Zone).save(zone);
+        await this.customFieldRelationService.updateRelations(ctx, Zone, input, newZone);
         await this.zones.refresh(ctx);
         await this.zones.refresh(ctx);
         await this.eventBus.publish(new ZoneEvent(ctx, newZone, 'created', input));
         await this.eventBus.publish(new ZoneEvent(ctx, newZone, 'created', input));
         return assertFound(this.findOne(ctx, newZone.id));
         return assertFound(this.findOne(ctx, newZone.id));
@@ -130,6 +133,7 @@ export class ZoneService {
         const zone = await this.connection.getEntityOrThrow(ctx, Zone, input.id);
         const zone = await this.connection.getEntityOrThrow(ctx, Zone, input.id);
         const updatedZone = patchEntity(zone, input);
         const updatedZone = patchEntity(zone, input);
         await this.connection.getRepository(ctx, Zone).save(updatedZone, { reload: false });
         await this.connection.getRepository(ctx, Zone).save(updatedZone, { reload: false });
+        await this.customFieldRelationService.updateRelations(ctx, Zone, input, updatedZone);
         await this.zones.refresh(ctx);
         await this.zones.refresh(ctx);
         await this.eventBus.publish(new ZoneEvent(ctx, zone, 'updated', input));
         await this.eventBus.publish(new ZoneEvent(ctx, zone, 'updated', input));
         return assertFound(this.findOne(ctx, zone.id));
         return assertFound(this.findOne(ctx, zone.id));