public void ReplaceAllNotifiesOfChangesMade() { IEnumerable <int> loadedInts = new int[] { 1, 2, 3, 4 }; var replacements = new int[] { 5, 6 }; var expectedChanges = loadedInts.Select(i => new ItemChange <int>(ChangeType.Removed, i)) .Concat(replacements.Select(i => new ItemChange <int>(ChangeType.Added, i))); var loader = new ThreadSafeAsyncLoader <int>( Seq.ListBased, loadDataAsync: tok => Task.FromResult(loadedInts), eventContext: new RunInlineSynchronizationContext()); loader.LoadAsync(); // load initial values var listener = Substitute.For <CollectionChangedHandler <int> >(); loader.CollectionChanged += listener; loader.Should().Equal(loadedInts); // sanity check loader.ReplaceAll(replacements); // --- Perform --- loader.Should().Equal(replacements); // sanity check listener.Received().Invoke(loader, Fluent.Match <IntChangesAlias>( changes => changes.Should().BeEquivalentTo(expectedChanges))); }
public void ReplaceAllUsesIdentityComparerGivenAtConstruction() { IEnumerable <IntWrapper> originalItems = new IntWrapper[] { 1, 2, 3 }; var replacements = new IntWrapper[] { 1, 3 }; // NOTE: Due to conservate update check, unchanged items will appear as item changes of type update // NOTE2: Need to use the actual instances, since IntWrapper uses reference equality var expectedChanges = new ItemChange <IntWrapper>[] { new ItemChange <IntWrapper>(ChangeType.Updated, replacements[0]), new ItemChange <IntWrapper>(ChangeType.Updated, replacements[1]), new ItemChange <IntWrapper>(ChangeType.Removed, originalItems.ElementAt(1)) }; var loader = new ThreadSafeAsyncLoader <IntWrapper>( Seq.ListBased, loadDataAsync: _ => Task.FromResult(originalItems), identityComparer: new IntWrapperComparer(), eventContext: new RunInlineSynchronizationContext()); loader.LoadAsync(); // load initial values loader.CollectionChanged += (s, e) => { // Verify that the actual changes match the expected changes e.Should().BeEquivalentTo(expectedChanges); }; loader.ReplaceAll(replacements); // --- Perform --- }
public void ReplaceAllDelegatesToUnderlyingSeq() { var items = new[] { 1, 2, 3, 4 }; var seq = Substitute.For <ISeq <int> >(); var loader = new ThreadSafeAsyncLoader <int>(enumerable => seq); loader.ReplaceAll(items); // --- Perform --- seq.Received().ReplaceAll(items); }
public void ReplaceAllDoesNotAllowDuplicatesInNewItems() { IEnumerable <int> loadedInts = new[] { 1, 2, 3 }; var replacements = new[] { 2, 2 }; var loader = new ThreadSafeAsyncLoader <int>( Seq.ListBased, loadDataAsync: tok => Task.FromResult(loadedInts), eventContext: new RunInlineSynchronizationContext()); loader.LoadAsync(); // load initial values // --- Perform --- Action callingReplaceAll = () => loader.ReplaceAll(replacements); callingReplaceAll.ShouldThrow <ArgumentException>("because duplicates are not allowed").WithMessage("*duplicates*"); }
public void ReplaceAllUsesUpdateComparerGivenAtConstruction() { IEnumerable <int> originalItems = new int[] { 1, 2, 3 }; var replacements = new int[] { 1, 3 }; // Since equal int values will now count as unchanged, we do not expect item changes that are updates var expectedChanges = new ItemChange <int>[] { new ItemChange <int>(ChangeType.Removed, 2) }; var loader = new ThreadSafeAsyncLoader <int>( Seq.ListBased, loadDataAsync: _ => Task.FromResult(originalItems), updateComparer: new IntUpdateComparer(), eventContext: new RunInlineSynchronizationContext()); loader.LoadAsync(); // load initial values loader.CollectionChanged += (s, e) => { // Verify that the actual changes match the expected changes e.Should().BeEquivalentTo(expectedChanges); }; loader.ReplaceAll(replacements); // --- Perform --- }