public virtual void ValidateActionData(WorkflowDataValidationResult result, IeBaseAction action,
                                               bool ignoreIds)
        {
            if (action == null)
            {
                return;
            }

            switch (action.ActionType)
            {
            case ActionTypes.EmailNotification:
                ValidateEmailNotificationActionData(result, (IeEmailNotificationAction)action, ignoreIds);
                break;

            case ActionTypes.PropertyChange:
                ValidatePropertyChangeActionData(result, (IePropertyChangeAction)action, ignoreIds);
                break;

            case ActionTypes.Generate:
                ValidateGenerateActionData(result, (IeGenerateAction)action, ignoreIds);
                break;

            case ActionTypes.Webhook:
                // No data to validate
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(action.ActionType));
            }
        }
        public void ValidatePropertyChangeActionData_PropertyValueValidationFailure_Error()
        {
            // Arrange
            const string propertyName = "some";
            var result = new WorkflowDataValidationResult { StandardTypes = new ProjectTypes() };
            var propertyType = new PropertyType { Id = 1, Name = propertyName };
            var itemType = new ItemType { Id = 1, CustomPropertyTypeIds = { propertyType.Id } };
            result.StandardPropertyTypeMapByName.Add(propertyName, propertyType);
            result.StandardTypes.ArtifactTypes.Add(itemType);
            result.AssociatedArtifactTypeIds.Add(itemType.Id);
            var action = new IePropertyChangeAction { PropertyName = propertyName };
            const WorkflowDataValidationErrorCodes errorCode = WorkflowDataValidationErrorCodes.ProjectByIdNotFound;
            _propertyValueValidatorMock
                .Setup(m => m.Validate(action, propertyType, result))
                .Callback(() => result.Errors.Add(new WorkflowDataValidationError { Element = propertyName, ErrorCode = errorCode }));

            // Act
            _dataValidatorMock.Object.ValidatePropertyChangeActionData(result, action, true);

            // Assert
            Assert.IsTrue(result.HasErrors);
            Assert.AreEqual(1, result.Errors.Count);
            Assert.AreEqual(errorCode, result.Errors[0].ErrorCode);
            Assert.AreEqual(propertyName, result.Errors[0].Element as string);
        }
        private async Task FillInGroupProjectIdsAsync(WorkflowDataValidationResult result, IeWorkflow workflow)
        {
            var groupsWithoutProjectId = new List <IeUserGroup>();

            workflow.TransitionEvents?.ForEach(t => CollectGroupsWithUnassignedProjectId(t, groupsWithoutProjectId));
            workflow.PropertyChangeEvents?.ForEach(
                pce => CollectGroupsWithUnassignedProjectId(pce, groupsWithoutProjectId));
            workflow.NewArtifactEvents?.ForEach(nae => CollectGroupsWithUnassignedProjectId(nae, groupsWithoutProjectId));

            if (!groupsWithoutProjectId.Any())
            {
                return;
            }

            var projectMap = (await
                              _workflowRepository.GetProjectIdsByProjectPathsAsync(groupsWithoutProjectId.Select(g => g.GroupProjectPath)))
                             .ToDictionary(p => p.ProjectPath, p => p.ProjectId);

            groupsWithoutProjectId.ForEach(g =>
            {
                int projectId;
                if (projectMap.TryGetValue(g.GroupProjectPath, out projectId))
                {
                    g.GroupProjectId = projectId;
                }
                else
                {
                    result.Errors.Add(new WorkflowDataValidationError
                    {
                        Element   = g.GroupProjectPath,
                        ErrorCode = WorkflowDataValidationErrorCodes.ProjectByPathNotFound
                    });
                }
            });
        }
        private async Task <WorkflowDataValidationResult> InitializeDataValidationResultAsync(IeWorkflow workflow, bool ignoreIds, ProjectTypes standardTypes = null)
        {
            var result = new WorkflowDataValidationResult();

            result.StandardTypes = standardTypes ?? await _projectMetaRepository.GetStandardProjectTypesAsync();

            result.StandardTypes.ArtifactTypes?.RemoveAll(at => at.PredefinedType != null &&
                                                          !at.PredefinedType.Value.IsRegularArtifactType());
            result.StandardArtifactTypeMapByName.AddRange(result.StandardTypes.ArtifactTypes.ToDictionary(pt => pt.Name));
            result.StandardPropertyTypeMapByName.AddRange(result.StandardTypes.PropertyTypes.ToDictionary(pt => pt.Name));
            ISet <string> groupNamesToLookup;
            ISet <string> userNamesToLookup;
            ISet <int>    groupIdsToLookup;
            ISet <int>    userIdsToLookup;

            CollectUsersAndGroupsToLookup(workflow, out userNamesToLookup, out groupNamesToLookup,
                                          out userIdsToLookup, out groupIdsToLookup, ignoreIds);
            result.Users.AddRange(await _userRepository.GetExistingUsersByNamesAsync(userNamesToLookup));
            result.Groups.AddRange(await _userRepository.GetExistingGroupsByNamesAsync(groupNamesToLookup, false));

            if (!ignoreIds)
            {
                result.StandardArtifactTypeMapById.AddRange(result.StandardTypes.ArtifactTypes.ToDictionary(pt => pt.Id));
                result.StandardPropertyTypeMapById.AddRange(result.StandardTypes.PropertyTypes.ToDictionary(pt => pt.Id));
                result.Users.AddRange(await _userRepository.GetExistingUsersByIdsAsync(userIdsToLookup));
                result.Groups.AddRange(await _userRepository.GetExistingGroupsByIds(groupIdsToLookup, false));
            }

            return(result);
        }
        public virtual void ValidateEmailNotificationActionData(WorkflowDataValidationResult result,
                                                                IeEmailNotificationAction action, bool ignoreIds)
        {
            if (action == null)
            {
                return;
            }

            PropertyType propertyType;

            // Update Name where Id is present (to null if Id is not found)
            if (!ignoreIds && action.PropertyId.HasValue)
            {
                if (!result.StandardPropertyTypeMapById.TryGetValue(action.PropertyId.Value, out propertyType))
                {
                    result.Errors.Add(new WorkflowDataValidationError
                    {
                        Element   = action.PropertyId.Value,
                        ErrorCode = WorkflowDataValidationErrorCodes.EmailNotificationActionPropertyTypeNotFoundById
                    });
                }
                action.PropertyName = propertyType?.Name;
            }

            if (action.PropertyName == null)
            {
                return;
            }

            if (!result.StandardPropertyTypeMapByName.TryGetValue(action.PropertyName, out propertyType))
            {
                result.Errors.Add(new WorkflowDataValidationError
                {
                    Element   = action.PropertyName,
                    ErrorCode = WorkflowDataValidationErrorCodes.EmailNotificationActionPropertyTypeNotFoundByName
                });
            }
            else
            {
                if (propertyType.PrimitiveType != PropertyPrimitiveType.Text && propertyType.PrimitiveType != PropertyPrimitiveType.User)
                {
                    result.Errors.Add(new WorkflowDataValidationError
                    {
                        Element   = action.PropertyName,
                        ErrorCode = WorkflowDataValidationErrorCodes.EmailNotificationActionUnacceptablePropertyType
                    });
                }

                if (!IsAssociatedWithWorkflowArtifactTypes(propertyType, result))
                {
                    result.Errors.Add(new WorkflowDataValidationError
                    {
                        Element   = action.PropertyName,
                        ErrorCode = WorkflowDataValidationErrorCodes.EmailNotificationActionPropertyTypeNotAssociated
                    });
                }
            }
        }
        public virtual void ValidatePropertyChangeActionData(WorkflowDataValidationResult result,
                                                             IePropertyChangeAction action, bool ignoreIds)
        {
            if (action == null)
            {
                return;
            }

            PropertyType propertyType;

            // Update Name where Id is present (to null if Id is not found)
            if (!ignoreIds && action.PropertyId.HasValue)
            {
                if (!result.StandardPropertyTypeMapById.TryGetValue(action.PropertyId.Value, out propertyType) &&
                    !WorkflowHelper.TryGetNameOrDescriptionPropertyType(action.PropertyId.Value, out propertyType))
                {
                    result.Errors.Add(new WorkflowDataValidationError
                    {
                        Element   = action.PropertyId.Value,
                        ErrorCode = WorkflowDataValidationErrorCodes.PropertyChangeActionPropertyTypeNotFoundById
                    });
                }

                action.PropertyName = propertyType?.Name;
            }

            if (action.PropertyName == null)
            {
                return;
            }

            if (!result.StandardPropertyTypeMapByName.TryGetValue(action.PropertyName, out propertyType) &&
                !WorkflowHelper.TryGetNameOrDescriptionPropertyType(action.PropertyName, out propertyType))
            {
                result.Errors.Add(new WorkflowDataValidationError
                {
                    Element   = action.PropertyName,
                    ErrorCode = WorkflowDataValidationErrorCodes.PropertyChangeActionPropertyTypeNotFoundByName
                });

                return;
            }

            if (!IsAssociatedWithWorkflowArtifactTypes(propertyType, result))
            {
                result.Errors.Add(new WorkflowDataValidationError
                {
                    Element   = action.PropertyName,
                    ErrorCode = WorkflowDataValidationErrorCodes.PropertyChangeActionPropertyTypeNotAssociated
                });

                return;
            }

            var propertyValueValidator = _propertyValueValidatorFactory.Create(propertyType, result.Users, result.Groups, ignoreIds);

            propertyValueValidator.Validate(action, propertyType, result);
        }
        private static void ValidateArtifactTypesDataAsync(WorkflowDataValidationResult result, List <IeProject> projects, bool ignoreIds)
        {
            if (projects.IsEmpty() || result.ValidProjectIds.IsEmpty())
            {
                return;
            }

            // Update Name where Id is present (to null if Id is not found)
            if (!ignoreIds)
            {
                projects.ForEach(p => p.ArtifactTypes?.ForEach(at =>
                {
                    ItemType itemType;
                    if (at.Id.HasValue)
                    {
                        if (!result.StandardArtifactTypeMapById.TryGetValue(at.Id.Value, out itemType))
                        {
                            result.Errors.Add(new WorkflowDataValidationError
                            {
                                Element   = at.Id.Value,
                                ErrorCode = WorkflowDataValidationErrorCodes.StandardArtifactTypeNotFoundById
                            });
                        }
                        at.Name = itemType?.Name;
                    }
                    else
                    {
                        // Assing Id to artifact types for the workflow diffing.
                        // A negative artifact type Id means Id is not specified in xml.
                        if (result.StandardArtifactTypeMapByName.TryGetValue(at.Name, out itemType) &&
                            itemType != null)
                        {
                            at.Id = itemType.Id * -1;
                        }
                    }
                }));
            }

            var artifactTypesInProjects = projects.SelectMany(p => p.ArtifactTypes?.Where(at => at.Name != null).Select(at => at.Name)).ToList();

            artifactTypesInProjects.ForEach(at =>
            {
                ItemType itemType;
                if (!result.StandardArtifactTypeMapByName.TryGetValue(at, out itemType))
                {
                    result.Errors.Add(new WorkflowDataValidationError
                    {
                        Element   = at,
                        ErrorCode = WorkflowDataValidationErrorCodes.StandardArtifactTypeNotFoundByName
                    });
                }
                else
                {
                    result.AssociatedArtifactTypeIds.Add(itemType.Id);
                }
            });
        }
        private static void ValidateConditionData(WorkflowDataValidationResult result, IeCondition condition,
                                                  bool ignoreIds)
        {
            if (condition == null)
            {
                return;
            }

            // For now the only condition IeStateCondition does not require data validation.
        }
        private void ValidateTriggerData(WorkflowDataValidationResult result, IeTrigger trigger,
                                         bool ignoreIds)
        {
            if (trigger == null)
            {
                return;
            }

            ValidateConditionData(result, trigger.Condition, ignoreIds);
            ValidateActionData(result, trigger.Action, ignoreIds);
        }
        private void ValidateTransitionData(WorkflowDataValidationResult result, IeTransitionEvent transition,
                                            bool ignoreIds)
        {
            if (transition == null)
            {
                return;
            }

            ValidatePermissionGroupsData(result, transition.PermissionGroups, ignoreIds);
            transition.Triggers?.ForEach(t => ValidateTriggerData(result, t, ignoreIds));
        }
        internal void ValidatePropertyChangeEventData(WorkflowDataValidationResult result, IePropertyChangeEvent pcEvent, bool ignoreIds)
        {
            if (pcEvent == null)
            {
                return;
            }

            PropertyType propertyType;

            // Update Name where Id is present (to null if Id is not found)
            if (!ignoreIds && pcEvent.PropertyId.HasValue)
            {
                if (!WorkflowHelper.TryGetNameOrDescriptionPropertyType(pcEvent.PropertyId.Value, out propertyType) &&
                    !result.StandardPropertyTypeMapById.TryGetValue(pcEvent.PropertyId.Value, out propertyType))
                {
                    result.Errors.Add(new WorkflowDataValidationError
                    {
                        Element   = pcEvent.PropertyId.Value,
                        ErrorCode = WorkflowDataValidationErrorCodes.PropertyNotFoundById
                    });
                }

                pcEvent.PropertyName = propertyType?.Name;
            }

            if (pcEvent.PropertyName != null)
            {
                if (!WorkflowHelper.TryGetNameOrDescriptionPropertyType(pcEvent.PropertyName, out propertyType) &&
                    !result.StandardPropertyTypeMapByName.TryGetValue(pcEvent.PropertyName, out propertyType))
                {
                    result.Errors.Add(new WorkflowDataValidationError
                    {
                        Element   = pcEvent.PropertyName,
                        ErrorCode = WorkflowDataValidationErrorCodes.PropertyNotFoundByName
                    });

                    return;
                }

                if (!IsAssociatedWithWorkflowArtifactTypes(propertyType, result))
                {
                    result.Errors.Add(new WorkflowDataValidationError
                    {
                        Element   = pcEvent.PropertyName,
                        ErrorCode = WorkflowDataValidationErrorCodes.PropertyNotAssociated
                    });

                    return;
                }
            }

            pcEvent.Triggers?.ForEach(t => ValidateTriggerData(result, t, ignoreIds));
        }
        private async Task ValidateWorkflowNameForUniquenessAsync(WorkflowDataValidationResult result, IeWorkflow workflow, int?exceptWorkflowId = null)
        {
            var duplicateNames = await _workflowRepository.CheckLiveWorkflowsForNameUniquenessAsync(new[] { workflow.Name }, exceptWorkflowId);

            if (duplicateNames.Any())
            {
                result.Errors.Add(new WorkflowDataValidationError
                {
                    Element   = workflow,
                    ErrorCode = WorkflowDataValidationErrorCodes.WorkflowNameNotUnique
                });
            }
        }
        public void ValidateActionData_PropertyChangeAction_CalledRespectiveValidationMethod()
        {
            // Arrange
            var result = new WorkflowDataValidationResult();
            var action = new IePropertyChangeAction();
            _dataValidatorMock.Setup(m => m.ValidatePropertyChangeActionData(result, action, true)).Verifiable();

            // Act
            _dataValidatorMock.Object.ValidateActionData(result, action, true);

            // Assert
            _dataValidatorMock.Verify();
        }
        public void ValidateGenerateActionData_ChildArtifacts_CalledRespectiveValidationMethod()
        {
            // Arrange
            var result = new WorkflowDataValidationResult();
            var action = new IeGenerateAction { GenerateActionType = GenerateActionTypes.Children };
            _dataValidatorMock.Setup(m => m.ValidateGenerateChildArtifactsActionData(result, action, true)).Verifiable();

            // Act
            _dataValidatorMock.Object.ValidateGenerateActionData(result, action, true);

            // Assert
            _dataValidatorMock.Verify();
        }
        private async Task ValidateEventsDataAsync(WorkflowDataValidationResult result, IeWorkflow workflow,
                                                   bool ignoreIds)
        {
            // For the workflow update Ids are already filled in.
            if (ignoreIds)
            {
                await FillInGroupProjectIdsAsync(result, workflow);
            }

            workflow.TransitionEvents?.ForEach(t => ValidateTransitionData(result, t, ignoreIds));
            workflow.PropertyChangeEvents?.ForEach(pce => ValidatePropertyChangeEventData(result, pce, ignoreIds));
            workflow.NewArtifactEvents?.ForEach(nae => ValidateNewArtifactEventData(result, nae, ignoreIds));
        }
        public void ValidatePropertyChangeActionData_PropertyTypeNotAssociated_Error()
        {
            // Arrange
            const string propertyName = "some";
            var result = new WorkflowDataValidationResult { StandardTypes = new ProjectTypes() };
            result.StandardPropertyTypeMapByName.Add(propertyName, new PropertyType { Name = propertyName });
            var action = new IePropertyChangeAction { PropertyName = propertyName };

            // Act
            _dataValidatorMock.Object.ValidatePropertyChangeActionData(result, action, true);

            // Assert
            Assert.AreEqual(true, result.HasErrors);
            Assert.AreEqual(1, result.Errors.Count);
            Assert.AreEqual(WorkflowDataValidationErrorCodes.PropertyChangeActionPropertyTypeNotAssociated, result.Errors[0].ErrorCode);
            Assert.AreEqual(propertyName, result.Errors[0].Element as string);
        }
        public void ValidatePropertyChangeActionData_PropertyValueValidationSuccess_Success()
        {
            // Arrange
            const string propertyName = "some";
            var result = new WorkflowDataValidationResult { StandardTypes = new ProjectTypes() };
            var propertyType = new PropertyType { Id = 1, Name = propertyName };
            var itemType = new ItemType { Id = 1, CustomPropertyTypeIds = { propertyType.Id } };
            result.StandardPropertyTypeMapByName.Add(propertyName, propertyType);
            result.StandardTypes.ArtifactTypes.Add(itemType);
            result.AssociatedArtifactTypeIds.Add(itemType.Id);
            var action = new IePropertyChangeAction { PropertyName = propertyName };

            // Act
            _dataValidatorMock.Object.ValidatePropertyChangeActionData(result, action, true);

            // Assert
            Assert.AreEqual(false, result.HasErrors);
        }
        public void ValidateGenerateChildArtifactsActionData_ArtifcatTypeFound_Success()
        {
            // Arrange
            const string artifactType = "some";
            var result = new WorkflowDataValidationResult();
            result.StandardArtifactTypeMapByName.Add(artifactType, new ItemType());
            var action = new IeGenerateAction
            {
                GenerateActionType = GenerateActionTypes.Children,
                ArtifactType = artifactType
            };

            // Act
            _dataValidatorMock.Object.ValidateGenerateChildArtifactsActionData(result, action, true);

            // Assert
            Assert.AreEqual(false, result.HasErrors);
        }
        public void ValidatePropertyChangeEventData_Description_ArtifactTypesAssociated_NoError()
        {
            // Arrange
            var propertyType = new PropertyType { Id = WorkflowConstants.PropertyTypeFakeIdDescription, Name = "Description" };
            var artifactType = new ItemType { Id = 1 };
            var result = new WorkflowDataValidationResult { StandardTypes = new ProjectTypes() };
            result.StandardPropertyTypeMapByName.Add(propertyType.Name, propertyType);
            result.StandardTypes.ArtifactTypes.Add(artifactType);
            result.AssociatedArtifactTypeIds.Add(artifactType.Id);
            var propertyChangeEvent = new IePropertyChangeEvent { PropertyName = propertyType.Name };

            // Act
            _dataValidatorMock.Object.ValidatePropertyChangeEventData(result, propertyChangeEvent, true);

            // Assert
            Assert.AreEqual(false, result.HasErrors);
            Assert.AreEqual(0, result.Errors.Count);
        }
        public void ValidateEmailNotificationActionData_Name_ArtifactTypesAssociated_NoError()
        {
            // Arrange
            var propertyType = new PropertyType { Id = WorkflowConstants.PropertyTypeFakeIdName, Name = "Name", PrimitiveType = PropertyPrimitiveType.Text };
            var artifactType = new ItemType { Id = 1 };
            var result = new WorkflowDataValidationResult { StandardTypes = new ProjectTypes() };
            result.StandardPropertyTypeMapByName.Add(propertyType.Name, propertyType);
            result.StandardTypes.ArtifactTypes.Add(artifactType);
            result.AssociatedArtifactTypeIds.Add(artifactType.Id);
            var action = new IeEmailNotificationAction { PropertyName = propertyType.Name };

            // Act
            _dataValidatorMock.Object.ValidateEmailNotificationActionData(result, action, true);

            // Assert
            Assert.AreEqual(false, result.HasErrors);
            Assert.AreEqual(0, result.Errors.Count);
        }
        private static void ValidatePermissionGroupsData(WorkflowDataValidationResult result, List <IeGroup> groups,
                                                         bool ignoreIds)
        {
            if (groups.IsEmpty())
            {
                return;
            }

            var instanceGroupNames   = new HashSet <string>();
            var instanceGroupMapById = new Dictionary <int, string>();

            result.Groups.Where(g => g.ProjectId == null).ForEach(g =>
            {
                instanceGroupNames.Add(g.Name);
                instanceGroupMapById.Add(g.GroupId, g.Name);
            });

            groups.ForEach(g =>
            {
                // Update Name where Id is present (to null if Id is not found)
                if (!ignoreIds && g.Id.HasValue)
                {
                    string name;
                    if (!instanceGroupMapById.TryGetValue(g.Id.Value, out name))
                    {
                        result.Errors.Add(new WorkflowDataValidationError
                        {
                            Element   = g.Id.Value,
                            ErrorCode = WorkflowDataValidationErrorCodes.InstanceGroupNotFoundById
                        });
                    }
                    g.Name = name;
                }

                if (g.Name != null && !instanceGroupNames.Contains(g.Name))
                {
                    result.Errors.Add(new WorkflowDataValidationError
                    {
                        Element   = g.Name,
                        ErrorCode = WorkflowDataValidationErrorCodes.InstanceGroupNotFoundByName
                    });
                }
            });
        }
        public void ValidateEmailNotificationActionData_Description_NoArtifactTypesAssociated_Error()
        {
            // Arrange
            var propertyType = new PropertyType { Id = WorkflowConstants.PropertyTypeFakeIdDescription, Name = "Description", PrimitiveType = PropertyPrimitiveType.Text };
            var artifactType = new ItemType { Id = 1 };
            var result = new WorkflowDataValidationResult { StandardTypes = new ProjectTypes() };
            result.StandardPropertyTypeMapByName.Add(propertyType.Name, propertyType);
            result.StandardTypes.ArtifactTypes.Add(artifactType);
            var action = new IeEmailNotificationAction { PropertyName = propertyType.Name };

            // Act
            _dataValidatorMock.Object.ValidateEmailNotificationActionData(result, action, true);

            // Assert
            Assert.AreEqual(true, result.HasErrors);
            Assert.AreEqual(1, result.Errors.Count);
            Assert.AreEqual(WorkflowDataValidationErrorCodes.EmailNotificationActionPropertyTypeNotAssociated, result.Errors[0].ErrorCode);
            Assert.AreEqual(propertyType.Name, result.Errors[0].Element as string);
        }
        public void ValidatePropertyChangeEventData_Name_NoArtifactTypesAssociated_Error()
        {
            // Arrange
            var propertyType = new PropertyType { Id = WorkflowConstants.PropertyTypeFakeIdName, Name = "Name" };
            var artifactType = new ItemType { Id = 1 };
            var result = new WorkflowDataValidationResult { StandardTypes = new ProjectTypes() };
            result.StandardPropertyTypeMapByName.Add(propertyType.Name, propertyType);
            result.StandardTypes.ArtifactTypes.Add(artifactType);
            var propertyChangeEvent = new IePropertyChangeEvent { PropertyName = propertyType.Name };

            // Act
            _dataValidatorMock.Object.ValidatePropertyChangeEventData(result, propertyChangeEvent, true);

            // Assert
            Assert.AreEqual(true, result.HasErrors);
            Assert.AreEqual(1, result.Errors.Count);
            Assert.AreEqual(WorkflowDataValidationErrorCodes.PropertyNotAssociated, result.Errors[0].ErrorCode);
            Assert.AreEqual(propertyType.Name, result.Errors[0].Element as string);
        }
        public void ValidatePropertyChangeActionData_PropertyTypeNotFound_Error()
        {
            // Arrange
            const string propertyName = "some";
            var result = new WorkflowDataValidationResult();
            var action = new IePropertyChangeAction
            {
                PropertyName = propertyName
            };

            // Act
            _dataValidatorMock.Object.ValidatePropertyChangeActionData(result, action, true);

            // Assert
            Assert.AreEqual(true, result.HasErrors);
            Assert.AreEqual(1, result.Errors.Count);
            Assert.AreEqual(WorkflowDataValidationErrorCodes.PropertyChangeActionPropertyTypeNotFoundByName, result.Errors[0].ErrorCode);
            Assert.AreEqual(propertyName, result.Errors[0].Element as string);
        }
        public void ValidateEmailNotificationActionData_CustomProperty_NotAssociatedWithArtifactTypes_Error()
        {
            // Arrange
            var propertyType = new PropertyType { Id = 1, Name = "My Standard Property", PrimitiveType = PropertyPrimitiveType.User };
            var artifactType = new ItemType { Id = 1 };
            var result = new WorkflowDataValidationResult { StandardTypes = new ProjectTypes() };
            result.StandardPropertyTypeMapByName.Add(propertyType.Name, propertyType);
            result.StandardTypes.ArtifactTypes.Add(artifactType);
            result.AssociatedArtifactTypeIds.Add(artifactType.Id);
            var action = new IeEmailNotificationAction { PropertyName = propertyType.Name };

            // Act
            _dataValidatorMock.Object.ValidateEmailNotificationActionData(result, action, true);

            // Assert
            Assert.AreEqual(true, result.HasErrors);
            Assert.AreEqual(1, result.Errors.Count);
            Assert.AreEqual(WorkflowDataValidationErrorCodes.EmailNotificationActionPropertyTypeNotAssociated, result.Errors[0].ErrorCode);
            Assert.AreEqual(propertyType.Name, result.Errors[0].Element as string);
        }
        public void ValidateGenerateChildArtifactsActionData_ArtifcatTypeNotFound_Error()
        {
            // Arrange
            const string artifactType = "some";
            var result = new WorkflowDataValidationResult();
            var action = new IeGenerateAction
            {
                GenerateActionType = GenerateActionTypes.Children,
                ArtifactType = artifactType
            };

            // Act
            _dataValidatorMock.Object.ValidateGenerateChildArtifactsActionData(result, action, true);

            // Assert
            Assert.AreEqual(true, result.HasErrors);
            Assert.AreEqual(1, result.Errors.Count);
            Assert.AreEqual(WorkflowDataValidationErrorCodes.GenerateChildArtifactsActionArtifactTypeNotFoundByName, result.Errors[0].ErrorCode);
            Assert.AreEqual(artifactType, result.Errors[0].Element as string);
        }
        public void ValidatePropertyChangeActionData_CustomProperty_AssociatedWithArtifactTypes_NoError()
        {
            // Arrange
            var propertyType = new PropertyType { Id = 1, Name = "My Standard Property" };
            var artifactType = new ItemType { Id = 1 };
            var result = new WorkflowDataValidationResult { StandardTypes = new ProjectTypes() };
            result.StandardPropertyTypeMapByName.Add(propertyType.Name, propertyType);
            result.StandardTypes.ArtifactTypes.Add(artifactType);
            result.AssociatedArtifactTypeIds.Add(artifactType.Id);
            var action = new IePropertyChangeAction { PropertyName = propertyType.Name };

            artifactType.CustomPropertyTypeIds.Add(propertyType.Id);

            // Act
            _dataValidatorMock.Object.ValidatePropertyChangeActionData(result, action, true);

            // Assert
            Assert.AreEqual(false, result.HasErrors);
            Assert.AreEqual(0, result.Errors.Count);
        }
        public virtual void ValidateGenerateActionData(WorkflowDataValidationResult result, IeGenerateAction action, bool ignoreIds)
        {
            if (action == null)
            {
                return;
            }

            switch (action.GenerateActionType)
            {
            case GenerateActionTypes.Children:
                ValidateGenerateChildArtifactsActionData(result, action, ignoreIds);
                break;

            case GenerateActionTypes.UserStories:
            case GenerateActionTypes.TestCases:
                // No data validation is required.
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(action.GenerateActionType));
            }
        }
        public virtual void ValidateGenerateChildArtifactsActionData(WorkflowDataValidationResult result,
                                                                     IeGenerateAction action, bool ignoreIds)
        {
            if (action == null)
            {
                return;
            }

            // Update Name where Id is present (to null if Id is not found)
            if (!ignoreIds && action.ArtifactTypeId.HasValue)
            {
                ItemType itemType;
                if (!result.StandardArtifactTypeMapById.TryGetValue(action.ArtifactTypeId.Value, out itemType))
                {
                    result.Errors.Add(new WorkflowDataValidationError
                    {
                        Element   = action.ArtifactTypeId.Value,
                        ErrorCode = WorkflowDataValidationErrorCodes.GenerateChildArtifactsActionArtifactTypeNotFoundById
                    });
                }
                action.ArtifactType = itemType?.Name;
            }

            if (action.ArtifactType == null)
            {
                return;
            }

            if (!result.StandardArtifactTypeMapByName.ContainsKey(action.ArtifactType))
            {
                result.Errors.Add(new WorkflowDataValidationError
                {
                    Element   = action.ArtifactType,
                    ErrorCode = WorkflowDataValidationErrorCodes.GenerateChildArtifactsActionArtifactTypeNotFoundByName
                });
            }
        }
        private static bool IsAssociatedWithWorkflowArtifactTypes(PropertyType propertyType, WorkflowDataValidationResult result)
        {
            if (WorkflowHelper.IsNameOrDescriptionProperty(propertyType.Id))
            {
                return(result.AssociatedArtifactTypeIds.Any());
            }

            return(result.StandardTypes.ArtifactTypes
                   .Where(at => result.AssociatedArtifactTypeIds.Contains(at.Id))
                   .SelectMany(at => at.CustomPropertyTypeIds)
                   .Contains(propertyType.Id));
        }