public void TestMockClient_CancellationSupport() { Cities.CityDomainContext dp = new Cities.CityDomainContext(new CitiesMockDomainClient()); bool domainClientQueryCompleted = false; dp.DomainClient.BeginQuery( new EntityQuery<Cities.City>(dp.DomainClient, "GetCities", null, true, false), delegate(IAsyncResult getCitiesAsyncResult) { ExceptionHelper.ExpectException<NotSupportedException>(delegate { dp.DomainClient.CancelQuery(getCitiesAsyncResult); }, string.Format(CultureInfo.CurrentCulture, Resource.DomainClient_CancellationNotSupported, typeof(CitiesMockDomainClient).FullName)); domainClientQueryCompleted = true; }, null); EnqueueConditional(() => domainClientQueryCompleted); EnqueueCallback(delegate { var query = dp.GetCitiesQuery(); LoadOperation lo = dp.Load(query, false); Assert.IsFalse(lo.CanCancel, "Cancellation should not be supported."); Assert.IsFalse(dp.DomainClient.SupportsCancellation, "Cancellation should not be supported."); ExceptionHelper.ExpectException<NotSupportedException>(delegate { lo.Cancel(); }, string.Format(CultureInfo.CurrentCulture, Resources.AsyncOperation_CancelNotSupported)); }); EnqueueTestComplete(); }
public void TestMockClient_Query() { Cities.CityDomainContext dp = new Cities.CityDomainContext(new CitiesMockDomainClient()); string myState = "Test User State"; var query = dp.GetCitiesQuery().Where(p => p.StateName == "WA").OrderBy(p => p.CountyName).Take(4); LoadOperation lo = dp.Load(query, null, myState); lo.Completed += (o, e) => { LoadOperation loadOp = (LoadOperation)o; if (loadOp.HasError) { loadOp.MarkErrorAsHandled(); } }; EnqueueConditional(delegate { return(lo.IsComplete); }); EnqueueCallback(delegate { Assert.IsNull(lo.Error); Assert.AreEqual(4, dp.Cities.Count); Assert.IsTrue(dp.Cities.All(p => p.StateName == "WA")); Assert.AreEqual(myState, lo.UserState); }); EnqueueTestComplete(); }
public void TestMockClient_Query() { Cities.CityDomainContext dp = new Cities.CityDomainContext(new CitiesMockDomainClient()); string myState = "Test User State"; var query = dp.GetCitiesQuery().Where(p => p.StateName == "WA").OrderBy(p => p.CountyName).Take(4); LoadOperation lo = dp.Load(query, null, myState); lo.Completed += (o, e) => { LoadOperation loadOp = (LoadOperation)o; if (loadOp.HasError) { loadOp.MarkErrorAsHandled(); } }; EnqueueConditional(delegate { return lo.IsComplete; }); EnqueueCallback(delegate { Assert.IsNull(lo.Error); Assert.AreEqual(4, dp.Cities.Count); Assert.IsTrue(dp.Cities.All(p => p.StateName == "WA")); Assert.AreEqual(myState, lo.UserState); }); EnqueueTestComplete(); }
public void TestMockClient_CancellationSupport() { Cities.CityDomainContext dp = new Cities.CityDomainContext(new CitiesMockDomainClient()); var query = dp.GetCitiesQuery(); LoadOperation lo = dp.Load(query, false); Assert.IsFalse(lo.CanCancel, "Cancellation should not be supported."); Assert.IsFalse(dp.DomainClient.SupportsCancellation, "Cancellation should not be supported."); ExceptionHelper.ExpectException <NotSupportedException>(delegate { lo.Cancel(); }, string.Format(CultureInfo.CurrentCulture, Resources.AsyncOperation_CancelNotSupported)); }
public void TestMockClient_Invoke() { Cities.CityDomainContext dp = new Cities.CityDomainContext(new CitiesMockDomainClient()); string myState = "Test User State"; InvokeOperation invoke = dp.Echo("TestInvoke", TestHelperMethods.DefaultOperationAction, myState); EnqueueConditional(delegate { return(invoke.IsComplete); }); EnqueueCallback(delegate { Assert.IsNull(invoke.Error); Assert.AreSame(myState, invoke.UserState); Assert.AreEqual("Echo: TestInvoke", invoke.Value); }); EnqueueTestComplete(); }
public void TestMockClient_Submit() { Cities.CityDomainContext dp = new Cities.CityDomainContext(new CitiesMockDomainClient()); string myState = "Test User State"; Cities.Zip newZip = new Cities.Zip { Code = 93551, FourDigit = 1234, CityName = "Issaquah", StateName = "Issaquah" }; dp.Zips.Add(newZip); SubmitOperation so = dp.SubmitChanges(TestHelperMethods.DefaultOperationAction, null); EnqueueConditional(delegate { return(so.IsComplete); }); EnqueueCallback(delegate { // verify that validation logic is run Assert.IsNotNull(so.Error); Assert.AreSame(newZip, so.EntitiesInError.Single()); // fix by setting the Name newZip.StateName = "WA"; so = dp.SubmitChanges(null, myState); }); EnqueueConditional(delegate { return(so.IsComplete); }); EnqueueCallback(delegate { Assert.IsNull(so.Error); Assert.AreEqual(myState, so.UserState); }); EnqueueTestComplete(); }
public void CancelEdit_Restores_ValidationErrors_ForUnmodifiedEntity() { Cities.CityDomainContext dp = new Cities.CityDomainContext(TestURIs.Cities); // Abs URI so runs on desktop too LoadOperation lo = dp.Load(dp.GetCitiesQuery(), false); EnqueueConditional(() => lo.IsComplete); EnqueueCallback(() => { // Start with an existing, valid entity Cities.City city = dp.Cities.First(); IEditableObject editableCity = (IEditableObject)city; string customEntityError = "Entity-level error that was added manually"; city.ValidationErrors.Add(new ValidationResult(customEntityError)); // We want to add a two-member error manually. When we re-validate ZoneID, the error for CountyName will also go away. string customPropertyError = "Property-level error that was added manually"; city.ValidationErrors.Add(new ValidationResult(customPropertyError, new string[] { "ZoneID", "CountyName" })); Assert.AreEqual<int>(2, city.ValidationErrors.Count, "Error count before editing"); // Edit the city, making changes that will replace the property errors for ZoneID and CountyName (because it was tied to the ZoneID member too) // with new errors, leaving the entity-level error in place. editableCity.BeginEdit(); city.ZoneID = -1; // Out of range city.ZoneName = Cities.CityPropertyValidator.InvalidZoneName; Assert.AreEqual<int>(3, city.ValidationErrors.Count, "Error count before CancelEdit"); INotifyDataErrorInfo notifier = (INotifyDataErrorInfo)city; List<Tuple<string, IEnumerable<ValidationResult>>> errorNotifications = new List<Tuple<string, IEnumerable<ValidationResult>>>(); notifier.ErrorsChanged += (s, e) => { errorNotifications.Add(new Tuple<string, IEnumerable<ValidationResult>>(e.PropertyName, notifier.GetErrors(e.PropertyName).Cast<ValidationResult>())); }; /// When we cancel the edit, the following changes will occur to the validation errors, in no particular order /// - RejectChanges is called, which clears all validation errors, raising ErrorsChanged for ZoneName, ZoneID, and null (entity-level) /// - Resurrection of the manually-added Name/CountyName error /// - Resurrection of the manually-added entity-level error /// /// This results in a total of 6 ErrorsChanged events, with 2 events each for ZoneID and null (entity-level), and 1 each /// for CountyName and ZoneName. /// /// Note that this is different from when we call CancelEdit on an Added or Modified entity, because /// state is restored in one step rather than in two. This difference is acceptable. editableCity.CancelEdit(); // Verify our validation errors count reverted back to the 2 errors we had before editing Assert.AreEqual<int>(2, city.ValidationErrors.Count, "Error count after CancelEdit"); // Verify the entity-level error that we manually added still shows up Assert.AreEqual<string>(customEntityError, city.ValidationErrors.Single(e => e.MemberNames.Count() == 0 || (e.MemberNames.Count() == 1 && string.IsNullOrEmpty(e.MemberNames.Single()))).ErrorMessage, "ErrorMessage after CancelEdit"); // Verify the property-level error that we manually added still shows up Assert.AreEqual<string>(customPropertyError, city.ValidationErrors.Single(e => e.MemberNames.Contains("ZoneID")).ErrorMessage, "ErrorMessage for ZoneID after CancelEdit"); Assert.AreEqual<string>(customPropertyError, city.ValidationErrors.Single(e => e.MemberNames.Contains("CountyName")).ErrorMessage, "ErrorMessage for CountyName after CancelEdit"); // Verify that we got the 6 expected notifications from INotifyDataErrorInfo Assert.AreEqual<int>(6, errorNotifications.Count, "Error notification count"); // Two notifications for Name and null (clearing, and adding), and one for StateName (cleared) and CountyName (added) Assert.AreEqual<int>(2, errorNotifications.Count(e => e.Item1 == "ZoneID"), "Count of ZoneID notifications"); Assert.AreEqual<int>(1, errorNotifications.Count(e => e.Item1 == "ZoneName"), "Count of ZoneName notifications"); Assert.AreEqual<int>(1, errorNotifications.Count(e => e.Item1 == "CountyName"), "Count of CountyName notifications"); Assert.AreEqual<int>(2, errorNotifications.Count(e => string.IsNullOrEmpty(e.Item1)), "Count of entity-level notifications"); // When the first Name and null notifications occurred, there were no errors for either // When the StateName notification occurred, there was no error for that property // When the second Name and null notification occurred, an error had been added for each // When the CountyName notification occurred, there was an error added for that property Assert.AreEqual<int>(0, errorNotifications.First(e => e.Item1 == "ZoneID").Item2.Count(), "Error count for ZoneID at time of first notification"); Assert.AreEqual<int>(0, errorNotifications.First(e => string.IsNullOrEmpty(e.Item1)).Item2.Count(), "Error count for entity errors at time of first notification"); Assert.AreEqual<int>(0, errorNotifications.Single(e => e.Item1 == "ZoneName").Item2.Count(), "Error count for ZoneName at time of notification"); Assert.AreEqual<int>(1, errorNotifications.Where(e => e.Item1 == "ZoneID").Skip(1).First().Item2.Count(), "Error count for ZoneID at time of second notification"); Assert.AreEqual<int>(1, errorNotifications.Where(e => string.IsNullOrEmpty(e.Item1)).Skip(1).First().Item2.Count(), "Error count for entity errors at time of second notification"); Assert.AreEqual<int>(1, errorNotifications.Single(e => e.Item1 == "CountyName").Item2.Count(), "Error count for CountyName at time of notification"); // Verify the manually-added errors were in place at the time of the notifications Assert.AreEqual<string>(customPropertyError, errorNotifications.Where(e => e.Item1 == "ZoneID").Skip(1).First().Item2.Single().ErrorMessage, "ErrorMessage of the ZoneID error when its notification was raised"); Assert.AreEqual<string>(customPropertyError, errorNotifications.Single(e => e.Item1 == "CountyName").Item2.Single().ErrorMessage, "ErrorMessage of the StateName error when its notification was raised"); Assert.AreEqual<string>(customEntityError, errorNotifications.Where(e => string.IsNullOrEmpty(e.Item1)).Skip(1).First().Item2.Single().ErrorMessage, "ErrorMessage of the entity-level error when its notification was raised"); }); EnqueueTestComplete(); }
public void Entity_RevertChanges_EndEdit_Clears_Entity_ValidationErrors() { Cities.CityDomainContext dp = new Cities.CityDomainContext(TestURIs.Cities); // Abs URI so runs on desktop too LoadOperation lo = dp.Load(dp.GetCitiesQuery(), false); EnqueueConditional(() => lo.IsComplete); EnqueueCallback(() => { Cities.City city = dp.Cities.First(); IEditableObject editableCity = (IEditableObject)city; // Make the entity have entity-level validation errors editableCity.BeginEdit(); city.MakeEntityValidationFail = true; editableCity.EndEdit(); Assert.AreEqual<int>(1, city.ValidateCityCallCount, "Our entity-level validation should have been called"); Assert.AreEqual<int>(1, city.ValidationErrors.Count, "We should have a validation error after the first EndEdit"); Assert.IsTrue(city.HasValidationErrors, "HasValidationErrors after the first EndEdit"); // Make the entity have no entity-level errors editableCity.BeginEdit(); city.MakeEntityValidationFail = false; city.ValidateCityCallCount = 0; // reset the call count editableCity.EndEdit(); Assert.AreEqual<int>(1, city.ValidateCityCallCount, "Our entity-level validation should have been called"); Assert.AreEqual<int>(0, city.ValidationErrors.Count, "ValidationErrors should be cleared after the second EndEdit"); Assert.IsFalse(city.HasValidationErrors, "HasValidationErrors after the second EndEdit"); }); EnqueueTestComplete(); }
public void Entity_RevertChanges_EndEdit_Clears_Property_ValidationErrors() { Cities.CityDomainContext dp = new Cities.CityDomainContext(TestURIs.Cities); // Abs URI so runs on desktop too LoadOperation lo = dp.Load(dp.GetCitiesQuery(), false); EnqueueConditional(() => lo.IsComplete); EnqueueCallback(() => { Cities.City city = dp.Cities.First(); IEditableObject editableCity = (IEditableObject)city; string originalName = city.Name; // Edit the entity to give it property-level validation errors editableCity.BeginEdit(); city.Name = null; editableCity.EndEdit(); Assert.AreEqual<int>(1, city.ValidationErrors.Count, "We should have a validation error after the first EndEdit"); Assert.IsTrue(city.HasValidationErrors, "HasValidationErrors after the first EndEdit"); // Revert the changes so that it doesn't have property-level validation errors anymore editableCity.BeginEdit(); city.Name = originalName; editableCity.EndEdit(); Assert.AreEqual<int>(0, city.ValidationErrors.Count, "ValidationErrors should be cleared after the second EndEdit"); Assert.IsFalse(city.HasValidationErrors, "HasValidationErrors after the second EndEdit"); }); EnqueueTestComplete(); }
public void Entity_RejectChanges_Clears_ValidationErrors() { // This test requires an entity that is attached Cities.CityDomainContext domainContext = new Cities.CityDomainContext(); Cities.City entity = new Cities.City(); domainContext.Cities.Add(entity); INotifyDataErrorInfo notifier = (INotifyDataErrorInfo)entity; List<string> actualErrors = new List<string>(); notifier.ErrorsChanged += (s, e) => actualErrors.Add(e.PropertyName); entity.StateName = "Not a State Name"; // Marks the entity as changed and adds a validation result for StateName entity.ValidationErrors.Add(new ValidationResult("Invalid Property Error", new string[] { "Foo" })); entity.ValidationErrors.Add(new ValidationResult("Entity Error", null)); string[] membersNotifed = new string[] { "StateName", "Foo", null }; Assert.IsTrue(actualErrors.OrderBy(s => s).SequenceEqual(membersNotifed.OrderBy(s => s)), "The list of errors when adding errors"); actualErrors.Clear(); ((IRevertibleChangeTracking)entity).RejectChanges(); Assert.IsTrue(actualErrors.OrderBy(s => s).SequenceEqual(membersNotifed.OrderBy(s => s)), "The list of errors when rejecting changes"); }
public void ValidationContextUpdatedForEntityWhenChangedForDomainContext() { Cities.CityDomainContext domainContext = new Cities.CityDomainContext(TestURIs.Cities); Cities.City newCity = new Cities.City(); domainContext.Cities.Add(newCity); // Set up the ValidationContext after adding the entity into the domain context // to ensure that the updated validation context is plumbed through Dictionary<object, object> items = new Dictionary<object, object>(); items.Add("TestMethod", "ValidationContextUsedForPropertyValidation"); ValidationContext providedValidationContext = new ValidationContext(this, null, items); domainContext.ValidationContext = providedValidationContext; bool callbackCalled = false; Action<ValidationContext> assertValidationContext = validationValidationContext => { Assert.AreNotSame(providedValidationContext, validationValidationContext, "The ValidationContext provided to ValidationProperty should not be the same actual instance of the ValidationContext we provided"); Assert.IsTrue(validationValidationContext.Items.ContainsKey("TestMethod"), "The ValidationContext provided should have the items we provided"); Assert.AreEqual(providedValidationContext.Items["TestMethod"], validationValidationContext.Items["TestMethod"], "The ValidationContext provided should have the items we provided"); callbackCalled = true; }; newCity.ValidatePropertyCallback = assertValidationContext; newCity.ValidateCityCallback = assertValidationContext; // Entity-level validation is performed by calling EndEdit with valid properties IEditableObject editableCity = (IEditableObject)newCity; editableCity.BeginEdit(); newCity.Name = "Cincinnati"; newCity.StateName = "OH"; newCity.CountyName = "Hamilton"; editableCity.EndEdit(); Assert.IsTrue(callbackCalled, "Make sure our callback was called to perform the test"); }
public void ValidationContextUsedForPropertyValidation() { Dictionary<object, object> items = new Dictionary<object,object>(); items.Add("TestMethod", "ValidationContextUsedForPropertyValidation"); ValidationContext providedValidationContext = new ValidationContext(this, null, items); Cities.CityDomainContext domainContext = new Cities.CityDomainContext(TestURIs.Cities); domainContext.ValidationContext = providedValidationContext; bool callbackCalled = false; Cities.City newCity = new Cities.City(); domainContext.Cities.Add(newCity); newCity.ValidatePropertyCallback = validationValidationContext => { Assert.AreNotSame(providedValidationContext, validationValidationContext, "The ValidationContext provided to ValidationProperty should not be the same actual instance of the ValidationContext we provided"); Assert.IsTrue(validationValidationContext.Items.ContainsKey("TestMethod"), "The ValidationContext provided should have the items we provided"); Assert.AreEqual(providedValidationContext.Items["TestMethod"], validationValidationContext.Items["TestMethod"], "The ValidationContext provided should have the items we provided"); callbackCalled = true; }; // Set a property, triggering property validation newCity.Name = "Foo"; Assert.IsTrue(callbackCalled, "Make sure our callback was called to perform the test"); }
public void TestMockClient_Submit() { Cities.CityDomainContext dp = new Cities.CityDomainContext(new CitiesMockDomainClient()); string myState = "Test User State"; Cities.Zip newZip = new Cities.Zip { Code = 93551, FourDigit = 1234, CityName = "Issaquah", StateName = "Issaquah" }; dp.Zips.Add(newZip); SubmitOperation so = dp.SubmitChanges(TestHelperMethods.DefaultOperationAction, null); EnqueueConditional(delegate { return so.IsComplete; }); EnqueueCallback(delegate { // verify that validation logic is run Assert.IsNotNull(so.Error); Assert.AreSame(newZip, so.EntitiesInError.Single()); // fix by setting the Name newZip.StateName = "WA"; so = dp.SubmitChanges(null, myState); }); EnqueueConditional(delegate { return so.IsComplete; }); EnqueueCallback(delegate { Assert.IsNull(so.Error); Assert.AreEqual(myState, so.UserState); }); EnqueueTestComplete(); }
public void TestMockClient_Invoke() { Cities.CityDomainContext dp = new Cities.CityDomainContext(new CitiesMockDomainClient()); string myState = "Test User State"; InvokeOperation invoke = dp.Echo("TestInvoke", TestHelperMethods.DefaultOperationAction, myState); EnqueueConditional(delegate { return invoke.IsComplete; }); EnqueueCallback(delegate { Assert.IsNull(invoke.Error); Assert.AreSame(myState, invoke.UserState); Assert.AreEqual("Echo: TestInvoke", invoke.Value); }); EnqueueTestComplete(); }