                 return item.identifier
             })
 
-            XCTAssert(mappedIDs == ["0","2","1"])
-        }
-
-        self.whenDataSource(dataSource, hasSectionIDs: ["a","b","c"])
-        XCTAssert(dataSource.numberOfSectionsInTableView(tableView) == 3, "...")
-
-        dataSource.updateRows([MockTVItem(identifier:"0"),MockTVItem(identifier:"1"),MockTVItem(identifier:"2")], section: "a", animated: true)
-        XCTAssert(dataSource.tableView(tableView, numberOfRowsInSection: 0) == 3, "...")
-
-        dataSource.tableView(tableView, moveRowAtIndexPath: NSIndexPath(forRow: 2, inSection: 0), toIndexPath: NSIndexPath(forRow: 1, inSection: 0))
-    }
-
-    func testMoveBeyondLastItem() {
-        let (tableView,dataSource) = self.whenDelegate()
-        self.whenDataSource(dataSource, canMoveItemAtSectionID: "a", rowID: "1")
-
-        let expectation = expectationWithDescription("sections changed callback")
-        dataSource.didChangeSectionIDs = { (inSectionIDs:Dictionary<String,Array<MockTVItem>>) -> Void in
-            expectation.fulfill()
-            XCTAssert(inSectionIDs.count == 1, "should be only one section")
-
-            guard let rows = inSectionIDs["a"] else {
-                XCTFail("no rows?")
-                return
-            }
-
-            let mappedIDs = rows.map({ (item) -> String in
-                return item.identifier
-            })
-
-            XCTAssert(mappedIDs == ["0","2","1"])
-        }
-
-        self.whenDataSource(dataSource, hasSectionIDs: ["a","b","c"])
-        XCTAssert(dataSource.numberOfSectionsInTableView(tableView) == 3, "...")
-
-        self.whenDataSource(dataSource, hasRowIDs: ["0","1","2"], forSectionID: "a")
-        XCTAssert(dataSource.tableView(tableView, numberOfRowsInSection: 0) == 3, "...")
-
-        dataSource.tableView(tableView, moveRowAtIndexPath: NSIndexPath(forRow: 1, inSection: 0), toIndexPath: NSIndexPath(forRow: 3, inSection: 0))
-
-        waitForExpectationsWithTimeout(10, handler: nil)
-    }
-
-
-    func testMoveAcrossSections() {
-        let (tableView,dataSource) = self.whenDelegate()
-        self.whenDataSource(dataSource, hasSectionIDs: ["a","b","c"])
-
-        self.whenDataSource(dataSource, hasRowIDs: ["0","1","2","3"], forSectionID: "a")
-        self.whenDataSource(dataSource, hasRowIDs: ["0","1","2"], forSectionID: "b")
-
-        self.whenDataSource(dataSource, canMoveItemAtSectionID: "a", rowID: "3")
-
-        let expectation = expectationWithDescription("sections changed callback")
-
-        dataSource.didChangeSectionIDs = { (inSectionIDs:Dictionary<String,Array<MockTVItem>>) -> Void in
-            expectation.fulfill()
-            XCTAssert(inSectionIDs.count == 2, "should be only two sections")
-
-            guard let rowsA = inSectionIDs["a"] else {
-                XCTFail("no rows for a?")
-                return
-            }
-
-            let mappedIDsA = rowsA.map({ (item) -> String in
-                return item.identifier
-            })
-
-            XCTAssert(mappedIDsA == ["0","1","2"])
-
-            guard let rowsB = inSectionIDs["b"] else {
-                XCTFail("no rows for b?")
-                return
-            }
-
-            let mappedIDsB = rowsB.map({ (item) -> String in
-                return item.identifier
-            })
-
-            XCTAssert(mappedIDsB == ["0","1","3","2"])
-        }
-
-        dataSource.tableView(tableView, moveRowAtIndexPath: NSIndexPath(forRow: 3, inSection: 0), toIndexPath: NSIndexPath(forRow: 2, inSection: 1))
-        waitForExpectationsWithTimeout(10, handler: nil)
-    }
-
-    func testMoveWithCorrectedTarget() {
-        let (tableView,dataSource) = self.whenDelegate()
-        self.whenDataSource(dataSource, hasSectionIDs: ["a","b","c"])
-
-        self.whenDataSource(dataSource, hasRowIDs: ["0","1","2","3"], forSectionID: "a")
-        self.whenDataSource(dataSource, hasRowIDs: ["0","1","2"], forSectionID: "b")
-
-        self.whenDataSource(dataSource, canMoveItemAtSectionID: "a", rowID: "3")
-        self.whenDataSource(dataSource, retargetsToLocation: LocationWithOptionalItem(tableView: tableView, sectionID:"a", item:MockTVItem(identifier: "1")))
-
-        let indexPath = dataSource.tableView(tableView, targetIndexPathForMoveFromRowAtIndexPath: NSIndexPath(forRow: 3, inSection: 0), toProposedIndexPath: NSIndexPath(forRow: 2, inSection: 0))
-        XCTAssert(indexPath.section == 0)
-        XCTAssert(indexPath.row == 1)
-
-    }
-
-    // testing: optional func tableView(_ tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool
-    func testCanEditItem() {
-        let (tableView,dataSource) = self.whenDelegate()
-        self.whenDataSource(dataSource, hasSectionIDs: ["a"])
-        self.whenDataSource(dataSource, hasRowIDs: ["0","1","2","3"], forSectionID: "a")
-
-        self.whenDataSource(dataSource, canEditItemAtSectionID: "a", rowID: "1")
-
-        XCTAssert(dataSource.tableView(tableView, canEditRowAtIndexPath: NSIndexPath(forRow: 1, inSection: 0)) == true)
-        XCTAssert(dataSource.tableView(tableView, canEditRowAtIndexPath: NSIndexPath(forRow: 0, inSection: 0)) == false)
-        XCTAssert(dataSource.tableView(tableView, canEditRowAtIndexPath: NSIndexPath(forRow: 1000, inSection: 0)) == false)
-        XCTAssert(dataSource.tableView(tableView, canEditRowAtIndexPath: NSIndexPath(forRow: 0, inSection: 1000)) == false)
-    }
-
-    func testDeleteItem() {
-        let (tableView,dataSource) = self.whenDelegate()
-        self.whenDataSource(dataSource, hasSectionIDs: ["a"])
-        self.whenDataSource(dataSource, hasRowIDs: ["0","1","2","3"], forSectionID: "a")
-
-        let willDeleteExpectation = expectationWithDescription("will delete callback")
-        let didDeleteExpectation = expectationWithDescription("did delete callback")
-        let sectionChangedExpectation = expectationWithDescription("sections changed callback")
-
-        dataSource.willDelete = { (atLocation:Location<MockTVItem>) -> Void in
-            XCTAssert(atLocation.sectionID == "a")
-            XCTAssert(atLocation.item.identifier == "1")
-            willDeleteExpectation.fulfill()
-        }
-
-        dataSource.didDelete = { (item: MockTVItem) -> Void in
-            XCTAssert(item.identifier == "1")
-            didDeleteExpectation.fulfill()
-        }
-
-        dataSource.didChangeSectionIDs = { (inSectionIDs:Dictionary<String,Array<MockTVItem>>) -> Void in
-            sectionChangedExpectation.fulfill()
-            XCTAssert(inSectionIDs.count == 1, "should be only one section")
-
-            guard let rows = inSectionIDs["a"] else {
-                XCTFail("no rows?")
-                return
-            }
-
-            let mappedIDs = rows.map({ (item) -> String in
-                return item.identifier
-            })
-
             XCTAssert(mappedIDs == ["0","2","3"])
 
         }
 
+        guard let tableView = self.tableView else {
+            XCTFail("no table view")
+            return
+        }
         dataSource.tableView(tableView, commitEditingStyle: UITableViewCellEditingStyle.Delete, forRowAtIndexPath: NSIndexPath(forRow: 1, inSection: 0))
         waitForExpectationsWithTimeout(10, handler: nil)
     }

