diff --git a/src/XrmMockupShared/Core.cs b/src/XrmMockupShared/Core.cs index 234c095e..1c132278 100644 --- a/src/XrmMockupShared/Core.cs +++ b/src/XrmMockupShared/Core.cs @@ -211,6 +211,7 @@ private void InitializeDB() new CloseIncidentRequestHandler(this, db, metadata, security), new AddMembersTeamRequestHandler(this, db, metadata, security), new RemoveMembersTeamRequestHandler(this, db, metadata, security), + new SendEmailRequestHandler(this, db, metadata, security), #if !(XRM_MOCKUP_2011 || XRM_MOCKUP_2013) new IsValidStateTransitionRequestHandler(this, db, metadata, security), new CalculateRollupFieldRequestHandler(this, db, metadata, security), @@ -679,6 +680,10 @@ internal OrganizationResponse Execute(OrganizationRequest request, EntityReferen pluginContext.OutputParameters["BusinessEntityCollection"] = (response as RetrieveMultipleResponse)?.EntityCollection; } + else if (request is RetrieveRequest) + { + pluginContext.OutputParameters["BusinessEntity"] = TryRetrieve((request as RetrieveRequest).Target); + } if (!string.IsNullOrEmpty(eventOp)) { diff --git a/src/XrmMockupShared/Database/DbAttributeTypeMap.cs b/src/XrmMockupShared/Database/DbAttributeTypeMap.cs index 803e3598..0db531a4 100644 --- a/src/XrmMockupShared/Database/DbAttributeTypeMap.cs +++ b/src/XrmMockupShared/Database/DbAttributeTypeMap.cs @@ -1,7 +1,7 @@ -using Microsoft.Xrm.Sdk.Metadata; +using Microsoft.Xrm.Sdk; +using Microsoft.Xrm.Sdk.Metadata; using System; using System.Collections.Generic; -using System.Text; namespace DG.Tools.XrmMockup.Database { @@ -27,7 +27,7 @@ internal static class DbAttributeTypeHelper { AttributeTypeCode.Money, typeof(decimal) }, { AttributeTypeCode.Owner, typeof(DbRow) }, { AttributeTypeCode.Customer, typeof(DbRow) }, - { AttributeTypeCode.PartyList, typeof(DbRow[]) }, + { AttributeTypeCode.PartyList, typeof(EntityCollection) }, { AttributeTypeCode.String, typeof(string) }, { AttributeTypeCode.Uniqueidentifier, typeof(Guid) }, { AttributeTypeCode.Virtual, typeof(DbRow[]) } @@ -37,7 +37,7 @@ public static bool IsValidType(AttributeMetadata attrMetadata, object value) { if (value == null) return true; _metadataTypeMap.TryGetValue(attrMetadata.AttributeType.Value, out Type expectedType); if (expectedType == null) { - throw new NotImplementedException($"Attribute of type '{attrMetadata.AttributeType.Value}' is not implemeted in XrmMockup yet."); + throw new NotImplementedException($"Attribute of type '{attrMetadata.AttributeType.Value}' is not implemented in XrmMockup yet."); } if (expectedType.Name == "DbRow[]" && attrMetadata.AttributeType.Value == AttributeTypeCode.Virtual) return true; diff --git a/src/XrmMockupShared/Mappings.cs b/src/XrmMockupShared/Mappings.cs index dfb4ffe9..513d8602 100644 --- a/src/XrmMockupShared/Mappings.cs +++ b/src/XrmMockupShared/Mappings.cs @@ -24,6 +24,7 @@ internal static partial class Mappings { { typeof(UpdateRequest), "Target" }, { typeof(AssociateRequest), "Target" }, { typeof(DisassociateRequest), "Target" }, + { typeof(RetrieveRequest), "Target" }, }; public static Dictionary RequestToEventOperation = new Dictionary() diff --git a/src/XrmMockupShared/Requests/CloseIncidentRequestHandler.cs b/src/XrmMockupShared/Requests/CloseIncidentRequestHandler.cs index 6c952d79..c5a360bc 100644 --- a/src/XrmMockupShared/Requests/CloseIncidentRequestHandler.cs +++ b/src/XrmMockupShared/Requests/CloseIncidentRequestHandler.cs @@ -1,9 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.Xrm.Sdk; +using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Messages; -using Microsoft.Xrm.Sdk.Query; using System.Linq; using Microsoft.Crm.Sdk.Messages; using System.ServiceModel; @@ -80,12 +76,6 @@ internal override OrganizationResponse Execute(OrganizationRequest orgRequest, E throw new FaultException($"incident With Id = {incidentRef.Id} is allready cancelled and connot be closed"); } - var setStaterequest = new SetStateRequest(); - setStaterequest.EntityMoniker = incidentRef; - setStaterequest.State = new OptionSetValue(1); - setStaterequest.Status = request.Status; - core.Execute(setStaterequest, userRef); - var incidentResolution = db.GetDbRowOrNull(request.IncidentResolution.ToEntityReference()); if (incidentResolution != null) @@ -95,6 +85,17 @@ internal override OrganizationResponse Execute(OrganizationRequest orgRequest, E db.Add(request.IncidentResolution); + incident["statecode"] = new OptionSetValue(1); + incident["statuscode"] = request.Status; + + var updateRequest = new UpdateRequest + { + Target = incident, + ["CloseIncidentRequestHandler"] = true, + }; + + core.Execute(updateRequest, userRef); + return new CloseIncidentResponse(); } } diff --git a/src/XrmMockupShared/Requests/RetrieveMultipleRequestHandler.cs b/src/XrmMockupShared/Requests/RetrieveMultipleRequestHandler.cs index 0b9b55a5..33c07cd7 100644 --- a/src/XrmMockupShared/Requests/RetrieveMultipleRequestHandler.cs +++ b/src/XrmMockupShared/Requests/RetrieveMultipleRequestHandler.cs @@ -145,6 +145,12 @@ internal override OrganizationResponse Execute(OrganizationRequest orgRequest, E colToReturn = new EntityCollection(collection.Select(x => x.Value).ToList()); } + if (queryExpr.Distinct) + { + var uniqueIds = new HashSet(); + colToReturn = new EntityCollection(colToReturn.Entities.Where(entity => uniqueIds.Add(entity.Id)).ToList()); + } + // According to docs, should return -1 if ReturnTotalRecordCount set to false colToReturn.TotalRecordCount = queryExpr.PageInfo.ReturnTotalRecordCount ? colToReturn.Entities.Count : -1; diff --git a/src/XrmMockupShared/Requests/SendEmailRequestHandler.cs b/src/XrmMockupShared/Requests/SendEmailRequestHandler.cs new file mode 100644 index 00000000..1f338a48 --- /dev/null +++ b/src/XrmMockupShared/Requests/SendEmailRequestHandler.cs @@ -0,0 +1,140 @@ +using DG.Tools.XrmMockup.Database; +using Microsoft.Crm.Sdk.Messages; +using Microsoft.Xrm.Sdk; +using System; +using System.ServiceModel; + +namespace DG.Tools.XrmMockup +{ + internal class SendEmailRequestHandler : RequestHandler + { + const int EMAIL_STATE_COMPLETED = 1; + const int EMAIL_STATUS_DRAFT = 1; + const int EMAIL_STATUS_PENDING_SEND = 6; + const int EMAIL_STATUS_SENT = 3; + + public SendEmailRequestHandler(Core core, XrmDb db, MetadataSkeleton metadata, Security security) : base(core, db, metadata, security, "SendEmail") { } + + internal override void CheckSecurity(OrganizationRequest orgRequest, EntityReference userRef) + { + var request = MakeRequest(orgRequest); + if (request.EmailId == Guid.Empty) + { + throw new FaultException("Required field 'EmailId' is missing"); + } + + var emailRef = new EntityReference("email", request.EmailId); + + if (!security.HasPermission(emailRef, AccessRights.ReadAccess, userRef)) + { + throw new FaultException($"Principal user (Id={userRef.Id}) is missing Read privilege for email (Id={emailRef.Id})"); + } + + if (!security.HasPermission(emailRef, AccessRights.WriteAccess, userRef)) + { + throw new FaultException($"Principal user (Id={userRef.Id}) is missing Write privilege for email (Id={emailRef.Id})"); + } + + var email = db.GetEntityOrNull(emailRef) ?? throw new FaultException($"email with Id = {request.EmailId} does not exist"); + + if (email.Contains("regardingobjectid")) + { + var regardingObject = email.GetAttributeValue("regardingobjectid"); + + if (!security.HasPermission(regardingObject, AccessRights.ReadAccess, userRef)) + { + throw new FaultException($"Principal user (Id={userRef.Id}) is missing Read privilege for {regardingObject.LogicalName} (Id={regardingObject.Id})"); + } + } + + // Remaining security checks have been omitted to reduce complexity + } + + internal override OrganizationResponse Execute(OrganizationRequest orgRequest, EntityReference userRef) + { + var request = MakeRequest(orgRequest); + + var email = db.GetEntity(new EntityReference("email", request.EmailId)); + + if (email.GetAttributeValue("statuscode").Value != EMAIL_STATUS_DRAFT) + { + throw new FaultException("Email must be in Draft status to send"); + } + + if (email.GetAttributeValue("directioncode") is false) + { + throw new FaultException("Cannot send incoming email messages"); + } + + if (email.Contains("from")) + { + var from = email.GetAttributeValue("from"); + if (from.Entities.Count != 1) + { + throw new FaultException("The email must have one and only one sender"); + } + + var activityParty = from.Entities[0]; + if (activityParty.Contains("partyid")) + { + var partyRef = activityParty.GetAttributeValue("partyid"); + if (db.GetEntityOrNull(partyRef) is null) + { + throw new FaultException($"{partyRef.LogicalName} with Id = {partyRef.Id} does not exist"); + } + } + else + { + throw new FaultException("Sender cannot be unresolved"); + } + } + else + { + throw new FaultException("The email must have a sender"); + } + + if (email.Contains("to")) + { + var to = email.GetAttributeValue("to"); + if (to.Entities.Count is 0) + { + throw new FaultException("The email must have at least one recipient before it can be sent"); + } + + foreach (Entity activityParty in to.Entities) + { + if (activityParty.Contains("partyid")) + { + var partyRef = activityParty.GetAttributeValue("partyid"); + if (db.GetEntityOrNull(partyRef) is null) + { + throw new FaultException($"{partyRef.LogicalName} with Id = {partyRef.Id} does not exist"); + } + } + else if (!activityParty.Contains("addressused")) + { + throw new FaultException("Invalid ActivityParty"); + } + } + } + else + { + throw new FaultException("The email must have at least one recipient before it can be sent"); + } + + + email["statecode"] = new OptionSetValue(EMAIL_STATE_COMPLETED); + email["statuscode"] = new OptionSetValue(request.IssueSend ? EMAIL_STATUS_PENDING_SEND : EMAIL_STATUS_SENT); + + db.Update(email); + + return new SendEmailResponse + { + Results = new ParameterCollection + { + { "Subject", email.Contains("subject") ? email.GetAttributeValue("subject") : null } + } + }; + } + } +} diff --git a/src/XrmMockupShared/Requests/UpdateRequestHandler.cs b/src/XrmMockupShared/Requests/UpdateRequestHandler.cs index 55b95d37..620af30a 100644 --- a/src/XrmMockupShared/Requests/UpdateRequestHandler.cs +++ b/src/XrmMockupShared/Requests/UpdateRequestHandler.cs @@ -72,8 +72,14 @@ internal override OrganizationResponse Execute(OrganizationRequest orgRequest, E var request = MakeRequest(orgRequest); var settings = MockupExecutionContext.GetSettings(request); + if (request.Target.LogicalName is "incident" && + request.Target.GetAttributeValue("statecode").Value is 1 && + !request.Parameters.ContainsKey("CloseIncidentRequestHandler")) + { + throw new FaultException("This message can not be used to set the state of incident to Resolved. In order to set state of incident to Resolved, use the CloseIncidentRequest message instead."); + } + var entRef = request.Target.ToEntityReferenceWithKeyAttributes(); - var entity = request.Target; var row = db.GetDbRow(entRef); if (settings.ServiceRole == MockupServiceSettings.Role.UI && diff --git a/src/XrmMockupShared/XrmMockupShared.projitems b/src/XrmMockupShared/XrmMockupShared.projitems index 0ec8998a..45b5462b 100644 --- a/src/XrmMockupShared/XrmMockupShared.projitems +++ b/src/XrmMockupShared/XrmMockupShared.projitems @@ -17,6 +17,7 @@ + diff --git a/tests/SharedPluginsAndCodeactivites/IncidentDeleteAllRelatedResolutionsOnClose.cs b/tests/SharedPluginsAndCodeactivites/IncidentDeleteAllRelatedResolutionsOnClose.cs new file mode 100644 index 00000000..8ea76d6a --- /dev/null +++ b/tests/SharedPluginsAndCodeactivites/IncidentDeleteAllRelatedResolutionsOnClose.cs @@ -0,0 +1,39 @@ +using DG.XrmFramework.BusinessDomain.ServiceContext; +using System.Linq; + +namespace DG.Some.Namespace +{ + public class IncidentDeleteAllRelatedResolutionsOnClose : Plugin + { + public IncidentDeleteAllRelatedResolutionsOnClose() : base(typeof(IncidentDeleteAllRelatedResolutionsOnClose)) + { + RegisterPluginStep( + EventOperation.Update, + ExecutionStage.PostOperation, + ExecuteDeleteAllRelatedResolutionsOnClose) + .AddFilteredAttributes(x => x.StateCode) + .AddImage(ImageType.PreImage, x => x.StateCode, x => x.Title) + .AddImage(ImageType.PostImage, x => x.StateCode) + .SetExecutionOrder(10); + } + + protected void ExecuteDeleteAllRelatedResolutionsOnClose(LocalPluginContext localContext) + { + var preImage = localContext.PluginExecutionContext.PreEntityImages["PreImage"].ToEntity(); + if (preImage.Title != "TestRemovalOfResolutionsAfterClose") return; + + var postImage = localContext.PluginExecutionContext.PostEntityImages["PostImage"].ToEntity(); + + if (preImage.StateCode == IncidentState.Active && postImage.StateCode != IncidentState.Active) + { + using (var context = new Xrm(localContext.OrganizationService)) + { + context.IncidentResolutionSet + .Where(x => x.IncidentId.Id == localContext.PluginExecutionContext.PrimaryEntityId) + .ToList() + .ForEach(x => localContext.OrganizationAdminService.Delete(x.LogicalName, x.Id)); + } + } + } + } +} diff --git a/tests/SharedPluginsAndCodeactivites/RetrievePlugin.cs b/tests/SharedPluginsAndCodeactivites/RetrievePlugin.cs new file mode 100644 index 00000000..740bcdda --- /dev/null +++ b/tests/SharedPluginsAndCodeactivites/RetrievePlugin.cs @@ -0,0 +1,27 @@ +using DG.XrmFramework.BusinessDomain.ServiceContext; +using Microsoft.Xrm.Sdk; + + +namespace DG.Some.Namespace +{ + public class RetrievePlugin : Plugin + { + public RetrievePlugin() : base(typeof(RetrievePlugin)) + { + RegisterPluginStep( + EventOperation.Retrieve, + ExecutionStage.PostOperation, + ExecutePostRetrieve); + } + + protected void ExecutePostRetrieve(LocalPluginContext localContext) + { + var entity = localContext.PluginExecutionContext.OutputParameters["BusinessEntity"] as Entity; + + if (entity.ToEntity().StateCode == ContactState.Inactive) + { + throw new InvalidPluginExecutionException("Inactive contacts cannot be retrieved."); + } + } + } +} diff --git a/tests/SharedPluginsAndCodeactivites/SharedPluginsAndCodeactivites.projitems b/tests/SharedPluginsAndCodeactivites/SharedPluginsAndCodeactivites.projitems index 11c7fc45..6521d658 100644 --- a/tests/SharedPluginsAndCodeactivites/SharedPluginsAndCodeactivites.projitems +++ b/tests/SharedPluginsAndCodeactivites/SharedPluginsAndCodeactivites.projitems @@ -10,6 +10,7 @@ + @@ -17,6 +18,7 @@ + diff --git a/tests/SharedTests/SharedTests.projitems b/tests/SharedTests/SharedTests.projitems index b1c08505..9d88ac4b 100644 --- a/tests/SharedTests/SharedTests.projitems +++ b/tests/SharedTests/SharedTests.projitems @@ -20,6 +20,7 @@ + diff --git a/tests/SharedTests/TestIncident.cs b/tests/SharedTests/TestIncident.cs index 80ba9737..0f96b451 100644 --- a/tests/SharedTests/TestIncident.cs +++ b/tests/SharedTests/TestIncident.cs @@ -539,5 +539,45 @@ public void TestUpdateResolvedIncidentSucceedsWhenFieldModificationIsAllowed() var retrievedIncident = Incident.Retrieve(orgAdminService, incident.Id); Assert.Equal(IncidentState.Active, retrievedIncident.StateCode); } + + [Fact] + public void TestRemovalOfResolutionsAfterClose() + { + var incident = new Incident + { + Title = "TestRemovalOfResolutionsAfterClose" + }; + incident.Id = orgAdminUIService.Create(incident); + + var incidentResolution = new IncidentResolution + { + Subject = "Resolved Sample Incident", + IncidentId = incident.ToEntityReference() + }; + var closeIncidentRequest = new CloseIncidentRequest + { + IncidentResolution = incidentResolution, + Status = new OptionSetValue((int)Incident_StatusCode.ProblemSolved) + }; + orgAdminUIService.Execute(closeIncidentRequest); + + using (var context = new Xrm(orgAdminUIService)) + { + var retrievedIncidentResolutions = context.IncidentResolutionSet.Where(x => x.IncidentId.Id == incident.Id); + Assert.Empty(retrievedIncidentResolutions); + } + } + + [Fact] + public void TestUpdateIncidentAsResolvedFails() + { + var incident = new Incident(); + incident.Id = orgAdminUIService.Create(incident); + + incident.StateCode = IncidentState.Resolved; + incident.StatusCode = Incident_StatusCode.ProblemSolved; + + Assert.Throws(() => orgAdminService.Update(incident)); + } } } diff --git a/tests/SharedTests/TestRetrieve.cs b/tests/SharedTests/TestRetrieve.cs index fedd028f..5fcb4b3c 100644 --- a/tests/SharedTests/TestRetrieve.cs +++ b/tests/SharedTests/TestRetrieve.cs @@ -301,5 +301,19 @@ public void TestRetrieveUserByFullName() var users = orgAdminService.RetrieveMultiple(q); Assert.Single(users.Entities); } + + [Fact] + public void TestRetrievePlugin() + { + var accountId = orgAdminService.Create(new Contact { LastName = "Test" }); + + orgAdminUIService.Update(new Contact(accountId) + { + StateCode = ContactState.Inactive, + StatusCode = Contact_StatusCode.Inactive + }); + + Assert.Throws(() => Contact.Retrieve(orgAdminService, accountId, x => x.LastName)); + } } } diff --git a/tests/SharedTests/TestRetrieveMultiple.cs b/tests/SharedTests/TestRetrieveMultiple.cs index 76fae032..e0d3b249 100644 --- a/tests/SharedTests/TestRetrieveMultiple.cs +++ b/tests/SharedTests/TestRetrieveMultiple.cs @@ -773,6 +773,44 @@ public void TestQueryExpressionLinkEntityNoSetEntityName() Assert.Equal(2, res.Count()); } + [Fact] + public void RetrieveMultipleWithLinkEntitiesReturnDistinctResults() + { + var lead = new Lead() + { + Subject = "Lead", + ParentContactId = contact1.ToEntityReference() + }; + orgAdminService.Create(lead); + + var linkEntity = new LinkEntity + { + LinkToEntityName = "lead", + LinkToAttributeName = "parentcontactid", + LinkFromEntityName = "contact", + LinkFromAttributeName = "contactid", + Columns = new ColumnSet(false), + EntityAlias = "contact", + JoinOperator = JoinOperator.LeftOuter, + }; + + var filter = new FilterExpression(LogicalOperator.And); + filter.AddCondition(new ConditionExpression("lastname", ConditionOperator.Equal, contact1.LastName)); + + var query = new QueryExpression("contact") + { + Distinct = true, + ColumnSet = new ColumnSet(), + LinkEntities = { linkEntity } + }; + + var res = orgAdminService.RetrieveMultiple(query).Entities; + + var distinctIdCount = res.Select(x => x.Id).Distinct().Count(); + + Assert.Equal(distinctIdCount, res.Count); + } + #endif [Fact] @@ -921,5 +959,16 @@ public void TestCaseSensitivity() Assert.Equal("MATT", res.Entities.Single().GetAttributeValue("firstname")); } + + [Fact] + public void TestRetrieveMultipleFailWithNonExistentAttribute() + { + var query = new QueryExpression("contact") + { + ColumnSet = new ColumnSet("x") + }; + + Assert.Throws(() => orgAdminService.RetrieveMultiple(query)); + } } } diff --git a/tests/SharedTests/TestSendEmail.cs b/tests/SharedTests/TestSendEmail.cs new file mode 100644 index 00000000..329b2571 --- /dev/null +++ b/tests/SharedTests/TestSendEmail.cs @@ -0,0 +1,361 @@ +using DG.XrmFramework.BusinessDomain.ServiceContext; +using Microsoft.Crm.Sdk.Messages; +using System; +using System.Linq; +using System.ServiceModel; +using Xunit; + +namespace DG.XrmMockupTest +{ + public class TestSendEmail : UnitTestBase + { + public TestSendEmail(XrmMockupFixture fixture) : base(fixture) { } + + [Fact] + public void TestSendEmailRequestSuccessWhenIssueSendTrue() + { + var contact = new Contact + { + FirstName = "Test", + EMailAddress1 = "test@test.com" + }; + contact.Id = orgAdminUIService.Create(contact); + + var email = new Email + { + From = new ActivityParty[] + { + new ActivityParty + { + PartyId = crm.AdminUser + } + }, + To = new ActivityParty[] + { + new ActivityParty + { + PartyId = contact.ToEntityReference() + } + }, + Subject = "Test Email", + }; + email.Id = orgAdminUIService.Create(email); + + var sendEmailRequest = new SendEmailRequest + { + EmailId = email.Id, + IssueSend = true + }; + + var response = orgAdminUIService.Execute(sendEmailRequest) as SendEmailResponse; + Assert.NotNull(response); + Assert.Equal(email.Subject, response.Subject); + + using (var context = new Xrm(orgAdminUIService)) + { + var retrievedEmail = context.EmailSet.FirstOrDefault(); + Assert.Equal(EmailState.Completed, retrievedEmail.StateCode); + Assert.Equal(Email_StatusCode.PendingSend, retrievedEmail.StatusCode); + } + } + + [Fact] + public void TestSendEmailRequestSuccessWhenIssueSendFalse() + { + var contact = new Contact + { + FirstName = "Test", + EMailAddress1 = "test@test.com" + }; + contact.Id = orgAdminUIService.Create(contact); + + var email = new Email + { + From = new ActivityParty[] + { + new ActivityParty + { + PartyId = crm.AdminUser + } + }, + To = new ActivityParty[] + { + new ActivityParty + { + PartyId = contact.ToEntityReference() + } + }, + Subject = "Test Email", + }; + email.Id = orgAdminUIService.Create(email); + + var sendEmailRequest = new SendEmailRequest + { + EmailId = email.Id + }; + + var response = orgAdminUIService.Execute(sendEmailRequest) as SendEmailResponse; + Assert.NotNull(response); + Assert.Equal(email.Subject, response.Subject); + + using (var context = new Xrm(orgAdminUIService)) + { + var retrievedEmail = context.EmailSet.FirstOrDefault(); + Assert.Equal(EmailState.Completed, retrievedEmail.StateCode); + Assert.Equal(Email_StatusCode.Sent, retrievedEmail.StatusCode); + } + } + + [Fact] + public void TestSendEmailRequestSuccessWithUnresolvedRecipient() + { + var email = new Email + { + From = new ActivityParty[] + { + new ActivityParty + { + PartyId = crm.AdminUser + } + }, + To = new ActivityParty[] + { + new ActivityParty + { + AddressUsed = "test@test.com" + } + }, + Subject = "Test Email", + }; + email.Id = orgAdminUIService.Create(email); + + var sendEmailRequest = new SendEmailRequest + { + EmailId = email.Id, + IssueSend = true + }; + + var response = orgAdminUIService.Execute(sendEmailRequest) as SendEmailResponse; + Assert.NotNull(response); + Assert.Equal(email.Subject, response.Subject); + + using (var context = new Xrm(orgAdminUIService)) + { + var retrievedEmail = context.EmailSet.FirstOrDefault(); + Assert.Equal(EmailState.Completed, retrievedEmail.StateCode); + Assert.Equal(Email_StatusCode.PendingSend, retrievedEmail.StatusCode); + } + } + + [Fact] + public void TestSendEmailRequestFailsWhenTryingToSendAgain() + { + var contact = new Contact + { + FirstName = "Test", + EMailAddress1 = "test@test.com" + }; + contact.Id = orgAdminUIService.Create(contact); + + var email = new Email + { + From = new ActivityParty[] + { + new ActivityParty + { + PartyId = crm.AdminUser + } + }, + To = new ActivityParty[] + { + new ActivityParty + { + PartyId = contact.ToEntityReference() + } + }, + Subject = "Test Email", + }; + email.Id = orgAdminUIService.Create(email); + + var sendEmailRequest = new SendEmailRequest + { + EmailId = email.Id, + IssueSend = true + }; + + orgAdminUIService.Execute(sendEmailRequest); + + Assert.Throws(() => orgAdminUIService.Execute(sendEmailRequest)); + } + + [Fact] + public void TestSendEmailRequestFailsWhenEmailDirectionCodeIncoming() + { + var email = new Email + { + From = new ActivityParty[] + { + new ActivityParty + { + PartyId = crm.AdminUser + } + }, + To = new ActivityParty[] + { + new ActivityParty + { + AddressUsed = "test@test.com" + } + }, + Subject = "Test Email", + DirectionCode = false + }; + email.Id = orgAdminUIService.Create(email); + + var sendEmailRequest = new SendEmailRequest + { + EmailId = email.Id, + IssueSend = true + }; + + Assert.Throws(() => orgAdminUIService.Execute(sendEmailRequest)); + } + + [Fact] + public void TestSendEmailRequestFailsWhenNoSender() + { + var email = new Email(); + email.Id = orgAdminUIService.Create(email); + + var sendEmailRequest = new SendEmailRequest + { + EmailId = email.Id + }; + + Assert.Throws(() => orgAdminUIService.Execute(sendEmailRequest)); + } + + [Fact] + public void TestSendEmailRequestFailsWhenSenderNotCreated() + { + var contact = new Contact + { + FirstName = "Test", + EMailAddress1 = "test@test.com" + }; + + var email = new Email + { + From = new ActivityParty[] + { + new ActivityParty + { + PartyId = contact.ToEntityReference() + } + } + }; + email.Id = orgAdminUIService.Create(email); + + var sendEmailRequest = new SendEmailRequest + { + EmailId = email.Id + }; + + Assert.Throws(() => orgAdminUIService.Execute(sendEmailRequest)); + } + + [Fact] + public void TestSendEmailRequestFailsWhenSenderUnresolved() + { + var email = new Email + { + From = new ActivityParty[] + { + new ActivityParty() + { + AddressUsed = "test@test.com" + } + } + }; + email.Id = orgAdminUIService.Create(email); + + var sendEmailRequest = new SendEmailRequest + { + EmailId = email.Id + }; + + Assert.Throws(() => orgAdminUIService.Execute(sendEmailRequest)); + } + + [Fact] + public void TestSendEmailRequestFailsWhenMoreThanOneSender() + { + var email = new Email + { + From = new ActivityParty[] + { + new ActivityParty(), + new ActivityParty(), + } + }; + email.Id = orgAdminUIService.Create(email); + + var sendEmailRequest = new SendEmailRequest + { + EmailId = email.Id + }; + + Assert.Throws(() => orgAdminUIService.Execute(sendEmailRequest)); + } + + [Fact] + public void TestSendEmailRequestFailsWhenNoRecipients() + { + var email = new Email + { + From = new ActivityParty[] + { + new ActivityParty + { + PartyId = crm.AdminUser + } + } + }; + email.Id = orgAdminUIService.Create(email); + + var sendEmailRequest = new SendEmailRequest + { + EmailId = email.Id + }; + + Assert.Throws(() => orgAdminUIService.Execute(sendEmailRequest)); + } + + [Fact] + public void TestSendEmailRequestFailsWhenRecipientInvalid() + { + var email = new Email + { + From = new ActivityParty[] + { + new ActivityParty + { + PartyId = crm.AdminUser + } + }, + To = new ActivityParty[] + { + new ActivityParty() + } + }; + email.Id = orgAdminUIService.Create(email); + + var sendEmailRequest = new SendEmailRequest + { + EmailId = email.Id + }; + + Assert.Throws(() => orgAdminUIService.Execute(sendEmailRequest)); + } + } +}