public void Inherit_Run_CUD_Update_Derived() { // Inheritance is City <-- CityWithEditHistory <-- CityWithInfo CityDomainContext citiesContext = new CityDomainContext(TestURIs.Cities); DateTime priorLastUpdated = DateTime.Now; // Load all cities, not just derived ones LoadOperation lo = citiesContext.Load(citiesContext.GetCitiesQuery()); SubmitOperation so = null; CityWithInfo cityWithInfo = null; string originalName = null; string originalStateName = null; string originalCountyName = null; // wait for Load to complete EnqueueConditional(() => lo.IsComplete); EnqueueCallback(delegate { cityWithInfo = citiesContext.Cities.OfType <CityWithInfo>().FirstOrDefault(); Assert.IsNotNull(cityWithInfo, "expected to find at least one CityWithInfo entity"); Assert.IsFalse(cityWithInfo.EditHistory.Contains("update"), "Did not expect edit history to be set yet."); originalName = cityWithInfo.Name; originalStateName = cityWithInfo.StateName; originalCountyName = cityWithInfo.CountyName; cityWithInfo.Info = "inserted new info"; so = citiesContext.SubmitChanges(); }); // wait for submit to complete EnqueueConditional(() => so.IsComplete); EnqueueCallback(delegate { if (so.Error != null) { Assert.Fail("Unexpected error on submit: " + so.Error.Message); } // verify entities are auto-synced back to the client as a result of the domain method execution on server CityWithInfo updatedCity = citiesContext.Cities.OfType <CityWithInfo>().SingleOrDefault <CityWithInfo> (c => (c.Name == originalName && c.StateName == originalStateName && c.CountyName == originalCountyName)); Assert.IsNotNull(updatedCity, "Did not find modified City after the submit"); Assert.IsTrue(updatedCity.EditHistory.Contains("update"), "EditHistory was" + updatedCity.EditHistory); Assert.AreEqual("inserted new info", updatedCity.Info, "Updated Info did not get applied"); }); EnqueueTestComplete(); }
public void Inherit_Run_CUD_Insert_Derived() { // Inheritance is City <-- CityWithEditHistory <-- CityWithInfo CityDomainContext citiesContext = new CityDomainContext(TestURIs.Cities); DateTime priorLastUpdated = DateTime.Now; // Load all cities, not just derived ones LoadOperation lo = citiesContext.Load(citiesContext.GetCitiesQuery()); SubmitOperation so = null; // wait for Load to complete EnqueueConditional(() => lo.IsComplete); EnqueueCallback(delegate { CityWithInfo newCity = new CityWithInfo() { Name = "CocoaVille", StateName = "WA", CountyName = "King", Info = "stuff" }; citiesContext.Cities.Add(newCity); so = citiesContext.SubmitChanges(); }); // wait for submit to complete EnqueueConditional(() => so.IsComplete); EnqueueCallback(delegate { if (so.Error != null) { Assert.Fail("Unexpected error on submit: " + so.Error.Message); } // verify entities are auto-synced back to the client as a result of the domain method execution on server CityWithInfo newCity = citiesContext.Cities.OfType <CityWithInfo>().SingleOrDefault <CityWithInfo>(c => (c.Name == "CocoaVille")); Assert.IsNotNull(newCity, "Did not find modified City after the submit"); Assert.IsTrue(newCity.EditHistory.Contains("insert"), "EditHistory was" + newCity.EditHistory); }); EnqueueTestComplete(); }
public void Inherit_Run_CUD_Delete_Derived() { // Inheritance is City <-- CityWithEditHistory <-- CityWithInfo CityDomainContext citiesContext = new CityDomainContext(TestURIs.Cities); DateTime priorLastUpdated = DateTime.Now; LoadOperation lo = null; SubmitOperation so = null; CityWithInfo cityWithInfo = null; string originalName = null; string originalStateName = null; string originalCountyName = null; // Invoke service operation to clear out all static data // (we rely on static data for deleted cities so that it // survives across queries) InvokeOperation invoke = citiesContext.ResetData(null, null); EnqueueConditional(delegate { return(invoke.IsComplete); }); EnqueueCallback(delegate { if (invoke.Error != null) { Assert.Fail("Failed on invoke of ResetData: " + invoke.Error.Message); } }); EnqueueCallback(delegate { // Load all cities, not just derived ones lo = citiesContext.Load(citiesContext.GetCitiesQuery()); }); // wait for Load to complete EnqueueConditional(() => lo.IsComplete); EnqueueCallback(delegate { cityWithInfo = citiesContext.Cities.OfType <CityWithInfo>().FirstOrDefault(); Assert.IsNotNull(cityWithInfo, "expected to find at least one CityWithInfo entity"); Assert.IsFalse(cityWithInfo.EditHistory.Contains("update"), "Did not expect edit history to be set yet."); originalName = cityWithInfo.Name; originalStateName = cityWithInfo.StateName; originalCountyName = cityWithInfo.CountyName; // Delete it. Note that the delete CUD method in the CityDomainService // moves the deleted city over into DeletedCities so it can still be found citiesContext.Cities.Remove(cityWithInfo); so = citiesContext.SubmitChanges(); }); // wait for submit to complete EnqueueConditional(() => so.IsComplete); EnqueueCallback(delegate { if (so.Error != null) { Assert.Fail("Unexpected error on submit: " + so.Error.Message); } // verify entities are auto-synced back to the client as a result of the domain method execution on server CityWithInfo deletedCity = citiesContext.Cities.OfType <CityWithInfo>().SingleOrDefault <CityWithInfo> (c => (c.Name == originalName && c.StateName == originalStateName && c.CountyName == originalCountyName)); Assert.IsNull(deletedCity, "Did not expect to find deleted City after the submit"); // Load the deleted cities (it was tombstoned) citiesContext.Cities.Clear(); lo = citiesContext.Load(citiesContext.GetDeletedCitiesQuery()); }); // Wait for deleted city query to complete EnqueueConditional(() => lo.IsComplete); EnqueueCallback(delegate { if (lo.Error != null) { Assert.Fail("Unexpected error on load of deleted queries: " + lo.Error.Message); } // verify entities are auto-synced back to the client as a result of the domain method execution on server CityWithInfo deletedCity = citiesContext.Cities.OfType <CityWithInfo>().SingleOrDefault <CityWithInfo> (c => (c.Name == originalName && c.StateName == originalStateName && c.CountyName == originalCountyName)); Assert.IsNotNull(deletedCity, "Expected to find deleted City in the tombstone list"); Assert.IsTrue(deletedCity.EditHistory.Contains("delete"), "Expected edit history to show delete but it only shows: " + deletedCity.EditHistory); }); EnqueueTestComplete(); }
public void Inherit_Run_Call_Derived_Custom_Method_On_Abstract_Base_() { // Inheritance is City <-- CityWithEditHistory <-- CityWithInfo // This test invokes a custom method declared on CityWithEditHistory via a CityWithInfo instance EntityChangeSet changeset; List <string> propChanged = new List <string>(); CityDomainContext citiesProvider = new CityDomainContext(TestURIs.Cities); CityWithInfo cityWithInfo = null; DateTime priorLastUpdated = DateTime.Now; LoadOperation lo = citiesProvider.Load(citiesProvider.GetCitiesWithInfoQuery()); SubmitOperation so = null; // wait for Load to complete, then invoke some domain methods EnqueueConditional(() => lo.IsComplete); EnqueueCallback(delegate { cityWithInfo = citiesProvider.Cities.FirstOrDefault() as CityWithInfo; Assert.IsNotNull(cityWithInfo, "Cities[0] should have been CityWithInfo but was " + citiesProvider.Cities.First().GetType().Name); changeset = citiesProvider.EntityContainer.GetChanges(); Assert.IsTrue(changeset.IsEmpty); cityWithInfo.PropertyChanged += delegate(object sender, System.ComponentModel.PropertyChangedEventArgs e) { // We filter to only those properties we see in the City hierarchy BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly; bool isCityProperty = (typeof(CityWithInfo).GetProperty(e.PropertyName, flags) != null || typeof(CityWithEditHistory).GetProperty(e.PropertyName, flags) != null || typeof(City).GetProperty(e.PropertyName, flags) != null); if (isCityProperty) { propChanged.Add(e.PropertyName); } }; priorLastUpdated = cityWithInfo.LastUpdated; Assert.IsTrue(cityWithInfo.CanTouchHistory); cityWithInfo.TouchHistory("xxx"); }); // wait for prop changed for domain method guards EnqueueConditional(() => propChanged.Count > 0); // Inject small delay so DateTime.Now executed on server is later than value in cithWithInfo EnqueueDelay(50); // Test validation that we will, in fact, get a different time stamp EnqueueCallback(delegate { Assert.AreNotEqual(priorLastUpdated, DateTime.Now, "Expected difference in times after small delay"); }); EnqueueCallback(delegate { Assert.IsTrue(propChanged.Contains("CanTouchHistory")); propChanged.Clear(); changeset = citiesProvider.EntityContainer.GetChanges(); Assert.AreEqual(1, changeset.ModifiedEntities.Count); so = citiesProvider.SubmitChanges(); Assert.AreEqual(1, so.ChangeSet.ModifiedEntities.Count); Assert.AreEqual(0, so.ChangeSet.AddedEntities.Count); Assert.AreEqual(0, so.ChangeSet.RemovedEntities.Count); }); // wait for submit to complete, then verify invokedEntities in changeset EnqueueConditional(() => so.IsComplete); EnqueueCallback(delegate { Assert.IsNull(so.Error); Assert.AreEqual(1, so.ChangeSet.ModifiedEntities.Count); // verify we got the property change notification for the city entity as a result of autosync Assert.AreEqual(13, propChanged.Count, "Received different property notifications than expected:\r\n" + string.Join(",", propChanged.ToArray())); Assert.AreEqual(1, propChanged.Count(prop => prop == "EditHistory")); Assert.AreEqual(1, propChanged.Count(prop => prop == "LastUpdated")); Assert.AreEqual(2, propChanged.Count(prop => prop == "CanAssignCityZone")); Assert.AreEqual(2, propChanged.Count(prop => prop == "CanAssignCityZoneIfAuthorized")); Assert.AreEqual(2, propChanged.Count(prop => prop == "CanAutoAssignCityZone")); Assert.AreEqual(2, propChanged.Count(prop => prop == "CanTouchHistory")); Assert.AreEqual(1, propChanged.Count(prop => prop == "IsTouchHistoryInvoked")); Assert.AreEqual(2, propChanged.Count(prop => prop == "CanSetCityInfo")); // verify entities are auto-synced back to the client as a result of the domain method execution on server CityWithInfo newCityWithInfo = citiesProvider.Cities.OfType <CityWithInfo>().SingleOrDefault <CityWithInfo>(c => (c.EditHistory.Contains("touch"))); Assert.IsNotNull(newCityWithInfo, "Did not find modified CityWithInfo after the submit"); Assert.AreNotEqual(newCityWithInfo.LastUpdated, priorLastUpdated, "Expected lastUpdated to be modified by submit"); Assert.IsTrue(newCityWithInfo.EditHistory.Contains("touch=xxx"), "EditHistory was" + newCityWithInfo.EditHistory); }); EnqueueTestComplete(); }
public void Inherit_Run_Call_Base_Custom_Method_On_Derived_Entity() { EntityChangeSet changeset; List <string> propChanged = new List <string>(); CityDomainContext citiesProvider = new CityDomainContext(TestURIs.Cities); LoadOperation lo = citiesProvider.Load(citiesProvider.GetCitiesQuery()); SubmitOperation so = null; CityWithInfo cityWithInfo = null; // wait for Load to complete, then invoke some domain methods EnqueueConditional(() => lo.IsComplete); EnqueueCallback(delegate { changeset = citiesProvider.EntityContainer.GetChanges(); Assert.IsTrue(changeset.IsEmpty); cityWithInfo = citiesProvider.Cities.OfType <CityWithInfo>().FirstOrDefault(); Assert.IsNotNull(cityWithInfo, "Expected to find a CityWithInfo type in entity list"); cityWithInfo.PropertyChanged += delegate(object sender, System.ComponentModel.PropertyChangedEventArgs e) { // We filter to only those properties we see in the City hierarchy BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly; bool isCityProperty = (typeof(CityWithInfo).GetProperty(e.PropertyName, flags) != null || typeof(CityWithEditHistory).GetProperty(e.PropertyName, flags) != null || typeof(City).GetProperty(e.PropertyName, flags) != null); if (isCityProperty) { propChanged.Add(e.PropertyName); } }; Assert.IsTrue(cityWithInfo.CanAssignCityZone); cityWithInfo.AssignCityZone("Zone15"); }); // wait for prop changed for domain method guards EnqueueConditional(() => propChanged.Count > 0); EnqueueCallback(delegate { Assert.IsTrue(propChanged.Contains("CanAssignCityZone")); propChanged.Clear(); changeset = citiesProvider.EntityContainer.GetChanges(); Assert.AreEqual(1, changeset.ModifiedEntities.Count); so = citiesProvider.SubmitChanges(); Assert.AreEqual(1, so.ChangeSet.ModifiedEntities.Count); Assert.AreEqual(0, so.ChangeSet.AddedEntities.Count); Assert.AreEqual(0, so.ChangeSet.RemovedEntities.Count); }); // wait for submit to complete, then verify invokedEntities in changeset EnqueueConditional(() => so.IsComplete); EnqueueCallback(delegate { if (so.Error != null) { Assert.Fail(so.Error.Message); } Assert.AreEqual(1, so.ChangeSet.ModifiedEntities.Count); // verify we got the property change notification for the city entity as a result of autosync Assert.AreEqual(14, propChanged.Count, "Received different property notifications than expected:\r\n" + string.Join(",", propChanged.ToArray())); Assert.AreEqual(1, propChanged.Count(prop => prop == "EditHistory")); Assert.AreEqual(1, propChanged.Count(prop => prop == "ZoneName")); Assert.AreEqual(1, propChanged.Count(prop => prop == "ZoneID")); Assert.AreEqual(2, propChanged.Count(prop => prop == "CanAssignCityZone")); Assert.AreEqual(1, propChanged.Count(prop => prop == "IsAssignCityZoneInvoked")); Assert.AreEqual(2, propChanged.Count(prop => prop == "CanAutoAssignCityZone")); Assert.AreEqual(2, propChanged.Count(prop => prop == "CanAssignCityZoneIfAuthorized")); Assert.AreEqual(2, propChanged.Count(prop => prop == "CanSetCityInfo")); Assert.AreEqual(2, propChanged.Count(prop => prop == "CanTouchHistory")); // verify entities are auto-synced back to the client as a result of the domain method execution on server Assert.AreEqual(15, citiesProvider.Cities.Single <City>(c => (c.ZoneName == "Zone15")).ZoneID); // verify unchanged entities Assert.AreEqual(0, citiesProvider.Cities.First(c => (c.ZoneName == null)).ZoneID); }); EnqueueTestComplete(); }