public async Task SubmitAsync_Cancel_DomainClientCancel()
        {
            var mockDomainClient = new CitiesMockDomainClient();

            Cities.CityDomainContext ctx = new Cities.CityDomainContext(mockDomainClient);

            // If cancellation results in request beeing cancelled the result should be cancelled
            var tcs = new TaskCompletionSource <SubmitCompletedResult>();

            using var cts = new CancellationTokenSource();
            mockDomainClient.SubmitCompletedResult = tcs.Task;

            ctx.Cities.Add(new City()
            {
                Name = "NewCity", StateName = "NN", CountyName = "NewCounty"
            });

            var submitTask = ctx.SubmitChangesAsync(cts.Token);

            cts.Cancel();
            Assert.IsTrue(ctx.IsSubmitting);
            Assert.IsTrue(ctx.Cities.First().IsSubmitting, "entity should be in submitting state");

            // Return cancellation from domain client
            tcs.TrySetCanceled(cts.Token);

            await ExceptionHelper.ExpectExceptionAsync <TaskCanceledException>(() => submitTask);

            Assert.IsTrue(submitTask.IsCanceled);
            Assert.IsFalse(ctx.IsSubmitting);
            Assert.IsFalse(ctx.Cities.First().IsSubmitting, "entity should not be in submitting state");
        }
        public async Task CUD_TaskAsyncWithValidationException_InTask()
        {
            // Setup
            var ctx = new ServerSideAsyncDomainContext(TestURIs.ServerSideAsync);
            var rangeItemCreated = new RangeItem()
            {
                ThrowValidationException = true
            };
            var rangeItemUpdated = new RangeItem()
            {
                Id = -1, ThrowValidationException = true
            };
            var rangeItemDeleted = new RangeItem()
            {
                Id = -2, ThrowValidationException = true
            };

            ctx.RangeItems.Attach(rangeItemUpdated);
            ctx.RangeItems.Attach(rangeItemDeleted);

            ctx.RangeItems.Add(rangeItemCreated);
            ctx.RangeItems.Remove(rangeItemDeleted);
            rangeItemUpdated.Text = "updated";

            // Act
            var exception = await ExceptionHelper.ExpectExceptionAsync <SubmitOperationException>(ctx.SubmitChangesAsync);

            // Verify
            Assert.IsTrue(rangeItemCreated.HasValidationErrors);
            Assert.IsTrue(rangeItemUpdated.HasValidationErrors);
            Assert.IsTrue(rangeItemDeleted.HasValidationErrors);
        }
        public async Task SubmitAsync_Exceptions()
        {
            var mockDomainClient = new CitiesMockDomainClient();

            Cities.CityDomainContext ctx = new Cities.CityDomainContext(mockDomainClient);
            DomainOperationException ex  = new DomainOperationException("Submit Failed!", OperationErrorStatus.ServerError, 42, "StackTrace");

            // If cancellation results in request beeing cancelled the result should be cancelled
            mockDomainClient.SubmitCompletedResult = Task.FromException <SubmitCompletedResult>(ex);

            ctx.Cities.Add(new City()
            {
                Name = "NewCity", StateName = "NN", CountyName = "NewCounty"
            });

            Assert.IsTrue(ctx.EntityContainer.HasChanges);
            var submitEx = await ExceptionHelper.ExpectExceptionAsync <SubmitOperationException>(() => ctx.SubmitChangesAsync());

            // verify the exception properties
            Assert.AreEqual(string.Format(Resource.DomainContext_SubmitOperationFailed, ex.Message), submitEx.Message);
            Assert.AreEqual(ex.StackTrace, submitEx.StackTrace);
            Assert.AreEqual(ex.Status, submitEx.Status);
            Assert.AreEqual(ex.ErrorCode, submitEx.ErrorCode);
            Assert.IsTrue(ctx.EntityContainer.HasChanges);

            // now test with validation exception
            var changeSet = ctx.EntityContainer.GetChanges();
            IEnumerable <ChangeSetEntry> entries = ChangeSetBuilder.Build(changeSet);
            ChangeSetEntry entry = entries.First();

            entry.ValidationErrors = new ValidationResultInfo[] { new ValidationResultInfo("Foo", new string[] { "Bar" }) };

            mockDomainClient.SubmitCompletedResult = Task.FromResult(new SubmitCompletedResult(changeSet, entries));
            submitEx = await ExceptionHelper.ExpectExceptionAsync <SubmitOperationException>(() => ctx.SubmitChangesAsync());

            // verify the exception properties
            Assert.AreEqual(Resource.DomainContext_SubmitOperationFailed_Validation, submitEx.Message);
            Assert.AreEqual(OperationErrorStatus.ValidationFailed, submitEx.Status);
            Assert.AreEqual(1, submitEx.EntitiesInError.Count);
            Assert.AreEqual(entry.ClientEntity, submitEx.EntitiesInError.First());

            // now test again with conflicts
            entries = ChangeSetBuilder.Build(changeSet);
            entry   = entries.First();
            entry.ConflictMembers = new string[] { nameof(City.CountyName) };
            entry.StoreEntity     = new City()
            {
                CountyName = "OtherCounty"
            };

            mockDomainClient.SubmitCompletedResult = Task.FromResult(new SubmitCompletedResult(changeSet, entries));
            submitEx = await ExceptionHelper.ExpectExceptionAsync <SubmitOperationException>(() => ctx.SubmitChangesAsync());

            // verify the exception properties
            Assert.AreEqual(Resource.DomainContext_SubmitOperationFailed_Conflicts, submitEx.Message);
            Assert.AreEqual(OperationErrorStatus.Conflicts, submitEx.Status);
            Assert.AreEqual(1, submitEx.EntitiesInError.Count);
            Assert.AreEqual(entry.ClientEntity, submitEx.EntitiesInError.First());
        }
        public async Task LoadAsync_ValidationErrors()
        {
            var mockDomainClient = new CitiesMockDomainClient();

            ValidationResult[] validationErrors = new ValidationResult[] { new ValidationResult("Foo", new string[] { "Bar" }) };
            mockDomainClient.QueryCompletedResult = Task.FromResult(new QueryCompletedResult(Enumerable.Empty <Entity>(), Enumerable.Empty <Entity>(), 0, validationErrors));
            Cities.CityDomainContext ctx = new Cities.CityDomainContext(mockDomainClient);

            var ex = await ExceptionHelper.ExpectExceptionAsync <DomainOperationException>(
                () => ctx.LoadAsync(ctx.GetCitiesQuery()),
                string.Format(Resource.DomainContext_LoadOperationFailed_Validation, "GetCities"));

            // verify the exception properties
            Assert.AreEqual(OperationErrorStatus.ValidationFailed, ex.Status);
            CollectionAssert.AreEqual(validationErrors, (ICollection)ex.ValidationErrors);
        }
        public async Task InvokeAsync_ValidationErrors()
        {
            var mockDomainClient = new CitiesMockDomainClient();

            ValidationResult[] validationErrors = new ValidationResult[] { new ValidationResult("Foo", new string[] { "Bar" }) };
            mockDomainClient.InvokeCompletedResult = Task.FromResult(new InvokeCompletedResult(null, validationErrors));
            Cities.CityDomainContext ctx = new Cities.CityDomainContext(mockDomainClient);

            var ex = await ExceptionHelper.ExpectExceptionAsync <DomainOperationException>(
                () => ctx.EchoAsync("TestInvoke"),
                string.Format(Resource.DomainContext_InvokeOperationFailed_Validation, "Echo"));

            // verify the exception properties
            Assert.AreEqual(OperationErrorStatus.ValidationFailed, ex.Status);
            CollectionAssert.AreEqual(validationErrors, (ICollection)ex.ValidationErrors);
        }
        public async Task Insert_TaskAsyncWithException_InTask()
        {
            // Setup
            var ctx       = new ServerSideAsyncDomainContext(TestURIs.ServerSideAsync);
            var rangeItem = new RangeItem()
            {
                ThrowDomainException = true
            };

            ctx.RangeItems.Add(rangeItem);

            // Act
            var domainException = await ExceptionHelper.ExpectExceptionAsync <DomainException>(ctx.SubmitChangesAsync, "InsertRangeAsync");

            // Verify
            Assert.AreEqual(25, domainException.ErrorCode, "Wrong error code returned or expected operation was not executed");
        }
        public async Task InvokeAsync_DomainOperationException()
        {
            var mockDomainClient = new CitiesMockDomainClient();
            DomainOperationException exception = new DomainOperationException("Operation Failed!", OperationErrorStatus.ServerError, 42, "StackTrace");

            mockDomainClient.InvokeCompletedResult = Task.FromException <InvokeCompletedResult>(exception);
            Cities.CityDomainContext ctx = new Cities.CityDomainContext(mockDomainClient);

            var ex = await ExceptionHelper.ExpectExceptionAsync <DomainOperationException>(
                () => ctx.EchoAsync("TestInvoke"),
                string.Format(Resource.DomainContext_InvokeOperationFailed, "Echo", exception.Message));

            // verify the exception properties
            Assert.AreEqual(null, ex.InnerException);
            Assert.AreEqual(ex.StackTrace, exception.StackTrace);
            Assert.AreEqual(ex.Status, exception.Status);
            Assert.AreEqual(ex.ErrorCode, exception.ErrorCode);
        }
        public async Task InvokeAsync_Cancel_DomainClientCancel()
        {
            var mockDomainClient = new CitiesMockDomainClient();

            Cities.CityDomainContext ctx = new Cities.CityDomainContext(mockDomainClient);

            // If cancellation results in request beeing cancelled the result should be cancelled
            var tcs = new TaskCompletionSource <InvokeCompletedResult>();

            using var cts = new CancellationTokenSource();
            mockDomainClient.InvokeCompletedResult = tcs.Task;
            var invokeTask = ctx.EchoAsync("TestInvoke", cts.Token);

            cts.Cancel();
            tcs.TrySetCanceled(cts.Token);

            await ExceptionHelper.ExpectExceptionAsync <TaskCanceledException>(() => invokeTask);

            Assert.IsTrue(invokeTask.IsCanceled);
        }
        public async Task LoadAsync_Cancel_DomainClientCancel()
        {
            var mockDomainClient = new CitiesMockDomainClient();

            Cities.CityDomainContext ctx = new Cities.CityDomainContext(mockDomainClient);

            // If cancellation results in request beeing cancelled the result should be cancelled
            var tcs = new TaskCompletionSource <QueryCompletedResult>();

            using var cts = new CancellationTokenSource();
            mockDomainClient.QueryCompletedResult = tcs.Task;
            var loadTask = ctx.LoadAsync(ctx.GetCitiesQuery(), cts.Token);

            Assert.IsTrue(ctx.IsLoading);
            cts.Cancel();
            tcs.TrySetCanceled(cts.Token);

            await ExceptionHelper.ExpectExceptionAsync <OperationCanceledException>(() => loadTask, allowDerivedExceptions : true);

            Assert.IsTrue(loadTask.IsCanceled);
            Assert.IsFalse(ctx.IsLoading);
        }