UNPKG

fakexrmeasy

Version:

This project aims to provide mocks already implemented for Web API calls made from Javascript. This is a work in progress and way less mature than [its C# counterpart](https://github.com/jordimontana82/fake-xrm-easy).

349 lines 15.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Guid = require('guid'); var Enumerable = require("linq"); var ODataUrlParser_1 = require("./ODataUrlParser"); var Dictionary_1 = require("./Dictionary"); var FakeXmlHttpRequest_1 = require("./FakeXmlHttpRequest"); var Entity_1 = require("./Entity"); var XrmFakedContext = /** @class */ (function () { function XrmFakedContext(apiVersion, fakeAbsoluteUrlPrefix, autoMockGlobalNamespace) { this._apiVersion = "v9.0"; this._fakeAbsoluteUrlPrefix = "http://fakecrmurl:5555/fakeOrgName"; this._oDataUrlParser = new ODataUrlParser_1.default(); this._executors = []; this._apiVersion = apiVersion; this._fakeAbsoluteUrlPrefix = fakeAbsoluteUrlPrefix; this._data = new Dictionary_1.default(); this._executors = []; if (autoMockGlobalNamespace) { this.setupGlobalMock(); } } XrmFakedContext.prototype.setupGlobalMock = function () { var self = this; var fakeXhr = new FakeXmlHttpRequest_1.FakeXmlHttpRequest(); fakeXhr.sendCallback = function (xhr) { self.executeRequest(xhr); }; global.XMLHttpRequest = function () { return fakeXhr; }; var self = this; if (!global.Xrm) { global.Xrm = { Page: { context: { getClientUrl: function () { return self._fakeAbsoluteUrlPrefix; } } } }; } }; XrmFakedContext.prototype.initialize = function (entities) { for (var i = 0; i < entities.length; i++) { var e = entities[i]; if (!Guid.isGuid(e.id)) { throw "Entity " + i.toString() + " must have a valid id property (Guid expected)"; } if (!e.logicalName) { throw "Entity " + i.toString() + " must have a valid logicalName attribute"; } e.id = e.id.toString(); var entityName = e.logicalName.toLowerCase(); if (!this._data.containsKey(entityName)) { this._data.add(entityName, new Dictionary_1.default()); } var entityDictionary = this._data.get(entityName); if (!entityDictionary.containsKey(e.id.toString())) { entityDictionary.add(e.id.toString(), e); } else { entityDictionary.set(e.id.toString(), e); } } }; XrmFakedContext.prototype.getEntity = function (logicalName, id) { if (!this._data.containsKey(logicalName)) { throw "Entity with logicalName '" + logicalName + "' does not exist"; } if (!this.getAllData().get(logicalName).containsKey(id)) { throw "Entity with logicalName '" + logicalName + "' and id '" + id + "' does not exist"; } return this.getAllData().get(logicalName).get(id); }; XrmFakedContext.prototype.addEntity = function (entity) { var id = entity.id; if (!id) { id = Guid.create(); } if (!this._data.containsKey(entity.logicalName)) { this._data.add(entity.logicalName, new Dictionary_1.default()); } this._data[entity.logicalName].add(id.toString(), entity); return id.toString(); }; XrmFakedContext.prototype.removeEntity = function (logicalName, id) { var entity = this.getEntity(logicalName, id); //should throw if not exists this._data.get(logicalName).remove(id); }; XrmFakedContext.prototype.updateEntity = function (entity) { var existingEntity = this.getEntity(entity.logicalName, entity.id.toString()); for (var attribute in entity.attributes) { existingEntity.attributes[attribute] = entity.attributes[attribute]; } this._data.get(entity.logicalName).set(entity.id.toString(), existingEntity); }; XrmFakedContext.prototype.replaceEntity = function (entity) { var existingEntity = this.getEntity(entity.logicalName, entity.id.toString()); this._data.get(entity.logicalName).set(entity.id.toString(), entity); }; XrmFakedContext.prototype.createQuery = function (logicalName) { if (!this._data.containsKey(logicalName)) { throw "Entity with logicalName '" + logicalName + "' does not exist"; } var entities = this._data.get(logicalName).values(); var queryable = Enumerable.from(entities); return queryable; }; XrmFakedContext.prototype.getAllData = function () { return this._data; }; XrmFakedContext.prototype.executeRequest = function (fakeXhr) { //Only process requests which belong to the CRM URL if (fakeXhr.url.indexOf(this._fakeAbsoluteUrlPrefix) < 0) { return; } //Get relative url fakeXhr.relativeApiUrl = fakeXhr.url.replace(this._fakeAbsoluteUrlPrefix, ""); //Check web api >= v8 if (fakeXhr.relativeApiUrl.indexOf("/api/data/" + this._apiVersion) < 0) { throw 'Only Web API Requests are supported (' + this._apiVersion + ')'; } //get url part after version fakeXhr.relativeUrl = fakeXhr.relativeApiUrl.replace("/api/data/" + this._apiVersion + "/", ""); //Check if a custom fake executor exists for that request (relativeUrl and method) var executor = this.findExecutorFor(fakeXhr.relativeUrl, fakeXhr.method.toUpperCase()); if (executor) { this.executeCustomExecutor(executor, fakeXhr); return; } //Undo substring and parse body if (fakeXhr.requestHeaders["Content-Type"] && fakeXhr.requestHeaders["Content-Type"].indexOf("application/json") >= 0) { switch (fakeXhr.method.toUpperCase()) { case "POST": this.executePostRequest(fakeXhr); break; case "GET": this.executeGetRequest(fakeXhr); break; case "PUT": throw 'PUT method not yet supported'; case "DELETE": this.executeDeleteRequest(fakeXhr); case "PATCH": this.executePatchRequest(fakeXhr); } } else { throw 'Content-Type not supported. Fake server supports JSON requests only'; } }; XrmFakedContext.prototype.addFakeMessageExecutor = function (executor) { this._executors.push(executor); }; XrmFakedContext.prototype.executePostRequest = function (fakeXhr) { var parsedOData = this._oDataUrlParser.parse(fakeXhr.relativeUrl); var entityName = this.getSingularSetName(parsedOData.entitySetName); var jsonData = JSON.parse(fakeXhr.requestBody); //Create a new record of the specified entity in the context var id = Guid.create(); if (!this._data.containsKey(entityName)) { this._data.add(entityName, new Dictionary_1.default()); } var entityDictionary = this._data.get(entityName); entityDictionary.add(id.toString(), new Entity_1.Entity(entityName, id, jsonData)); //Compose fake response var response = {}; fakeXhr.status = 204; fakeXhr.response = JSON.stringify({}); fakeXhr.readyState = 4; //Completed //Headers var entityIdUrl = this._fakeAbsoluteUrlPrefix + '/api/data/' + this._apiVersion + '/' + parsedOData.entitySetName + '(' + id.toString() + ')'; fakeXhr.setResponseHeader("OData-EntityId", entityIdUrl); //Force onload if (fakeXhr.onload) { fakeXhr.onload(); return; } //Force callback if (fakeXhr.onreadystatechange) fakeXhr.onreadystatechange(); }; XrmFakedContext.prototype.executePatchRequest = function (fakeXhr) { var parsedOData = this._oDataUrlParser.parse(fakeXhr.relativeUrl); var entityName = this.getSingularSetName(parsedOData.entitySetName); var jsonData = JSON.parse(fakeXhr.requestBody); if (!parsedOData.id || parsedOData.id == "") { throw "Patch message requires an id"; } var id = parsedOData.id; if (!this._data.containsKey(entityName)) { this._data.add(entityName, new Dictionary_1.default()); } var entityDictionary = this._data.get(entityName); if (entityDictionary.containsKey(id)) { var currentEntity = entityDictionary.get(id); for (var attr in jsonData) { currentEntity.attributes[attr] = jsonData[attr]; } entityDictionary.set(id, currentEntity); } else { entityDictionary.add(id.toString(), new Entity_1.Entity(entityName, id, jsonData)); } //Compose fake response var response = {}; fakeXhr.status = 204; fakeXhr.response = JSON.stringify({}); fakeXhr.readyState = 4; //Completed //Force onload if (fakeXhr.onload) { fakeXhr.onload(); return; } //Force callback if (fakeXhr.onreadystatechange) fakeXhr.onreadystatechange(); }; XrmFakedContext.prototype.executeDeleteRequest = function (fakeXhr) { var parsedOData = this._oDataUrlParser.parse(fakeXhr.relativeUrl); var entityName = this.getSingularSetName(parsedOData.entitySetName); var jsonData = JSON.parse(fakeXhr.requestBody); if (!parsedOData.id || parsedOData.id == "") { throw "Delete message requires an id"; } var id = parsedOData.id; if (!this._data.containsKey(entityName)) { this._data.add(entityName, new Dictionary_1.default()); } var entityDictionary = this._data.get(entityName); if (entityDictionary.containsKey(id)) { entityDictionary.remove(id); } else { throw 'Entity with entity name = "' + entityName + '" and id="' + id + '"does not exist'; } //Compose fake response var response = {}; fakeXhr.status = 204; fakeXhr.response = JSON.stringify({}); fakeXhr.readyState = 4; //Completed //Force onload if (fakeXhr.onload) { fakeXhr.onload(); return; } //Force callback if (fakeXhr.onreadystatechange) fakeXhr.onreadystatechange(); }; XrmFakedContext.prototype.executeGetRequest = function (fakeXhr) { var parsedOData = this._oDataUrlParser.parse(fakeXhr.relativeUrl); var entityName = this.getSingularSetName(parsedOData.entitySetName); //query entities var queryResult = this.executeQuery(entityName, parsedOData); //Return a list of entities var response = {}; response["@odata.context"] = ""; var entities = []; for (var i = 0; i < queryResult.length; i++) { var odataEntity = queryResult[i].toXrmEntity(); odataEntity["@odata.etag"] = "W/\"" + i.toString() + "\""; entities.push(odataEntity); } if (!parsedOData.wasSingleRetrieve) { response.value = entities; } else { response = entities[0]; } fakeXhr.status = 200; fakeXhr.response = JSON.stringify(response); fakeXhr.responseText = JSON.stringify(response); fakeXhr.readyState = 4; //Completed //Force onload if (fakeXhr.onload) { fakeXhr.onload(); return; } if (fakeXhr.onreadystatechange) fakeXhr.onreadystatechange(); }; XrmFakedContext.prototype.getSingularSetName = function (pluralEntitySetName) { var ending3 = pluralEntitySetName.slice(-3); var ending2 = pluralEntitySetName.slice(-2); var ending = pluralEntitySetName.slice(-1); if (ending3 == "ies") return pluralEntitySetName.substring(0, pluralEntitySetName.length - 3) + "y"; if (ending2 == "es") return pluralEntitySetName.substring(0, pluralEntitySetName.length - 2) + "s"; return pluralEntitySetName.substring(0, pluralEntitySetName.length - 1); //remove last "s" in any other case }; XrmFakedContext.prototype.executeQuery = function (entityName, parsedQuery) { if (!this._data.containsKey(entityName)) return []; var entityDictionary = this._data.get(entityName); var records = entityDictionary.values(); //from //join / expands //where clause //projection //orderby var columnSet = parsedQuery.queryParams ? parsedQuery.queryParams['$select'] : null; var filter = parsedQuery.queryParams ? parsedQuery.queryParams['$filter'] : null; var topCount = parsedQuery.queryParams ? parsedQuery.queryParams['$top'] : null; var queryeable = Enumerable.from(records) //.join() .where(function (e, index) { return parsedQuery.id && parsedQuery.id !== "" ? parsedQuery.id == e.id.toString() : true; }) //Single id filter if retrieving single record .where(function (e, index) { return e.satisfiesFilter(filter); }) .select(function (e, index) { return e.projectAttributes(columnSet); }); //orderby if (topCount) { queryeable = queryeable.take(topCount); } var arrayResult = queryeable.toArray(); var result = []; for (var i = 0; i < arrayResult.length; i++) { result.push(arrayResult[i]); } return result; }; XrmFakedContext.prototype.findExecutorFor = function (relativeUrl, method) { for (var i = 0; i < this._executors.length; i++) { var potentialExecutor = this._executors[i]; if (potentialExecutor.method === method && potentialExecutor.relativeUrl === relativeUrl) return potentialExecutor; } return null; }; XrmFakedContext.prototype.executeCustomExecutor = function (executor, fakeXhr) { var response = executor.execute(fakeXhr.requestBody); var fakeXhrResponse = {}; fakeXhr.status = response.statusCode; fakeXhr.response = JSON.stringify(response.responseBody); fakeXhr.responseText = JSON.stringify(response.responseBody); fakeXhr.readyState = 4; //Completed //Force onload if (fakeXhr.onload) { fakeXhr.onload(); return; } if (fakeXhr.onreadystatechange) fakeXhr.onreadystatechange(); }; return XrmFakedContext; }()); exports.XrmFakedContext = XrmFakedContext; //# sourceMappingURL=XrmFakedContext.js.map