From 438bb442ee916b80ea6a3e7ba3acd139fb5f3568 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Wed, 29 Mar 2017 04:41:31 -0700 Subject: [PATCH 1/3] + Format="0" when provisioning CalculatedField #969 + 1.2.120-beta4 -> 1.2.120-beta5 --- SPMeta2/Build/build.json | 56 +- .../Fields/CalculatedFieldModelHandler.cs | 203 +++--- .../Utils/FieldSchemaXmlUtils.cs | 539 +++++++-------- .../CalculatedFieldDefinitionValidator.cs | 275 ++++---- .../Fields/CalculatedFieldScenariousTest.cs | 633 ++++++++++-------- .../Impl/Syntax/TypedSyntaxTests.cs | 5 + .../SPMeta2.Regression.Tests.csproj | 1 + .../ExpectUpdatAsDisplayFormatService.cs | 37 + .../Fields/CalculatedFieldModelHandler.cs | 220 +++--- .../Attributes/Regression/ExpectUpdate.cs | 5 + .../Fields/CalculatedFieldDefinition.cs | 249 +++---- 11 files changed, 1192 insertions(+), 1031 deletions(-) create mode 100644 SPMeta2/SPMeta2.Regression.Tests/Services/ExpectUpdateServices/ExpectUpdatAsDisplayFormatService.cs diff --git a/SPMeta2/Build/build.json b/SPMeta2/Build/build.json index 2ce2da3d1..c21e9ae41 100644 --- a/SPMeta2/Build/build.json +++ b/SPMeta2/Build/build.json @@ -227,7 +227,7 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2", "Id": "SPMeta2.Core", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", "ProjectUrl": "https://github.com/SubPointSolutions/spmeta2", @@ -266,11 +266,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.Standard", "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -311,11 +311,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -348,15 +348,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -389,11 +389,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM", "Id": "SPMeta2.SSOM.Foundation", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -426,15 +426,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM.Standard", "Id": "SPMeta2.SSOM.Standard", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.SSOM.Foundation", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -468,11 +468,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation-v14", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -498,15 +498,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard-v14", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation-v14", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -532,11 +532,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM", "Id": "SPMeta2.SSOM.Foundation-v14", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -562,15 +562,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM.Standard", "Id": "SPMeta2.SSOM.Standard-v14", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.SSOM.Foundation-v14", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -596,11 +596,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation-v16", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" }, { "Id": "Microsoft.SharePointOnline.CSOM", @@ -637,15 +637,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard-v16", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation-v16", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" }, { "Id": "Microsoft.SharePointOnline.CSOM", diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/Fields/CalculatedFieldModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/Fields/CalculatedFieldModelHandler.cs index d0a6a539d..2a17ed55c 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/Fields/CalculatedFieldModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/Fields/CalculatedFieldModelHandler.cs @@ -1,98 +1,105 @@ -using System; -using System.Xml.Linq; -using Microsoft.SharePoint.Client; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Fields; -using SPMeta2.Enumerations; -using SPMeta2.Services; -using SPMeta2.Utils; - -namespace SPMeta2.CSOM.ModelHandlers.Fields -{ - public class CalculatedFieldModelHandler : FieldModelHandler - { - #region properties - - public override Type TargetType - { - get { return typeof(CalculatedFieldDefinition); } - } - - protected override Type GetTargetFieldType(FieldDefinition model) - { - return typeof(FieldCalculated); - } - - #endregion - - #region methods - - protected override void ProcessFieldProperties(Field field, FieldDefinition fieldModel) - { - // let base setting be setup - base.ProcessFieldProperties(field, fieldModel); - - var typedFieldModel = fieldModel.WithAssertAndCast("model", value => value.RequireNotNull()); - var typedField = field.Context.CastTo(field); - - if (!string.IsNullOrEmpty(typedFieldModel.Formula)) - { - // can't really validate it automatically - // Improve CalculatedFieldDefinition with field ref check - // https://github.com/SubPointSolutions/spmeta2/issues/648 - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Updating formula for a CalculatedField. Ensure FieldReferences are correct."); - - typedField.Formula = typedFieldModel.Formula; - } - - if (!string.IsNullOrEmpty(typedFieldModel.OutputType)) - typedField.OutputType = (FieldType)Enum.Parse(typeof(FieldType), typedFieldModel.OutputType); - } - - protected override void ProcessSPFieldXElement(XElement fieldTemplate, FieldDefinition fieldModel) - { - base.ProcessSPFieldXElement(fieldTemplate, fieldModel); - - var typedFieldModel = fieldModel.WithAssertAndCast("model", value => value.RequireNotNull()); - - if (typedFieldModel.CurrencyLocaleId.HasValue) - fieldTemplate.SetAttribute(BuiltInFieldAttributes.LCID, typedFieldModel.CurrencyLocaleId); - - // can't really validate it automatically - // Improve CalculatedFieldDefinition with field ref check - // https://github.com/SubPointSolutions/spmeta2/issues/648 - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Crafting formula for a CalculatedField. Ensure FieldReferences are correct."); - - // should be a new XML node - var formulaNode = new XElement(BuiltInFieldAttributes.Formula, typedFieldModel.Formula); - fieldTemplate.Add(formulaNode); - - fieldTemplate.SetAttribute(BuiltInFieldAttributes.Format, (int)Enum.Parse(typeof(DateTimeFieldFormatType), typedFieldModel.DateFormat)); - - if (typedFieldModel.ShowAsPercentage.HasValue) - fieldTemplate.SetAttribute(BuiltInFieldAttributes.Percentage, typedFieldModel.ShowAsPercentage.Value.ToString().ToUpper()); - - if (!string.IsNullOrEmpty(typedFieldModel.DisplayFormat)) - fieldTemplate.SetAttribute(BuiltInFieldAttributes.Decimals, NumberFieldModelHandler.GetDecimalsValue(typedFieldModel.DisplayFormat)); - - fieldTemplate.SetAttribute(BuiltInFieldAttributes.ResultType, typedFieldModel.OutputType); - - if (typedFieldModel.FieldReferences.Count > 0) - { - var fieldRefsNode = new XElement("FieldRefs"); - - foreach (var fieldRef in typedFieldModel.FieldReferences) - { - var fieldRefNode = new XElement("FieldRef"); - - fieldRefNode.SetAttribute("Name", fieldRef); - fieldRefsNode.Add(fieldRefNode); - } - - fieldTemplate.Add(fieldRefsNode); - } - } - - #endregion - } -} +using System; +using System.Xml.Linq; +using Microsoft.SharePoint.Client; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Fields; +using SPMeta2.Enumerations; +using SPMeta2.Services; +using SPMeta2.Utils; + +namespace SPMeta2.CSOM.ModelHandlers.Fields +{ + public class CalculatedFieldModelHandler : FieldModelHandler + { + #region properties + + public override Type TargetType + { + get { return typeof(CalculatedFieldDefinition); } + } + + protected override Type GetTargetFieldType(FieldDefinition model) + { + return typeof(FieldCalculated); + } + + #endregion + + #region methods + + protected override void ProcessFieldProperties(Field field, FieldDefinition fieldModel) + { + // let base setting be setup + base.ProcessFieldProperties(field, fieldModel); + + var typedFieldModel = fieldModel.WithAssertAndCast("model", value => value.RequireNotNull()); + var typedField = field.Context.CastTo(field); + + if (!string.IsNullOrEmpty(typedFieldModel.Formula)) + { + // can't really validate it automatically + // Improve CalculatedFieldDefinition with field ref check + // https://github.com/SubPointSolutions/spmeta2/issues/648 + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Updating formula for a CalculatedField. Ensure FieldReferences are correct."); + + typedField.Formula = typedFieldModel.Formula; + + typedField.DateFormat = (DateTimeFieldFormatType) + Enum.Parse(typeof(DateTimeFieldFormatType), typedFieldModel.DateFormat); + } + + if (!string.IsNullOrEmpty(typedFieldModel.OutputType)) + typedField.OutputType = (FieldType)Enum.Parse(typeof(FieldType), typedFieldModel.OutputType); + } + + protected override void ProcessSPFieldXElement(XElement fieldTemplate, FieldDefinition fieldModel) + { + base.ProcessSPFieldXElement(fieldTemplate, fieldModel); + + var typedFieldModel = fieldModel.WithAssertAndCast("model", value => value.RequireNotNull()); + + if (typedFieldModel.CurrencyLocaleId.HasValue) + fieldTemplate.SetAttribute(BuiltInFieldAttributes.LCID, typedFieldModel.CurrencyLocaleId); + + // can't really validate it automatically + // Improve CalculatedFieldDefinition with field ref check + // https://github.com/SubPointSolutions/spmeta2/issues/648 + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Crafting formula for a CalculatedField. Ensure FieldReferences are correct."); + + // should be a new XML node + var formulaNode = new XElement(BuiltInFieldAttributes.Formula, typedFieldModel.Formula); + fieldTemplate.Add(formulaNode); + + // must be enum name, actually + + // Format="0" when provisioning CalculatedField #969 + // https://github.com/SubPointSolutions/spmeta2/issues/969 + fieldTemplate.SetAttribute(BuiltInFieldAttributes.Format, typedFieldModel.DateFormat); + + if (typedFieldModel.ShowAsPercentage.HasValue) + fieldTemplate.SetAttribute(BuiltInFieldAttributes.Percentage, typedFieldModel.ShowAsPercentage.Value.ToString().ToUpper()); + + if (!string.IsNullOrEmpty(typedFieldModel.DisplayFormat)) + fieldTemplate.SetAttribute(BuiltInFieldAttributes.Decimals, NumberFieldModelHandler.GetDecimalsValue(typedFieldModel.DisplayFormat)); + + fieldTemplate.SetAttribute(BuiltInFieldAttributes.ResultType, typedFieldModel.OutputType); + + if (typedFieldModel.FieldReferences.Count > 0) + { + var fieldRefsNode = new XElement("FieldRefs"); + + foreach (var fieldRef in typedFieldModel.FieldReferences) + { + var fieldRefNode = new XElement("FieldRef"); + + fieldRefNode.SetAttribute("Name", fieldRef); + fieldRefsNode.Add(fieldRefNode); + } + + fieldTemplate.Add(fieldRefsNode); + } + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.Regression.CSOM/Utils/FieldSchemaXmlUtils.cs b/SPMeta2/SPMeta2.Regression.CSOM/Utils/FieldSchemaXmlUtils.cs index 3df8ed671..f1173037e 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM/Utils/FieldSchemaXmlUtils.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM/Utils/FieldSchemaXmlUtils.cs @@ -1,268 +1,271 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using System.Xml.Linq; -using Microsoft.SharePoint.Client; -using SPMeta2.Enumerations; -using SPMeta2.Utils; - -namespace SPMeta2.Regression.CSOM.Utils -{ - internal static class FieldSchemaXmlUtils - { - public static string GetSystemInstanceName(this Field field) - { - var xml = field.SchemaXml; - return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.SystemInstance)); - } - - public static string GetEntityNamespace(this Field field) - { - var xml = field.SchemaXml; - return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.EntityNamespace)); - } - - public static string GetEntityName(this Field field) - { - var xml = field.SchemaXml; - return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.EntityName)); - } - - public static string GetBdcFieldName(this Field field) - { - var xml = field.SchemaXml; - return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.BdcField)); - } - - public static string GetEditFormat(this Field field) - { - var xml = field.SchemaXml; - return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Format)); - } - - public static string GetFriendlyDisplayFormat(this FieldDateTime field) - { - return field.FriendlyDisplayFormat.ToString(); - } - - public static string GetDisplayFormat(this FieldDateTime field) - { - return field.DisplayFormat.ToString(); - } - - public static string GetCalendarType(this FieldDateTime field) - { - return field.DateTimeCalendarType.ToString(); - } - - - - public static IEnumerable GetFieldReferences(this Field field) - { - var xml = field.SchemaXml; - - var result = new List(); - - var fieldRefRootNode = XElement.Parse(xml).Descendants("FieldRefs").FirstOrDefault(); - var fieldRefNodes = fieldRefRootNode.Descendants("FieldRef"); - - foreach (var fieldRefNode in fieldRefNodes) - result.Add(fieldRefNode.GetAttributeValue("Name")); - - return result; - } - - public static string GetOutputType(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ResultType)); - } - - public static string GetDisplayFormatString(this Field field) - { - var value = GetDisplayFormat(field); - - if (value == 0) - return BuiltInNumberFormatTypes.Automatic; - - if (value == 1) - return BuiltInNumberFormatTypes.OneDecimal; - - if (value == 2) - return BuiltInNumberFormatTypes.TwoDecimals; - - if (value == 3) - return BuiltInNumberFormatTypes.ThreeDecimals; - - if (value == 4) - return BuiltInNumberFormatTypes.FourDecimals; - - if (value == 5) - return BuiltInNumberFormatTypes.FiveDecimals; - - - - throw new ArgumentException("BuiltInNumberFormatTypes"); - - } - - - public static int GetDisplayFormat(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToInt(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Decimals)).Value; - } - - public static string GetDateFormatString(this Field field) - { - var value = GetDateFormat(field); - - if (value == 0) - return BuiltInDateTimeFieldFormatType.DateOnly; - - if (value == 1) - return BuiltInDateTimeFieldFormatType.DateTime; - - throw new ArgumentException("BuiltInDateTimeFieldFormatType"); - - } - - public static int GetDateFormat(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToInt(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Format)).Value; - } - - public static int GetCurrencyLocaleId(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToInt(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.LCID)).Value; - } - - - - public static bool GetShowAsPercentage(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Percentage)).Value; - } - - public static int GetDecimals(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToInt(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Decimals)).Value; - } - - public static string GetDecimalsAsString(this Field field) - { - var xml = field.SchemaXml; - - return GetDecimalsValue(GetDecimals(field)); - } - - private static string GetDecimalsValue(int value) - { - if (value == -1) - return BuiltInNumberFormatTypes.Automatic; - - if (value == 0) - return BuiltInNumberFormatTypes.NoDecimal; - - if (value == 1) - return BuiltInNumberFormatTypes.OneDecimal; - - if (value == 2) - return BuiltInNumberFormatTypes.TwoDecimals; - - if (value == 3) - return BuiltInNumberFormatTypes.ThreeDecimals; - - if (value == 4) - return BuiltInNumberFormatTypes.FourDecimals; - - if (value == 5) - return BuiltInNumberFormatTypes.FiveDecimals; - - throw new ArgumentException("Decimals"); - } - - - public static bool GetRichText(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBoolWithDefault(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.RichText), false); - } - - public static string GetRichTextMode(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.RichTextMode)); - } - - public static bool GetUnlimitedLengthInDocumentLibrary(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBoolWithDefault(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.UnlimitedLengthInDocumentLibrary), false); - } - - public static bool? GetShowInDisplayForm(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInDisplayForm)); - } - - public static bool? GetShowInEditForm(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInEditForm)); - } - - public static bool? GetShowInListSettings(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInListSettings)); - } - - public static bool? GetShowInNewForm(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInNewForm)); - } - - public static bool? GetShowInVersionHistory(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInVersionHistory)); - } - - public static bool? GetShowInViewForms(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInViewForms)); - } - - public static bool? GetAllowDeletion(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.AllowDeletion)); - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using System.Xml.Linq; +using Microsoft.SharePoint.Client; +using SPMeta2.Enumerations; +using SPMeta2.Utils; + +namespace SPMeta2.Regression.CSOM.Utils +{ + internal static class FieldSchemaXmlUtils + { + public static string GetSystemInstanceName(this Field field) + { + var xml = field.SchemaXml; + return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.SystemInstance)); + } + + public static string GetEntityNamespace(this Field field) + { + var xml = field.SchemaXml; + return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.EntityNamespace)); + } + + public static string GetEntityName(this Field field) + { + var xml = field.SchemaXml; + return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.EntityName)); + } + + public static string GetBdcFieldName(this Field field) + { + var xml = field.SchemaXml; + return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.BdcField)); + } + + public static string GetEditFormat(this Field field) + { + var xml = field.SchemaXml; + return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Format)); + } + + public static string GetFriendlyDisplayFormat(this FieldDateTime field) + { + return field.FriendlyDisplayFormat.ToString(); + } + + public static string GetDisplayFormat(this FieldDateTime field) + { + return field.DisplayFormat.ToString(); + } + + public static string GetCalendarType(this FieldDateTime field) + { + return field.DateTimeCalendarType.ToString(); + } + + + + public static IEnumerable GetFieldReferences(this Field field) + { + var xml = field.SchemaXml; + + var result = new List(); + + var fieldRefRootNode = XElement.Parse(xml).Descendants("FieldRefs").FirstOrDefault(); + var fieldRefNodes = fieldRefRootNode.Descendants("FieldRef"); + + foreach (var fieldRefNode in fieldRefNodes) + result.Add(fieldRefNode.GetAttributeValue("Name")); + + return result; + } + + public static string GetOutputType(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ResultType)); + } + + public static string GetDisplayFormatString(this Field field) + { + var value = GetDisplayFormat(field); + + if (value == 0) + return BuiltInNumberFormatTypes.Automatic; + + if (value == 1) + return BuiltInNumberFormatTypes.OneDecimal; + + if (value == 2) + return BuiltInNumberFormatTypes.TwoDecimals; + + if (value == 3) + return BuiltInNumberFormatTypes.ThreeDecimals; + + if (value == 4) + return BuiltInNumberFormatTypes.FourDecimals; + + if (value == 5) + return BuiltInNumberFormatTypes.FiveDecimals; + + + + throw new ArgumentException("BuiltInNumberFormatTypes"); + + } + + + public static int GetDisplayFormat(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToInt(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Decimals)).Value; + } + + public static string GetDateFormatString(this Field field) + { + var value = GetDateFormat(field); + + // Format="0" when provisioning CalculatedField #969 + // https://github.com/SubPointSolutions/spmeta2/issues/969 + + if (string.Compare(value, BuiltInDateTimeFieldFormatType.DateOnly, true) == 0) + return BuiltInDateTimeFieldFormatType.DateOnly; + + if (string.Compare(value, BuiltInDateTimeFieldFormatType.DateTime, true) == 0) + return BuiltInDateTimeFieldFormatType.DateTime; + + throw new ArgumentException("BuiltInDateTimeFieldFormatType was:" + value); + + } + + public static string GetDateFormat(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Format)); + } + + public static int GetCurrencyLocaleId(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToInt(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.LCID)).Value; + } + + + + public static bool GetShowAsPercentage(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Percentage)).Value; + } + + public static int GetDecimals(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToInt(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Decimals)).Value; + } + + public static string GetDecimalsAsString(this Field field) + { + var xml = field.SchemaXml; + + return GetDecimalsValue(GetDecimals(field)); + } + + private static string GetDecimalsValue(int value) + { + if (value == -1) + return BuiltInNumberFormatTypes.Automatic; + + if (value == 0) + return BuiltInNumberFormatTypes.NoDecimal; + + if (value == 1) + return BuiltInNumberFormatTypes.OneDecimal; + + if (value == 2) + return BuiltInNumberFormatTypes.TwoDecimals; + + if (value == 3) + return BuiltInNumberFormatTypes.ThreeDecimals; + + if (value == 4) + return BuiltInNumberFormatTypes.FourDecimals; + + if (value == 5) + return BuiltInNumberFormatTypes.FiveDecimals; + + throw new ArgumentException("Decimals"); + } + + + public static bool GetRichText(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBoolWithDefault(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.RichText), false); + } + + public static string GetRichTextMode(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.RichTextMode)); + } + + public static bool GetUnlimitedLengthInDocumentLibrary(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBoolWithDefault(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.UnlimitedLengthInDocumentLibrary), false); + } + + public static bool? GetShowInDisplayForm(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInDisplayForm)); + } + + public static bool? GetShowInEditForm(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInEditForm)); + } + + public static bool? GetShowInListSettings(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInListSettings)); + } + + public static bool? GetShowInNewForm(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInNewForm)); + } + + public static bool? GetShowInVersionHistory(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInVersionHistory)); + } + + public static bool? GetShowInViewForms(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInViewForms)); + } + + public static bool? GetAllowDeletion(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.AllowDeletion)); + } + } +} diff --git a/SPMeta2/SPMeta2.Regression.SSOM/Validation/Fields/CalculatedFieldDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.SSOM/Validation/Fields/CalculatedFieldDefinitionValidator.cs index fd36ab75a..4779a924f 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM/Validation/Fields/CalculatedFieldDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM/Validation/Fields/CalculatedFieldDefinitionValidator.cs @@ -1,120 +1,155 @@ -using System; -using System.Linq; -using SPMeta2.Containers.Assertion; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Fields; -using SPMeta2.Utils; -using Microsoft.SharePoint; -using SPMeta2.Containers.Utils; - -namespace SPMeta2.Regression.SSOM.Validation.Fields -{ - public class CalculatedFieldDefinitionValidator : FieldDefinitionValidator - { - public override Type TargetType - { - get - { - return typeof(CalculatedFieldDefinition); - } - } - - public override void DeployModel(object modelHost, DefinitionBase model) - { - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - var spObject = GetField(modelHost, definition); - - var assert = ServiceFactory.AssertService.NewAssert(model, definition, spObject); - - ValidateField(assert, spObject, definition); - - var typedField = spObject as SPFieldCalculated; - - var typedDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - var typedFieldAssert = ServiceFactory.AssertService.NewAssert(model, typedDefinition, typedField); - - typedFieldAssert.ShouldBeEqual(m => m.CurrencyLocaleId, o => o.CurrencyLocaleId); - typedFieldAssert.ShouldBeEqual(m => m.DateFormat, o => o.GetDateFormat()); - - typedFieldAssert.ShouldBeEqual(m => m.OutputType, o => o.GetOutputType()); - // - typedFieldAssert.ShouldBeEqual(m => m.DisplayFormat, o => o.GetDisplayFormat()); - - if (typedDefinition.ShowAsPercentage.HasValue) - typedFieldAssert.ShouldBeEqual(m => m.ShowAsPercentage, o => o.ShowAsPercentage); - else - typedFieldAssert.SkipProperty(m => m.ShowAsPercentage, "ShowAsPercentage is NULL. Skipping."); - - if (!string.IsNullOrEmpty(typedDefinition.Formula)) - typedFieldAssert.ShouldBeEqual(m => m.Formula, o => o.Formula); - else - typedFieldAssert.SkipProperty(m => m.Formula); - - IndentableTrace.WithScope(s => - { - s.WriteLine(string.Format("Formula: Src:[{0}] Dst:[{1}]", typedDefinition.Formula, typedField.Formula)); - }); - - // field refs - if (typedDefinition.FieldReferences.Count > 0) - { - var hasFieldRefs = true; - - if (typedField.FieldReferences != null) - { - foreach (var dstFieldRef in typedField.FieldReferences) - { - if (typedDefinition.FieldReferences.FirstOrDefault(c => c.ToUpper() == dstFieldRef.ToUpper()) == - null) - { - hasFieldRefs = false; - } - } - - if (typedField.FieldReferences.Length == 0) - hasFieldRefs = false; - } - else - { - hasFieldRefs = false; - } - - typedFieldAssert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(m => m.FieldReferences); - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - Dst = null, - IsValid = hasFieldRefs == true - }; - }); - } - else - { - typedFieldAssert.SkipProperty(m => m.FieldReferences, "FieldReferences.Count == 0. Skipping."); - } - - } - } - - internal static class SPFieldCalculatedUtils - { - public static string GetOutputType(this SPFieldCalculated field) - { - return field.OutputType.ToString(); - } - - public static string GetDisplayFormat(this SPFieldCalculated field) - { - return field.DisplayFormat.ToString(); - } - - public static string GetDateFormat(this SPFieldCalculated field) - { - return field.DateFormat.ToString(); - } - } -} +using System; +using System.Linq; +using SPMeta2.Containers.Assertion; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Fields; +using SPMeta2.Utils; +using Microsoft.SharePoint; +using SPMeta2.Containers.Utils; +using System.Xml.Linq; +using SPMeta2.Enumerations; + +namespace SPMeta2.Regression.SSOM.Validation.Fields +{ + public class CalculatedFieldDefinitionValidator : FieldDefinitionValidator + { + public override Type TargetType + { + get + { + return typeof(CalculatedFieldDefinition); + } + } + + public override void DeployModel(object modelHost, DefinitionBase model) + { + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var spObject = GetField(modelHost, definition); + + var assert = ServiceFactory.AssertService.NewAssert(model, definition, spObject); + + ValidateField(assert, spObject, definition); + + var typedField = spObject as SPFieldCalculated; + + var typedDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var typedFieldAssert = ServiceFactory.AssertService.NewAssert(model, typedDefinition, typedField); + + typedFieldAssert.ShouldBeEqual(m => m.CurrencyLocaleId, o => o.CurrencyLocaleId); + typedFieldAssert.ShouldBeEqual(m => m.DateFormat, o => o.GetDateFormat()); + + + + typedFieldAssert.ShouldBeEqual(m => m.OutputType, o => o.GetOutputType()); + // + typedFieldAssert.ShouldBeEqual(m => m.DisplayFormat, o => o.GetDisplayFormat()); + + if (typedDefinition.ShowAsPercentage.HasValue) + typedFieldAssert.ShouldBeEqual(m => m.ShowAsPercentage, o => o.ShowAsPercentage); + else + typedFieldAssert.SkipProperty(m => m.ShowAsPercentage, "ShowAsPercentage is NULL. Skipping."); + + if (!string.IsNullOrEmpty(typedDefinition.Formula)) + typedFieldAssert.ShouldBeEqual(m => m.Formula, o => o.Formula); + else + typedFieldAssert.SkipProperty(m => m.Formula); + + IndentableTrace.WithScope(s => + { + s.WriteLine(string.Format("Formula: Src:[{0}] Dst:[{1}]", typedDefinition.Formula, typedField.Formula)); + }); + + // field refs + if (typedDefinition.FieldReferences.Count > 0) + { + var hasFieldRefs = true; + + if (typedField.FieldReferences != null) + { + foreach (var dstFieldRef in typedField.FieldReferences) + { + if (typedDefinition.FieldReferences.FirstOrDefault(c => c.ToUpper() == dstFieldRef.ToUpper()) == + null) + { + hasFieldRefs = false; + } + } + + if (typedField.FieldReferences.Length == 0) + hasFieldRefs = false; + } + else + { + hasFieldRefs = false; + } + + typedFieldAssert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(m => m.FieldReferences); + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + Dst = null, + IsValid = hasFieldRefs == true + }; + }); + } + else + { + typedFieldAssert.SkipProperty(m => m.FieldReferences, "FieldReferences.Count == 0. Skipping."); + } + + } + } + + internal static class SPFieldCalculatedUtils + { + public static string GetOutputType(this SPFieldCalculated field) + { + return field.OutputType.ToString(); + } + + public static string GetDisplayFormat(this SPFieldCalculated field) + { + return field.DisplayFormat.ToString(); + } + + public static string GetDateFormat(this SPFieldCalculated field) + { + var value = field.DateFormat.ToString(); ; + + // also, wihtint expected range + field.GetDateFormatString(); + + return field.DateFormat.ToString(); + } + + public static string GetDateFormatString(this SPField field) + { + var value = GetDateFormat(field); + + // Format="0" when provisioning CalculatedField #969 + // https://github.com/SubPointSolutions/spmeta2/issues/969 + + if (string.Compare(value, BuiltInDateTimeFieldFormatType.DateOnly, true) == 0) + return BuiltInDateTimeFieldFormatType.DateOnly; + + if (string.Compare(value, BuiltInDateTimeFieldFormatType.DateTime, true) == 0) + return BuiltInDateTimeFieldFormatType.DateTime; + + throw new ArgumentException("BuiltInDateTimeFieldFormatType was:" + value); + + } + + public static string GetDateFormat(this SPField field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Format)); + } + } + + +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Fields/CalculatedFieldScenariousTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Fields/CalculatedFieldScenariousTest.cs index ad83b8c6f..bba778f36 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Fields/CalculatedFieldScenariousTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Fields/CalculatedFieldScenariousTest.cs @@ -1,288 +1,345 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.ComponentModel; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SPMeta2.Containers; - -using SPMeta2.Definitions; -using SPMeta2.Definitions.Fields; -using SPMeta2.Enumerations; -using SPMeta2.Exceptions; -using SPMeta2.Models; -using SPMeta2.Regression.Tests.Impl.Scenarios.Base; -using SPMeta2.Syntax.Default; -using SPMeta2.Syntax.Default.Modern; - -namespace SPMeta2.Regression.Tests.Impl.Scenarios.Fields -{ - [TestClass] - public class CalculatedFieldScenariousTest : SPMeta2RegresionScenarioTestBase - { - #region internal - - [ClassInitialize] - public static void Init(TestContext context) - { - InternalInit(); - } - - [ClassCleanup] - public static void Cleanup() - { - InternalCleanup(); - } - - #endregion - - #region utils - - protected CalculatedFieldDefinition GetCalculatedFieldDefinition() - { - return GetCalculatedFieldDefinition(null); - } - - protected CalculatedFieldDefinition GetCalculatedFieldDefinition(Action action) - { - var result = ModelGeneratorService.GetRandomDefinition(def => - { - def.ShowInNewForm = true; - def.ShowInEditForm = true; - def.ShowInDisplayForm = true; - - def.ShowInListSettings = true; - - def.Hidden = false; - def.Required = false; - }); - - if (action != null) - action(result); - - return result; - } - - protected FieldDefinition GetRandomFieldWithType(string type) - { - return ModelGeneratorService.GetRandomDefinition(def => - { - def.FieldType = type; - - def.ShowInNewForm = true; - def.ShowInEditForm = true; - def.ShowInDisplayForm = true; - - def.ShowInListSettings = true; - - def.Hidden = false; - def.Required = false; - }); - } - - #endregion - - #region formula changes - - - //[TestMethod] - //[TestCategory("Regression.Scenarios.Fields.CalculatedField")] - //public void CanDeploy_CalculatedSiteField_AndChangeFormula() - //{ - // //RegressionService.EnableDefinitionValidation = false; - // //RegressionService.EnableEventValidation = false; - - // var field = GetCalculatedFieldDefinition(def => - // { - // def.OutputType = BuiltInFieldTypes.Text; - // }); - - // var firstIntField = GetRandomFieldWithType(BuiltInFieldTypes.Integer); - // var firstTextField = GetRandomFieldWithType(BuiltInFieldTypes.Text); - // var firstNumberField = GetRandomFieldWithType(BuiltInFieldTypes.Number); - - // var secondIntField = GetRandomFieldWithType(BuiltInFieldTypes.Integer); - // var secondTextField = GetRandomFieldWithType(BuiltInFieldTypes.Text); - // var secondNumberField = GetRandomFieldWithType(BuiltInFieldTypes.Number); - - // field.FieldReferences = new Collection() - // { - // firstTextField.InternalName, - // firstTextField.InternalName, - // firstTextField.InternalName, - - // secondIntField.InternalName, - // secondTextField.InternalName, - // secondNumberField.InternalName - - // }; - - // var siteModel = SPMeta2Model.NewSiteModel(site => - // { - // site.AddField(firstIntField); - // site.AddField(firstTextField); - // site.AddField(firstNumberField); - - // site.AddField(secondIntField); - // site.AddField(secondTextField); - // site.AddField(secondNumberField); - - // site.AddField(field); - // }); - - // field.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", - // new String[] - // { - // firstTextField.InternalName, - // firstTextField.InternalName, - // firstTextField.InternalName, - // }); - - // RegressionService.ProvisionGenerationCount = 1; - - // TestModel(siteModel); - // TestModel(siteModel); - - // field.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", - // new String[] - // { - // secondIntField.InternalName, - // secondTextField.InternalName, - // secondNumberField.InternalName, - // }); - - // TestModel(siteModel); - // TestModel(siteModel); - //} - - - //[TestMethod] - //[TestCategory("Regression.Scenarios.Fields.CalculatedField")] - //public void CanDeploy_CalculatedFieldToList_AndChangeFormula() - //{ - // RegressionService.ProvisionGenerationCount = 1; - - // var calcField = GetCalculatedFieldDefinition(def => - // { - // def.OutputType = BuiltInFieldTypes.Text; - // }); - - // var firstIntField = GetRandomFieldWithType(BuiltInFieldTypes.Integer); - // var firstTextField = GetRandomFieldWithType(BuiltInFieldTypes.Text); - // var firstNumberField = GetRandomFieldWithType(BuiltInFieldTypes.Number); - - // var secondIntField = GetRandomFieldWithType(BuiltInFieldTypes.Integer); - // var secondTextField = GetRandomFieldWithType(BuiltInFieldTypes.Text); - // var secondNumberField = GetRandomFieldWithType(BuiltInFieldTypes.Number); - - // var contentTypeWithCalcField = ModelGeneratorService.GetRandomDefinition(def => - // { - // def.Hidden = false; - // def.ParentContentTypeId = BuiltInContentTypeId.Item; - // }); - - // var listWithCalcContentType = ModelGeneratorService.GetRandomDefinition(def => - // { - // def.ContentTypesEnabled = true; - // def.Hidden = false; - // def.TemplateType = BuiltInListTemplateTypeId.GenericList; - // }); - - // calcField.FieldReferences = new Collection() - // { - // firstIntField.InternalName, - // firstTextField.InternalName, - // firstNumberField.InternalName, - - // secondIntField.InternalName, - // secondTextField.InternalName, - // secondNumberField.InternalName, - // "Title" - // }; - - // var siteModel = SPMeta2Model.NewSiteModel(site => - // { - // site.AddField(firstIntField); - // site.AddField(firstTextField); - // site.AddField(firstNumberField); - - // site.AddField(secondIntField); - // site.AddField(secondTextField); - // site.AddField(secondNumberField); - - // site.AddField(calcField); - - // site.AddContentType(contentTypeWithCalcField, contentType => - // { - // contentType - // .AddContentTypeFieldLink(firstIntField) - // .AddContentTypeFieldLink(firstTextField) - // .AddContentTypeFieldLink(firstNumberField) - - // .AddContentTypeFieldLink(secondIntField) - // .AddContentTypeFieldLink(secondTextField) - // .AddContentTypeFieldLink(secondNumberField) - - // .AddContentTypeFieldLink(calcField); - // }); - // }); - - // calcField.Formula = string.Format("=[Title]"); - - // //calcField.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", - // // new String[] - // // { - // // firstIntField.InternalName, - // // firstNumberField.InternalName, - // // firstTextField.InternalName, - // // }); - - // TestModel(siteModel); - // TestModel(siteModel); - - // var webModel = SPMeta2Model.NewWebModel(web => - // { - // web.AddList(listWithCalcContentType, list => - // { - // list.AddContentTypeLink(contentTypeWithCalcField); - // }); - // }); - - // TestModel(webModel); - // TestModel(webModel); - - // calcField.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", - // new String[] - // { - // firstIntField.InternalName, - // firstNumberField.InternalName, - // firstTextField.InternalName, - // }); - - // var subSiteModel = SPMeta2Model.NewSiteModel(site => - // { - // site.AddField(calcField); - - // //site.AddContentType(contentTypeWithCalcField, contentType => - // //{ - // // contentType - // // .AddContentTypeFieldLink(calcField); - // //}); - // }); - - // TestModel(subSiteModel); - - // calcField.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", - // new String[] - // { - // firstIntField.InternalName, - // firstNumberField.InternalName, - // firstTextField.InternalName, - // }); - - // TestModel(siteModel); - // TestModel(siteModel); - //} - - #endregion - } -} +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SPMeta2.Containers; + +using SPMeta2.Definitions; +using SPMeta2.Definitions.Fields; +using SPMeta2.Enumerations; +using SPMeta2.Exceptions; +using SPMeta2.Models; +using SPMeta2.Regression.Tests.Impl.Scenarios.Base; +using SPMeta2.Syntax.Default; +using SPMeta2.Syntax.Default.Modern; + +namespace SPMeta2.Regression.Tests.Impl.Scenarios.Fields +{ + [TestClass] + public class CalculatedFieldScenariousTest : SPMeta2RegresionScenarioTestBase + { + #region internal + + [ClassInitialize] + public static void Init(TestContext context) + { + InternalInit(); + } + + [ClassCleanup] + public static void Cleanup() + { + InternalCleanup(); + } + + #endregion + + #region utils + + protected CalculatedFieldDefinition GetCalculatedFieldDefinition() + { + return GetCalculatedFieldDefinition(null); + } + + protected CalculatedFieldDefinition GetCalculatedFieldDefinition(Action action) + { + var result = ModelGeneratorService.GetRandomDefinition(def => + { + def.ShowInNewForm = true; + def.ShowInEditForm = true; + def.ShowInDisplayForm = true; + + def.ShowInListSettings = true; + + def.Hidden = false; + def.Required = false; + }); + + if (action != null) + action(result); + + return result; + } + + protected FieldDefinition GetRandomFieldWithType(string type) + { + return ModelGeneratorService.GetRandomDefinition(def => + { + def.FieldType = type; + + def.ShowInNewForm = true; + def.ShowInEditForm = true; + def.ShowInDisplayForm = true; + + def.ShowInListSettings = true; + + def.Hidden = false; + def.Required = false; + }); + } + + #endregion + + [TestMethod] + [TestCategory("Regression.Scenarios.Fields.CalculatedField")] + public void CanDeploy_CalculatedField_OutputType_All() + { + var outputTypes = new[] { + BuiltInFieldTypes.Text, + BuiltInFieldTypes.Number, + BuiltInFieldTypes.Integer, + BuiltInFieldTypes.Currency, + BuiltInFieldTypes.Boolean, + BuiltInFieldTypes.DateTime + }; + + var siteModel = SPMeta2Model.NewSiteModel(site => + { + foreach (var outputType in outputTypes) + { + var field = GetCalculatedFieldDefinition(def => + { + def.DateFormat = BuiltInDateTimeFieldFormatType.DateOnly; + def.OutputType = outputType; + }); + + site.AddCalculatedField(field); + } + }); + + TestModel(siteModel); + TestModel(siteModel); + } + + [TestMethod] + [TestCategory("Regression.Scenarios.Fields.CalculatedField")] + public void CanDeploy_CalculatedField_DateFormat_All() + { + var formatTypes = new[] { + BuiltInDateTimeFieldFormatType.DateOnly, + BuiltInDateTimeFieldFormatType.DateTime + }; + + var siteModel = SPMeta2Model.NewSiteModel(site => + { + foreach (var outputType in formatTypes) + { + var field = GetCalculatedFieldDefinition(def => + { + def.DateFormat = outputType; + }); + + site.AddCalculatedField(field); + } + }); + + TestModel(siteModel); + TestModel(siteModel); + } + + #region formula changes + + + //[TestMethod] + //[TestCategory("Regression.Scenarios.Fields.CalculatedField")] + //public void CanDeploy_CalculatedSiteField_AndChangeFormula() + //{ + // //RegressionService.EnableDefinitionValidation = false; + // //RegressionService.EnableEventValidation = false; + + // var field = GetCalculatedFieldDefinition(def => + // { + // def.OutputType = BuiltInFieldTypes.Text; + // }); + + // var firstIntField = GetRandomFieldWithType(BuiltInFieldTypes.Integer); + // var firstTextField = GetRandomFieldWithType(BuiltInFieldTypes.Text); + // var firstNumberField = GetRandomFieldWithType(BuiltInFieldTypes.Number); + + // var secondIntField = GetRandomFieldWithType(BuiltInFieldTypes.Integer); + // var secondTextField = GetRandomFieldWithType(BuiltInFieldTypes.Text); + // var secondNumberField = GetRandomFieldWithType(BuiltInFieldTypes.Number); + + // field.FieldReferences = new Collection() + // { + // firstTextField.InternalName, + // firstTextField.InternalName, + // firstTextField.InternalName, + + // secondIntField.InternalName, + // secondTextField.InternalName, + // secondNumberField.InternalName + + // }; + + // var siteModel = SPMeta2Model.NewSiteModel(site => + // { + // site.AddField(firstIntField); + // site.AddField(firstTextField); + // site.AddField(firstNumberField); + + // site.AddField(secondIntField); + // site.AddField(secondTextField); + // site.AddField(secondNumberField); + + // site.AddField(field); + // }); + + // field.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", + // new String[] + // { + // firstTextField.InternalName, + // firstTextField.InternalName, + // firstTextField.InternalName, + // }); + + // RegressionService.ProvisionGenerationCount = 1; + + // TestModel(siteModel); + // TestModel(siteModel); + + // field.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", + // new String[] + // { + // secondIntField.InternalName, + // secondTextField.InternalName, + // secondNumberField.InternalName, + // }); + + // TestModel(siteModel); + // TestModel(siteModel); + //} + + + //[TestMethod] + //[TestCategory("Regression.Scenarios.Fields.CalculatedField")] + //public void CanDeploy_CalculatedFieldToList_AndChangeFormula() + //{ + // RegressionService.ProvisionGenerationCount = 1; + + // var calcField = GetCalculatedFieldDefinition(def => + // { + // def.OutputType = BuiltInFieldTypes.Text; + // }); + + // var firstIntField = GetRandomFieldWithType(BuiltInFieldTypes.Integer); + // var firstTextField = GetRandomFieldWithType(BuiltInFieldTypes.Text); + // var firstNumberField = GetRandomFieldWithType(BuiltInFieldTypes.Number); + + // var secondIntField = GetRandomFieldWithType(BuiltInFieldTypes.Integer); + // var secondTextField = GetRandomFieldWithType(BuiltInFieldTypes.Text); + // var secondNumberField = GetRandomFieldWithType(BuiltInFieldTypes.Number); + + // var contentTypeWithCalcField = ModelGeneratorService.GetRandomDefinition(def => + // { + // def.Hidden = false; + // def.ParentContentTypeId = BuiltInContentTypeId.Item; + // }); + + // var listWithCalcContentType = ModelGeneratorService.GetRandomDefinition(def => + // { + // def.ContentTypesEnabled = true; + // def.Hidden = false; + // def.TemplateType = BuiltInListTemplateTypeId.GenericList; + // }); + + // calcField.FieldReferences = new Collection() + // { + // firstIntField.InternalName, + // firstTextField.InternalName, + // firstNumberField.InternalName, + + // secondIntField.InternalName, + // secondTextField.InternalName, + // secondNumberField.InternalName, + // "Title" + // }; + + // var siteModel = SPMeta2Model.NewSiteModel(site => + // { + // site.AddField(firstIntField); + // site.AddField(firstTextField); + // site.AddField(firstNumberField); + + // site.AddField(secondIntField); + // site.AddField(secondTextField); + // site.AddField(secondNumberField); + + // site.AddField(calcField); + + // site.AddContentType(contentTypeWithCalcField, contentType => + // { + // contentType + // .AddContentTypeFieldLink(firstIntField) + // .AddContentTypeFieldLink(firstTextField) + // .AddContentTypeFieldLink(firstNumberField) + + // .AddContentTypeFieldLink(secondIntField) + // .AddContentTypeFieldLink(secondTextField) + // .AddContentTypeFieldLink(secondNumberField) + + // .AddContentTypeFieldLink(calcField); + // }); + // }); + + // calcField.Formula = string.Format("=[Title]"); + + // //calcField.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", + // // new String[] + // // { + // // firstIntField.InternalName, + // // firstNumberField.InternalName, + // // firstTextField.InternalName, + // // }); + + // TestModel(siteModel); + // TestModel(siteModel); + + // var webModel = SPMeta2Model.NewWebModel(web => + // { + // web.AddList(listWithCalcContentType, list => + // { + // list.AddContentTypeLink(contentTypeWithCalcField); + // }); + // }); + + // TestModel(webModel); + // TestModel(webModel); + + // calcField.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", + // new String[] + // { + // firstIntField.InternalName, + // firstNumberField.InternalName, + // firstTextField.InternalName, + // }); + + // var subSiteModel = SPMeta2Model.NewSiteModel(site => + // { + // site.AddField(calcField); + + // //site.AddContentType(contentTypeWithCalcField, contentType => + // //{ + // // contentType + // // .AddContentTypeFieldLink(calcField); + // //}); + // }); + + // TestModel(subSiteModel); + + // calcField.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", + // new String[] + // { + // firstIntField.InternalName, + // firstNumberField.InternalName, + // firstTextField.InternalName, + // }); + + // TestModel(siteModel); + // TestModel(siteModel); + //} + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Syntax/TypedSyntaxTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Syntax/TypedSyntaxTests.cs index 22b4031a9..91b7e159a 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Syntax/TypedSyntaxTests.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Syntax/TypedSyntaxTests.cs @@ -232,6 +232,11 @@ public void CanPassTypedSyntax_WebLevel() .AddProperty(new PropertyDefinition()); + list.AddContentTypeLink(new ContentTypeLinkDefinition(), contentTypeLink => + { + contentTypeLink.AddWorkflowAssociation(new WorkflowAssociationDefinition()); + + }); list.AddUniqueContentTypeOrder(new UniqueContentTypeOrderDefinition()); list.AddHideContentTypeLinks(new HideContentTypeLinksDefinition()); list.AddRemoveContentTypeLinks(new RemoveContentTypeLinksDefinition()); diff --git a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj index f4c024c49..423dd6f01 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj +++ b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj @@ -273,6 +273,7 @@ + diff --git a/SPMeta2/SPMeta2.Regression.Tests/Services/ExpectUpdateServices/ExpectUpdatAsDisplayFormatService.cs b/SPMeta2/SPMeta2.Regression.Tests/Services/ExpectUpdateServices/ExpectUpdatAsDisplayFormatService.cs new file mode 100644 index 000000000..e87f69aac --- /dev/null +++ b/SPMeta2/SPMeta2.Regression.Tests/Services/ExpectUpdateServices/ExpectUpdatAsDisplayFormatService.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using SPMeta2.Attributes.Regression; +using SPMeta2.Containers.Services; +using SPMeta2.Enumerations; + +namespace SPMeta2.Regression.Tests.Services.ExpectUpdateServices +{ + public class ExpectUpdateAsDateFormatService : ExpectUpdateGenericService + { + public override object GetNewPropValue(ExpectUpdate attr, object obj, PropertyInfo prop) + { + object newValue = null; + + var curentValue = prop.GetValue(obj) as string; + + if (curentValue == BuiltInDateTimeFieldFormatType.DateOnly) + { + newValue = BuiltInDateTimeFieldFormatType.DateTime; + } + if (curentValue == BuiltInDateTimeFieldFormatType.DateTime) + { + newValue = BuiltInDateTimeFieldFormatType.DateOnly; + } + else + { + newValue = RndService.RandomFromArray(new string[]{ + BuiltInDateTimeFieldFormatType.DateOnly, + BuiltInDateTimeFieldFormatType.DateTime + }); + } + + return newValue; + } + } +} diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/Fields/CalculatedFieldModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/Fields/CalculatedFieldModelHandler.cs index 6dfd81165..07db2780e 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/Fields/CalculatedFieldModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/Fields/CalculatedFieldModelHandler.cs @@ -1,105 +1,115 @@ -using System; -using System.Linq; -using System.Xml.Linq; -using Microsoft.SharePoint; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Fields; -using SPMeta2.Enumerations; -using SPMeta2.Utils; -using SPMeta2.Services; - -namespace SPMeta2.SSOM.ModelHandlers.Fields -{ - public class CalculatedFieldModelHandler : FieldModelHandler - { - #region properties - - public override Type TargetType - { - get { return typeof(CalculatedFieldDefinition); } - } - - protected override Type GetTargetFieldType(FieldDefinition model) - { - return typeof(SPFieldCalculated); - } - - #endregion - - #region methods - - protected override void ProcessFieldProperties(SPField field, FieldDefinition fieldModel) - { - // let base setting be setup - base.ProcessFieldProperties(field, fieldModel); - - var typedFieldModel = fieldModel.WithAssertAndCast("model", value => value.RequireNotNull()); - var typedField = field as SPFieldCalculated; - - if (!string.IsNullOrEmpty(typedFieldModel.Formula)) - { - // can't really validate it automatically - // Improve CalculatedFieldDefinition with field ref check - // https://github.com/SubPointSolutions/spmeta2/issues/648 - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Updating formula for a CalculatedField. Ensure FieldReferences are correct."); - - typedField.Formula = typedFieldModel.Formula; - } - - if (typedFieldModel.ShowAsPercentage.HasValue) - typedField.ShowAsPercentage = typedFieldModel.ShowAsPercentage.Value; - - typedField.OutputType = (SPFieldType)Enum.Parse(typeof(SPFieldType), typedFieldModel.OutputType); - } - - protected override void ProcessSPFieldXElement(XElement fieldTemplate, FieldDefinition fieldModel) - { - base.ProcessSPFieldXElement(fieldTemplate, fieldModel); - - var typedFieldModel = fieldModel.WithAssertAndCast("model", value => value.RequireNotNull()); - - if (typedFieldModel.CurrencyLocaleId.HasValue) - fieldTemplate.SetAttribute(BuiltInFieldAttributes.LCID, typedFieldModel.CurrencyLocaleId); - - if (!string.IsNullOrEmpty(typedFieldModel.Formula)) - { - // can't really validate it automatically - // Improve CalculatedFieldDefinition with field ref check - // https://github.com/SubPointSolutions/spmeta2/issues/648 - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Crafting formula for a CalculatedField. Ensure FieldReferences are correct."); - - // should be a new XML node - var formulaNode = new XElement(BuiltInFieldAttributes.Formula, typedFieldModel.Formula); - fieldTemplate.Add(formulaNode); - - fieldTemplate.SetAttribute(BuiltInFieldAttributes.Format, - (int)Enum.Parse(typeof(SPDateTimeFieldFormatType), typedFieldModel.DateFormat)); - } - - if (typedFieldModel.ShowAsPercentage.HasValue) - fieldTemplate.SetAttribute(BuiltInFieldAttributes.Percentage, typedFieldModel.ShowAsPercentage.Value.ToString().ToUpper()); - - if (!string.IsNullOrEmpty(typedFieldModel.DisplayFormat)) - fieldTemplate.SetAttribute(BuiltInFieldAttributes.Decimals, NumberFieldModelHandler.GetDecimalsValue(typedFieldModel.DisplayFormat)); - - fieldTemplate.SetAttribute(BuiltInFieldAttributes.ResultType, typedFieldModel.OutputType); - - if (typedFieldModel.FieldReferences.Count > 0) - { - var fieldRefsNode = new XElement("FieldRefs"); - - foreach (var fieldRef in typedFieldModel.FieldReferences) - { - var fieldRefNode = new XElement("FieldRef"); - - fieldRefNode.SetAttribute("Name", fieldRef); - fieldRefsNode.Add(fieldRefNode); - } - - fieldTemplate.Add(fieldRefsNode); - } - } - - #endregion - } -} +using System; +using System.Linq; +using System.Xml.Linq; +using Microsoft.SharePoint; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Fields; +using SPMeta2.Enumerations; +using SPMeta2.Utils; +using SPMeta2.Services; + +namespace SPMeta2.SSOM.ModelHandlers.Fields +{ + public class CalculatedFieldModelHandler : FieldModelHandler + { + #region properties + + public override Type TargetType + { + get { return typeof(CalculatedFieldDefinition); } + } + + protected override Type GetTargetFieldType(FieldDefinition model) + { + return typeof(SPFieldCalculated); + } + + #endregion + + #region methods + + protected override void ProcessFieldProperties(SPField field, FieldDefinition fieldModel) + { + // let base setting be setup + base.ProcessFieldProperties(field, fieldModel); + + var typedFieldModel = fieldModel.WithAssertAndCast("model", value => value.RequireNotNull()); + var typedField = field as SPFieldCalculated; + + if (!string.IsNullOrEmpty(typedFieldModel.Formula)) + { + // can't really validate it automatically + // Improve CalculatedFieldDefinition with field ref check + // https://github.com/SubPointSolutions/spmeta2/issues/648 + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Updating formula for a CalculatedField. Ensure FieldReferences are correct."); + + typedField.Formula = typedFieldModel.Formula; + + var dateFormatValue = (SPDateTimeFieldFormatType)Enum.Parse(typeof(SPDateTimeFieldFormatType), typedFieldModel.DateFormat); + + typedField.DateFormat = dateFormatValue; + } + + if (typedFieldModel.ShowAsPercentage.HasValue) + typedField.ShowAsPercentage = typedFieldModel.ShowAsPercentage.Value; + + typedField.OutputType = (SPFieldType)Enum.Parse(typeof(SPFieldType), typedFieldModel.OutputType); + } + + protected override void ProcessSPFieldXElement(XElement fieldTemplate, FieldDefinition fieldModel) + { + base.ProcessSPFieldXElement(fieldTemplate, fieldModel); + + var typedFieldModel = fieldModel.WithAssertAndCast("model", value => value.RequireNotNull()); + + if (typedFieldModel.CurrencyLocaleId.HasValue) + fieldTemplate.SetAttribute(BuiltInFieldAttributes.LCID, typedFieldModel.CurrencyLocaleId); + + if (!string.IsNullOrEmpty(typedFieldModel.Formula)) + { + // can't really validate it automatically + // Improve CalculatedFieldDefinition with field ref check + // https://github.com/SubPointSolutions/spmeta2/issues/648 + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Crafting formula for a CalculatedField. Ensure FieldReferences are correct."); + + // should be a new XML node + var formulaNode = new XElement(BuiltInFieldAttributes.Formula, typedFieldModel.Formula); + fieldTemplate.Add(formulaNode); + + + // Format="0" when provisioning CalculatedField #969 + // https://github.com/SubPointSolutions/spmeta2/issues/969 + + //fieldTemplate.SetAttribute(BuiltInFieldAttributes.Format, + // (int)Enum.Parse(typeof(SPDateTimeFieldFormatType), typedFieldModel.DateFormat)); + + fieldTemplate.SetAttribute(BuiltInFieldAttributes.Format, typedFieldModel.DateFormat); + } + + if (typedFieldModel.ShowAsPercentage.HasValue) + fieldTemplate.SetAttribute(BuiltInFieldAttributes.Percentage, typedFieldModel.ShowAsPercentage.Value.ToString().ToUpper()); + + if (!string.IsNullOrEmpty(typedFieldModel.DisplayFormat)) + fieldTemplate.SetAttribute(BuiltInFieldAttributes.Decimals, NumberFieldModelHandler.GetDecimalsValue(typedFieldModel.DisplayFormat)); + + fieldTemplate.SetAttribute(BuiltInFieldAttributes.ResultType, typedFieldModel.OutputType); + + if (typedFieldModel.FieldReferences.Count > 0) + { + var fieldRefsNode = new XElement("FieldRefs"); + + foreach (var fieldRef in typedFieldModel.FieldReferences) + { + var fieldRefNode = new XElement("FieldRef"); + + fieldRefNode.SetAttribute("Name", fieldRef); + fieldRefsNode.Add(fieldRefNode); + } + + fieldTemplate.Add(fieldRefsNode); + } + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2/Attributes/Regression/ExpectUpdate.cs b/SPMeta2/SPMeta2/Attributes/Regression/ExpectUpdate.cs index 893055e01..7af883f43 100644 --- a/SPMeta2/SPMeta2/Attributes/Regression/ExpectUpdate.cs +++ b/SPMeta2/SPMeta2/Attributes/Regression/ExpectUpdate.cs @@ -218,4 +218,9 @@ public class ExpectUpdateAsXsltListViewXslLinkUrl : ExpectUpdateAsXsltListView } + public class ExpectUpdateAsDateFormat : ExpectUpdate + { + + } + } diff --git a/SPMeta2/SPMeta2/Definitions/Fields/CalculatedFieldDefinition.cs b/SPMeta2/SPMeta2/Definitions/Fields/CalculatedFieldDefinition.cs index d87415f18..ccc16420f 100644 --- a/SPMeta2/SPMeta2/Definitions/Fields/CalculatedFieldDefinition.cs +++ b/SPMeta2/SPMeta2/Definitions/Fields/CalculatedFieldDefinition.cs @@ -1,124 +1,125 @@ -using System; -using System.Collections.ObjectModel; -using System.Runtime.Serialization; -using SPMeta2.Attributes; -using SPMeta2.Attributes.Regression; -using SPMeta2.Enumerations; -using SPMeta2.Utils; - -namespace SPMeta2.Definitions.Fields -{ - /// - /// Allows to define and deploy calculated field. - /// - /// - [SPObjectType(SPObjectModelType.SSOM, "Microsoft.SharePoint.SPFieldCalculated", "Microsoft.SharePoint")] - [SPObjectType(SPObjectModelType.CSOM, "Microsoft.SharePoint.Client.FieldCalculated", "Microsoft.SharePoint.Client")] - - [DefaultParentHost(typeof(SiteDefinition))] - [DefaultRootHost(typeof(SiteDefinition))] - - [Serializable] - [DataContract] - [ExpectArrayExtensionMethod] - - [ExpectManyInstances] - - public class CalculatedFieldDefinition : FieldDefinition - { - #region constructors - - public CalculatedFieldDefinition() - { - FieldType = BuiltInFieldTypes.Calculated; - FieldReferences = new Collection(); - - DateFormat = BuiltInDateTimeFieldFormatType.DateOnly; - CurrencyLocaleId = 1033; - } - - #endregion - - #region properties - - [ExpectValidation] - [ExpectRequired] - [DataMember] - public override sealed string FieldType { get; set; } - - [ExpectValidation] - [DataMember] - public override string ValidationMessage - { - get { return string.Empty; } - set { } - } - - [ExpectValidation] - [DataMember] - public override string ValidationFormula - { - get { return string.Empty; } - set { } - } - - [ExpectValidation] - [DataMember] - public int? CurrencyLocaleId { get; set; } - - [ExpectValidation] - [DataMember] - public string DateFormat { get; set; } - - [ExpectValidation] - [DataMember] - public string DisplayFormat { get; set; } - - [ExpectValidation] - [ExpectUpdateAsCalculatedFieldFormula] - [DataMember] - [ExpectNullable] - public string Formula { get; set; } - - [ExpectValidation] - [ExpectUpdateAssCalculatedFieldOutputType] - [DataMember] - public string OutputType { get; set; } - - [ExpectValidation] - //[ExpectUpdate] - [DataMember] - public bool? ShowAsPercentage { get; set; } - - [ExpectValidation] - //[ExpectUpdateAssCalculatedFieldReferences] - [DataMember] - public Collection FieldReferences { get; set; } - - [ExpectValidation] - [DataMember] - public override string DefaultValue - { - get - { - // #SPBUG - // Calculated field MUST return string.Empty to avoid setting DefaultValue for field. - // SharePoint drive crazy if calculated field has default value. FieldRefs would be NULL, tons of failures would be there. - return string.Empty; - } - set { } - } - - #endregion - - #region methods - - public override string ToString() - { - return new ToStringResult(this, base.ToString()) - .ToString(); - } - - #endregion - } -} +using System; +using System.Collections.ObjectModel; +using System.Runtime.Serialization; +using SPMeta2.Attributes; +using SPMeta2.Attributes.Regression; +using SPMeta2.Enumerations; +using SPMeta2.Utils; + +namespace SPMeta2.Definitions.Fields +{ + /// + /// Allows to define and deploy calculated field. + /// + /// + [SPObjectType(SPObjectModelType.SSOM, "Microsoft.SharePoint.SPFieldCalculated", "Microsoft.SharePoint")] + [SPObjectType(SPObjectModelType.CSOM, "Microsoft.SharePoint.Client.FieldCalculated", "Microsoft.SharePoint.Client")] + + [DefaultParentHost(typeof(SiteDefinition))] + [DefaultRootHost(typeof(SiteDefinition))] + + [Serializable] + [DataContract] + [ExpectArrayExtensionMethod] + + [ExpectManyInstances] + + public class CalculatedFieldDefinition : FieldDefinition + { + #region constructors + + public CalculatedFieldDefinition() + { + FieldType = BuiltInFieldTypes.Calculated; + FieldReferences = new Collection(); + + DateFormat = BuiltInDateTimeFieldFormatType.DateOnly; + CurrencyLocaleId = 1033; + } + + #endregion + + #region properties + + [ExpectValidation] + [ExpectRequired] + [DataMember] + public override sealed string FieldType { get; set; } + + [ExpectValidation] + [DataMember] + public override string ValidationMessage + { + get { return string.Empty; } + set { } + } + + [ExpectValidation] + [DataMember] + public override string ValidationFormula + { + get { return string.Empty; } + set { } + } + + [ExpectValidation] + [DataMember] + public int? CurrencyLocaleId { get; set; } + + [ExpectValidation] + [DataMember] + [ExpectUpdateAsDateFormat] + public string DateFormat { get; set; } + + [ExpectValidation] + [DataMember] + public string DisplayFormat { get; set; } + + [ExpectValidation] + [ExpectUpdateAsCalculatedFieldFormula] + [DataMember] + [ExpectNullable] + public string Formula { get; set; } + + [ExpectValidation] + [ExpectUpdateAssCalculatedFieldOutputType] + [DataMember] + public string OutputType { get; set; } + + [ExpectValidation] + //[ExpectUpdate] + [DataMember] + public bool? ShowAsPercentage { get; set; } + + [ExpectValidation] + //[ExpectUpdateAssCalculatedFieldReferences] + [DataMember] + public Collection FieldReferences { get; set; } + + [ExpectValidation] + [DataMember] + public override string DefaultValue + { + get + { + // #SPBUG + // Calculated field MUST return string.Empty to avoid setting DefaultValue for field. + // SharePoint drive crazy if calculated field has default value. FieldRefs would be NULL, tons of failures would be there. + return string.Empty; + } + set { } + } + + #endregion + + #region methods + + public override string ToString() + { + return new ToStringResult(this, base.ToString()) + .ToString(); + } + + #endregion + } +} From 6195faea6b1706d48dc0ff2d6da1560ef6423de3 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Wed, 29 Mar 2017 07:23:01 -0700 Subject: [PATCH 2/3] + fixed ListItemAllFields error for WebPart Pages not in lists #984 + added CanDeploy_WebpartTo_VideoContentType_VideoPlayerPage + CSOM fix, green tests --- .../ModelHandlers/FolderModelHandler.cs | 25 ++- .../ModelHandlers/ModuleFileModelHandler.cs | 6 - .../ModelHandlers/WebPartModelHandler.cs | 6 + .../ModelHosts/FolderModelHost.cs | 54 +++---- .../ModelHosts/ListItemModelHost.cs | 4 +- .../Impl/Scenarios/WebpartScenariosTest.cs | 145 +++++++++++++----- 6 files changed, 170 insertions(+), 70 deletions(-) diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/FolderModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/FolderModelHandler.cs index 438d11eaf..330241166 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/FolderModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/FolderModelHandler.cs @@ -43,10 +43,33 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon var folderModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); var folderModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var isSpecialFolderContext = false; + if (folderModelHost.CurrentList != null && folderModelHost.CurrentList.BaseType == BaseType.DocumentLibrary) { var currentFolder = EnsureLibraryFolder(folderModelHost, folderModel); + // preload props to identify 'special folder' + // once done, pass down via model host + if (folderModel.Name.ToLower() == "forms") + { + currentFolder.Context.Load(currentFolder, f => f.Properties); + currentFolder.Context.ExecuteQueryWithTrace(); + + var doesFileHaveListItem = + //Forms folders + !(currentFolder != null + && + (currentFolder.Properties.FieldValues.ContainsKey("vti_winfileattribs") + && + currentFolder.Properties.FieldValues["vti_winfileattribs"].ToString() == + "00000012")); + + isSpecialFolderContext = !doesFileHaveListItem; + + folderModelHost.IsSpecialFolderContext = isSpecialFolderContext; + } + var newContext = ModelHostBase.Inherit(folderModelHost, c => { c.CurrentList = folderModelHost.CurrentList; @@ -383,7 +406,7 @@ private Folder EnsureLibraryFolder(FolderModelHost folderModelHost, FolderDefini var currentFolderItem = currentFolder.ListItemAllFields; // could be NULL, in the /Forms or other hidden folders - if (currentFolderItem != null + if (currentFolderItem != null && currentFolderItem.ServerObjectIsNull != null && !currentFolderItem.ServerObjectIsNull.Value) { diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ModuleFileModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ModuleFileModelHandler.cs index 5e4afb9a2..359de0415 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ModuleFileModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ModuleFileModelHandler.cs @@ -327,13 +327,7 @@ public static void WithSafeFileOperation(List list, File file, if (file != null) { context.Load(file, f => f.Exists); - context.Load(file, f => f.ListItemAllFields); //SergeiSnitko. Need to be loaded to get if object is null context.ExecuteQueryWithTrace(); - //SergeiSnitko. I don't know all logic based on doesFileHasListItem. So I fill doesFileHasListItem by the real value - //of ListItem existing only if doesFileHasListItem is true. This action helps to prevent exceptions on web part provision - //on the page without ListItem not only under Forms folder (for example Forms/ContentTypeName/videoplayerpage.aspx fires exception) - doesFileHasListItem = doesFileHasListItem ? !(bool)file.ListItemAllFields.ServerObjectIsNull : doesFileHasListItem; - if (file.Exists) { diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/WebPartModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/WebPartModelHandler.cs index ff08745f1..0d6e61791 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/WebPartModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/WebPartModelHandler.cs @@ -400,6 +400,12 @@ public override void DeployModel(object modelHost, DefinitionBase model) listItemModelHost.HostFolder.Properties.FieldValues["vti_winfileattribs"].ToString() == "00000012")); + // is parent /forms folder or nay other special page? + if (doesFileHasListItem) + { + doesFileHasListItem = !listItemModelHost.IsSpecialFolderContext; + } + #endif #if NET35 diff --git a/SPMeta2/SPMeta2.CSOM/ModelHosts/FolderModelHost.cs b/SPMeta2/SPMeta2.CSOM/ModelHosts/FolderModelHost.cs index a87f0944c..f3c966c81 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHosts/FolderModelHost.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHosts/FolderModelHost.cs @@ -1,26 +1,28 @@ -using Microsoft.SharePoint.Client; - -namespace SPMeta2.CSOM.ModelHosts -{ - public class FolderModelHost : CSOMModelHostBase - { - #region properties - - public List CurrentList { get; set; } - public ListItem CurrentListItem { get; set; } - - public Folder CurrentListFolder { get; set; } - - public Web CurrentWeb { get; set; } - public Folder CurrentWebFolder { get; set; } - - public ContentType CurrentContentType { get; set; } - public Folder CurrentContentTypeFolder { get; set; } - - //public Folder Folder { get; set; } - //public List List { get; set; } - //public Web Web { get; set; } - - #endregion - } -} +using Microsoft.SharePoint.Client; + +namespace SPMeta2.CSOM.ModelHosts +{ + public class FolderModelHost : CSOMModelHostBase + { + #region properties + + public List CurrentList { get; set; } + public ListItem CurrentListItem { get; set; } + + public Folder CurrentListFolder { get; set; } + + public Web CurrentWeb { get; set; } + public Folder CurrentWebFolder { get; set; } + + public ContentType CurrentContentType { get; set; } + public Folder CurrentContentTypeFolder { get; set; } + + //public Folder Folder { get; set; } + //public List List { get; set; } + //public Web Web { get; set; } + + public bool IsSpecialFolderContext { get; set; } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.CSOM/ModelHosts/ListItemModelHost.cs b/SPMeta2/SPMeta2.CSOM/ModelHosts/ListItemModelHost.cs index 8b710e0cb..ffab00c29 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHosts/ListItemModelHost.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHosts/ListItemModelHost.cs @@ -17,6 +17,8 @@ public class ListItemModelHost : CSOMModelHostBase #endregion - public List HostList { get; set; } + public List HostList { get; set; } + + public bool IsSpecialFolderContext { get; set; } } } diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebpartScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebpartScenariosTest.cs index 1f069bb15..0a1288e2d 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebpartScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebpartScenariosTest.cs @@ -148,6 +148,7 @@ public void CanDeploy_Random_V3_Webpart_WithAllChrome() [TestMethod] [TestCategory("Regression.Scenarios.Webparts.ListViews")] + [TestCategory("Regression.Scenarios.Webparts.Hosts")] public void CanDeploy_WebpartTo_UploadForm_InLibrary() { var model = SPMeta2Model @@ -170,6 +171,7 @@ public void CanDeploy_WebpartTo_UploadForm_InLibrary() [TestMethod] [TestCategory("Regression.Scenarios.Webparts.ListViews")] + [TestCategory("Regression.Scenarios.Webparts.Hosts")] public void CanDeploy_WebpartTo_OOTBListViews_InLibrary() { var model = SPMeta2Model @@ -205,6 +207,7 @@ public void CanDeploy_WebpartTo_OOTBListViews_InLibrary() } [TestMethod] + [TestCategory("Regression.Scenarios.Webparts.Hosts")] [TestCategory("Regression.Scenarios.Webparts.ListViews")] public void CanDeploy_WebpartTo_CustomListViews_InLibrary() { @@ -244,6 +247,7 @@ public void CanDeploy_WebpartTo_CustomListViews_InLibrary() [TestMethod] [TestCategory("Regression.Scenarios.Webparts.ListViews")] + [TestCategory("Regression.Scenarios.Webparts.Hosts")] public void CanDeploy_WebpartTo_OOTBListViews_InList() { var model = SPMeta2Model @@ -289,6 +293,7 @@ public void CanDeploy_WebpartTo_OOTBListViews_InList() [TestMethod] [TestCategory("Regression.Scenarios.Webparts.ListViews")] + [TestCategory("Regression.Scenarios.Webparts.Hosts")] public void CanDeploy_WebpartTo_CustomListViews_InList() { var model = SPMeta2Model @@ -331,6 +336,7 @@ public void CanDeploy_WebpartTo_CustomListViews_InList() [TestMethod] [TestCategory("Regression.Scenarios.Webparts.ListForms")] + [TestCategory("Regression.Scenarios.Webparts.Hosts")] public void CanDeploy_WebpartTo_ListForm_InLibrary() { var model = SPMeta2Model @@ -361,6 +367,7 @@ public void CanDeploy_WebpartTo_ListForm_InLibrary() } [TestMethod] + [TestCategory("Regression.Scenarios.Webparts.Hosts")] [TestCategory("Regression.Scenarios.Webparts.ListForms")] public void CanDeploy_WebpartTo_ListForm_InList() { @@ -431,7 +438,8 @@ public void CanDeploy_Webpart_With_AuthorizationFilter() [TestMethod] [TestCategory("Regression.Scenarios.Webparts")] - public void CanDeploy_WebpartToWebpartPage() + [TestCategory("Regression.Scenarios.Webparts.Hosts")] + public void CanDeploy_WebpartTo_WebpartPage() { var model = SPMeta2Model .NewWebModel(web => @@ -461,7 +469,8 @@ public void CanDeploy_WebpartToWebpartPage() [TestMethod] [TestCategory("Regression.Scenarios.Webparts")] - public void CanDeploy_WebpartToWebpartPage_WithCustomPageLayout() + [TestCategory("Regression.Scenarios.Webparts.Hosts")] + public void CanDeploy_WebpartTo_WebpartPage_WithCustomPageLayout() { var webPartPage1 = ModelGeneratorService.GetRandomDefinition(def => { @@ -538,40 +547,100 @@ public void CanDeploy_Webpart_WithTitleUrl_WithTokens() [TestMethod] [TestCategory("Regression.Scenarios.Webparts")] - public void CanDeploy_WebpartToPublishingPageWebPartZone() + [TestCategory("Regression.Scenarios.Webparts.Hosts")] + public void CanDeploy_WebpartTo_VideoContentType_VideoPlayerPage() { - var siteModel = SPMeta2Model - .NewSiteModel(site => - { - site - .AddSiteFeature(RegSiteFeatures.Publishing); - }); + // aiming to deploy a web part to the following page with in a library + // forms/videocontenttype/videoplayerpage.aspx + + var listDef = ModelGeneratorService.GetRandomDefinition(def => + { + def.ContentTypesEnabled = true; + def.TemplateType = BuiltInListTemplateTypeId.DocumentLibrary; + }); + + var contentTypeName = "Video"; + var contentTypeLinkDef = new ContentTypeLinkDefinition + { + ContentTypeName = contentTypeName, + ContentTypeId = BuiltInSiteContentTypeId.Video + }; + + var formsFolder = new FolderDefinition + { + Name = "Forms" + }; + + var contentTypeFolder = new FolderDefinition + { + Name = contentTypeName + }; + + var pageDefinition = new WebPartPageDefinition + { + FileName = "videoplayerpage.aspx", + PageLayoutTemplate = BuiltInWebPartPageTemplates.spstd1, + NeedOverride = false + }; + + var model = SPMeta2Model.NewWebModel(web => + { + web.AddList(listDef, list => + { + list.AddContentTypeLink(contentTypeLinkDef); + + list.AddFolder(formsFolder, forms => + { + forms.AddFolder(contentTypeFolder, folder => + { + folder.AddHostWebPartPage(pageDefinition, page => + { + page.AddRandomWebpart(); + page.AddRandomWebpart(); + page.AddRandomWebpart(); + }); + }); + }); + }); + }); + + TestModel(model); + } + + [TestMethod] + [TestCategory("Regression.Scenarios.Webparts")] + [TestCategory("Regression.Scenarios.Webparts.Hosts")] + public void CanDeploy_WebpartTo_PublishingPageWebPartZone() + { + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSiteFeature(RegSiteFeatures.Publishing); + }); TestModel(siteModel); - var webModel = SPMeta2Model - .NewWebModel(web => - { - web - .AddWebFeature(RegWebFeatures.Publishing) - .AddHostList(BuiltInListDefinitions.Pages, list => - { - list - .AddRandomPublishingPage(page => - { - page - .AddRandomWebpart() - .AddRandomWebpart(); - }) - .AddRandomPublishingPage(page => - { - page - .AddRandomWebpart() - .AddRandomWebpart(); - }); - }); + var webModel = SPMeta2Model.NewWebModel(web => + { + web + .AddWebFeature(RegWebFeatures.Publishing) + .AddHostList(BuiltInListDefinitions.Pages, list => + { + list + .AddRandomPublishingPage(page => + { + page + .AddRandomWebpart() + .AddRandomWebpart(); + }) + .AddRandomPublishingPage(page => + { + page + .AddRandomWebpart() + .AddRandomWebpart(); + }); + }); - }); + }); TestModel(webModel); } @@ -579,7 +648,8 @@ public void CanDeploy_WebpartToPublishingPageWebPartZone() [TestMethod] [TestCategory("Regression.Scenarios.Webparts")] - public void CanDeploy_WebpartToPublishingPageContent() + [TestCategory("Regression.Scenarios.Webparts.Hosts")] + public void CanDeploy_WebpartTo_PublishingPageContent() { var webModel = SPMeta2Model .NewWebModel(web => @@ -656,7 +726,8 @@ public void CanDeploy_WebpartToPublishingPageContent() [TestMethod] [TestCategory("Regression.Scenarios.Webparts")] - public void CanDeploy_WebpartToWikiPageContent_AsItIs() + [TestCategory("Regression.Scenarios.Webparts.Hosts")] + public void CanDeploy_WebpartTo_WikiPageContent_AsItIs() { // Some web part provision on wiki page give empty markup // https://github.com/SubPointSolutions/spmeta2/issues/693 @@ -683,7 +754,7 @@ public void CanDeploy_WebpartToWikiPageContent_AsItIs() [TestMethod] [TestCategory("Regression.Scenarios.Webparts")] - public void CanDeploy_ScriptEditorToWikiPageContent_As_AddToPageContent() + public void CanDeploy_ScriptEditorTo_WikiPageContent_As_AddToPageContent() { // Some web part provision on wiki page give empty markup // https://github.com/SubPointSolutions/spmeta2/issues/693 @@ -735,7 +806,8 @@ public void CanDeploy_ScriptEditorToWikiPageContent_As_AddToPageContent() [TestMethod] [TestCategory("Regression.Scenarios.Webparts")] - public void CanDeploy_WebpartToWikiPageContent_As_AddToPageContent() + [TestCategory("Regression.Scenarios.Webparts.Hosts")] + public void CanDeploy_WebpartTo_WikiPageContent_As_AddToPageContent() { // Some web part provision on wiki page give empty markup // https://github.com/SubPointSolutions/spmeta2/issues/693 @@ -800,7 +872,8 @@ public void CanDeploy_WebpartToWikiPageContent_As_AddToPageContent() [TestMethod] [TestCategory("Regression.Scenarios.Webparts")] - public void CanDeploy_WebpartToWikiPageContent() + [TestCategory("Regression.Scenarios.Webparts.Hosts")] + public void CanDeploy_WebpartTo_WikiPageContent() { var webModel = SPMeta2Model .NewWebModel(web => From 1ffb9de55c5785d2c2cc10728844ec26ad9964ea Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Wed, 29 Mar 2017 07:54:28 -0700 Subject: [PATCH 3/3] + NET35 fix --- .../ModelHandlers/FolderModelHandler.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/FolderModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/FolderModelHandler.cs index 330241166..23e4949cf 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/FolderModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/FolderModelHandler.cs @@ -53,18 +53,21 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon // once done, pass down via model host if (folderModel.Name.ToLower() == "forms") { + var doesFileHaveListItem = false; + +#if !NET35 currentFolder.Context.Load(currentFolder, f => f.Properties); currentFolder.Context.ExecuteQueryWithTrace(); - var doesFileHaveListItem = - //Forms folders - !(currentFolder != null - && - (currentFolder.Properties.FieldValues.ContainsKey("vti_winfileattribs") + doesFileHaveListItem = !(currentFolder != null && - currentFolder.Properties.FieldValues["vti_winfileattribs"].ToString() == - "00000012")); + (currentFolder.Properties.FieldValues.ContainsKey("vti_winfileattribs") + && + currentFolder.Properties.FieldValues["vti_winfileattribs"].ToString() == + "00000012")); + +#endif isSpecialFolderContext = !doesFileHaveListItem; folderModelHost.IsSpecialFolderContext = isSpecialFolderContext;