From badec4367243a624a8ff7e967783a1a501611cef Mon Sep 17 00:00:00 2001 From: Khoa Nguyen Date: Tue, 10 Dec 2024 16:45:49 +0000 Subject: [PATCH 1/5] added unit tests --- .../__tests__/unit-tests/field-lookup.test.ts | 64 +++++++++++++++++++ .../unit-tests/field-primitive.test.ts | 24 +++++++ src/dataverse-ify/odataify/odataifyFields.ts | 2 +- 3 files changed, 89 insertions(+), 1 deletion(-) diff --git a/src/dataverse-ify/__tests__/unit-tests/field-lookup.test.ts b/src/dataverse-ify/__tests__/unit-tests/field-lookup.test.ts index bd4e9b4..721dee1 100644 --- a/src/dataverse-ify/__tests__/unit-tests/field-lookup.test.ts +++ b/src/dataverse-ify/__tests__/unit-tests/field-lookup.test.ts @@ -47,3 +47,67 @@ test("odataify lookups", async () => { }; expect(JSON.stringify(sdkRecord)).toBe(JSON.stringify(expectedSdk)); }); + +test("odataify lookups with undefined", async () => { + setMetadataCache({ entities: { account: accountMetadata } }); + const accountSdk = { + logicalName: accountMetadata.logicalName, + parentaccountid: undefined, + } as Account; + + const accountOdata = await odataify("Create", accountSdk); + expect(accountOdata).toBeDefined(); + const expectedOdata = { + "@odata.type": "Microsoft.Dynamics.CRM.account", + parentaccountid: null, + }; + expect(accountOdata).toEqual(expectedOdata); +}); + +test("odataify lookups with null", async () => { + setMetadataCache({ entities: { account: accountMetadata } }); + const accountSdk = { + logicalName: accountMetadata.logicalName, + parentaccountid: null, + } as Account; + + const accountOdata = await odataify("Create", accountSdk); + expect(accountOdata).toBeDefined(); + const expectedOdata = { + "@odata.type": "Microsoft.Dynamics.CRM.account", + parentaccountid: null, + }; + expect(accountOdata).toEqual(expectedOdata); +}); + +test("odataify lookups with undefined and navigation property", async () => { + setMetadataCache({ entities: { account: accountMetadata } }); + const accountSdk = { + logicalName: accountMetadata.logicalName, + cdsify_account1: undefined, + } as Account; + + const accountOdata = await odataify("Create", accountSdk); + expect(accountOdata).toBeDefined(); + const expectedOdata = { + "@odata.type": "Microsoft.Dynamics.CRM.account", + cdsify_Account1: null, + }; + expect(accountOdata).toEqual(expectedOdata); +}); + +test("odataify lookups with null and navigation property", async () => { + setMetadataCache({ entities: { account: accountMetadata } }); + const accountSdk = { + logicalName: accountMetadata.logicalName, + cdsify_account1: null, + } as Account; + + const accountOdata = await odataify("Create", accountSdk); + expect(accountOdata).toBeDefined(); + const expectedOdata = { + "@odata.type": "Microsoft.Dynamics.CRM.account", + cdsify_Account1: null, + }; + expect(accountOdata).toEqual(expectedOdata); +}); diff --git a/src/dataverse-ify/__tests__/unit-tests/field-primitive.test.ts b/src/dataverse-ify/__tests__/unit-tests/field-primitive.test.ts index c2576f7..3c61eb5 100644 --- a/src/dataverse-ify/__tests__/unit-tests/field-primitive.test.ts +++ b/src/dataverse-ify/__tests__/unit-tests/field-primitive.test.ts @@ -52,6 +52,30 @@ test("Empty String, Integer, Double, Money, Date Attributes", async () => { expect(JSON.stringify(accountOdata)).toBe(JSON.stringify(expectedOdata)); }); +test("Null String, Integer, Double, Money, Date Attributes", async () => { + setMetadataCache({ entities: { account: accountMetadata } }); + const accountSdk = { + logicalName: accountMetadata.logicalName, + description: null, // String + address1_utcoffset: null, // Integer + address1_latitude: null, // Double + revenue: null, // Money + lastonholdtime: null, // Date + } as Account; + + const accountOdata = await odataify("Create", accountSdk); + expect(accountOdata).toBeDefined(); + const expectedOdata = { + description: null, + address1_utcoffset: null, // Int should be truncated + address1_latitude: null, + revenue: null, + lastonholdtime: null, + "@odata.type": "Microsoft.Dynamics.CRM.account", + }; + expect(accountOdata).toEqual(expectedOdata); +}); + test("sdkify Date fields", async () => { setMetadataCache({ entities: { account: accountMetadata } }); const accountOdata = { diff --git a/src/dataverse-ify/odataify/odataifyFields.ts b/src/dataverse-ify/odataify/odataifyFields.ts index 03f391c..6c924ae 100644 --- a/src/dataverse-ify/odataify/odataifyFields.ts +++ b/src/dataverse-ify/odataify/odataifyFields.ts @@ -72,7 +72,7 @@ async function addNullValueToOutput(field: string, metadata: EntityWebApiMetadat // if lookup field, use the Schema Name from navigation const navigation = caseInsensitiveSearch(field, metadata.navigation as Dictionary); - if (navigation) { + if (navigation && navigation.key !== field) { output[navigation.key] = null; delete output[field]; } From 2b8c2dc8c7aae9a89787f2e80b464fca2a0587a8 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen Date: Tue, 10 Dec 2024 22:00:54 +0000 Subject: [PATCH 2/5] use isostring date --- .../__tests__/integration-tests/odata-retrievemultiple.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dataverse-ify/__tests__/integration-tests/odata-retrievemultiple.test.ts b/src/dataverse-ify/__tests__/integration-tests/odata-retrievemultiple.test.ts index 06b1f15..ea30bbf 100644 --- a/src/dataverse-ify/__tests__/integration-tests/odata-retrievemultiple.test.ts +++ b/src/dataverse-ify/__tests__/integration-tests/odata-retrievemultiple.test.ts @@ -28,7 +28,7 @@ describe("retrieveMultiple", () => { const client = new XrmContextDataverseClient(Xrm.WebApi); // Create 12 records - const name = `fetch test ${new Date()}`; + const name = `fetch test ${new Date().toISOString()}`; const testRecord = { logicalName: cdsify_integrationtestMetadata.logicalName, cdsify_name: name, From f37f2bebc9f3242e5dbc61ddb63e97492481f58b Mon Sep 17 00:00:00 2001 From: Khoa Nguyen Date: Tue, 10 Dec 2024 22:45:19 +0000 Subject: [PATCH 3/5] updated expected error message --- src/webapi/node/__tests__/CRUD/response-errors.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webapi/node/__tests__/CRUD/response-errors.test.ts b/src/webapi/node/__tests__/CRUD/response-errors.test.ts index 0fb5738..624e2ff 100644 --- a/src/webapi/node/__tests__/CRUD/response-errors.test.ts +++ b/src/webapi/node/__tests__/CRUD/response-errors.test.ts @@ -30,7 +30,7 @@ describe("XrmWebApiNode", () => { await Xrm.WebApi.deleteRecord("account", "f0161204-0f0a-ed11-82e6-0022483d2320"); } catch (e) { expect((e as Error).message).toMatch( - /(Account With Id = f0161204-0f0a-ed11-82e6-0022483d2320 Does Not Exist)|(The requested record was not found or you do not have sufficient permissions to view it)/, + /(Account With Id = f0161204-0f0a-ed11-82e6-0022483d2320 Does Not Exist)|(The requested record was not found or you do not have sufficient permissions to view it)|Entity 'account' With Id = f0161204-0f0a-ed11-82e6-0022483d2320 Does Not Exist/, ); } }, 10000); From 77df916c53152db80869a06fb7be7ce1246d1601 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen Date: Tue, 10 Dec 2024 23:42:46 +0000 Subject: [PATCH 4/5] revert imports reorder --- src/dataverse-ify/odataify/odataifyFields.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dataverse-ify/odataify/odataifyFields.ts b/src/dataverse-ify/odataify/odataifyFields.ts index 283a44f..4aa002a 100644 --- a/src/dataverse-ify/odataify/odataifyFields.ts +++ b/src/dataverse-ify/odataify/odataifyFields.ts @@ -1,15 +1,15 @@ /* eslint-disable camelcase */ -import { AttributeTypeCode } from "../../dataverse-gen/enums/AttributeTypeCode"; +import { EntityReference } from "../../types/EntityReference"; +import { Entity } from "../../types/Entity"; +import { IEntity } from "../../types/IEntity"; import { EntityWebApiMetadata } from "../../metadata/EntityWebApiMetadata"; -import { caseInsensitiveSearch } from "../../metadata/MetadataCache"; import { ActivityParty, activityparty_participationtypemask } from "../../types/ActivityParty"; import { Dictionary } from "../../types/Dictionary"; -import { Entity } from "../../types/Entity"; -import { EntityCollection } from "../../types/EntityCollection"; -import { EntityReference } from "../../types/EntityReference"; -import { IEntity } from "../../types/IEntity"; import { getNavigationPathForEntityReference, IEntityReference } from "../../types/IEntityReference"; +import { EntityCollection } from "../../types/EntityCollection"; import { odataify } from "./odataify"; +import { AttributeTypeCode } from "../../dataverse-gen/enums/AttributeTypeCode"; +import { caseInsensitiveSearch } from "../../metadata/MetadataCache"; export async function odataifyFields( action: "Create" | "Update" | "Action", From a900c13cdfe5e6df120dd0277fe49c33648f5e00 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen Date: Thu, 12 Dec 2024 09:39:47 +0000 Subject: [PATCH 5/5] fix executeMultiple requests type --- src/dataverse-ify/DataverseClient/DataverseClient.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dataverse-ify/DataverseClient/DataverseClient.ts b/src/dataverse-ify/DataverseClient/DataverseClient.ts index a66e0d7..f3d9676 100644 --- a/src/dataverse-ify/DataverseClient/DataverseClient.ts +++ b/src/dataverse-ify/DataverseClient/DataverseClient.ts @@ -41,5 +41,5 @@ export interface DataverseClient { relatedEntities: EntityReference[], ): Promise; execute(request: WebApiExecuteRequest): Promise; - executeMultiple(requests: WebApiExecuteRequest[]): Promise; + executeMultiple(requests: (WebApiExecuteRequest | WebApiExecuteRequest[])[]): Promise; }