Name

sn_cmdb_int_util.CMDBIntegrationValidationTestUtils

Description

Test scripts to validate cmdb integrations

Script

var CMDBIntegrationValidationTestUtils = Class.create();
CMDBIntegrationValidationTestUtils.prototype = {
  initialize: function() {},

  getSessionApplicationSysId: function() {
      var applicationName = gs.getProperty("sn_cmdb_int_util.atf_test_cmdb_inst_application_name");
      if (!applicationName)
          return "";
      var gr = new GlideRecord("cmdb_inst_application");
      gr.addQuery("name", applicationName);
      gr.query();
      if (gr.next())
          return gr.getUniqueValue();
      return "";
  },

  validateApplication: function(applicationGr, outputs, steps, stepResult, assertEqual) {
      var applicationName = applicationGr.getValue('name');
      var applicationSysId = applicationGr.getUniqueValue();
      var applicationDisplay = this._buildDisplay('cmdb_inst_application', applicationSysId, applicationName);

      assertEqual({
          name: applicationDisplay + "No discovery_source found.  Please select one.",
          shouldbe: false,
          value: gs.nil(applicationGr.getValue('discovery_source'))
      });
      return true;
  },

  validateApplicationFeed: function(applicationFeedGr, outputs, steps, stepResult, assertEqual) {
      var applicationFeedName = applicationFeedGr.getValue('name');
      var applicationFeedSysId = applicationFeedGr.getUniqueValue();
      var applicationFeedDisplay = this._buildDisplay('cmdb_inst_application_feed', applicationFeedSysId, applicationFeedName);

      var importTableName = '';

      //check for data source
      var dataSourceSysId = applicationFeedGr.getValue('sys_data_source');
      assertEqual({
          name: applicationFeedDisplay + "No data source.  UI will require a data source.",
          shouldbe: false,
          value: gs.nil(dataSourceSysId)
      });

      var dataSourceGr = new GlideRecord('sys_data_source');
      dataSourceGr.addQuery('sys_id', dataSourceSysId);
      dataSourceGr.query();

      assertEqual({
          name: applicationFeedDisplay + "Data source reference is somehow invalid.  The referenced data source does not exist or cannot be found.",
          shouldbe: true,
          value: dataSourceGr.next()
      });

      importTableName = dataSourceGr.getValue('import_set_table_name');

      var importEntitySysId;

      // check entities
      var entityGr = new GlideRecord('cmdb_inst_entity');
      entityGr.addQuery('sys_rte_eb_definition', applicationFeedSysId);
      entityGr.query();

      entitySysIds = [];

      while (entityGr.next()) {
          var entityName = entityGr.getValue('name');
          var entitySysId = entityGr.getUniqueValue();
          var entityDisplay = this._buildDisplay('cmdb_inst_entity', entitySysId, entityName);

          var entityTargetTable = entityGr.getValue('table');
          var entityPath = entityGr.getValue('path');

          var lookupEntity = entityGr.getValue('lookup_for_entity');
          var relatedForEntity = entityGr.getValue('related_for_entity');
          var relationshipType = entityGr.getValue('relationship_type');

          entitySysIds.push(entitySysId);

          assertEqual({
              name: entityDisplay + "Has no name.  Name should be added.",
              shouldbe: false,
              value: gs.nil(entityName)
          });

          this._checkForExistence('cmdb_inst_entity', lookupEntity, entityDisplay, outputs, steps, stepResult, assertEqual);
          this._checkForExistence('cmdb_inst_entity', relatedForEntity, entityDisplay, outputs, steps, stepResult, assertEqual);
          this._checkForExistence('cmdb_rel_type', relationshipType, entityDisplay, outputs, steps, stepResult, assertEqual);

          // import entity
          if (entityName.toLowerCase().contains('import') && (entityTargetTable && importTableName === entityTargetTable)) {
              assertEqual({
                  name: entityDisplay + "Should be named 'Import' by convention",
                  shouldbe: true,
                  value: 'Import' == entityName
              });

              assertEqual({
                  name: entityDisplay + "Path must be empty.  The import set processor will not append any path to the processing complex object.",
                  shouldbe: true,
                  value: gs.nil(entityPath)
              });

              assertEqual({
                  name: applicationFeedDisplay + "Seems to have multiple 'Import' entities.  There should only be a single import entity to represent the import table.  Remove the other.",
                  shouldbe: true,
                  value: gs.nil(importEntitySysId)
              });

              assertEqual({
                  name: entityDisplay + "Import entity should not be a lookup rule.  Remove the Lookup For Entity value.",
                  shouldbe: true,
                  value: gs.nil(lookupEntity)
              });

              assertEqual({
                  name: entityDisplay + "Import entity should not be a related rule.  Remove the Related For Entity value.",
                  shouldbe: true,
                  value: gs.nil(relatedForEntity)
              });

              assertEqual({
                  name: entityDisplay + "Import entity should not be a relationship.  Remove the Relationship type value.",
                  shouldbe: true,
                  value: gs.nil(relationshipType)
              });

              importEntitySysId = entitySysId;
          }
          // temp entity
          else if (entityName.toLowerCase().startsWith('temp')) {

              assertEqual({
                  name: entityDisplay + "Should be named 'Temp' by convention",
                  shouldbe: true,
                  value: entityName.toLowerCase().startsWith("temp")
              });

              assertEqual({
                  name: entityDisplay + "Path should be 'temp' by convention.",
                  shouldbe: true,
                  value: entityPath.toLowerCase().startsWith("temp")
              });

              assertEqual({
                  name: entityDisplay + "Temp entity should not be a lookup rule.  Remove the Lookup For Entity value.",
                  shouldbe: true,
                  value: gs.nil(lookupEntity)
              });

              assertEqual({
                  name: entityDisplay + "Temp entity should not be a related rule.  Remove the Related For Entity value.",
                  shouldbe: true,
                  value: gs.nil(relatedForEntity)
              });

              assertEqual({
                  name: entityDisplay + "Temp entity should not be a relationship.  Remove the Relationship type value.",
                  shouldbe: true,
                  value: gs.nil(relationshipType)
              });
              this._validateFields(entitySysId, applicationFeedSysId, entityTargetTable, importEntitySysId === entitySysId, outputs, steps, stepResult, assertEqual);
          }
          //== cmdb entity
          else {
              this._validateCmdbEntity(entityDisplay, entityName, entityTargetTable, entityPath, outputs, steps, stepResult, assertEqual);

              if ('cmdb_rel_ci' == entityTargetTable) {
                  // cmdb_rel_ci tables should have a relationship type set
                  assertEqual({
                      name: entityDisplay + "Cmdb Relationship tables should have a Relationship Type selected.  Please add one.",
                      shouldbe: false,
                      value: gs.nil(relationshipType)
                  });
              } else if ('cmdb_rel_ci' != entityTargetTable && !lookupEntity) {
                  var sourceNativeKeyGr = new GlideRecord('sys_rte_eb_field');
                  sourceNativeKeyGr.addQuery('field', 'source_native_key');
                  sourceNativeKeyGr.addQuery('sys_rte_eb_entity', entitySysId);
                  sourceNativeKeyGr.query();

                  assertEqual({
                      name: entityDisplay + "All entities (except relationships, lookups, temp, and import) should have a field called 'source_native_key'.  Please add and map.",
                      shouldbe: true,
                      value: sourceNativeKeyGr.next()
                  });
              }
              this._validateFields(entitySysId, applicationFeedSysId, entityTargetTable, importEntitySysId === entitySysId, outputs, steps, stepResult, assertEqual);
          }

      }
      stepResult.setOutputMessage(gs.getMessage("Application feeds are valid"));
      return true;
  },

  validateOperations: function(applicationFeedGr, tempEntitySysIds, outputs, steps, stepResult, assertEqual) {
      if (!tempEntitySysIds || gs.nil(tempEntitySysIds))
          return;
      var applicationFeedName = applicationFeedGr.getValue('name');
      var applicationFeedSysId = applicationFeedGr.getUniqueValue();
      var applicationFeedDisplay = this._buildDisplay('cmdb_inst_application_feed', applicationFeedSysId, applicationFeedName);

      var gr = new GlideRecord('sys_rte_eb_operation');
      gr.addQuery('sys_rte_eb_definition', applicationFeedSysId);
      gr.query();

      while (gr.next()) {
          var operationSysId = gr.getUniqueValue();
          var operationName = gr.getValue('name');
          var operationDisplay = this._buildDisplay('sys_rte_eb_operation', operationSysId, operationName);

          var operationEntity = gr.getValue('sys_rte_eb_entity');

          var targetField = gr.getValue('target_sys_rte_eb_field');
          var targetFields = gr.getValue('target_sys_rte_eb_fields');
          var sourceField = gr.getValue('source_sys_rte_eb_field');
          var sourceFields = gr.getValue('source_sys_rte_eb_fields');

          var operationType = gr.getValue('type');

          assertEqual({
              name: operationDisplay + "By convention only the Temp entity should have operations assigned to it.  Please move operation to the Temp entity.",
              shouldbe: true,
              value: tempEntitySysIds.indexOf(operationEntity + "") > -1
          });

          // can't do the same check for sources because there are operations with no source fields
          assertEqual({
              name: operationDisplay + "Operation does not have any targets set.",
              shouldbe: false,
              value: !targetField && !targetFields
          });

          assertEqual({
              name: operationDisplay + "Missing operation type.  Please add operation type.",
              shouldbe: false,
              value: gs.nil(operationType)
          });

          if (sourceField) {
              this._checkForExistence('sys_rte_eb_field', sourceField, operationDisplay, outputs, steps, stepResult, assertEqual);

              assertEqual({
                  name: operationDisplay + "By convention only the Temp entity should have operations assigned to it.  Source field:" + sourceField + " is not a Temp entity field.",
                  shouldbe: true,
                  value: tempEntitySysIds.indexOf(gr.source_sys_rte_eb_field.sys_rte_eb_entity + "") > -1
              });

          }
          if (sourceFields) {
              var sourceFieldsSplit = sourceFields.split(',');

              for (var i = 0; i < sourceFieldsSplit.length; i++) {
                  var sourceFieldGr = new GlideRecord('sys_rte_eb_field');
                  sourceFieldGr.addQuery('sys_id', sourceFieldsSplit[i]);
                  sourceFieldGr.query();

                  assertEqual({
                      name: operationDisplay + "Source field:" + sourceFieldsSplit[i] + " does not exist or is invalid.",
                      shouldbe: true,
                      value: sourceFieldGr.next()
                  });
                  assertEqual({
                      name: operationDisplay + "By convention only the Temp entity should have operations assigned to it. Source field:" + sourceFieldsSplit[i] + " is not a Temp entity field.",
                      shouldbe: true,
                      value: tempEntitySysIds.indexOf(sourceFieldGr.getValue('sys_rte_eb_entity') + "") > -1
                  });
              }
          }

          if (targetField) {
              this._checkForExistence('sys_rte_eb_field', targetField, operationDisplay, outputs, steps, stepResult, assertEqual);

              assertEqual({
                  name: operationDisplay + "By convention only the Temp entity should have operations assigned to it.  Target field:" + targetField + " is not a Temp entity field.",
                  shouldbe: true,
                  value: tempEntitySysIds.indexOf(gr.target_sys_rte_eb_field.sys_rte_eb_entity + "") > -1
              });
          }

          if (targetFields) {
              var targetFieldsSplit = targetFields.split(',');

              for (var j = 0; j < targetFieldsSplit.length; j++) {
                  var targetFieldGr = new GlideRecord('sys_rte_eb_field');
                  targetFieldGr.addQuery('sys_id', targetFieldsSplit[j]);
                  targetFieldGr.query();

                  assertEqual({
                      name: operationDisplay + "Target field:" + targetFieldsSplit[j] + " does not exist or is invalid.",
                      shouldbe: true,
                      value: targetFieldGr.next()
                  });
                  assertEqual({
                      name: operationDisplay + "By convention only the Temp entity should have operations assigned to it. Target field:" + targetFieldsSplit[j] + " is not a Temp entity field.",
                      shouldbe: true,
                      value: tempEntitySysIds.indexOf(targetFieldGr.getValue('sys_rte_eb_entity') + "") > -1
                  });
              }
          }
      }
      stepResult.setOutputMessage(gs.getMessage("Operations are valid"));
  },

  validateEntityMappings: function(applicationFeedGr, importEntitySysId, tempEntitySysIds, outputs, steps, stepResult, assertEqual) {
      if (!tempEntitySysIds || gs.nil(tempEntitySysIds) || !importEntitySysId)
          return;

      var applicationFeedName = applicationFeedGr.getValue('name');
      var applicationFeedSysId = applicationFeedGr.getUniqueValue();
      var applicationFeedDisplay = this._buildDisplay('cmdb_inst_application_feed', applicationFeedSysId, applicationFeedName);
      var gr = new GlideRecord('sys_rte_eb_entity_mapping');
      gr.addQuery('sys_rte_eb_definition', applicationFeedSysId);
      gr.query();

      while (gr.next()) {
          var mappingSysId = gr.getUniqueValue();
          var mappingName = gr.getValue('name');
          var mappingDisplay = this._buildDisplay('sys_rte_eb_entity_mapping', mappingSysId, mappingName) + " ";

          var mappingSourceEntity = gr.getValue('source_sys_rte_eb_entity');
          var mappingTargetEntity = gr.getValue('target_sys_rte_eb_entity');

          this._checkForExistence('cmdb_inst_entity', mappingSourceEntity, mappingDisplay, outputs, steps, stepResult, assertEqual);
          this._checkForExistence('cmdb_inst_entity', mappingTargetEntity, mappingDisplay, outputs, steps, stepResult, assertEqual);

          var isSourceTempEntity = tempEntitySysIds.indexOf(mappingSourceEntity + "") > -1;
          var isTargetTempEntity = tempEntitySysIds.indexOf(mappingTargetEntity + "") > -1;

          assertEqual({
              name: mappingDisplay + "By convention the Import entity should only map to the Temp entity.  Please change mapping.",
              shouldbe: false,
              value: (mappingSourceEntity == importEntitySysId && !isTargetTempEntity)
          });

          assertEqual({
              name: mappingDisplay + "Source and target entity cannot match.  Remove this mapping.",
              shouldbe: false,
              value: mappingSourceEntity == mappingTargetEntity
          });

          assertEqual({
              name: mappingDisplay + "By convention nothing should map to the Import entity.  Remove this mapping.",
              shouldbe: false,
              value: mappingTargetEntity == importEntitySysId
          });

          assertEqual({
              name: mappingDisplay + "By convention only the Temp entity should map to any other non-Import entity.  Remove this mapping.",
              shouldbe: false,
              value: (isSourceTempEntity && ((mappingTargetEntity == importEntitySysId) || isTargetTempEntity))
          });

          for (var tempEntityIndex = 0; tempEntityIndex < tempEntitySysIds.length; tempEntityIndex++) {
              var tempEntitySysId = tempEntitySysIds[tempEntityIndex];
              this._validateEntityFieldMappings(applicationFeedSysId, mappingSysId, mappingSourceEntity, mappingTargetEntity, importEntitySysId, tempEntitySysId, tempEntitySysIds, outputs, steps, stepResult, assertEqual);
          }
      }
      stepResult.setOutputMessage(gs.getMessage("Entity mappings are valid"));
  },

  _validateEntityFieldMappings: function(applicationFeedSysId, mappingSysId, mappingSourceEntity, mappingTargetEntity, importEntitySysId, tempEntitySysId, tempEntitySysIds, outputs, steps, stepResult, assertEqual) {
      var gr = new GlideRecord('sys_rte_eb_field_mapping');
      gr.addQuery('sys_rte_eb_entity_mapping', mappingSysId);
      gr.query();

      while (gr.next()) {
          var fieldMappingSysId = gr.getUniqueValue();
          var fieldMappingDisplay = this._buildDisplay('sys_rte_eb_field_mapping', fieldMappingSysId, null) + " ";

          var fieldMappingTargetField = gr.target_sys_rte_eb_field;

          var fieldMappingTargetEntity = gr.target_sys_rte_eb_field.sys_rte_eb_entity + "";
          var fieldMappingSourceEntity = gr.source_sys_rte_eb_field.sys_rte_eb_entity + "";
          var fieldMappingReferencedEntity = gr.referenced_sys_rte_eb_entity + "";

          var fieldMappingTargetFieldField = gr.target_sys_rte_eb_field.field + "";
          var fieldMappingSourceFieldField = gr.source_sys_rte_eb_field.field + "";

          assertEqual({
              name: fieldMappingDisplay + "Field mappings must have a target.",
              shouldbe: false,
              value: gs.nil(fieldMappingTargetEntity)
          });

          assertEqual({
              name: fieldMappingDisplay + "Field mapping target not the same as entity mapping target.  Select a new field that is part of the target entity.",
              shouldbe: true,
              value: fieldMappingTargetEntity == mappingTargetEntity
          });

          assertEqual({
              name: fieldMappingDisplay + "Must have either a source field or referenced entity.",
              shouldbe: false,
              value: !fieldMappingSourceEntity && !fieldMappingReferencedEntity
          });

          assertEqual({
              name: fieldMappingDisplay + "Cannot have both a source field and referenced entity.  Remove one.",
              shouldbe: false,
              value: fieldMappingSourceEntity && fieldMappingReferencedEntity
          });

          assertEqual({
              name: fieldMappingDisplay + "Field mapping source not the same as entity mapping source.  Select a new field that is part of the source entity.",
              shouldbe: false,
              value: fieldMappingSourceEntity && (fieldMappingSourceEntity != mappingSourceEntity)
          });

          assertEqual({
              name: fieldMappingDisplay + "Referenced entity cannot be the Temp or Import entity.  Remove field mapping or change referenced entity.",
              shouldbe: false,
              value: fieldMappingReferencedEntity && (fieldMappingReferencedEntity == importEntitySysId || tempEntitySysId == fieldMappingReferencedEntity + "")
          });

          assertEqual({
              name: fieldMappingDisplay + "When an Import entity field is mapped to a temp entity the field values must match.  Update entity field " + fieldMappingTargetField + " to change the 'field' value from:" + fieldMappingTargetFieldField + " to:" + fieldMappingSourceFieldField,
              shouldbe: false,
              value: fieldMappingSourceFieldField && mappingSourceEntity == importEntitySysId && tempEntitySysIds.indexOf(mappingTargetEntity + "") > -1 && !fieldMappingSourceFieldField.endsWith(fieldMappingTargetFieldField)
          });
      }
  },

  validateMandatoryOperations: function(applicationGr, outputs, steps, stepResult, assertEqual) {
      var entityGr = new GlideAggregate('cmdb_inst_entity');
      entityGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
      entityGr.addAggregate('count');
      entityGr.groupBy('table');
      entityGr.query();
      // Iterate through each targeted class
      while (entityGr.next()) {
          var cmdbClass = entityGr.getValue("table");
          var fieldsChecked = [];
          var currentClass = cmdbClass;
          this._validateMandatoryOperationsByClass(applicationGr, outputs, steps, stepResult, assertEqual, cmdbClass, currentClass, fieldsChecked);
          // Walk up the hierarchy but ignore anything that may be overridden
          while (currentClass != this._getParentClass(currentClass)) {
              currentClass = this._getParentClass(currentClass);
              this._validateMandatoryOperationsByClass(applicationGr, outputs, steps, stepResult, assertEqual, cmdbClass, currentClass, fieldsChecked);
          }
      }
  },

  _validateMandatoryOperationsByClass: function(applicationGr, outputs, steps, stepResult, assertEqual, cmdbClass, currentClass, fieldsChecked) {
      var applicationName = applicationGr.getValue('name');
      var applicationSysId = applicationGr.getUniqueValue();
      var applicationDisplay = this._buildDisplay('cmdb_inst_application', applicationSysId, applicationName);

      var mandatoryFieldOperationsGr = new GlideRecord("sn_cmdb_int_util_cmdb_integration_field_operation");
      mandatoryFieldOperationsGr.addQuery("priority", ["Mandatory", "Invalid"]);
      mandatoryFieldOperationsGr.addQuery("active", true);
      mandatoryFieldOperationsGr.addQuery("field.cmdb_class.cmdb_class", currentClass);
      mandatoryFieldOperationsGr.addQuery('field.field.element', '!=', fieldsChecked);
      mandatoryFieldOperationsGr.orderBy("field.field.element");
      mandatoryFieldOperationsGr.orderByDesc("operation_order");
      mandatoryFieldOperationsGr.query();
      var previousField;
      var layer = 0;
      var fieldArray = [];
      while (mandatoryFieldOperationsGr.next()) {
          var mandatoryClass = currentClass;
          var mandatoryField = mandatoryFieldOperationsGr.field.field.element;
          if (gs.nil(previousField) || previousField.table != mandatoryClass || previousField.field != mandatoryField)
              layer = 0;
          else {
              // We need to crawl 1 layer deeper to find target field
              layer = layer + 1;
          }

          var mandatoryOperationTypes;
          var mandatoryOperationTypeNames;
          mandatoryOperationTypes = mandatoryFieldOperationsGr.sys_rte_eb_operation_types.split(",");
          var operationTypesGr = new GlideRecord("sys_rte_eb_operation_type");
          operationTypesGr.addQuery("sys_id", mandatoryOperationTypes);
          operationTypesGr.query();
          mandatoryOperationTypeNames = "One of ";
          while (operationTypesGr.next())
              mandatoryOperationTypeNames = mandatoryOperationTypeNames + " '" + operationTypesGr.name + "'";
          var mandatoryFieldOperationDisplay = "Mandatory field operation: " + applicationName + " " + mandatoryClass + "." + mandatoryField + " " + mandatoryOperationTypeNames + " ";

          var fieldMappingGr = new GlideRecord("sys_rte_eb_field_mapping");
          fieldMappingGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
          fieldMappingGr.addQuery("sys_rte_eb_entity_mapping.target_sys_rte_eb_entity.table", cmdbClass);
          fieldMappingGr.addQuery("target_sys_rte_eb_field.field", mandatoryField);
          fieldMappingGr.query();

          if (!fieldMappingGr.hasNext()) {
              // No mapping to this field, don't check anything
              continue;
          }

          fieldMappingGr.next();

          if (layer == 0) {
              fieldArray = [];
              fieldArray.push(fieldMappingGr.source_sys_rte_eb_field);
          }
          fieldArray = this._getSourceFields(mandatoryFieldOperationDisplay, fieldArray, mandatoryOperationTypes);

          previousField = {};
          previousField.table = mandatoryClass;
          previousField.field = mandatoryField;
      }
  },

  validateLookups: function(applicationGr, outputs, steps, stepResult, assertEqual) {
      var entityGr = new GlideAggregate('cmdb_inst_entity');
      entityGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
      entityGr.addAggregate('count');
      entityGr.groupBy('table');
      entityGr.query();
      // Iterate through each targeted class
      while (entityGr.next()) {
          var cmdbClass = entityGr.getValue("table");
          var currentClass = cmdbClass;
          this._validateLookupsByClass(applicationGr, outputs, steps, stepResult, assertEqual, cmdbClass, currentClass);
          // Walk up the hierarchy but ignore anything that may be overridden
          while (currentClass != this._getParentClass(currentClass)) {
              currentClass = this._getParentClass(currentClass);
              this._validateLookupsByClass(applicationGr, outputs, steps, stepResult, assertEqual, cmdbClass, currentClass);
          }
      }
  },

  _validateLookupsByClass: function(applicationGr, outputs, steps, stepResult, assertEqual, cmdbClass, currentClass) {
      var applicationName = applicationGr.getValue('name');
      var applicationSysId = applicationGr.getUniqueValue();
      var applicationDisplay = this._buildDisplay('cmdb_inst_application', applicationSysId, applicationName);

      var lookupsGr = new GlideRecord("sn_cmdb_int_util_cmdb_integration_lookup");
      lookupsGr.addQuery("priority", ["Mandatory", "Invalid"]);
      lookupsGr.addQuery("active", true);
      lookupsGr.addQuery("lookup_for_class.cmdb_class", currentClass);
      lookupsGr.query();
      while (lookupsGr.next()) {
          var lookupClass = lookupsGr.cmdb_class.cmdb_class;
          var lookupForClass = lookupsGr.lookup_for_class.cmdb_class;
          var priority = lookupsGr.getValue("priority");

          var entityGr = new GlideRecord("cmdb_inst_entity");
          entityGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
          entityGr.query("table", lookupClass);
          entityGr.query("lookup_for_entity.table", cmdbClass);
          entityGr.query();

          while (entityGr.next()) {
              var entityMappingGr = new GlideRecord("sys_rte_eb_entity_mapping");
              entityMappingGr.addQuery("target_sys_rte_eb_entity", entityGr.getUniqueValue());
              entityMappingGr.query();

              if (priority == "Mandatory") {
                  assertEqual({
                      name: applicationDisplay + "missing mandatory lookup for class:" + lookupClass + " as a lookup for:" + lookupForClass,
                      shouldbe: true,
                      value: entityMappingGr.hasNext()
                  });
              }
              if (priority == "Invalid") {
                  assertEqual({
                      name: applicationDisplay + "has invalid lookup for class:" + lookupClass + " as a lookup for:" + lookupForClass,
                      shouldbe: false,
                      value: entityMappingGr.hasNext()
                  });
              }
          }
      }
  },

  validateRelationships: function(applicationGr, outputs, steps, stepResult, assertEqual) {
      var applicationName = applicationGr.getValue('name');
      var applicationSysId = applicationGr.getUniqueValue();
      var applicationDisplay = this._buildDisplay('cmdb_inst_application', applicationSysId, applicationName);

      var integrationRelationships = new GlideRecord("sn_cmdb_int_util_cmdb_integration_relationship");
      integrationRelationships.addQuery("priority", ["Mandatory", "Invalid"]);
      integrationRelationships.addQuery("active", true);
      integrationRelationships.query();
      while (integrationRelationships.next()) {
          var parentClass = integrationRelationships.parent_class.cmdb_class;
          var childClass = integrationRelationships.child_class.cmdb_class;
          var relationshipTypes = integrationRelationships.getValue("relationship_type");
          var priority = integrationRelationships.getValue("priority");
          var relationshipTypeNames;
          var relationshipTypeArray = [];
          var relationshipArrayTemp = relationshipTypes.split(",");
          for (i = 0; i < relationshipArrayTemp.length; i++)
              relationshipTypeArray.push(relationshipArrayTemp[i]);
          var relTypeGr = new GlideRecord("cmdb_rel_type");
          relTypeGr.addQuery("sys_id", relationshipTypeArray);
          relTypeGr.query();
          relationshipTypeNames = "One of ";
          while (relTypeGr.next()) {
              relationshipTypeNames = relationshipTypeNames + " ''" + relTypeGr.getValue("name") + "''";
          }

          var relationshipDisplay = priority + " relationship with parent class '" + parentClass + "' child class '" + childClass + "' and relationship type of one of the following '" + relationshipTypeNames + "'";

          var entityGr = new GlideRecord("cmdb_inst_entity");
          entityGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
          entityGr.addQuery("table", "cmdb_rel_ci");
          entityGr.addQuery("relationship_type", relationshipTypeArray);
          entityGr.query();
          var foundRelationship = false;
          while (entityGr.next()) {
              var entityFieldMappingGr = new GlideRecord("sys_rte_eb_field_mapping");
              entityFieldMappingGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
              entityFieldMappingGr.addQuery("target_sys_rte_eb_field.sys_rte_eb_entity", entityGr.getUniqueValue());
              var parentCondition = entityFieldMappingGr.addQuery("target_sys_rte_eb_field.field", "parent");
              parentCondition.addCondition("referenced_sys_rte_eb_entity.table", parentClass);
              var childCondition = parentCondition.addOrCondition("target_sys_rte_eb_field.field", "child");
              childCondition.addCondition("referenced_sys_rte_eb_entity.table", childClass);
              entityFieldMappingGr.query();
              var rowCount = 0;
              while (entityFieldMappingGr.next())
                  rowCount++;

              if (rowCount == 2)
                  foundRelationship = true;
          }
          if (priority != "Invalid" && !foundRelationship) {
              // skip as we don't need to check relationships that don't exist
              continue;
          }

          if (priority == "Mandatory") {
              assertEqual({
                  name: applicationDisplay + " must have a " + relationshipDisplay,
                  shouldbe: true,
                  value: foundRelationship
              });
          }
          if (priority == "Invalid") {
              assertEqual({
                  name: applicationDisplay + " must have not have a " + relationshipDisplay,
                  shouldbe: false,
                  value: foundRelationship
              });
          }
      }
  },

  validateRelated: function(applicationGr, outputs, steps, stepResult, assertEqual) {
      var applicationName = applicationGr.getValue('name');
      var applicationSysId = applicationGr.getUniqueValue();
      var applicationDisplay = this._buildDisplay('cmdb_inst_application', applicationSysId, applicationName);

      var integrationRelated = new GlideRecord("sn_cmdb_int_util_cmdb_integration_related_entry");
      integrationRelated.addQuery("priority", ["Mandatory", "Invalid"]);
      integrationRelated.addQuery("active", true);
      integrationRelated.query();
      while (integrationRelated.next()) {
          var cmdbClass = integrationRelated.cmdb_class.cmdb_class;
          var relatedClass = integrationRelated.related_class.cmdb_class;
          var priority = integrationRelated.getValue("priority");

          var relatedDisplay = priority + " related with class '" + cmdbClass + "' related class '" + relatedClass + "'";

          var entityGr = new GlideRecord("cmdb_inst_entity");
          entityGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
          entityGr.addQuery("table", cmdbClass);
          entityGr.query();
          while (!gs.nil(cmdbClass) && !entityGr.hasNext()) {
              cmdbClass = this._getParentClass(cmdbClass);
              entityGr = new GlideRecord("cmdb_inst_entity");
              entityGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
              entityGr.addQuery("table", cmdbClass);
              entityGr.query();
          }
          if (gs.nil(cmdbClass) || !entityGr.hasNext()) {
              // skip this as we don't use this class as part of the integration
              continue;
          }
          entityGr = new GlideRecord("cmdb_inst_entity");
          entityGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
          entityGr.addQuery("related_for_entity.table", relatedClass);
          entityGr.query();
          while (!gs.nil(relatedClass) && !entityGr.hasNext()) {
              relatedClass = this._getParentClass(relatedClass);
              entityGr = new GlideRecord("cmdb_inst_entity");
              entityGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
              entityGr.addQuery("related_for_entity.table", relatedClass);
              entityGr.query();
          }
          if (gs.nil(relatedClass) || !entityGr.hasNext()) {
              // skip this as we don't use this class as part of the integration
              continue;
          }
          entityGr = new GlideRecord("cmdb_inst_entity");
          entityGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
          entityGr.addQuery("table", cmdbClass);
          entityGr.addQuery("related_for_entity.table", relatedClass);
          entityGr.query();

          if (priority == "Mandatory") {
              assertEqual({
                  name: applicationDisplay + " must have a " + relatedDisplay,
                  shouldbe: true,
                  value: entityGr.hasNext()
              });
          }
          if (priority == "Invalid") {
              assertEqual({
                  name: applicationDisplay + " must have not have a " + relatedDisplay,
                  shouldbe: true,
                  value: !entityGr.hasNext()
              });
          }
      }
  },

  validateReferences: function(applicationGr, outputs, steps, stepResult, assertEqual) {
      var entityGr = new GlideAggregate('cmdb_inst_entity');
      entityGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
      entityGr.addAggregate('count');
      entityGr.groupBy('table');
      entityGr.query();
      // Iterate through each targeted class
      while (entityGr.next()) {
          var cmdbClass = entityGr.getValue("table");
          var fieldsChecked = [];
          var currentClass = cmdbClass;
          this._validateReferencesByClass(applicationGr, outputs, steps, stepResult, assertEqual, cmdbClass, currentClass, fieldsChecked);
          // Walk up the hierarchy but ignore anything that may be overridden
          while (currentClass != this._getParentClass(currentClass)) {
              currentClass = this._getParentClass(currentClass);
              this._validateReferencesByClass(applicationGr, outputs, steps, stepResult, assertEqual, cmdbClass, currentClass, fieldsChecked);
          }
      }
  },

  _validateReferencesByClass: function(applicationGr, outputs, steps, stepResult, assertEqual, cmdbClass, currentClass, fieldsChecked) {
      var applicationName = applicationGr.getValue('name');
      var applicationSysId = applicationGr.getUniqueValue();
      var applicationDisplay = this._buildDisplay('cmdb_inst_application', applicationSysId, applicationName);

      var integrationReferences = new GlideRecord("sn_cmdb_int_util_cmdb_integration_field");
      integrationReferences.addQuery("priority", ["Mandatory", "Invalid"]);
      integrationReferences.addQuery("active", true);
      integrationReferences.addQuery("cmdb_class.cmdb_class", currentClass);
      integrationReferences.addQuery('field.element', '!=', fieldsChecked);
      integrationReferences.addNotNullQuery("field.reference");
      integrationReferences.query();
      while (integrationReferences.next()) {
          var referenceClass = integrationReferences.field.reference.name;
          var referenceByClass = currentClass;
          var referenceField = integrationReferences.field.element;
          var priority = integrationReferences.getValue("priority");

          var referenceDisplay = priority + " reference within class '" + referenceByClass + "' with field '" + referenceField + "' to class '" + referenceClass + "'";

          var entityGr = new GlideRecord("cmdb_inst_entity");
          entityGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
          entityGr.addQuery("table", referenceClass);
          entityGr.query();
          var hasReferenceClass = entityGr.next();
          while (!hasReferenceClass && referenceClass) {
              referenceClass = this._getParentClass(referenceClass);
              entityGr = new GlideRecord("cmdb_inst_entity");
              entityGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
              entityGr.addQuery("table", referenceClass);
              entityGr.query();
              hasReferenceClass = entityGr.next();
          }

          if (hasReferenceClass) {
              // We have both classes, we need to check that the reference exists
              var entityFieldMappingGr = new GlideRecord("sys_rte_eb_field_mapping");
              entityFieldMappingGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
              entityFieldMappingGr.addQuery("target_sys_rte_eb_field.field", referenceField);
              entityFieldMappingGr.addQuery("target_sys_rte_eb_field.sys_rte_eb_entity.table", cmdbClass);
              entityFieldMappingGr.query();

              if (priority == "Mandatory") {
                  assertEqual({
                      name: applicationDisplay + " must have a " + referenceDisplay,
                      shouldbe: true,
                      value: entityFieldMappingGr.hasNext()
                  });
              }
              if (priority == "Invalid") {
                  assertEqual({
                      name: applicationDisplay + " must NOT use an " + referenceDisplay,
                      shouldbe: false,
                      value: entityFieldMappingGr.hasNext()
                  });
              }
          }
      }
  },

  validateFields: function(applicationGr, outputs, steps, stepResult, assertEqual) {
      var entityGr = new GlideAggregate('cmdb_inst_entity');
      entityGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
      entityGr.addAggregate('count');
      entityGr.groupBy('table');
      entityGr.query();
      // Iterate through each targeted class
      while (entityGr.next()) {
          var cmdbClass = entityGr.getValue("table");
          var fieldsChecked = [];
          var currentClass = cmdbClass;
          this._validateFieldsByClass(applicationGr, outputs, steps, stepResult, assertEqual, cmdbClass, currentClass, fieldsChecked);
          // Walk up the hierarchy but ignore anything that may be overridden
          while (currentClass != this._getParentClass(currentClass)) {
              currentClass = this._getParentClass(currentClass);
              this._validateFieldsByClass(applicationGr, outputs, steps, stepResult, assertEqual, cmdbClass, currentClass, fieldsChecked);
          }
      }
  },

  _validateFieldsByClass: function(applicationGr, outputs, steps, stepResult, assertEqual, cmdbClass, currentClass, fieldsChecked) {
      var applicationName = applicationGr.getValue('name');
      var applicationSysId = applicationGr.getUniqueValue();
      var applicationDisplay = this._buildDisplay('cmdb_inst_application', applicationSysId, applicationName);

      var fieldMappingsGr = new GlideRecord("sys_rte_eb_field_mapping");
      fieldMappingsGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
      fieldMappingsGr.addQuery("target_sys_rte_eb_field.sys_rte_eb_entity.table", cmdbClass);
      fieldMappingsGr.query();
      var mappedFields = [];
      while (fieldMappingsGr.next()) {
          mappedFields.push(fieldMappingsGr.target_sys_rte_eb_field.field + "");
      }

      var fieldsGr = new GlideRecord("sn_cmdb_int_util_cmdb_integration_field");
      fieldsGr.addQuery("active", true);
      fieldsGr.addQuery("cmdb_class.cmdb_class", currentClass);
      fieldsGr.addQuery('field.element', '!=', fieldsChecked);
      fieldsGr.addQuery('field.element', mappedFields);
      fieldsGr.orderBy("field.element");
      fieldsGr.orderBy("priority");
      fieldsGr.query();
      while (fieldsGr.next()) {
          var name = fieldsGr.getValue("name");
          var field = fieldsGr.field.element;
          var priority = fieldsGr.getValue("priority");
          var fieldDisplay = this._buildDisplay('sys_rte_eb_field_mapping', fieldsGr.getUniqueValue(), applicationName) + " field '" + name + "'is " + priority;
          fieldsChecked.push(field);

          var fieldMappingGr = new GlideRecord("sys_rte_eb_field_mapping");
          fieldMappingGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
          fieldMappingGr.addQuery("target_sys_rte_eb_field.sys_rte_eb_entity.table", cmdbClass);
          fieldMappingGr.addQuery("target_sys_rte_eb_field.field", field);
          fieldMappingGr.query();

          if (priority == "Mandatory") {
              assertEqual({
                  name: fieldDisplay,
                  shouldbe: true,
                  value: fieldMappingGr.hasNext()
              });
          }
          if (priority == "Invalid") {
              assertEqual({
                  name: fieldDisplay,
                  shouldbe: false,
                  value: fieldMappingGr.hasNext()
              });
          }
      }
      return fieldsChecked;
  },

  _getSourceFields: function(mandatoryFieldOperationDisplay, fieldArray, mandatoryOperationTypes) {
      var operationGr = new GlideRecord("sys_rte_eb_operation");
      operationGr.addQuery("type", mandatoryOperationTypes);
      var condition = operationGr.addQuery("target_sys_rte_eb_field", fieldArray);
      for (var i = 0; i < fieldArray.length; i++)
          condition.addOrCondition("target_sys_rte_eb_fields", "CONTAINS", fieldArray[i]);
      operationGr.query();

      assertEqual({
          name: mandatoryFieldOperationDisplay + "is missing",
          shouldbe: true,
          value: operationGr.hasNext()
      });

      operationGr.next();
      fieldArray = [];
      if (!gs.nil(operationGr.source_sys_rte_eb_field))
          fieldArray.push(operationGr.getValue("source_sys_rte_eb_field"));
      else {
          var fieldArrayTemp = operationGr.getValue("source_sys_rte_eb_fields").split(",");
          for (i = 0; i < fieldArrayTemp.length; i++)
              fieldArray.push(fieldArrayTemp[i]);
      }
      return fieldArray;
  },

  _validateFields: function(entitySysId, applicationFeedSysId, entityTargetTable, isImportEntity, outputs, steps, stepResult, assertEqual) {
      var gr = new GlideRecord('sys_rte_eb_field');
      gr.addQuery('sys_rte_eb_entity', entitySysId);
      gr.query();

      while (gr.next()) {
          var fieldSysId = gr.getUniqueValue();
          var fieldName = gr.getValue('name');
          var fieldField = gr.getValue('field');
          var fieldDisplay = this._buildDisplay('sys_rte_eb_field', fieldSysId, fieldName);

          assertEqual({
              name: fieldDisplay + "Name value is missing.  Please add.",
              shouldbe: false,
              value: gs.nil(fieldName)
          });

          assertEqual({
              name: fieldDisplay + "Field value is missing.  Please add.",
              shouldbe: false,
              value: gs.nil(fieldField)
          });

          assertEqual({
              name: fieldDisplay + "Is not in the correct definition.  Set definition to be : " + applicationFeedSysId,
              shouldbe: true,
              value: gr.getValue('sys_rte_eb_definition') == applicationFeedSysId
          });

          // if this entity has a table, all of the fields should exist on that table
          if (entityTargetTable) {

              if (fieldField == 'source_native_key' || fieldField == 'source_recency_timestamp') {
                  continue;
              }

              var tableGr = new GlideRecord('sys_dictionary');
              tableGr.addQuery('name', entityTargetTable);
              tableGr.addQuery('element', fieldField);
              tableGr.query();

              if (!tableGr.next()) {
                  if (isImportEntity) {
                      var importSetRowTableGr = new GlideRecord('sys_dictionary');
                      importSetRowTableGr.addQuery('name', 'sys_import_set_row');
                      importSetRowTableGr.addQuery('element', fieldField);
                      importSetRowTableGr.query();

                      if (importSetRowTableGr.next())
                          continue;
                  }

                  // check to see if we subcluss, if so we can't check the table/column as we won't know until after transformation.
                  var fieldMappingGr = new GlideRecord("sys_rte_eb_field_mapping");
                  fieldMappingGr.addQuery("sys_rte_eb_entity_mapping.target_sys_rte_eb_entity", entitySysId);
                  fieldMappingGr.addQuery("target_sys_rte_eb_field.field", "sys_class_name");
                  fieldMappingGr.query();
                  if (fieldMappingGr.hasNext() || (entityTargetTable == "cmdb_sam_sw_install" && !GlidePluginManager.isActive('com.snc.software_asset_management') && !GlidePluginManager.isActive('com.snc.sams')))
                      continue;

                  assertEqual({
                      name: "'" + fieldDisplay + "' does not exist as a column in the target table:" + entityTargetTable + ".  All field values must be a column name on the target table (except for source_native_key and source_recency_timestamp).",
                      shouldbe: true,
                      value: false
                  });
              }

          }
      }
  },

  _validateCmdbEntity: function(entityDisplay, entityName, entityTargetTable, entityPath, outputs, steps, stepResult, assertEqual) {
      assertEqual({
          name: entityDisplay + " entity has a path:'" + entityPath + "' but should not",
          shouldbe: false,
          value: gs.nil(entityPath)
      });
  },

  _buildDisplay: function(table, sysId, name) {
      var url = gs.getProperty('glide.servlet.uri') + 'nav_to.do?uri=%2F' + table + '.do%3Fsys_id%3D' + sysId;
      if (name)
          return table + "(" + name + "," + sysId + ") : " + url;

      return table + "(" + sysId + ") : " + url;
  },

  _checkForExistence: function(table, sysId, sourceName, outputs, steps, stepResult, assertEqual) {
      if (!sysId) {
          return;
      }

      var gr = new GlideRecord(table);
      gr.addQuery('sys_id', sysId);
      gr.query();

      assertEqual({
          name: sourceName + "found sys_id:" + sysId + " in table " + table,
          shouldbe: true,
          value: gr.next()
      });
  },

  _getParentClass: function(className) {
      if (!className)
          return "";
      var gr = new GlideRecord("sys_db_object");
      gr.addQuery("name", className);
      gr.query();
      while (gr.next())
          return gr.super_class.name;
      return "";
  },

  _getChildClasses: function(className, childClasses) {
      if (!childClasses)
          childClasses = [];
      var gr = new GlideRecord("sys_db_object");
      gr.addQuery("super_class.name", className);
      gr.query();
      while (gr.next()) {
          childClasses.push(gr.getValue("name"));
          childClasses.push(this._getChildClasses(gr.getValue("name")));
      }
      return childClasses;
  },

  validateSourceAnalysis: function(applicationGr, outputs, steps, stepResult, assertEqual) {
      var applicationName = applicationGr.getValue('name');
      var applicationSysId = applicationGr.getUniqueValue();
      var applicationDisplay = this._buildDisplay('cmdb_inst_application', applicationSysId, applicationName);

      var sourceAnalysisGr = new GlideRecord("sn_cmdb_int_util_cmdb_integration_source_analysis");
      sourceAnalysisGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
      sourceAnalysisGr.query();
      while (sourceAnalysisGr.next()) {
          var sourceField = sourceAnalysisGr.getValue("source_field");
          var importTable = sourceAnalysisGr.servicenow_import_table;
          var importFieldName = sourceAnalysisGr.getValue("servicenow_import_field");
          var targetTable = sourceAnalysisGr.servicenow_target_table;
          var targetField = sourceAnalysisGr.getValue("servicenow_target_field");
          var referenceTo = sourceAnalysisGr.reference_to;
          var operations = sourceAnalysisGr.getValue("operations").split(",");

          var importEntity = this._getImportEntity(applicationGr, importTable.name);
          var importField = this._getImportField(applicationGr, importEntity, importFieldName);
          var tempEntities = this._getTempEntities(applicationGr, importEntity);
          var tempField = this._getTempField(applicationGr, importEntity, importField, tempEntities);
          var transformResults = this._getTransformResults(applicationGr, tempEntities, [tempField]);

          var message = applicationDisplay + "source_field:'" + sourceField + "' importTable:'" + importTable.name + "' " + importFieldName + "' ";
          message = message + "mapping to targetTable:'" + targetTable.name + "' targetField:'" + targetField + "' ";
          assertEqual({
              name: message + "is missing",
              shouldbe: true,
              value: this._hasTargetFieldMapping(applicationGr, tempEntities, transformResults.transformedFields, targetTable.name, targetField)
          });

          for (var i = 0; i < operations.length; i++) {
              var operationTypeGr = new GlideRecord("sys_rte_eb_operation_type");
              operationTypeGr.get(operations[i]);

              message = message + "operationType:'" + operationTypeGr.getValue("name") + "' ";
              assertEqual({
                  name: message + "is missing",
                  shouldbe: true,
                  value: transformResults.operations.indexOf(operations[i] + "") > -1
              });
          }
      }
  },

  _getImportEntity: function(applicationGr, importTable) {
      var entityGr = new GlideRecord("cmdb_inst_entity");
      entityGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
      entityGr.addQuery("table", importTable);
      entityGr.query();
      if (entityGr.next())
          return entityGr;
  },

  _getImportField: function(applicationGr, importEntity, importField) {
      var fieldGr = new GlideRecord("sys_rte_eb_field");
      fieldGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
      fieldGr.addQuery("sys_rte_eb_entity", importEntity.getUniqueValue());
      fieldGr.addQuery("field", importField);
      fieldGr.query();
      if (fieldGr.next())
          return fieldGr;
  },

  _getTempEntities: function(applicationGr, importEntity) {
      var entityMappingGr = new GlideRecord("sys_rte_eb_entity_mapping");
      entityMappingGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
      entityMappingGr.addQuery("source_sys_rte_eb_entity", importEntity.getUniqueValue());
      entityMappingGr.query();
      var tempEntitites = [];
      while (entityMappingGr.next())
          tempEntitites.push(entityMappingGr.target_sys_rte_eb_entity);
      return tempEntitites;
  },

  _getTempField: function(applicationGr, importEntity, importField, tempEntities) {
      var fieldMappingGr = new GlideRecord("sys_rte_eb_field_mapping");
      fieldMappingGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
      fieldMappingGr.addQuery("source_sys_rte_eb_field.sys_rte_eb_entity", importEntity.getUniqueValue());
      fieldMappingGr.addQuery("source_sys_rte_eb_field", importField.getUniqueValue());
      fieldMappingGr.addQuery("target_sys_rte_eb_field.sys_rte_eb_entity", tempEntities);
      fieldMappingGr.query();
      if (fieldMappingGr.next())
          return fieldMappingGr.target_sys_rte_eb_field;
  },

  _hasTargetFieldMapping: function(applicationGr, tempEntities, transformedFields, targetTable, targetField) {
      var fieldMappingGr = new GlideRecord("sys_rte_eb_field_mapping");
      fieldMappingGr.addQuery("sys_scope", applicationGr.getValue("sys_scope"));
      fieldMappingGr.addQuery("source_sys_rte_eb_field.sys_rte_eb_entity", tempEntities);
      fieldMappingGr.addQuery("source_sys_rte_eb_field", transformedFields);
      fieldMappingGr.addQuery("target_sys_rte_eb_field.sys_rte_eb_entity.table", targetTable);
      fieldMappingGr.addQuery("target_sys_rte_eb_field.field", targetField);
      fieldMappingGr.query();
      while (fieldMappingGr.next())
          return true;
      return false;
  },

  _getTransformResults: function(applicationGr, tempEntities, tempFields) {
      var transformResults = {};
      transformResults.operations = [];
      transformResults.transformedFields = tempFields;

      var operationsGr = new GlideRecord("sys_rte_eb_operation");
      operationsGr.addQuery("sys_rte_eb_entity", tempEntities);
      var fieldQuery = operationsGr.addQuery("source_sys_rte_eb_field", tempFields);
      fieldQuery.addOrCondition("source_sys_rte_eb_fields", "CONTAINS", tempFields);
      operationsGr.query();
      while (operationsGr.next()) {
          transformResults.operations.push(operationsGr.getValue("type"));
          var transformedResults;
          if (operationsGr.target_sys_rte_eb_field)
              transformedResults = this._getTransformResults(applicationGr, tempEntities, [operationsGr.target_sys_rte_eb_field]);
          else
              transformedResults = this._getTransformResults(applicationGr, tempEntities, operationsGr.target_sys_rte_eb_fields.split(","));
          transformResults.transformedFields = transformResults.transformedFields.concat(transformedResults.transformedFields);
          transformResults.operations = transformResults.operations.concat(transformedResults.operations);

      }

      return transformResults;
  },

  _getTargetFieldSourceFields: function(fieldArray, previousFields) {
      if (gs.nil(previousFields))
          previousFields = [];
      previousFields = previousFields.concat(fieldArray);
      var importFields = [];
      for (var i = 0; i < fieldArray.length; i++) {
          var field = fieldArray[i];
          var operationGr = new GlideRecord("sys_rte_eb_operation");
          var condition = operationGr.addQuery("target_sys_rte_eb_field", field);
          condition.addOrCondition("target_sys_rte_eb_fields", "CONTAINS", field);
          operationGr.query();
          if (!operationGr.hasNext()) {
              importFields.push(field);
              continue;
          }
          while (operationGr.next()) {
              var newFieldArray = [];
              if (!gs.nil(operationGr.source_sys_rte_eb_field)) {
                  if (previousFields.indexOf(operationGr.getValue("source_sys_rte_eb_field") < 0))
                      newFieldArray.push(operationGr.getValue("source_sys_rte_eb_field"));
              } else if (!gs.nil(operationGr.source_sys_rte_eb_fields)) {
                  var fieldArrayTemp = operationGr.getValue("source_sys_rte_eb_fields").split(",");
                  for (j = 0; j < fieldArrayTemp.length; j++) {
                      if (previousFields.indexOf(fieldArrayTemp[j] < 0))
                          newFieldArray.push(fieldArrayTemp[j]);
                  }
              }
              var fieldsToPush = this._getTargetFieldSourceFields(newFieldArray, previousFields);
              importFields = importFields.concat(fieldsToPush);
          }
      }
      return importFields;
  },

  verifyModulesForScopedApplications: function(scopeGr) {
      // Will add check for proper top level navigation
      // check for setup module
      var moduleGr = new GlideRecord("sys_app_module");
      moduleGr.addQuery("sys_scope", scopeGr.getUniqueValue());
      moduleGr.addQuery("title", "setup");
      moduleGr.query();
      assertEqual({
          name: "No setup module found for " + scopeGr.name + ". Please create one.",
          shouldbe: true,
          value: moduleGr.hasNext()
      });
      gs.info(scopeGr.name + " has a valid setup module");

      // check for data sources
      var dataSourceGr = new GlideRecord("sys_data_source");
      dataSourceGr.addQuery("sys_scope", scopeGr.getUniqueValue());
      dataSourceGr.query();
      if (dataSourceGr.next()) {
          // verify there is a data source module
          moduleGr = new GlideRecord("sys_app_module");
          moduleGr.addQuery("sys_scope", scopeGr.getUniqueValue());
          moduleGr.addQuery("title", "Data Sources");
          moduleGr.query();
          assertEqual({
              name: "No data source module found for " + scopeGr.name + ". Please create one.",
              shouldbe: true,
              value: moduleGr.hasNext()
          });
          gs.info(scopeGr.name + " has a valid data source module");

          // verify there is a data source module
          moduleGr = new GlideRecord("sys_app_module");
          moduleGr.addQuery("sys_scope", scopeGr.getUniqueValue());
          moduleGr.addQuery("title", "Data Sources");
          moduleGr.query();
          assertEqual({
              name: "No data source module found for " + scopeGr.name + ". Please create one.",
              shouldbe: true,
              value: moduleGr.hasNext()
          });
          gs.info(scopeGr.name + " has a valid data source module");
      }
  },

  verifyScheduledImports: function(scopeGr) {
      var dataSourceGr = new GlideRecord("sys_data_source");
      dataSourceGr.addQuery("sys_scope", scopeGr.getUniqueValue());
      dataSourceGr.query();
      while (dataSourceGr.next()) {
          // if the data source is not file based it should have a scheduled import
          if (dataSourceGr.getValue("type") == "File") {
              continue;
          }
          var scheduledImportGr = new GlideRecord("scheduled_import_set");
          scheduledImportGr.addQuery("sys_scope", scopeGr.getUniqueValue());
          scheduledImportGr.addQuery("data_source", dataSourceGr.getUniqueValue());
          scheduledImportGr.query();
          assertEqual({
              name: "No scheduled import found for " + scopeGr.name + " " + dataSourceGr.name + ". Please create one.",
              shouldbe: true,
              value: scheduledImportGr.hasNext()
          });
          scheduledImportGr.next();
          assertEqual({
              name: "Scheduled import should not have a run as user for " + scopeGr.name + " " + scheduledImportGr.name + ".",
              shouldbe: true,
              value: gs.nil(scheduledImportGr.getValue("run_as"))
          });
          if (scheduledImportGr.getValue("run_type") != "parent") {
              assertEqual({
                  name: "Scheduled import without run type of parent should be inactive for " + scopeGr.name + " " + scheduledImportGr.name + ".",
                  shouldbe: true,
                  value: scheduledImportGr.getValue("active") == false
              });
          }
      }
  },

  verifyFlowActions: function(scopeGr) {
      var flowActionGr = new GlideRecord("sys_hub_action_type_definition");
      flowActionGr.addQuery("sys_scope", scopeGr.getUniqueValue());
      flowActionGr.query();
      while (flowActionGr.next()) {
          assertEqual({
              name: "Flow action is not published " + scopeGr.name + " " + flowActionGr.name + ".",
              shouldbe: true,
              value: flowActionGr.state == "published"
          });
      }
  },

  type: 'CMDBIntegrationValidationTestUtils'
};

Sys ID

5bf326b17350101032f927b751ab9e31

Offical Documentation

Official Docs: