UNPKG

@shko.online/componentframework-mock

Version:

Mocking library to help with testing PowerApps Component Framework Components

269 lines (268 loc) 12.1 kB
/* Copyright (c) 2022 Betim Beja and Shko Online LLC Licensed under the MIT license. */ import { stub } from 'sinon'; import { parseOData } from '@shko.online/dataverse-odata'; import { AttributeType } from './PropertyTypes'; import { DelayedPromise } from '../utils/DelayedPromise'; export class WebApiMock { constructor(db, formatting) { this._Delay = 200; this._ConvertRowToOData = void 0; this.createRecord = void 0; this.deleteRecord = void 0; this.updateRecord = void 0; this.retrieveMultipleRecords = void 0; this.retrieveRecord = void 0; this._ConvertRowToOData = stub(); this._ConvertRowToOData.callsFake((row, entityMetadata) => { const oldRow = row; if (entityMetadata.Attributes) { entityMetadata.Attributes.forEach(attribute => { const key = attribute.LogicalName; if (/* attribute.AttributeType === AttributeType.Uniqueidentifier ||*/ attribute.AttributeType === AttributeType.Boolean) { if (row[key] === undefined || row[key] === null) { delete row[key]; } } else if (attribute.AttributeType === AttributeType.Lookup) { const key = `_${attribute.LogicalName}_value`; const lookupValue = oldRow[key]; if (key in row) { var _lookupValue$id; row[key] = (_lookupValue$id = lookupValue === null || lookupValue === void 0 ? void 0 : lookupValue.id) !== null && _lookupValue$id !== void 0 ? _lookupValue$id : null; if (lookupValue !== null && lookupValue !== void 0 && lookupValue.id) { row[`${key}@Microsoft.Dynamics.CRM.lookuplogicalname`] = lookupValue.entityType; if (lookupValue.name != null) { row[`${key}@OData.Community.Display.V1.FormattedValue`] = lookupValue.name; } if (oldRow[`${attribute.LogicalName}navigation`]) { row[`${key}@Microsoft.Dynamics.CRM.associatednavigationproperty`] = oldRow[`${attribute.LogicalName}navigation`]; } } } delete row[`${attribute.LogicalName}type`]; delete row[`${attribute.LogicalName}navigation`]; } else if (attribute.AttributeType === AttributeType.DateTime) { const dateValue = row[key]; if (dateValue) { const YYYY = dateValue.getFullYear(); let MM = '0' + (dateValue.getMonth() + 1); MM = MM.substring(MM.length - 2); let DD = '0' + dateValue.getDate(); DD = DD.substring(DD.length - 2); let HH = '0' + dateValue.getUTCHours(); HH = HH.substring(HH.length - 2); let mm = '0' + dateValue.getMinutes(); mm = mm.substring(mm.length - 2); let ss = '0' + dateValue.getSeconds(); ss = ss.substring(ss.length - 2); row[key] = `${YYYY}-${MM}-${DD}T${HH}:${mm}:${ss}Z`; row[`${key}@OData.Community.Display.V1.FormattedValue`] = `${dateValue.getUTCMonth() + 1}/${dateValue.getUTCDate()}/${dateValue.getUTCFullYear()} ${(dateValue.getUTCHours() - 1) % 12 + 1}:${dateValue.getUTCMinutes()} ${dateValue.getUTCHours() > 12 || dateValue.getUTCHours() == 12 && dateValue.getMinutes() > 0 ? 'PM' : 'AM'}`; } else { delete row[key]; } } else if (attribute.AttributeType === AttributeType.Integer || attribute.AttributeType === AttributeType.BigInt) { if (row[key] !== null && row[key] !== undefined) { row[key + '@OData.Community.Display.V1.FormattedValue'] = formatting.formatInteger(row[key]); } } if (!!attribute.AttributeOf) { var _entityMetadata$Attri, _original$LogicalName, _original$LogicalName2; const original = (_entityMetadata$Attri = entityMetadata.Attributes) === null || _entityMetadata$Attri === void 0 ? void 0 : _entityMetadata$Attri.find(att => att.LogicalName == attribute.AttributeOf); if ((original === null || original === void 0 ? void 0 : original.AttributeType) !== AttributeType.Lookup && oldRow[(_original$LogicalName = original === null || original === void 0 ? void 0 : original.LogicalName) !== null && _original$LogicalName !== void 0 ? _original$LogicalName : ''] !== undefined && oldRow[(_original$LogicalName2 = original === null || original === void 0 ? void 0 : original.LogicalName) !== null && _original$LogicalName2 !== void 0 ? _original$LogicalName2 : ''] !== null && oldRow[key] !== null && oldRow[key] !== undefined && (original === null || original === void 0 ? void 0 : original.LogicalName) in row) { row[(original === null || original === void 0 ? void 0 : original.LogicalName) + '@OData.Community.Display.V1.FormattedValue'] = oldRow[key]; } delete row[key]; } }); } Object.getOwnPropertyNames(row).forEach(key => { if (row[key] === undefined) { row[key] = null; } }); }); this.createRecord = stub(); this.createRecord.callsFake((entityType, data) => { const metadata = db.getTableMetadata(entityType); if (!metadata) { return DelayedPromise.rejectAfterDelay({ message: `Entity ${entityType} does not exist.` }, this._Delay); } return DelayedPromise.resolveAfterDelay({ id: db.AddRow(entityType, data, metadata) || '', name: data[metadata.PrimaryNameAttribute || 'name'], entityType: entityType }, this._Delay); }); this.deleteRecord = stub(); this.deleteRecord.callsFake((entityType, id) => { return new Promise((resolve, reject) => { setTimeout(() => { var _result$row; const result = db.GetRow(entityType, id); if (!result.entityMetadata) { return reject({ message: `Entity ${entityType} does not exist.` }); } if (!result.row) { return reject({ message: `Could not find record with id: '${id}' for entity: '${entityType}'.` }); } db.RemoveRow(entityType, id); resolve({ id, name: (_result$row = result.row) === null || _result$row === void 0 ? void 0 : _result$row[result.entityMetadata.PrimaryNameAttribute || 'name'], entityType }); }, this._Delay); }); }); this.updateRecord = stub(); this.updateRecord.callsFake((entityType, id, data) => { var _metadata$Attributes, _result$row2; const attributeHandler = attribute => { if (attribute.AttributeOf || attribute.AttributeType === AttributeType.Virtual) { return; } const key = attribute.AttributeType === AttributeType.Lookup ? `_${attribute.LogicalName}_value` : attribute.LogicalName; if (key in data) { db.UpdateValue(data[key], entityType, key, id); } }; const metadata = db.getTableMetadata(entityType); if (!metadata) { return DelayedPromise.rejectAfterDelay(`Entity ${entityType} does not exist.`, this._Delay); } (_metadata$Attributes = metadata.Attributes) === null || _metadata$Attributes === void 0 || _metadata$Attributes.forEach(attributeHandler); const result = db.GetRow(entityType, id); return DelayedPromise.resolveAfterDelay({ id, name: (_result$row2 = result.row) === null || _result$row2 === void 0 ? void 0 : _result$row2[metadata.PrimaryNameAttribute || 'name'], entityType }, this._Delay); }); this.retrieveMultipleRecords = stub(); this.retrieveMultipleRecords.callsFake((entityType, options, maxPageSize) => { return new Promise((resolve, reject) => { const parsed = options ? parseOData(options) : {}; if (parsed.error) { reject(parsed.error); } const entityMetadata = db.getTableMetadata(entityType); if (!entityMetadata) { reject(`Table ${entityType} does not exist`); return; } if (parsed.userQuery) { const userQuery = db.GetRow('userquery', parsed.userQuery); if (!userQuery.row) { reject({ code: '0x80040217', message: `Entity 'userquery' With Id = ${parsed.userQuery} Does Not Exist` }); return; } if (userQuery.row['returnedtypecode'] !== entityMetadata.LogicalName) { reject({ code: '0x80060888', message: 'No Query View exists with the Given Query Id on the Entity Set.' }); return; } const parsedUserQuery = parseOData('?fetchXml=' + encodeURIComponent(userQuery.row['fetchxml'])); if (!parsedUserQuery.fetchXml) { throw new Error(`User Query with id ${parsed.userQuery} contains wrong data`); } const entities = db.SelectUsingFetchXml(parsedUserQuery.fetchXml); resolve({ entities, nextLink: 'next' }); return; } if (parsed.savedQuery) { const savedQuery = db.GetRow('savedquery', parsed.savedQuery); if (!savedQuery.row) { reject({ code: '0x80040217', message: `Entity 'savedquery' With Id = ${parsed.savedQuery} Does Not Exist` }); return; } if (savedQuery.row['returnedtypecode'] !== entityMetadata.LogicalName) { reject({ code: '0x80060888', message: 'No Query View exists with the Given Query Id on the Entity Set.' }); return; } const parsedSavedQuery = parseOData('?fetchXml=' + encodeURIComponent(savedQuery.row['fetchxml'])); if (!parsedSavedQuery.fetchXml) { throw new Error(`Saved Query with id ${parsed.savedQuery} contains wrong data`); } const entities = db.SelectUsingFetchXml(parsedSavedQuery.fetchXml); resolve({ entities, nextLink: 'next' }); return; } if (parsed.fetchXml) { const entities = db.SelectUsingFetchXml(parsed.fetchXml); resolve({ entities, nextLink: 'next' }); return; } const entities = db.SelectUsingOData(entityMetadata, parsed); entities.forEach(row => { this._ConvertRowToOData(row, entityMetadata); }); resolve({ entities, nextLink: 'string' }); }); }); this.retrieveRecord = stub(); this.retrieveRecord.callsFake((entityType, id, options) => { return new Promise((resolve, reject) => { setTimeout(() => { const result = db.GetRowForAPI(entityType, id); if (!result.entityMetadata) { return reject({ message: `Entity ${entityType} does not exist.` }); } if (!result.row) { return reject({ message: `Could not find record with id: '${id}' for entity: '${entityType}'.` }); } if (options) { var parsed = parseOData(options); if (parsed.$select) { const oldRow = result.row; result.row = {}; parsed.$select.forEach(attribute => { result.row[attribute] = oldRow[attribute]; }); if (result.entityMetadata.PrimaryIdAttribute !== undefined && !parsed.$select.includes(result.entityMetadata.PrimaryIdAttribute)) { result.row[result.entityMetadata.PrimaryIdAttribute] = oldRow[result.entityMetadata.PrimaryIdAttribute]; } } } this._ConvertRowToOData(result.row, result.entityMetadata); resolve(result.row); }, this._Delay); }); }); } }