diff --git a/src/XrmMockup365/Internal/EntityMatcher.cs b/src/XrmMockup365/Internal/EntityMatcher.cs index f6964fb3..69d216ea 100644 --- a/src/XrmMockup365/Internal/EntityMatcher.cs +++ b/src/XrmMockup365/Internal/EntityMatcher.cs @@ -126,6 +126,10 @@ private static bool Matches(object attr, ConditionOperator op, IEnumerable _)) == string.Join(",", optionSetValueCollection.ToList().Select(_ => _.Value).OrderBy(_ => _)); + } return values.Contains(ValueConverter.ConvertTo(attr, values.FirstOrDefault()?.GetType())); case ConditionOperator.NotIn: diff --git a/tests/XrmMockup365Test/TestFetchConditionOperators.cs b/tests/XrmMockup365Test/TestFetchConditionOperators.cs index 34d1c077..51d2ee7a 100644 --- a/tests/XrmMockup365Test/TestFetchConditionOperators.cs +++ b/tests/XrmMockup365Test/TestFetchConditionOperators.cs @@ -3,6 +3,8 @@ using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Query; using System; +using System.Collections.Generic; +using System.Linq; using Xunit; namespace DG.XrmMockupTest { @@ -10,6 +12,127 @@ public class TestFetchConditionOperators : UnitTestBase { public TestFetchConditionOperators(XrmMockupFixture fixture) : base(fixture) { + CreateAccount(new List { Account_dg_Multiselect.Item1 }); + CreateAccount(new List { Account_dg_Multiselect.Item2 }); + CreateAccount(new List { Account_dg_Multiselect.Item3 }); + CreateAccount(new List { Account_dg_Multiselect.Item4 }); + CreateAccount(new List { Account_dg_Multiselect.checkmark }); + CreateAccount(new List { Account_dg_Multiselect.Item }); + CreateAccount(new List { Account_dg_Multiselect.Item1, Account_dg_Multiselect.Item2 }); + CreateAccount(new List { Account_dg_Multiselect.Item1, Account_dg_Multiselect.Item3 }); + CreateAccount(new List { Account_dg_Multiselect.Item1, Account_dg_Multiselect.Item4 }); + CreateAccount(new List { Account_dg_Multiselect.Item2, Account_dg_Multiselect.Item3 }); + CreateAccount(new List { Account_dg_Multiselect.Item2, Account_dg_Multiselect.Item4 }); + CreateAccount(new List { Account_dg_Multiselect.Item3, Account_dg_Multiselect.Item4 }); + CreateAccount(new List { Account_dg_Multiselect.Item1, Account_dg_Multiselect.Item2, Account_dg_Multiselect.Item3 }); + CreateAccount(new List { Account_dg_Multiselect.Item1, Account_dg_Multiselect.Item2, Account_dg_Multiselect.Item4 }); + CreateAccount(new List { Account_dg_Multiselect.Item1, Account_dg_Multiselect.Item3, Account_dg_Multiselect.Item4 }); + CreateAccount(new List { Account_dg_Multiselect.Item2, Account_dg_Multiselect.Item3, Account_dg_Multiselect.Item4 }); + CreateAccount(new List { Account_dg_Multiselect.Item1, Account_dg_Multiselect.Item2, Account_dg_Multiselect.Item3, Account_dg_Multiselect.Item4 }); + + void CreateAccount(List list) + { + for (int i = 0; i < 2; i++) + { + list.Reverse(); + var account = new Account(); + account.dg_Multiselect = list; + account.Id = orgAdminUIService.Create(account); + } + } + } + + private class MultiselectCases : TheoryData> + { + public MultiselectCases() + { + Add(new List { Account_dg_Multiselect.Item1 }); + Add(new List { Account_dg_Multiselect.Item2 }); + Add(new List { Account_dg_Multiselect.Item3 }); + Add(new List { Account_dg_Multiselect.Item4 }); + Add(new List { Account_dg_Multiselect.Item1, Account_dg_Multiselect.Item2 }); + Add(new List { Account_dg_Multiselect.Item1, Account_dg_Multiselect.Item3 }); + Add(new List { Account_dg_Multiselect.Item1, Account_dg_Multiselect.Item4 }); + Add(new List { Account_dg_Multiselect.Item2, Account_dg_Multiselect.Item3 }); + Add(new List { Account_dg_Multiselect.Item2, Account_dg_Multiselect.Item4 }); + Add(new List { Account_dg_Multiselect.Item3, Account_dg_Multiselect.Item4 }); + Add(new List { Account_dg_Multiselect.Item1, Account_dg_Multiselect.Item2, Account_dg_Multiselect.Item3 }); + Add(new List { Account_dg_Multiselect.Item1, Account_dg_Multiselect.Item2, Account_dg_Multiselect.Item4 }); + Add(new List { Account_dg_Multiselect.Item1, Account_dg_Multiselect.Item3, Account_dg_Multiselect.Item4 }); + Add(new List { Account_dg_Multiselect.Item2, Account_dg_Multiselect.Item3, Account_dg_Multiselect.Item4 }); + Add(new List { Account_dg_Multiselect.Item1, Account_dg_Multiselect.Item2, Account_dg_Multiselect.Item3, Account_dg_Multiselect.Item4 }); + } + } + + [Theory] + [ClassData(typeof(MultiselectCases))] + public void TestMultiselectConditionOperatorIn(List optionSetValueCollection) + { + using (var context = new Xrm(orgAdminUIService)) + { + var optionSetValues = optionSetValueCollection.Select(_ => (int)_).ToList(); + for (int i = 0; i < 2; i++) + { + optionSetValues.Reverse(); + string values = string.Empty; + foreach (var value in optionSetValues) + { + values += $"{value}"; + } + + var fetchXml = + $@" + + + + {values} + + + + "; + EntityCollection result = Fetch(fetchXml); + Assert.Equal(2, result.Entities.Count); + } + } + } + + [Theory] + [ClassData(typeof(MultiselectCases))] + public void TestMultiselectConditionOperatorNotIn(List optionSetValueCollection) + { + using (var context = new Xrm(orgAdminUIService)) + { + var fetchXmlCount = + $@" + + + + "; + var count = Fetch(fetchXmlCount).Entities.Count; + var optionSetValues = optionSetValueCollection.Select(_ => (int)_).ToList(); + for (int i = 0; i < 2; i++) + { + optionSetValues.Reverse(); + string values = string.Empty; + foreach (var value in optionSetValues) + { + values += $"{value}"; + } + + var fetchXml = + $@" + + + + {values} + + + + "; + EntityCollection result = Fetch(fetchXml); + Assert.Equal(count - 2, result.Entities.Count); + } + } } [Theory] diff --git a/tests/XrmMockup365Test/TestFormulaFields.cs b/tests/XrmMockup365Test/TestFormulaFields.cs index 577f316c..cc537649 100644 --- a/tests/XrmMockup365Test/TestFormulaFields.cs +++ b/tests/XrmMockup365Test/TestFormulaFields.cs @@ -54,26 +54,36 @@ public async TTask CanEvaluateExpressionWithRelatedEntity() [ClassData(typeof(FunctionCases))] public async TTask CanEvaluateFunction(string formula, object expected) { - var evaluator = new FormulaFieldEvaluator(serviceFactory); - var result = await evaluator.Evaluate(formula, new Account(), TimeSpan.Zero); - - if (result is ErrorValue error && expected is string errorString) - { - var errorMessage = string.Join("\n", error.Errors.Select(e => e.Message)); - Assert.Contains(errorString, errorMessage); - } - else if (result is DateTime resultDateTime) + var targetCulture = new CultureInfo("en-US"); + var originalUICulture = CultureInfo.CurrentUICulture; + try { - var expectedDateTime = (expected is DateTime dt) - ? dt - : (expected is "DateTime.Now") - ? DateTime.Now - : throw new InvalidOperationException("Expected value is not a DateTime or 'DateTime.Now'"); + CultureInfo.CurrentUICulture = targetCulture; + var evaluator = new FormulaFieldEvaluator(serviceFactory); + var result = await evaluator.Evaluate(formula, new Account(), TimeSpan.Zero); + + if (result is ErrorValue error && expected is string errorString) + { + var errorMessage = string.Join("\n", error.Errors.Select(e => e.Message)); + Assert.Contains(errorString, errorMessage); + } + else if (result is DateTime resultDateTime) + { + var expectedDateTime = (expected is DateTime dt) + ? dt + : (expected is "DateTime.Now") + ? DateTime.Now + : throw new InvalidOperationException("Expected value is not a DateTime or 'DateTime.Now'"); Assert.Equal(expectedDateTime, resultDateTime, TimeSpan.FromSeconds(1)); + } + else + { + Assert.Equal(expected, result); + } } - else + finally { - Assert.Equal(expected, result); + CultureInfo.CurrentUICulture = originalUICulture; } }