Browse Source

move the iriEncodedFields management in ApiResource and refactor

Olivier Massot 2 năm trước cách đây
mục cha
commit
ba3bc28e31

+ 12 - 1
models/ApiResource.ts

@@ -5,7 +5,18 @@ import {Model} from "pinia-orm";
  */
 export class ApiResource extends Model {
 
-    public static relations: Record<string, ApiResource>
+    protected static _iriEncodedFields: Record<string, ApiResource>
+
+    public static addIriEncodedField(name: string, target: ApiResource) {
+        if (!this._iriEncodedFields) {
+            this._iriEncodedFields = {}
+        }
+        this._iriEncodedFields[name] = target
+    }
+
+    public static getIriEncodedFields() {
+        return this._iriEncodedFields
+    }
 
     /**
      * Fix the 'Cannot stringify arbitrary non-POJOs' warning, meaning server can not parse the store

+ 1 - 5
models/decorators.ts

@@ -14,11 +14,7 @@ export function IriEncoded (
         //@ts-ignore
         const self = target.$self()
 
-        if (!self.hasOwnProperty("relations")) {
-            self.relations = {}
-        }
-
         //@ts-ignore
-        self.relations[propertyKey] = apiResource
+        self.addIriEncodedField(propertyKey, apiResource)
     }
 }

+ 6 - 16
services/data/normalizer/hydraNormalizer.ts

@@ -16,7 +16,7 @@ class HydraNormalizer {
    * @param entity
    */
   public static normalizeEntity(entity: ApiResource): AnyJson {
-    const iriEncodedFields = HydraNormalizer.getIriEncodedFields(entity)
+    const iriEncodedFields = Object.getPrototypeOf(entity).constructor.getIriEncodedFields()
 
     for (const field in iriEncodedFields) {
       const value = entity[field]
@@ -146,13 +146,15 @@ class HydraNormalizer {
 
   protected static denormalizeEntity(model: typeof ApiResource, item: AnyJson) {
     const instance = new model(item)
-
-    const iriEncodedFields = HydraNormalizer.getIriEncodedFields(instance)
+    const iriEncodedFields = model.getIriEncodedFields()
 
     for (const field in iriEncodedFields) {
       const value = instance[field]
-      const targetEntity = iriEncodedFields[field].entity
+      if (value === null) {
+        continue
+      }
 
+      const targetEntity = iriEncodedFields[field].entity
       if (_.isArray(value)) {
         instance[field] = value.map((iri: string) => {
           return HydraNormalizer.getIdFromEntityIri(iri, targetEntity)
@@ -187,18 +189,6 @@ class HydraNormalizer {
     }
   }
 
-  /**
-   * Get the array of the entity's fields marked as IRIEncoded
-   * @see models/decorators.ts
-   *
-   * @param entity
-   * @protected
-   */
-  protected static getIriEncodedFields(entity: ApiResource): Record<string, ApiResource> {
-    const prototype = Object.getPrototypeOf(entity)
-    return prototype.constructor.relations
-  }
-
   /**
    * Retrieve the entitie's id from the given IRI
    * Throws an error if the IRI does not match the expected entity

+ 26 - 50
tests/units/services/data/normalizer/hydraNormalizer.test.ts

@@ -40,13 +40,9 @@ afterEach(() => {
 
 describe('normalize', () => {
     const initialMakeUriMethod = UrlUtils.makeIRI
-    //@ts-ignore
-    const initialGetIriEncodedFieldsMethod = HydraNormalizer.getIriEncodedFields
 
     afterEach(() => {
         UrlUtils.makeIRI = initialMakeUriMethod
-        //@ts-ignore
-        HydraNormalizer.getIriEncodedFields = initialGetIriEncodedFieldsMethod
     })
 
     test('should normalize an entity into a JSON Object', () => {
@@ -57,16 +53,6 @@ describe('normalize', () => {
             oneToManyRelation: [123, 124, 125]
         })
 
-        //@ts-ignore
-        HydraNormalizer.getIriEncodedFields = vi.fn(
-            (entity) => {
-                return {
-                    oneToOneRelation: DummyApiChild,
-                    oneToManyRelation: DummyApiChild
-                }
-            }
-        )
-
         //@ts-ignore
         UrlUtils.makeIRI = vi.fn(
             (targetEntity, id) => {
@@ -390,14 +376,10 @@ describe('denormalizeItem', () => {
 })
 
 describe('denormalizeEntity', () => {
-    //@ts-ignore
-    const initialGetIriEncodedFieldsMethod = HydraNormalizer.getIriEncodedFields
     //@ts-ignore
     const initialGetIdFromEntityIriMethod = HydraNormalizer.getIdFromEntityIri
 
     afterEach(() => {
-        //@ts-ignore
-        HydraNormalizer.getIriEncodedFields = initialGetIriEncodedFieldsMethod
         //@ts-ignore
         HydraNormalizer.getIdFromEntityIri = initialGetIdFromEntityIriMethod
     })
@@ -410,16 +392,6 @@ describe('denormalizeEntity', () => {
             oneToManyRelation: ['/api/dummyChild/123', '/api/dummyChild/124', '/api/dummyChild/125']
         }
 
-        //@ts-ignore
-        HydraNormalizer.getIriEncodedFields = vi.fn(
-            (entity) => {
-                return {
-                    oneToOneRelation: DummyApiChild,
-                    oneToManyRelation: DummyApiChild
-                }
-            }
-        )
-
         //@ts-ignore
         HydraNormalizer.getIdFromEntityIri = vi.fn((iri) => {
             return {
@@ -439,7 +411,33 @@ describe('denormalizeEntity', () => {
             oneToOneRelation: 99,
             oneToManyRelation: [123, 124, 125]
         }))
+    })
+
+    test('should ignore relations fields when missing in the incoming data', () => {
+        const data = {
+            id: 7351,
+            name: 'Bob',
+            oneToManyRelation: ['/api/dummyChild/123', '/api/dummyChild/124', '/api/dummyChild/125']
+        }
 
+        //@ts-ignore
+        HydraNormalizer.getIdFromEntityIri = vi.fn((iri) => {
+            return {
+                '/api/dummyChild/123': 123,
+                '/api/dummyChild/124': 124,
+                '/api/dummyChild/125': 125
+            }[iri]
+        })
+
+        //@ts-ignore
+        const result = HydraNormalizer.denormalizeEntity(DummyApiModel, data)
+
+        expect(result).toStrictEqual(new DummyApiModel({
+            id: 7351,
+            name: "Bob",
+            oneToOneRelation: null,
+            oneToManyRelation: [123, 124, 125]
+        }))
     })
 })
 
@@ -478,28 +476,6 @@ describe('parseEntityIRI', () => {
     })
 })
 
-describe('getIriEncodedFields', () => {
-    const initialRelations = DummyApiModel.relations
-
-    afterEach(() => {
-        DummyApiModel.relations = initialRelations
-    })
-
-    test('get relations', () => {
-        //@ts-ignore
-        const relations:  Record<string, ApiResource> = {'someField': DummyApiChild}
-
-        DummyApiModel.relations = relations
-
-        const entity = new DummyApiModel()
-
-        //@ts-ignore
-        const results = HydraNormalizer.getIriEncodedFields(entity)
-
-        expect(results).toEqual(relations)
-    })
-})
-
 describe('getIdFromEntityIri', () => {
     //@ts-ignore
     const initialParseEntityIRI = HydraNormalizer.parseEntityIRI