From e70c1f9fa392af9e7dab71f899080dff75311d85 Mon Sep 17 00:00:00 2001
From: Kazuhiro Hayashi <kazuhiro.hayashi.49@gmail.com>
Date: Sun, 20 Jan 2019 18:52:35 +0900
Subject: [PATCH 1/3] added guard statement when numberOfItem is zero

---
 PagingKit/PagingMenuView.swift | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/PagingKit/PagingMenuView.swift b/PagingKit/PagingMenuView.swift
index e59ef1a..cb7c3f0 100644
--- a/PagingKit/PagingMenuView.swift
+++ b/PagingKit/PagingMenuView.swift
@@ -346,6 +346,10 @@ open class PagingMenuView: UIScrollView {
     /// - Parameter index: An index that identifies a item by its index.
     /// - Returns: A rectangle defining the area in which the table view draws the row or right edge rect if index is over the number of items.
     open func rectForItem(at index: Int) -> CGRect {
+        guard 0 < widths.count else {
+            return CGRect(x: 0, y: 0, width: 0, height: bounds.height)
+        }
+        
         guard index < widths.count else {
             let rightEdge = widths.reduce(CGFloat(0)) { (sum, width) in sum + width }
             let mostRightWidth = widths[widths.endIndex - 1]

From 4696cdc85bf3a35a4119200e15203f869bbc949e Mon Sep 17 00:00:00 2001
From: Kazuhiro Hayashi <kazuhiro.hayashi.49@gmail.com>
Date: Sun, 20 Jan 2019 19:09:50 +0900
Subject: [PATCH 2/3] added a boundary tests

---
 PagingKit/PagingMenuView.swift           |  6 ++
 PagingKitTests/PagingMenuViewTests.swift | 74 +++++++++++++++++++++++-
 2 files changed, 77 insertions(+), 3 deletions(-)

diff --git a/PagingKit/PagingMenuView.swift b/PagingKit/PagingMenuView.swift
index cb7c3f0..f882cb3 100644
--- a/PagingKit/PagingMenuView.swift
+++ b/PagingKit/PagingMenuView.swift
@@ -356,6 +356,12 @@ open class PagingMenuView: UIScrollView {
             return CGRect(x: rightEdge, y: 0, width: mostRightWidth, height: bounds.height)
         }
         
+        guard 0 <= index else {
+            let leftEdge = -widths[0]
+            let mostLeftWidth = widths[0]
+            return CGRect(x: leftEdge, y: 0, width: mostLeftWidth, height: bounds.height)
+        }
+        
         var x = (0..<index).reduce(0) { (sum, idx) in
             return sum + widths[idx]
         }
diff --git a/PagingKitTests/PagingMenuViewTests.swift b/PagingKitTests/PagingMenuViewTests.swift
index 4e0a19c..c0e88f2 100644
--- a/PagingKitTests/PagingMenuViewTests.swift
+++ b/PagingKitTests/PagingMenuViewTests.swift
@@ -115,9 +115,77 @@ class PagingMenuViewTests: XCTestCase {
         pagingMenuView?.dataSource = dataSource
         pagingMenuView?.reloadData()
         
-        let rect = pagingMenuView?.rectForItem(at: 3)
-        XCTAssertEqual(rect,
-                       CGRect(x: 300, y: 0, width: 100, height: 44), "get correct rect")
+
+        do {
+            let rect = pagingMenuView?.rectForItem(at: -2)
+            XCTAssertEqual(rect,
+                           CGRect(x: -100, y: 0, width: 100, height: 44), "get correct rect")
+        }
+        
+        do {
+            let rect = pagingMenuView?.rectForItem(at: -1)
+            XCTAssertEqual(rect,
+                           CGRect(x: -100, y: 0, width: 100, height: 44), "get correct rect")
+        }
+        
+        do {
+            // first index
+            let rect = pagingMenuView?.rectForItem(at: 0)
+            XCTAssertEqual(rect,
+                           CGRect(x: 0, y: 0, width: 100, height: 44), "get correct rect")
+        }
+        
+        do {
+            let rect = pagingMenuView?.rectForItem(at: 3)
+            XCTAssertEqual(rect,
+                           CGRect(x: 300, y: 0, width: 100, height: 44), "get correct rect")
+        }
+        
+        do {
+            // last index
+            let rect = pagingMenuView?.rectForItem(at: 19)
+            XCTAssertEqual(rect,
+                           CGRect(x: 1900, y: 0, width: 100, height: 44), "get correct rect")
+        }
+        
+        do {
+            let rect = pagingMenuView?.rectForItem(at: 20)
+            XCTAssertEqual(rect,
+                           CGRect(x: 2000, y: 0, width: 100, height: 44), "get correct rect")
+        }
+        
+        do {
+            let rect = pagingMenuView?.rectForItem(at: 21)
+            XCTAssertEqual(rect,
+                           CGRect(x: 2000, y: 0, width: 100, height: 44), "get correct rect")
+        }
+    }
+    
+    func testRectForItemWhenDataSourceHasNoElement() {
+        let dataSource = MenuViewDataSourceSpy()
+        dataSource.widthForItem = 100
+        dataSource.registerNib(to: pagingMenuView)
+        dataSource.data = []
+        pagingMenuView?.dataSource = dataSource
+        pagingMenuView?.reloadData()
+        
+        do {
+            let rect = pagingMenuView?.rectForItem(at: -1)
+            XCTAssertEqual(rect,
+                           CGRect(x: 0, y: 0, width: 0, height: 44), "get correct rect")
+        }
+        
+        do {
+            let rect = pagingMenuView?.rectForItem(at: 0)
+            XCTAssertEqual(rect,
+                           CGRect(x: 0, y: 0, width: 0, height: 44), "get correct rect")
+        }
+        
+        do {
+            let rect = pagingMenuView?.rectForItem(at: 1)
+            XCTAssertEqual(rect,
+                           CGRect(x: 0, y: 0, width: 0, height: 44), "get correct rect")
+        }
     }
     
     func testRectForItemToEdgeCase() {

From 9511e46251b5b75029151ea14963b0cc446d7027 Mon Sep 17 00:00:00 2001
From: Kazuhiro Hayashi <kazuhiro.hayashi.49@gmail.com>
Date: Sun, 20 Jan 2019 19:24:39 +0900
Subject: [PATCH 3/3] added boundary test for spacing

---
 PagingKit/PagingMenuView.swift           | 11 ++---
 PagingKitTests/PagingMenuViewTests.swift | 55 ++++++++++++++++++++++++
 2 files changed, 61 insertions(+), 5 deletions(-)

diff --git a/PagingKit/PagingMenuView.swift b/PagingKit/PagingMenuView.swift
index f882cb3..8abaed6 100644
--- a/PagingKit/PagingMenuView.swift
+++ b/PagingKit/PagingMenuView.swift
@@ -217,6 +217,11 @@ open class PagingMenuView: UIScrollView {
     /// space setting between cells
     open var cellSpacing: CGFloat = 0
     
+    /// total space between cells
+    open var totalSpacing: CGFloat {
+        return cellSpacing * numberOfCellSpacing
+    }
+    
     /// The object that acts as the data source of the paging menu view.
     open weak var dataSource: PagingMenuViewDataSource?
     
@@ -351,7 +356,7 @@ open class PagingMenuView: UIScrollView {
         }
         
         guard index < widths.count else {
-            let rightEdge = widths.reduce(CGFloat(0)) { (sum, width) in sum + width }
+            let rightEdge = widths.reduce(CGFloat(0)) { (sum, width) in sum + width } + totalSpacing
             let mostRightWidth = widths[widths.endIndex - 1]
             return CGRect(x: rightEdge, y: 0, width: mostRightWidth, height: bounds.height)
         }
@@ -525,10 +530,6 @@ open class PagingMenuView: UIScrollView {
         return max(CGFloat(numberOfItem - 1), 0)
     }
     
-    private var totalSpacing: CGFloat {
-        return cellSpacing * numberOfCellSpacing
-    }
-
     private func recenterIfNeeded() {
         let currentOffset = contentOffset
         let contentWidth = contentSize.width
diff --git a/PagingKitTests/PagingMenuViewTests.swift b/PagingKitTests/PagingMenuViewTests.swift
index c0e88f2..b7027d3 100644
--- a/PagingKitTests/PagingMenuViewTests.swift
+++ b/PagingKitTests/PagingMenuViewTests.swift
@@ -161,6 +161,61 @@ class PagingMenuViewTests: XCTestCase {
         }
     }
     
+    func testRectForItemWithSpacing() {
+        let dataSource = MenuViewDataSourceSpy()
+        dataSource.widthForItem = 100
+        dataSource.registerNib(to: pagingMenuView)
+        dataSource.data = Array(repeating: "foo", count: 20)
+        pagingMenuView?.dataSource = dataSource
+        pagingMenuView?.cellSpacing = 10
+        pagingMenuView?.reloadData()
+        
+        
+        do {
+            let rect = pagingMenuView?.rectForItem(at: -2)
+            XCTAssertEqual(rect,
+                           CGRect(x: -100, y: 0, width: 100, height: 44), "get correct rect")
+        }
+        
+        do {
+            let rect = pagingMenuView?.rectForItem(at: -1)
+            XCTAssertEqual(rect,
+                           CGRect(x: -100, y: 0, width: 100, height: 44), "get correct rect")
+        }
+        
+        do {
+            // first index
+            let rect = pagingMenuView?.rectForItem(at: 0)
+            XCTAssertEqual(rect,
+                           CGRect(x: 0, y: 0, width: 100, height: 44), "get correct rect")
+        }
+        
+        do {
+            let rect = pagingMenuView?.rectForItem(at: 3)
+            XCTAssertEqual(rect,
+                           CGRect(x: 330, y: 0, width: 100, height: 44), "get correct rect")
+        }
+        
+        do {
+            // last index
+            let rect = pagingMenuView?.rectForItem(at: 19)
+            XCTAssertEqual(rect,
+                           CGRect(x: 2090, y: 0, width: 100, height: 44), "get correct rect")
+        }
+        
+        do {
+            let rect = pagingMenuView?.rectForItem(at: 20)
+            XCTAssertEqual(rect,
+                           CGRect(x: 2190, y: 0, width: 100, height: 44), "get correct rect")
+        }
+        
+        do {
+            let rect = pagingMenuView?.rectForItem(at: 21)
+            XCTAssertEqual(rect,
+                           CGRect(x: 2190, y: 0, width: 100, height: 44), "get correct rect")
+        }
+    }
+    
     func testRectForItemWhenDataSourceHasNoElement() {
         let dataSource = MenuViewDataSourceSpy()
         dataSource.widthForItem = 100