diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c9001dae..0330a4c06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ - [Introduce support for layout customization for `Item`, `HeaderFooter`, and `Section`](https://github.com/kyleve/Listable/pull/257) for all `ListLayout` types, not just `.table`. +- [Add `inserted` and `removed` items to `.onContentChanged`](https://github.com/kyleve/Listable/pull/260), to easier determine what content was added or removed from the list a central location. + ### Removed ### Changed diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index eed30df3b..cf5d199b4 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -614,6 +614,7 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; diff --git a/ListableUI/Sources/Internal/Diff/ArrayDiff.swift b/ListableUI/Sources/Internal/Diff/ArrayDiff.swift index ec9589434..b6879d74d 100644 --- a/ListableUI/Sources/Internal/Diff/ArrayDiff.swift +++ b/ListableUI/Sources/Internal/Diff/ArrayDiff.swift @@ -23,6 +23,8 @@ struct ArrayDiff struct Added { + let identifier : Identifier + let newIndex : Int let new : Element @@ -30,6 +32,8 @@ struct ArrayDiff struct Removed { + let identifier : Identifier + let oldIndex : Int let old : Element @@ -37,12 +41,16 @@ struct ArrayDiff struct Moved { + let identifier : Identifier + let old : Removed let new : Added } struct Updated { + let identifier : Identifier + let oldIndex : Int let newIndex : Int @@ -52,6 +60,8 @@ struct ArrayDiff struct NoChange { + let identifier : Identifier + let oldIndex : Int let newIndex : Int @@ -105,11 +115,19 @@ struct ArrayDiff let removed = old.subtractDifference(from: new) self.added = added.map { - Added(newIndex: $0.index, new: $0.value) + Added( + identifier: $0.identifier.base, + newIndex: $0.index, + new: $0.value + ) } self.removed = removed.map { - Removed(oldIndex: $0.index, old: $0.value) + Removed( + identifier: $0.identifier.base, + oldIndex: $0.index, + old: $0.value + ) } // @@ -145,11 +163,22 @@ struct ArrayDiff ) self.moved.append(Moved( - old: Removed(oldIndex: pair.old.index, old: pair.old.value), - new: Added(newIndex: pair.new.index, new: pair.new.value) + identifier: pair.new.identifier.base, + + old: Removed( + identifier: pair.old.identifier.base, + oldIndex: pair.old.index, + old: pair.old.value + ), + new: Added( + identifier: pair.new.identifier.base, + newIndex: pair.new.index, + new: pair.new.value + ) )) } else if pair.updated { self.updated.append(Updated( + identifier: pair.new.identifier.base, oldIndex: pair.old.index, newIndex: pair.new.index, old: pair.old.value, @@ -157,6 +186,7 @@ struct ArrayDiff )) } else { self.noChange.append(NoChange( + identifier: pair.new.identifier.base, oldIndex: pair.old.index, newIndex: pair.new.index, old: pair.old.value, @@ -199,14 +229,32 @@ struct ArrayDiff let old = old[index] let new = new[index] - guard identifierProvider(old) == identifierProvider(new) else { + let newID = identifierProvider(new) + + guard identifierProvider(old) == newID else { return nil } if updated(old, new) { - updates.append(Updated(oldIndex: index, newIndex: index, old: old, new: new)) + updates.append( + Updated( + identifier: newID, + oldIndex: index, + newIndex: index, + old: old, + new: new + ) + ) } else { - notChanged.append(NoChange(oldIndex: index, newIndex: index, old: old, new: new)) + notChanged.append( + NoChange( + identifier: newID, + oldIndex: index, + newIndex: index, + old: old, + new: new + ) + ) } } @@ -423,7 +471,8 @@ private class DiffContainer private struct UniqueIdentifier : Hashable { - private let base : Identifier + let base : Identifier + private let modifier : Int private let hash : Int diff --git a/ListableUI/Sources/Internal/Diff/SectionedDiff.swift b/ListableUI/Sources/Internal/Diff/SectionedDiff.swift index 4f0e871b7..2c9ab0214 100644 --- a/ListableUI/Sources/Internal/Diff/SectionedDiff.swift +++ b/ListableUI/Sources/Internal/Diff/SectionedDiff.swift @@ -87,6 +87,7 @@ struct SectionedDiff + let removedItemIdentifiers : Set let sectionsChangeCount : Int let itemsChangeCount : Int @@ -113,6 +114,7 @@ struct SectionedDiff 0 || sectionsChangeCount > 0 - self.addedItemIdentifiers = Set(allIDs) + if hasChanges { + let oldIDs = Self.allItemIDs(in: old, configuration: configuration) + let newIDs = Self.allItemIDs(in: new, configuration: configuration) + + self.addedItemIdentifiers = newIDs.subtracting(oldIDs) + self.removedItemIdentifiers = oldIDs.subtracting(newIDs) + } else { + self.addedItemIdentifiers = [] + self.removedItemIdentifiers = [] + } - self.sectionsChangeCount = self.added.count - + self.removed.count - + self.moved.count + listablePrecondition(diff.updated.isEmpty, "Must not have any updates for sections; sections can only move.") + } + + private static func allItemIDs(in sections : [Section], configuration : Configuration) -> Set { - self.itemsChangeCount = - self.moved.reduce(0, { $0 + $1.itemChanges.changeCount }) + - self.noChange.reduce(0, { $0 + $1.itemChanges.changeCount }) + var IDs = Set() - listablePrecondition(diff.updated.isEmpty, "Must not have any updates for sections; sections can only move.") + for section in sections { + for item in configuration.section.items(section) { + IDs.insert(configuration.item.identifier(item)) + } + } + + return IDs } struct Added { + let identifier : SectionIdentifier + let newIndex : Int let newValue : Section @@ -198,6 +216,8 @@ struct SectionedDiff) { + + self.sections = ChangedIDs( + inserted: Set(diff.changes.added.map{ $0.identifier }), + removed: Set(diff.changes.removed.map{ $0.identifier }) + ) + + self.items = ChangedIDs( + inserted: diff.changes.addedItemIdentifiers, + removed: diff.changes.removedItemIdentifiers + ) + } + + public struct ChangedIDs { + public var inserted : Set + public var removed : Set + } + } } diff --git a/ListableUI/Sources/ListView/ListView.swift b/ListableUI/Sources/ListView/ListView.swift index fc242f37c..e925efeb1 100644 --- a/ListableUI/Sources/ListView/ListView.swift +++ b/ListableUI/Sources/ListView/ListView.swift @@ -869,7 +869,7 @@ public final class ListView : UIView, KeyboardObserverDelegate if case .contentChanged(_, _) = reason { ListStateObserver.perform(self.stateObserver.onContentUpdated, "Content Updated", with: self) { actions in ListStateObserver.ContentUpdated( - hadChanges: diff.changes.isEmpty == false, + changes: .init(diff: diff), actions: actions, positionInfo: self.scrollPositionInfo ) diff --git a/ListableUI/Tests/Internal/Diff/ArrayDiffTests.swift b/ListableUI/Tests/Internal/Diff/ArrayDiffTests.swift index faf7c3727..d59dd90b4 100644 --- a/ListableUI/Tests/Internal/Diff/ArrayDiffTests.swift +++ b/ListableUI/Tests/Internal/Diff/ArrayDiffTests.swift @@ -46,10 +46,10 @@ class ArrayDiffTests: XCTestCase XCTAssertEqual(diff.updated, []) XCTAssertEqual(diff.noChange, [ - ArrayDiff.NoChange(oldIndex: 0, newIndex: 0, old: "a", new: "a"), - ArrayDiff.NoChange(oldIndex: 1, newIndex: 1, old: "b", new: "b"), - ArrayDiff.NoChange(oldIndex: 2, newIndex: 2, old: "c", new: "c"), - ArrayDiff.NoChange(oldIndex: 3, newIndex: 3, old: "d", new: "d"), + ArrayDiff.NoChange(identifier:"a", oldIndex: 0, newIndex: 0, old: "a", new: "a"), + ArrayDiff.NoChange(identifier:"b", oldIndex: 1, newIndex: 1, old: "b", new: "b"), + ArrayDiff.NoChange(identifier:"c", oldIndex: 2, newIndex: 2, old: "c", new: "c"), + ArrayDiff.NoChange(identifier:"d", oldIndex: 3, newIndex: 3, old: "d", new: "d"), ]) } @@ -70,13 +70,13 @@ class ArrayDiffTests: XCTestCase XCTAssertEqual(diff.moved, []) XCTAssertEqual(diff.updated, [ - ArrayDiff.Updated(oldIndex: 0, newIndex: 0, old: "a", new: "A") + ArrayDiff.Updated(identifier:"a", oldIndex: 0, newIndex: 0, old: "a", new: "A") ]) XCTAssertEqual(diff.noChange, [ - ArrayDiff.NoChange(oldIndex: 1, newIndex: 1, old: "b", new: "b"), - ArrayDiff.NoChange(oldIndex: 2, newIndex: 2, old: "c", new: "c"), - ArrayDiff.NoChange(oldIndex: 3, newIndex: 3, old: "d", new: "d"), + ArrayDiff.NoChange(identifier:"b", oldIndex: 1, newIndex: 1, old: "b", new: "b"), + ArrayDiff.NoChange(identifier:"c", oldIndex: 2, newIndex: 2, old: "c", new: "c"), + ArrayDiff.NoChange(identifier:"d", oldIndex: 3, newIndex: 3, old: "d", new: "d"), ]) } } @@ -95,10 +95,10 @@ class ArrayDiffTests: XCTestCase XCTAssertEqual(diff.usedFastPath, false) XCTAssertEqual(diff.added, [ - ArrayDiff.Added(newIndex: 0, new: "a"), - ArrayDiff.Added(newIndex: 1, new: "b"), - ArrayDiff.Added(newIndex: 2, new: "c"), - ArrayDiff.Added(newIndex: 3, new: "d"), + ArrayDiff.Added(identifier:"a", newIndex: 0, new: "a"), + ArrayDiff.Added(identifier:"b", newIndex: 1, new: "b"), + ArrayDiff.Added(identifier:"c", newIndex: 2, new: "c"), + ArrayDiff.Added(identifier:"d", newIndex: 3, new: "d"), ]) XCTAssertEqual(diff.removed, []) @@ -121,10 +121,10 @@ class ArrayDiffTests: XCTestCase XCTAssertEqual(diff.added, []) XCTAssertEqual(diff.removed, [ - ArrayDiff.Removed(oldIndex: 3, old: "d"), - ArrayDiff.Removed(oldIndex: 2, old: "c"), - ArrayDiff.Removed(oldIndex: 1, old: "b"), - ArrayDiff.Removed(oldIndex: 0, old: "a"), + ArrayDiff.Removed(identifier:"d", oldIndex: 3, old: "d"), + ArrayDiff.Removed(identifier:"c", oldIndex: 2, old: "c"), + ArrayDiff.Removed(identifier:"b", oldIndex: 1, old: "b"), + ArrayDiff.Removed(identifier:"a", oldIndex: 0, old: "a"), ]) XCTAssertEqual(diff.moved, []) @@ -144,9 +144,9 @@ class ArrayDiffTests: XCTestCase XCTAssertEqual(diff.usedFastPath, false) XCTAssertEqual(diff.added, [ - ArrayDiff.Added(newIndex: 1, new: "a2"), - ArrayDiff.Added(newIndex: 4, new: "c2"), - ArrayDiff.Added(newIndex: 6, new: "d2"), + ArrayDiff.Added(identifier:"a2", newIndex: 1, new: "a2"), + ArrayDiff.Added(identifier:"c2", newIndex: 4, new: "c2"), + ArrayDiff.Added(identifier:"d2", newIndex: 6, new: "d2"), ]) XCTAssertEqual(diff.removed, []) @@ -154,10 +154,10 @@ class ArrayDiffTests: XCTestCase XCTAssertEqual(diff.updated, []) XCTAssertEqual(diff.noChange, [ - ArrayDiff.NoChange(oldIndex: 0, newIndex: 0, old: "a", new: "a"), - ArrayDiff.NoChange(oldIndex: 1, newIndex: 2, old: "b", new: "b"), - ArrayDiff.NoChange(oldIndex: 2, newIndex: 3, old: "c", new: "c"), - ArrayDiff.NoChange(oldIndex: 3, newIndex: 5, old: "d", new: "d"), + ArrayDiff.NoChange(identifier:"a", oldIndex: 0, newIndex: 0, old: "a", new: "a"), + ArrayDiff.NoChange(identifier:"b", oldIndex: 1, newIndex: 2, old: "b", new: "b"), + ArrayDiff.NoChange(identifier:"c", oldIndex: 2, newIndex: 3, old: "c", new: "c"), + ArrayDiff.NoChange(identifier:"d", oldIndex: 3, newIndex: 5, old: "d", new: "d"), ]) } @@ -175,19 +175,19 @@ class ArrayDiffTests: XCTestCase XCTAssertEqual(diff.added, []) XCTAssertEqual(diff.removed, [ - ArrayDiff.Removed(oldIndex: 6, old: "d2"), - ArrayDiff.Removed(oldIndex: 4, old: "c2"), - ArrayDiff.Removed(oldIndex: 1, old: "a2"), + ArrayDiff.Removed(identifier:"d2", oldIndex: 6, old: "d2"), + ArrayDiff.Removed(identifier:"c2", oldIndex: 4, old: "c2"), + ArrayDiff.Removed(identifier:"a2", oldIndex: 1, old: "a2"), ]) XCTAssertEqual(diff.moved, []) XCTAssertEqual(diff.updated, []) XCTAssertEqual(diff.noChange, [ - ArrayDiff.NoChange(oldIndex: 0, newIndex: 0, old: "a", new: "a"), - ArrayDiff.NoChange(oldIndex: 2, newIndex: 1, old: "b", new: "b"), - ArrayDiff.NoChange(oldIndex: 3, newIndex: 2, old: "c", new: "c"), - ArrayDiff.NoChange(oldIndex: 5, newIndex: 3, old: "d", new: "d"), + ArrayDiff.NoChange(identifier:"a", oldIndex: 0, newIndex: 0, old: "a", new: "a"), + ArrayDiff.NoChange(identifier:"b", oldIndex: 2, newIndex: 1, old: "b", new: "b"), + ArrayDiff.NoChange(identifier:"c", oldIndex: 3, newIndex: 2, old: "c", new: "c"), + ArrayDiff.NoChange(identifier:"d", oldIndex: 5, newIndex: 3, old: "d", new: "d"), ]) } @@ -203,22 +203,22 @@ class ArrayDiffTests: XCTestCase XCTAssertEqual(diff.usedFastPath, false) XCTAssertEqual(diff.added, [ - ArrayDiff.Added(newIndex: 1, new: "a2"), - ArrayDiff.Added(newIndex: 3, new: "c2"), - ArrayDiff.Added(newIndex: 4, new: "d2"), + ArrayDiff.Added(identifier:"a2", newIndex: 1, new: "a2"), + ArrayDiff.Added(identifier:"c2", newIndex: 3, new: "c2"), + ArrayDiff.Added(identifier:"d2", newIndex: 4, new: "d2"), ]) XCTAssertEqual(diff.removed, [ - ArrayDiff.Removed(oldIndex: 3, old: "d"), - ArrayDiff.Removed(oldIndex: 1, old: "b"), + ArrayDiff.Removed(identifier:"d", oldIndex: 3, old: "d"), + ArrayDiff.Removed(identifier:"b", oldIndex: 1, old: "b"), ]) XCTAssertEqual(diff.moved, []) XCTAssertEqual(diff.updated, []) XCTAssertEqual(diff.noChange, [ - ArrayDiff.NoChange(oldIndex: 0, newIndex: 0, old: "a", new: "a"), - ArrayDiff.NoChange(oldIndex: 2, newIndex: 2, old: "c", new: "c"), + ArrayDiff.NoChange(identifier:"a", oldIndex: 0, newIndex: 0, old: "a", new: "a"), + ArrayDiff.NoChange(identifier:"c", oldIndex: 2, newIndex: 2, old: "c", new: "c"), ]) } } @@ -241,17 +241,18 @@ class ArrayDiffTests: XCTestCase XCTAssertEqual(diff.moved, [ ArrayDiff.Moved( - old: ArrayDiff.Removed(oldIndex: 0, old: "a"), - new: ArrayDiff.Added(newIndex: 3, new: "a") + identifier:"a", + old: ArrayDiff.Removed(identifier:"a", oldIndex: 0, old: "a"), + new: ArrayDiff.Added(identifier:"a", newIndex: 3, new: "a") ) ]) XCTAssertEqual(diff.updated, []) XCTAssertEqual(diff.noChange, [ - ArrayDiff.NoChange(oldIndex: 1, newIndex: 0, old: "b", new: "b"), - ArrayDiff.NoChange(oldIndex: 2, newIndex: 1, old: "c", new: "c"), - ArrayDiff.NoChange(oldIndex: 3, newIndex: 2, old: "d", new: "d"), + ArrayDiff.NoChange(identifier:"b", oldIndex: 1, newIndex: 0, old: "b", new: "b"), + ArrayDiff.NoChange(identifier:"c", oldIndex: 2, newIndex: 1, old: "c", new: "c"), + ArrayDiff.NoChange(identifier:"d", oldIndex: 3, newIndex: 2, old: "d", new: "d"), ]) } @@ -271,18 +272,19 @@ class ArrayDiffTests: XCTestCase XCTAssertEqual(diff.moved, [ ArrayDiff.Moved( - old: ArrayDiff.Removed(oldIndex: 1, old: "b"), - new: ArrayDiff.Added(newIndex: 3, new: "B") + identifier:"b", + old: ArrayDiff.Removed(identifier:"b", oldIndex: 1, old: "b"), + new: ArrayDiff.Added(identifier:"b", newIndex: 3, new: "B") ) ]) XCTAssertEqual(diff.updated, [ - ArrayDiff.Updated(oldIndex: 0, newIndex: 0, old: "a", new: "A") + ArrayDiff.Updated(identifier:"a", oldIndex: 0, newIndex: 0, old: "a", new: "A") ]) XCTAssertEqual(diff.noChange, [ - ArrayDiff.NoChange(oldIndex: 2, newIndex: 1, old: "c", new: "c"), - ArrayDiff.NoChange(oldIndex: 3, newIndex: 2, old: "d", new: "d") + ArrayDiff.NoChange(identifier:"c", oldIndex: 2, newIndex: 1, old: "c", new: "c"), + ArrayDiff.NoChange(identifier:"d", oldIndex: 3, newIndex: 2, old: "d", new: "d") ]) } } @@ -301,10 +303,10 @@ class ArrayDiffTests: XCTestCase XCTAssertEqual(diff.usedFastPath, false) XCTAssertEqual(diff.added, [ - ArrayDiff.Added(newIndex: 1, new: "a"), - ArrayDiff.Added(newIndex: 3, new: "b"), - ArrayDiff.Added(newIndex: 5, new: "c"), - ArrayDiff.Added(newIndex: 7, new: "d"), + ArrayDiff.Added(identifier:"a", newIndex: 1, new: "a"), + ArrayDiff.Added(identifier:"b", newIndex: 3, new: "b"), + ArrayDiff.Added(identifier:"c", newIndex: 5, new: "c"), + ArrayDiff.Added(identifier:"d", newIndex: 7, new: "d"), ]) XCTAssertEqual(diff.removed, []) @@ -312,10 +314,10 @@ class ArrayDiffTests: XCTestCase XCTAssertEqual(diff.updated, []) XCTAssertEqual(diff.noChange, [ - ArrayDiff.NoChange(oldIndex: 0, newIndex: 0, old: "a", new: "a"), - ArrayDiff.NoChange(oldIndex: 1, newIndex: 2, old: "b", new: "b"), - ArrayDiff.NoChange(oldIndex: 2, newIndex: 4, old: "c", new: "c"), - ArrayDiff.NoChange(oldIndex: 3, newIndex: 6, old: "d", new: "d"), + ArrayDiff.NoChange(identifier:"a", oldIndex: 0, newIndex: 0, old: "a", new: "a"), + ArrayDiff.NoChange(identifier:"b", oldIndex: 1, newIndex: 2, old: "b", new: "b"), + ArrayDiff.NoChange(identifier:"c", oldIndex: 2, newIndex: 4, old: "c", new: "c"), + ArrayDiff.NoChange(identifier:"d", oldIndex: 3, newIndex: 6, old: "d", new: "d"), ]) } @@ -333,20 +335,20 @@ class ArrayDiffTests: XCTestCase XCTAssertEqual(diff.added, []) XCTAssertEqual(diff.removed, [ - ArrayDiff.Removed(oldIndex: 7, old: "d"), - ArrayDiff.Removed(oldIndex: 5, old: "c"), - ArrayDiff.Removed(oldIndex: 3, old: "b"), - ArrayDiff.Removed(oldIndex: 1, old: "a"), + ArrayDiff.Removed(identifier:"d", oldIndex: 7, old: "d"), + ArrayDiff.Removed(identifier:"c", oldIndex: 5, old: "c"), + ArrayDiff.Removed(identifier:"b", oldIndex: 3, old: "b"), + ArrayDiff.Removed(identifier:"a", oldIndex: 1, old: "a"), ]) XCTAssertEqual(diff.moved, []) XCTAssertEqual(diff.updated, []) XCTAssertEqual(diff.noChange, [ - ArrayDiff.NoChange(oldIndex: 0, newIndex: 0, old: "a", new: "a"), - ArrayDiff.NoChange(oldIndex: 2, newIndex: 1, old: "b", new: "b"), - ArrayDiff.NoChange(oldIndex: 4, newIndex: 2, old: "c", new: "c"), - ArrayDiff.NoChange(oldIndex: 6, newIndex: 3, old: "d", new: "d"), + ArrayDiff.NoChange(identifier:"a", oldIndex: 0, newIndex: 0, old: "a", new: "a"), + ArrayDiff.NoChange(identifier:"b", oldIndex: 2, newIndex: 1, old: "b", new: "b"), + ArrayDiff.NoChange(identifier:"c", oldIndex: 4, newIndex: 2, old: "c", new: "c"), + ArrayDiff.NoChange(identifier:"d", oldIndex: 6, newIndex: 3, old: "d", new: "d"), ]) } } diff --git a/ListableUI/Tests/Internal/Diff/SectionedDiffTests.swift b/ListableUI/Tests/Internal/Diff/SectionedDiffTests.swift index 77d821c14..b0a84aabb 100644 --- a/ListableUI/Tests/Internal/Diff/SectionedDiffTests.swift +++ b/ListableUI/Tests/Internal/Diff/SectionedDiffTests.swift @@ -31,10 +31,13 @@ class SectionedDiffTests: XCTestCase { let diff = makeDiff(old: old, new: new) - let addedIdentifier = 2 + XCTAssertEqual(diff.changes.addedItemIdentifiers, [2]) + XCTAssertEqual(diff.changes.removedItemIdentifiers, []) + + let diffInverse = makeDiff(old: new, new: old) - XCTAssert(diff.changes.addedItemIdentifiers.contains(addedIdentifier)) - XCTAssertEqual(diff.changes.addedItemIdentifiers.count, 1) + XCTAssertEqual(diffInverse.changes.addedItemIdentifiers, []) + XCTAssertEqual(diffInverse.changes.removedItemIdentifiers, [2]) } self.testcase("test_added_items_in_no_change_section") { @@ -49,13 +52,13 @@ class SectionedDiffTests: XCTestCase { let diff = makeDiff(old: old, new: new) - let firstAddedIndentifier = 2 - let secondAddedIndentifier = 3 + XCTAssertEqual(diff.changes.addedItemIdentifiers, [2, 3]) + XCTAssertEqual(diff.changes.removedItemIdentifiers, []) + + let diffInverse = makeDiff(old: new, new: old) - XCTAssert(diff.changes.addedItemIdentifiers.contains(firstAddedIndentifier)) - XCTAssert(diff.changes.addedItemIdentifiers.contains(secondAddedIndentifier)) - - XCTAssertEqual(diff.changes.addedItemIdentifiers.count, 2) + XCTAssertEqual(diffInverse.changes.addedItemIdentifiers, []) + XCTAssertEqual(diffInverse.changes.removedItemIdentifiers, [2, 3]) } self.testcase("test_added_items_in_moved_section") { @@ -69,12 +72,16 @@ class SectionedDiffTests: XCTestCase { Section(identifier: 1, items: [2, 3]), Section(identifier: 0, items: [0, 1, 4]), ] + let diff = makeDiff(old: old, new: new) - let addedIdentifier = 4 + XCTAssertEqual(diff.changes.addedItemIdentifiers, [4]) + XCTAssertEqual(diff.changes.removedItemIdentifiers, []) + + let diffInverse = makeDiff(old: new, new: old) - XCTAssert(diff.changes.addedItemIdentifiers.contains(addedIdentifier)) - XCTAssertEqual(diff.changes.addedItemIdentifiers.count, 1) + XCTAssertEqual(diffInverse.changes.addedItemIdentifiers, []) + XCTAssertEqual(diffInverse.changes.removedItemIdentifiers, [4]) } self.testcase("test_moving_item_is_not_added") { @@ -89,7 +96,13 @@ class SectionedDiffTests: XCTestCase { let diff = makeDiff(old: old, new: new) - XCTAssert(diff.changes.addedItemIdentifiers.isEmpty) + XCTAssertEqual(diff.changes.addedItemIdentifiers, []) + XCTAssertEqual(diff.changes.removedItemIdentifiers, []) + + let diffInverse = makeDiff(old: new, new: old) + + XCTAssertEqual(diffInverse.changes.addedItemIdentifiers, []) + XCTAssertEqual(diffInverse.changes.removedItemIdentifiers, []) } func makeDiff(old: [Section], new: [Section]) -> SectionedDiff {