crmfetchkit
Version:
Library for Dynamics CRM that allows the execution of fetchxml-queries via JavaScript
477 lines (378 loc) • 25.4 kB
JavaScript
/*globals describe, chai, it, beforeEach */
var soapParser = require('../../src/util/soapXmlParser');
var BusinessEntity = require('../../src/util/BusinessEntity');
describe("Specification - soapXmlParser", function(){
'use strict';
var expect = chai.expect,
parsedFetchXml = null,
fakePageNr = 2,
fakeCookie ='foobar-paging-cookie',
fetchxml = [
'<fetch version="1.0">',
' <entity name="account">',
' <attribute name="name" />',
' <attribute name="accountid" />',
' <attribute name="accountcategorycode" />',
' <filter type="and">',
' <condition attribute="name"',
' operator="eq" value="John Doe Inc." />',
' </filter>',
' </entity>',
'</fetch>'].join(''),
trimLine = function(line){ return line.trim(); };
it("should inject the paging-cookie", function(){
// action
parsedFetchXml = soapParser.setPagingDetails(fetchxml,
fakePageNr, fakeCookie);
// assert
var parser = new DOMParser();
var doc = parser.parseFromString(parsedFetchXml, 'text/xml');
var fetchElem = doc.getElementsByTagName('fetch')[0];
expect(fetchElem.getAttribute('paging-cookie')).to.equal(fakeCookie);
});
it("should inject the paging number", function(){
// action
parsedFetchXml = soapParser.setPagingDetails(fetchxml, fakePageNr, fakeCookie);
// assert
var parser = new DOMParser();
var doc = parser.parseFromString(parsedFetchXml, 'text/xml');
var fetchElem = doc.getElementsByTagName('fetch')[0];
var injectedPageNr = parseInt(fetchElem.getAttribute('page'), 10);
expect(injectedPageNr).to.equal(fakePageNr);
});
it('should extract the server-error message', function(){
// arrange - http-response with error
var responseXmlObj,
errorMsg,
faultString = "'Account' entity doesn't contain attribute with Name = 'THIS_ATTR_DOES_NOT_EXIST'.",
parser = new DOMParser(),
responseXml = [
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">",
" <s:Body>",
" <s:Fault>",
" <faultcode>s:Client</faultcode>",
" <faultstring xml:lang=\"en-US\">"+faultString+"</faultstring>",
" <detail>",
" <OrganizationServiceFault xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">",
" <ErrorCode>-2147217149</ErrorCode>",
" <ErrorDetails xmlns:a=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\" />",
" <Message>"+faultString+"</Message>",
" <Timestamp>2015-01-16T06:51:11.9541094Z</Timestamp>",
" <InnerFault>",
" <ErrorCode>-2147217149</ErrorCode>",
" <ErrorDetails xmlns:a=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\" />",
" <Message>"+faultString+"</Message>",
" <Timestamp>2015-01-16T06:51:11.9541094Z</Timestamp>",
" <InnerFault i:nil=\"true\" />",
" <TraceText i:nil=\"true\" />",
" </InnerFault>",
" <TraceText i:nil=\"true\" />",
" </OrganizationServiceFault>",
" </detail>",
" </s:Fault>",
" </s:Body>",
"</s:Envelope>"];
// arrange - remove whitespaces
responseXml = responseXml.map(trimLine).join("");
// arrange - convert string to XML Object
responseXmlObj = parser.parseFromString(responseXml, 'text/xml');
// action
errorMsg = soapParser.getSoapError(responseXmlObj);
// assert
expect(errorMsg).to.equal(faultString);
});
describe('method "getFetchResult"', function (){
var userid = 'bf507d0c-093a-e411-bfe4-2c59e54216bc',
parser = new DOMParser(),
responseXml;
beforeEach(function(){
var xml = [
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">",
" <s:Body>",
" <ExecuteResponse xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\">",
" <ExecuteResult xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" i:type=\"a:RetrieveMultipleResponse\">",
" <a:ResponseName xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">RetrieveMultiple</a:ResponseName>",
" <a:Results xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">",
" <a:KeyValuePairOfstringanyType>",
" <b:key xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">EntityCollection</b:key>",
" <b:value xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\" i:type=\"a:EntityCollection\">",
" <a:Entities>",
" <a:Entity>",
" <a:Attributes>",
" <a:KeyValuePairOfstringanyType>",
" <b:key>accountid</b:key>",
" <b:value i:type=\"c:guid\">a8eb7f93-569d-e411-88f8-6c3be5beb2f4</b:value>",
" </a:KeyValuePairOfstringanyType>",
" <a:KeyValuePairOfstringanyType>",
" <b:key>accountcategorycode</b:key>",
" <b:value i:type=\"a:OptionSetValue\">",
" <a:Value>1</a:Value>",
" </b:value>",
" </a:KeyValuePairOfstringanyType>",
" <a:KeyValuePairOfstringanyType>",
" <b:key>createdon</b:key>",
" <b:value i:type=\"c:dateTime\">2015-01-16T08:06:32Z</b:value>",
" </a:KeyValuePairOfstringanyType>",
" <a:KeyValuePairOfstringanyType>",
" <b:key>createdby</b:key>",
" <b:value i:type=\"a:EntityReference\">",
" <a:Id>" +userid+ "</a:Id>",
" <a:LogicalName>systemuser</a:LogicalName>",
" <a:Name>Daniel Rene Thul</a:Name>",
" </b:value>",
" </a:KeyValuePairOfstringanyType>",
" <a:KeyValuePairOfstringanyType>",
" <b:key>donotemail</b:key>",
" <b:value i:type=\"c:boolean\">false</b:value>",
" </a:KeyValuePairOfstringanyType>",
" <a:KeyValuePairOfstringanyType>",
" <b:key>donotfax</b:key>",
" <b:value i:type=\"c:boolean\">true</b:value>",
" </a:KeyValuePairOfstringanyType>",
" <a:KeyValuePairOfstringanyType>",
" <b:key>name</b:key>",
" <b:value i:type=\"c:string\">fetch-integration-test</b:value>",
" </a:KeyValuePairOfstringanyType>",
" </a:Attributes><a:EntityState i:nil=\"true\" />",
" <a:FormattedValues>",
" <a:KeyValuePairOfstringstring>",
" <b:key>accountcategorycode</b:key>",
" <b:value>Preferred Customer</b:value>",
" </a:KeyValuePairOfstringstring>",
" <a:KeyValuePairOfstringstring>",
" <b:key>createdon</b:key>",
" <b:value>16.01.2015 09:06</b:value>",
" </a:KeyValuePairOfstringstring>",
" <a:KeyValuePairOfstringstring>",
" <b:key>donotemail</b:key>",
" <b:value>Allow</b:value>",
" </a:KeyValuePairOfstringstring>",
" <a:KeyValuePairOfstringstring>",
" <b:key>donotfax</b:key>",
" <b:value>Do Not Allow</b:value>",
" </a:KeyValuePairOfstringstring>",
" </a:FormattedValues>",
" <a:Id>a8eb7f93-569d-e411-88f8-6c3be5beb2f4</a:Id>",
" <a:LogicalName>account</a:LogicalName><a:RelatedEntities /></a:Entity>",
" </a:Entities>",
" <a:EntityName>account</a:EntityName>",
" <a:MinActiveRowVersion>-1</a:MinActiveRowVersion>",
" <a:MoreRecords>false</a:MoreRecords>",
" <a:PagingCookie><cookie page=\"1\"><accountid last=\"{A8EB7F93-569D-E411-88F8-6C3BE5BEB2F4}\" first=\"{A8EB7F93-569D-E411-88F8-6C3BE5BEB2F4}\" /></cookie></a:PagingCookie>",
" <a:TotalRecordCount>-1</a:TotalRecordCount>",
" <a:TotalRecordCountLimitExceeded>false</a:TotalRecordCountLimitExceeded>",
" </b:value>",
" </a:KeyValuePairOfstringanyType>",
" </a:Results>",
" </ExecuteResult>",
" </ExecuteResponse>",
" </s:Body>",
"</s:Envelope>" ];
// arrange - remove whitespaces
responseXml = xml.map(trimLine).join("");
});
it('should parse the xml and generate a array of "BusinessEntities" (single element)', function(){
// arrange - convert string to XML Object
var responseXmlObj = parser.parseFromString(responseXml, 'text/xml');
// action
var result = soapParser.getFetchResult(responseXmlObj);
// assert
expect(result.entities).to.be.a('array');
});
it('should parse the xml and generate "BusinessEntity" record)', function(){
// arrange - convert string to XML Object
var responseXmlObj = parser.parseFromString(responseXml, 'text/xml');
// action
var result = soapParser.getFetchResult(responseXmlObj);
// assert
expect(result.entities[0]).to.be.an.instanceof(BusinessEntity);
});
it('should parse the id of the lookup-value record', function() {
// arrange - convert string to XML Object
var responseXmlObj = parser.parseFromString(responseXml, 'text/xml');
// action
var result = soapParser.getFetchResult(responseXmlObj);
// assert - "createBy" is a lookup to the "SystemUser" entity
expect(result.entities[0].getValue('createdby')).to.equal(userid);
});
it('should parse the entity-technicalname of the lookup-value record', function() {
// arrange - convert string to XML Object
var responseXmlObj = parser.parseFromString(responseXml, 'text/xml');
// action
var result = soapParser.getFetchResult(responseXmlObj);
// assert - "createBy" is a lookup to the "SystemUser" entity
expect(result.entities[0].getValue('createdby', 'logicalName')).to.equal('systemuser');
});
it('should parse the primary attr. of the referenced record', function() {
// arrange - convert string to XML Object
var responseXmlObj = parser.parseFromString(responseXml, 'text/xml');
// action
var result = soapParser.getFetchResult(responseXmlObj);
// assert - "createBy" is a lookup to the "SystemUser" entity
expect(result.entities[0].getValue('createdby', 'name')).to.exist();
});
it('should pasre the for an empty optionset-value "NULL" not "NaN"', function() {
// arrange - convert string to XML Object
var responseXmlObj = parser.parseFromString(responseXml, 'text/xml');
// action
var result = soapParser.getFetchResult(responseXmlObj);
// assert - the category-code is of type "number"
expect(result.entities[0].getValue('industrycode')).to.equal(null);
});
describe('data-type parsing', function(){
it('should parse the "createdon" as date', function() {
// arrange - convert string to XML Object
var responseXmlObj = parser.parseFromString(responseXml, 'text/xml');
// action
var result = soapParser.getFetchResult(responseXmlObj);
// assert - "createOn" of type "Date"
expect(result.entities[0].getValue('createdon')).to.a('Date');
});
it('should parse the boolen attributes as boolean', function() {
// arrange - convert string to XML Object
var responseXmlObj = parser.parseFromString(responseXml, 'text/xml');
// action
var result = soapParser.getFetchResult(responseXmlObj);
var account = result.entities[0];
// assert - "donotmail"
expect(account.getValue('donotemail')).to.be.a('boolean');
expect(account.getValue('donotemail')).to.be.equal(false);
// assert - "donotfax"
expect(account.getValue('donotfax')).to.be.a('boolean');
expect(account.getValue('donotfax')).to.be.equal(true);
});
it('should parse the "category-code" (optionset) of the account', function() {
// arrange - convert string to XML Object
var responseXmlObj = parser.parseFromString(responseXml, 'text/xml');
// action
var result = soapParser.getFetchResult(responseXmlObj);
// assert - the category-code is populated
expect(result.entities[0].getValue('accountcategorycode')).to.be.equal(1);
});
it('should parse the optionset-value as "number"', function() {
// arrange - convert string to XML Object
var responseXmlObj = parser.parseFromString(responseXml, 'text/xml');
// action
var result = soapParser.getFetchResult(responseXmlObj);
// assert the category-code is of type "number"
expect(result.entities[0].getValue('accountcategorycode')).to.be.a('number');
});
});
describe('relevant information for the "FetchMore" method', function(){
it('should parse the "moreRecords" information', function() {
// arrange - convert string to XML Object
var responseXmlObj = parser.parseFromString(responseXml, 'text/xml');
// action
var result = soapParser.getFetchResult(responseXmlObj);
// assert - moreRecords is true
expect(result).to.have.property('moreRecords');
expect(result.moreRecords).to.be.a('boolean');
expect(result.moreRecords).to.be.equal(false);
});
it('should parse the "entityName" information', function() {
// arrange - convert string to XML Object
var responseXmlObj = parser.parseFromString(responseXml, 'text/xml');
// action
var result = soapParser.getFetchResult(responseXmlObj);
// assert - moreRecords is true
expect(result).to.have.property('entityName');
expect(result.entityName).to.be.a('string');
expect(result.entityName).to.be.equal('account');
});
it('should parse the "totalRecordcount" information', function() {
// arrange - convert string to XML Object
var responseXmlObj = parser.parseFromString(responseXml, 'text/xml');
// action
var result = soapParser.getFetchResult(responseXmlObj);
// assert
expect(result.totalRecordCount).to.exist();
});
it('should parse the "totalRecordcount" information as number', function() {
// arrange - convert string to XML Object
var responseXmlObj = parser.parseFromString(responseXml, 'text/xml');
// action
var result = soapParser.getFetchResult(responseXmlObj);
// assert
expect(result.totalRecordCount).to.be.a('number');
});
});
});
describe('method - "getRetrieveResult"', function(){
var parser = new DOMParser(),
fakeAccountName = 'foobar-unit-testing',
responseXml;
beforeEach(function(){
var xml = [ "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">",
" <s:Body>",
" <ExecuteResponse xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\">",
" <ExecuteResult xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" i:type=\"a:RetrieveResponse\">",
" <a:ResponseName xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">Retrieve</a:ResponseName>",
" <a:Results xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">",
" <a:KeyValuePairOfstringanyType>",
" <b:key xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">Entity</b:key>",
" <b:value xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\" i:type=\"a:Entity\">",
" <a:Attributes>",
" <a:KeyValuePairOfstringanyType>",
" <b:key>accountid</b:key>",
" <b:value i:type=\"c:guid\">fe9ce180-3881-e511-8100-3863bb35fde0</b:value>",
" </a:KeyValuePairOfstringanyType>",
" <a:KeyValuePairOfstringanyType>",
" <b:key>donotemail</b:key>",
" <b:value i:type=\"c:boolean\">false</b:value>",
" </a:KeyValuePairOfstringanyType>",
" <a:KeyValuePairOfstringanyType>",
" <b:key>donotfax</b:key>",
" <b:value i:type=\"c:boolean\">true</b:value>",
" </a:KeyValuePairOfstringanyType>",
" <a:KeyValuePairOfstringanyType>",
" <b:key>name</b:key>",
" <b:value i:type=\"c:string\">"+fakeAccountName+"</b:value>",
" </a:KeyValuePairOfstringanyType>",
" <a:KeyValuePairOfstringanyType>",
" <b:key>createdon</b:key>",
" <b:value i:type=\"c:dateTime\">2015-11-02T08:05:43Z</b:value>",
" </a:KeyValuePairOfstringanyType>",
" </a:Attributes><a:EntityState i:nil=\"true\" />",
" <a:FormattedValues>",
" <a:KeyValuePairOfstringstring>",
" <b:key>donotemail</b:key>",
" <b:value>Allow</b:value>",
" </a:KeyValuePairOfstringstring>",
" <a:KeyValuePairOfstringstring>",
" <b:key>donotfax</b:key>",
" <b:value>Do Not Allow</b:value>",
" </a:KeyValuePairOfstringstring>",
" <a:KeyValuePairOfstringstring>",
" <b:key>createdon</b:key>",
" <b:value>02.11.2015 09:05</b:value>",
" </a:KeyValuePairOfstringstring>",
" </a:FormattedValues>",
" <a:Id>fe9ce180-3881-e511-8100-3863bb35fde0</a:Id><a:KeyAttributes />",
" <a:LogicalName>account</a:LogicalName><a:RelatedEntities /><a:RowVersion i:nil=\"true\" /></b:value>",
" </a:KeyValuePairOfstringanyType>",
" </a:Results>",
" </ExecuteResult>",
" </ExecuteResponse>",
" </s:Body>",
"</s:Envelope>"];
// arrange - remove whitespaces
responseXml = xml.map(trimLine).join("");
});
it('should parse the retrieve response and generate a "BusinessEntity" record', function(){
// arrange - convert string to XML Object
var responseXmlObj = parser.parseFromString(responseXml, 'text/xml');
// action
var result = soapParser.getRetrieveResult(responseXmlObj);
// assert
expect(result).to.be.an.instanceof(BusinessEntity);
});
it('should parse the "name" attribute', function(){
// arrange - convert string to XML Object
var responseXmlObj = parser.parseFromString(responseXml, 'text/xml');
// action
var result = soapParser.getRetrieveResult(responseXmlObj);
// assert
expect(result.getValue('name')).to.equal(fakeAccountName);
});
});
});