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();
        }
예제 #2
0
        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();
        }
예제 #4
0
        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));
        }
예제 #5
0
        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();
        }
예제 #6
0
        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();
        }