Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 65 additions & 3 deletions src/DynamicData.Tests/List/TransformAsyncFixture.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
using System;
using System.Linq;
using System.Threading;
using System.Reactive.Linq;
using System.Threading.Tasks;
using DynamicData.Kernel;
using DynamicData.Tests.Domain;

using FluentAssertions;
using Xunit;

using DynamicData.Tests.Domain;
using DynamicData.Tests.Utilities;

namespace DynamicData.Tests.List;

[Obsolete("Not obsolete - test commented out due to test run freezing on Appveyor")]
Expand Down Expand Up @@ -187,4 +189,64 @@ public void TransformAsyncCancelsTokenOnUnSubscribe()
sub.Dispose();
Assert.True(tcs.Task.IsCanceled);
}

// Covers https://github.com/reactivemarbles/DynamicData/issues/1169
[Fact]
public void RemoveWithoutIndex()
{
var source = Enumerable.Empty<IChangeSet<int>>()
.Append(new ChangeSet<int>()
{
new Change<int>(
reason: ListChangeReason.AddRange,
items: Enumerable.Range(1, 3))
})
.Append(new ChangeSet<int>()
{
new Change<int>(
reason: ListChangeReason.Remove,
current: 2)
})
.ToObservable();

using var subscription = source
.TransformAsync(static item => Task.FromResult(item.ToString()))
.ValidateChangeSets()
.RecordListItems(out var results);

results.Error.Should().BeNull("no errors should have occurred");
results.RecordedChangeSets.Count.Should().Be(2, "2 source operations were performed");
results.RecordedItems.Should().BeEquivalentTo(new[] { "1", "3" }, static options => options.WithStrictOrdering(), "The middle item in the list should have been removed");
results.HasCompleted.Should().BeTrue("the source, and all asynchronous operations, have completed");
}

// Covers https://github.com/reactivemarbles/DynamicData/issues/1169
[Fact]
public void RemoveRangeWithoutIndex()
{
var source = Enumerable.Empty<IChangeSet<int>>()
.Append(new ChangeSet<int>()
{
new Change<int>(
reason: ListChangeReason.AddRange,
items: Enumerable.Range(1, 5))
})
.Append(new ChangeSet<int>()
{
new Change<int>(
reason: ListChangeReason.RemoveRange,
items: new[] { 1, 3, 5 })
})
.ToObservable();

using var subscription = source
.TransformAsync(static item => Task.FromResult(item.ToString()))
.ValidateChangeSets()
.RecordListItems(out var results);

results.Error.Should().BeNull("no errors should have occurred");
results.RecordedChangeSets.Count.Should().Be(2, "2 source operations were performed");
results.RecordedItems.Should().BeEquivalentTo(new[] { "2", "4" }, static options => options.WithStrictOrdering(), "The odd-numbered items in the list should have been removed");
results.HasCompleted.Should().BeTrue("the source, and all asynchronous operations, have completed");
}
}
27 changes: 22 additions & 5 deletions src/DynamicData/List/Internal/TransformAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,16 @@ await _containerFactory(
}
else
{
var toRemove = transformed.FirstOrDefault(t => ReferenceEquals(t.Source, t));
var indexToRemove = transformed
.Select((pair, index) => (
sourceItem: pair.Source,
index: (int?)index))
.FirstOrDefault(pair => EqualityComparer<TSource>.Default.Equals(pair.sourceItem, change.Current))
.index;

if (toRemove is not null)
if (indexToRemove is not null)
{
transformed.Remove(toRemove);
transformed.RemoveAt(indexToRemove.Value);
}
}

Expand All @@ -197,8 +202,20 @@ await _containerFactory(
}
else
{
var toRemove = transformed.Where(t => ReferenceEquals(t.Source, t)).ToArray();
transformed.RemoveMany(toRemove);
foreach (var removedItem in item.Range)
{
var indexToRemove = transformed
.Select((pair, index) => (
sourceItem: pair.Source,
index: (int?)index))
.FirstOrDefault(pair => EqualityComparer<TSource>.Default.Equals(pair.sourceItem, removedItem))
.index;

if (indexToRemove is not null)
{
transformed.RemoveAt(indexToRemove.Value);
}
}
}

break;
Expand Down
Loading