//  Created by Ruotger Deecke on 28.07.15.
//  Copyright © 2015 Deecke,Roddi. All rights reserved.
//

import XCTest


        super.tearDown()
    }

    var tableView: MockTableView? = nil
    var dataSource: DataSource<MockTVItem>? = nil

    // MARK: - helper

    func mockTVItemsForIdentifiers(identifiers: [String]) -> [MockTVItem] {
        return identifiers.map { return MockTVItem(identifier:$0) }
    }

    // MARK: - given

    func givenDelegateAndDataSource() {
        self.tableView = MockTableView(frame: CGRect(x: 0, y: 0, width: 320, height: 960), style: .Plain)
        guard let tableView = self.tableView else {
            XCTFail("could not instantiate table view")
            return
        }
        self.dataSource = DataSource<MockTVItem>(tableView: tableView) { (inLocation) -> UITableViewCell in
            cellForSectionID(inLocation.sectionID, item: inLocation.item, tableView: inLocation.tableView)
        }

        tableView.insertCallback = { print("insert \($0)") }
        tableView.deleteCallback = { print("delete \($0)") }
        didCallDidSelectHandler = false
    }

    func givenDataSourceCanMoveItemAtSectionID(inSectionID: String, rowID inRowID: String) {
        guard let dataSource = self.dataSource else {
            XCTFail("no data source")
            return
        }
        dataSource.canMove = {(toLocation:Location<MockTVItem>) -> Bool in
            return toLocation.sectionID == inSectionID && toLocation.item.identifier == inRowID
        }
    }

    func givenDataSourceRetargetsToRowIDSectionID(rowID: String, sectionID: String) {
        guard let dataSource = self.dataSource else {
            XCTFail("no data source")
            return
        }
        guard let tableView = self.tableView else {
            XCTFail("could not instantiate table view")
            return
        }
        let location = LocationWithOptionalItem(tableView: tableView, sectionID: sectionID, item: MockTVItem(identifier: rowID))
        dataSource.targetMovedItem = { (fromLocation:Location<MockTVItem>, proposedLocation:LocationWithOptionalItem<MockTVItem>) -> LocationWithOptionalItem<MockTVItem> in
            return location
        }
    }

    func givenDataSourceCanEditItemAtSectionID(inSectionID: String, rowID inRowID: String) {
        guard let dataSource = self.dataSource else {
            XCTFail("no data source")
            return
        }
        dataSource.canEdit = {(atLocation:Location<MockTVItem>) -> Bool in
            return atLocation.sectionID == inSectionID && atLocation.item.identifier == inRowID
        }
    }

    var didCallDidSelectHandler = false

    func givenDataSourceWillAllowSelectInSectionID(sectionID: String, rowID inRowID: String) {
        guard let dataSource = self.dataSource else {
            XCTFail("no data source")
            return
        }
        didCallDidSelectHandler = false
        dataSource.didSelect = { (inLocation:Location<MockTVItem>) -> Void in
            XCTAssert(inLocation.sectionID == "a")
            XCTAssert(inLocation.item.identifier == "1")
            self.didCallDidSelectHandler = true
        }
    }

    func givenDiffsAreCleared() {
        guard let tableView = self.tableView else {
            XCTFail("no table view")
            return
        }
        tableView.deletionIndexPaths = []
        tableView.insertionIndexPaths = []
    }

    func givenExpectRowIDsAfterMove(rowIDs: [String], forSectionID sectionID: String, withSectionCount sectionCount: Int) {
        guard let dataSource = self.dataSource else {
            XCTFail("no data source")
            return
        }
        dataSource.didChangeSectionIDs = { (inSectionIDs:Dictionary<String,Array<MockTVItem>>) -> Void in
            XCTAssert(inSectionIDs.count == sectionCount)

            guard let rows = inSectionIDs[sectionID] else {
                XCTFail("no rows?")
                return
            }

            let mappedIDs = rows.map({ (item) -> String in
                return item.identifier
            })

            XCTAssert(mappedIDs == rowIDs)
        }

    }

    // MARK: - when

    func whenDataSourceHasSectionIDs(inSectionIDs:Array<String>) {
        guard let dataSource = self.dataSource else {
            XCTFail("no data source")
            return
        }
        dataSource.updateSections(inSectionIDs, animated: true)
    }

    func whenUpdatingRowsWithIdentifiers(identifiers: [String], sectionID: String) {
        guard let dataSource = self.dataSource else {
            XCTFail("no data source")
            return
        }
        dataSource.updateRows(self.mockTVItemsForIdentifiers(identifiers), section: sectionID, animated: true)
    }

    func whenSelectingRow(row: Int, section: Int) {
        guard let dataSource = self.dataSource else {
            XCTFail("no data source")
            return
        }
        guard let tableView = self.tableView else {
            XCTFail("no table view")
            return
        }
        let indexPath = NSIndexPath(forRow: row, inSection: section)
        dataSource.tableView(tableView, didSelectRowAtIndexPath: indexPath)

    }

    func whenMovingRow(sourceRow: Int, sourceSection: Int, toRow destinationRow: Int, toSection destinationSection: Int) {
        guard let dataSource = self.dataSource else {
            XCTFail("no data source")
            return
        }
        guard let tableView = self.tableView else {
            XCTFail("no table view")
            return
        }
        dataSource.tableView(tableView, moveRowAtIndexPath: NSIndexPath(forRow: sourceRow, inSection: sourceSection), toIndexPath: NSIndexPath(forRow: destinationRow, inSection: destinationSection))
    }

    // MARK: - then

    func thenNumberOfSectionsIs(numberOfSections: Int) {
        guard let dataSource = self.dataSource else {
            XCTFail("no data source")
            return
        }
        guard let tableView = self.tableView else {
            XCTFail("no table view")
            return
        }
        XCTAssert(dataSource.numberOfSectionsInTableView(tableView) == numberOfSections, "...")
    }

    func thenNumberOfRowsIs(numberOfRows: Int, sectionIndex: Int) {
        guard let dataSource = self.dataSource else {
            XCTFail("no data source")
            return
        }
        guard let tableView = self.tableView else {
            XCTFail("no table view")
            return
        }
        XCTAssert(dataSource.tableView(tableView, numberOfRowsInSection: sectionIndex) == numberOfRows)
    }

    let indexListMapper = { (indexList: [Int]) -> NSIndexPath in
        if indexList.count != 2 {
            return NSIndexPath(forItem: Int.max, inSection: Int.max)
        }
        return NSIndexPath(forItem: indexList[0], inSection: indexList[1])
    }

    func thenInsertionRowsSectionsAre(indexPaths: [[Int]]) {
        guard let tableView = self.tableView else {
            XCTFail("no table view")
            return
        }

        let realIndexPaths = indexPaths.map(indexListMapper)

        XCTAssert(tableView.insertionIndexPaths == realIndexPaths)
    }

    func thenDeletionRowsSectionsAre(indexPaths: [[Int]]) {
        guard let tableView = self.tableView else {
            XCTFail("no table view")
            return
        }

        let realIndexPaths = indexPaths.map(indexListMapper)

        XCTAssert(tableView.deletionIndexPaths == realIndexPaths)
    }

    func thenCanSelectHandlerWasCalled() {
        XCTAssert(self.didCallDidSelectHandler)
    }

    func thenCanMoveItemAtRow(row: Int, section: Int, canMove: Bool) {
        guard let dataSource = self.dataSource else {
            XCTFail("no data source")
            return
        }
        guard let tableView = self.tableView else {
            XCTFail("no table view")
            return
        }
        XCTAssert(dataSource.tableView(tableView, canMoveRowAtIndexPath: NSIndexPath(forRow: row, inSection: section)) == canMove);

    }

    func thenCanEditItemAtRow(row: Int, section: Int, canMove: Bool) {
        guard let dataSource = self.dataSource else {
            XCTFail("no data source")
            return
        }
        guard let tableView = self.tableView else {
            XCTFail("no table view")
            return
        }
        XCTAssert(dataSource.tableView(tableView, canEditRowAtIndexPath: NSIndexPath(forRow: row, inSection: section)) == canMove);
    }

    // MARK: - test

    func testDataSourceSections() {
        self.givenDelegateAndDataSource()

        self.dataSource?.updateSections(["a","b","c"], animated: true)
        self.thenNumberOfSectionsIs(3)

        self.dataSource?.updateSections(["a","d","c"], animated: true)
        self.thenNumberOfSectionsIs(3)

        self.dataSource?.updateSections([], animated: true)
        self.thenNumberOfSectionsIs(0)

    }

    func testDataSourceRows() {
        self.givenDelegateAndDataSource()

        self.whenDataSourceHasSectionIDs(["a","b","c"])
        self.thenNumberOfSectionsIs(3)

        self.whenUpdatingRowsWithIdentifiers(["0","1","2"], sectionID: "a")

        self.thenNumberOfRowsIs(3, sectionIndex: 0)
        self.thenInsertionRowsSectionsAre([[0,0],[1,0],[2,0]])
        self.thenDeletionRowsSectionsAre([])

        self.givenDiffsAreCleared()

        self.whenUpdatingRowsWithIdentifiers(["0","2","3"], sectionID: "a")
        self.thenNumberOfSectionsIs(3)
        self.thenInsertionRowsSectionsAre([[2,0]])
        self.thenDeletionRowsSectionsAre([[1,0]])
    }

    func testDataSourceRowsDelete() {
        self.givenDelegateAndDataSource()

        self.whenDataSourceHasSectionIDs(["a","b","c"])
        self.thenNumberOfSectionsIs(3)

        self.whenUpdatingRowsWithIdentifiers(["0","1","2"], sectionID: "a")
        self.givenDiffsAreCleared()

        self.whenUpdatingRowsWithIdentifiers(["0","5","4","2"], sectionID: "a")
        self.thenNumberOfRowsIs(4, sectionIndex: 0)
        self.thenInsertionRowsSectionsAre([[1,0],[2,0]])
        self.thenDeletionRowsSectionsAre([[1,0]])

        self.givenDiffsAreCleared()

        print("")

        self.whenUpdatingRowsWithIdentifiers(["0","2"], sectionID: "a")
        self.thenNumberOfRowsIs(2, sectionIndex: 0)
        self.thenInsertionRowsSectionsAre([])
        self.thenDeletionRowsSectionsAre([[1,0],[2,0]])

        self.givenDiffsAreCleared()

        self.whenUpdatingRowsWithIdentifiers(["0","1","2","3","4","5"], sectionID: "a")
        self.givenDiffsAreCleared()

        self.whenUpdatingRowsWithIdentifiers(["0","2","4"], sectionID: "a")
        self.thenNumberOfRowsIs(3, sectionIndex: 0)
        self.thenInsertionRowsSectionsAre([])
        self.thenDeletionRowsSectionsAre([[1,0],[3,0],[5,0]])
    }

    func testDataSourceWhenCompletelyEmpty() {
        self.givenDelegateAndDataSource()

        self.thenNumberOfSectionsIs(0)
        self.thenNumberOfRowsIs(0, sectionIndex: 0)
    }

    func testDidSelect() {
        self.givenDelegateAndDataSource()
        self.givenDataSourceWillAllowSelectInSectionID("a", rowID: "1")

        self.whenDataSourceHasSectionIDs(["a","b","c"])
        self.thenNumberOfSectionsIs(3)

        self.whenUpdatingRowsWithIdentifiers(["0","1","2"], sectionID: "a")
        self.thenNumberOfRowsIs(3, sectionIndex: 0)

        self.whenSelectingRow(1, section: 0)
        self.thenCanSelectHandlerWasCalled()
    }

    func testCanMove() {
        self.givenDelegateAndDataSource()
        self.givenDataSourceCanMoveItemAtSectionID("a", rowID: "2")

        self.whenDataSourceHasSectionIDs(["a","b","c"])
        self.thenNumberOfSectionsIs(3)

        self.whenUpdatingRowsWithIdentifiers(["0","1","2"], sectionID: "a")
        self.thenNumberOfRowsIs(3, sectionIndex: 0)

        self.thenCanMoveItemAtRow(2, section: 0, canMove: true)
        self.thenCanMoveItemAtRow(1, section: 0, canMove: false)
    }

    func testMove() {
        self.givenDelegateAndDataSource()
        self.givenDataSourceCanMoveItemAtSectionID("a", rowID: "2")
        self.givenExpectRowIDsAfterMove(["0","2","1"], forSectionID: "a", withSectionCount: 1)


        self.whenDataSourceHasSectionIDs(["a","b","c"])
        self.thenNumberOfSectionsIs(3)

        self.whenUpdatingRowsWithIdentifiers(["0","1","2"], sectionID: "a")
        self.thenNumberOfRowsIs(3, sectionIndex: 0)

        self.whenMovingRow(2, sourceSection: 0, toRow: 1, toSection: 0)
    }

    func testMoveBeyondLastItem() {
        self.givenDelegateAndDataSource()
        self.givenDataSourceCanMoveItemAtSectionID("a", rowID: "1")
        self.givenExpectRowIDsAfterMove(["0","2","1"], forSectionID: "a", withSectionCount: 1)

        self.whenDataSourceHasSectionIDs(["a","b","c"])
        self.thenNumberOfSectionsIs(3)

        self.whenUpdatingRowsWithIdentifiers(["0","1","2"], sectionID: "a")
        self.thenNumberOfRowsIs(3, sectionIndex: 0)

        self.whenMovingRow(1, sourceSection: 0, toRow: 3, toSection: 0)
    }


    func testMoveAcrossSections() {
        self.givenDelegateAndDataSource()
        self.givenDataSourceCanMoveItemAtSectionID("a", rowID: "3")

        self.whenDataSourceHasSectionIDs(["a","b","c"])

        self.whenUpdatingRowsWithIdentifiers(["0","1","2","3"], sectionID: "a")
        self.whenUpdatingRowsWithIdentifiers(["0","1","2"], sectionID: "b")

        let expectation = expectationWithDescription("sections changed callback")

        guard let dataSource = self.dataSource else {
            XCTFail()
            return
        }

        dataSource.didChangeSectionIDs = { (inSectionIDs:Dictionary<String,Array<MockTVItem>>) -> Void in
            expectation.fulfill()
            XCTAssert(inSectionIDs.count == 2, "should be only two sections")

            guard let rowsA = inSectionIDs["a"] else {
                XCTFail("no rows for a?")
                return
            }

            let mappedIDsA = rowsA.map({ (item) -> String in
                return item.identifier
            })

            XCTAssert(mappedIDsA == ["0","1","2"])

            guard let rowsB = inSectionIDs["b"] else {
                XCTFail("no rows for b?")
                return
            }

            let mappedIDsB = rowsB.map({ (item) -> String in
                return item.identifier
            })

            XCTAssert(mappedIDsB == ["0","1","3","2"])
        }

        self.whenMovingRow(3, sourceSection: 0, toRow: 2, toSection: 1)

        self.waitForExpectationsWithTimeout(10, handler: nil)
    }

    func testMoveWithCorrectedTarget() {
        self.givenDelegateAndDataSource()
        self.givenDataSourceCanMoveItemAtSectionID("a", rowID: "3")
        self.givenDataSourceRetargetsToRowIDSectionID("1", sectionID: "a")

        self.whenDataSourceHasSectionIDs(["a","b","c"])

        self.whenUpdatingRowsWithIdentifiers(["0","1","2","3"], sectionID: "a")
        self.whenUpdatingRowsWithIdentifiers(["0","1","2"], sectionID: "b")

        guard let dataSource = self.dataSource else {
            XCTFail()
            return
        }
        guard let tableView = self.tableView else {
            XCTFail("no table view")
            return
        }
        let indexPath = dataSource.tableView(tableView, targetIndexPathForMoveFromRowAtIndexPath: NSIndexPath(forRow: 3, inSection: 0), toProposedIndexPath: NSIndexPath(forRow: 2, inSection: 0))
        XCTAssert(indexPath.section == 0)
        XCTAssert(indexPath.row == 1)
    }

    // testing: optional func tableView(_ tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool
    func testCanEditItem() {
        self.givenDelegateAndDataSource()
        self.givenDataSourceCanEditItemAtSectionID("a", rowID: "1")

        self.whenDataSourceHasSectionIDs(["a"])
        self.whenUpdatingRowsWithIdentifiers(["0","1","2","3"], sectionID: "a")

        self.thenCanEditItemAtRow(1, section: 0, canMove: true)
        self.thenCanEditItemAtRow(0, section: 0, canMove: false)
        self.thenCanEditItemAtRow(1000, section: 0, canMove: false)
        self.thenCanEditItemAtRow(0, section: 1000, canMove: false)
    }

    func testDeleteItem() {
        self.givenDelegateAndDataSource()
        self.whenDataSourceHasSectionIDs(["a"])
        self.whenUpdatingRowsWithIdentifiers(["0","1","2","3"], sectionID: "a")

        let willDeleteExpectation = expectationWithDescription("will delete callback")
        let didDeleteExpectation = expectationWithDescription("did delete callback")
        let sectionChangedExpectation = expectationWithDescription("sections changed callback")

        guard let dataSource = self.dataSource else {
            XCTFail()
            return
        }
        dataSource.willDelete = { (atLocation:Location<MockTVItem>) -> Void in
            XCTAssert(atLocation.sectionID == "a")
            XCTAssert(atLocation.item.identifier == "1")
            willDeleteExpectation.fulfill()
        }

        dataSource.didDelete = { (item: MockTVItem) -> Void in
            XCTAssert(item.identifier == "1")
            didDeleteExpectation.fulfill()
        }

        dataSource.didChangeSectionIDs = { (inSectionIDs:Dictionary<String,Array<MockTVItem>>) -> Void in
            sectionChangedExpectation.fulfill()
            XCTAssert(inSectionIDs.count == 1, "should be only one section")

            guard let rows = inSectionIDs["a"] else {
