Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for vertical scrolling/peeking implementation #15

Merged
merged 6 commits into from
Jun 27, 2018
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; };
607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; };
607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; };
607FACEC1AFB9204008FA782 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* Tests.swift */; };
607FACEC1AFB9204008FA782 /* HorizontalScrollDirectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* HorizontalScrollDirectionTests.swift */; };
69A57A2E20E39A1700D492D4 /* VerticalScrollDirectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69A57A2D20E39A1700D492D4 /* VerticalScrollDirectionTests.swift */; };
6CC61A01D070E53B5C9713D3 /* Pods_MSPeekCollectionViewDelegateImplementation_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D63706738AAABD8B65F2802 /* Pods_MSPeekCollectionViewDelegateImplementation_Example.framework */; };
/* End PBXBuildFile section */

Expand All @@ -39,7 +40,8 @@
607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
607FACE51AFB9204008FA782 /* MSPeekCollectionViewDelegateImplementation_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MSPeekCollectionViewDelegateImplementation_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
607FACEB1AFB9204008FA782 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = "<group>"; };
607FACEB1AFB9204008FA782 /* HorizontalScrollDirectionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HorizontalScrollDirectionTests.swift; sourceTree = "<group>"; };
69A57A2D20E39A1700D492D4 /* VerticalScrollDirectionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerticalScrollDirectionTests.swift; sourceTree = "<group>"; };
6D62A78B4ED727736705D900 /* Pods-MSPeekCollectionViewDelegateImplementation_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MSPeekCollectionViewDelegateImplementation_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-MSPeekCollectionViewDelegateImplementation_Example/Pods-MSPeekCollectionViewDelegateImplementation_Example.release.xcconfig"; sourceTree = "<group>"; };
7C9735FF72CB49CDCEB9B535 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
A2049B1E9B6ED415F87F1C5A /* MSPeekCollectionViewDelegateImplementation.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = MSPeekCollectionViewDelegateImplementation.podspec; path = ../MSPeekCollectionViewDelegateImplementation.podspec; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
Expand Down Expand Up @@ -135,7 +137,8 @@
607FACE81AFB9204008FA782 /* Tests */ = {
isa = PBXGroup;
children = (
607FACEB1AFB9204008FA782 /* Tests.swift */,
607FACEB1AFB9204008FA782 /* HorizontalScrollDirectionTests.swift */,
69A57A2D20E39A1700D492D4 /* VerticalScrollDirectionTests.swift */,
607FACE91AFB9204008FA782 /* Supporting Files */,
);
path = Tests;
Expand Down Expand Up @@ -331,7 +334,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
607FACEC1AFB9204008FA782 /* Tests.swift in Sources */,
69A57A2E20E39A1700D492D4 /* VerticalScrollDirectionTests.swift in Sources */,
607FACEC1AFB9204008FA782 /* HorizontalScrollDirectionTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
delegate = MSPeekCollectionViewDelegateImplementation(maximumItemsToScroll: 3)
delegate = MSPeekCollectionViewDelegateImplementation()
collectionView.configureForPeekingDelegate()
collectionView.delegate = delegate
collectionView.dataSource = self
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import XCTest
@testable import MSPeekCollectionViewDelegateImplementation_Example
@testable import MSPeekCollectionViewDelegateImplementation

class Tests: XCTestCase {
class HorizontalScrollDirectionTests: XCTestCase {

var sut: MSPeekCollectionViewDelegateImplementation!
var collectionView: UICollectionView!
Expand All @@ -21,7 +21,7 @@ class Tests: XCTestCase {
super.tearDown()
}

private func simulateVerticalScroll(distance: CGFloat) -> UnsafeMutablePointer<CGPoint> {
private func simulateHorizontalScroll(distance: CGFloat) -> UnsafeMutablePointer<CGPoint> {
sut.scrollViewWillBeginDragging(collectionView)
let simulatedTargetContentOffset = UnsafeMutablePointer<CGPoint>.allocate(capacity: 1)
simulatedTargetContentOffset.pointee = CGPoint(x: collectionView.contentOffset.x + distance, y: 0)
Expand Down Expand Up @@ -97,30 +97,30 @@ class Tests: XCTestCase {
sut = MSPeekCollectionViewDelegateImplementation(cellSpacing: 20, cellPeekWidth: 20, scrollThreshold: 50)
collectionView.contentOffset = CGPoint(x: 0, y: 0)
sut.scrollViewWillBeginDragging(collectionView)
let simulatedTargetContentOffset = simulateVerticalScroll(distance: 50)
let simulatedTargetContentOffset = simulateHorizontalScroll(distance: 50)
XCTAssertEqual(simulatedTargetContentOffset.pointee.x, 260)
}

func test_ScrollViewWillEndDragging_ScrollGreaterThanThreshold_DirectionLeft_ShouldScrollToPreviousItem() {
collectionView.frame = CGRect(x: 0, y: 0, width: 320, height: 200)
sut = MSPeekCollectionViewDelegateImplementation(cellSpacing: 20, cellPeekWidth: 20, scrollThreshold: 50)
collectionView.contentOffset = CGPoint(x: 260, y: 0)
let simulatedTargetContentOffset = simulateVerticalScroll(distance: -210)
let simulatedTargetContentOffset = simulateHorizontalScroll(distance: -51)
XCTAssertEqual(simulatedTargetContentOffset.pointee.x, 0)
}

func test_ScrollDistanceIsLarge_MaxIsDefault_ShouldScroll1ItemByDefault() {
collectionView.frame = CGRect(x: 0, y: 0, width: 320, height: 200)
sut = MSPeekCollectionViewDelegateImplementation(cellSpacing: 20, cellPeekWidth: 20, scrollThreshold: 50)
let simulatedTargetContentOffset = simulateVerticalScroll(distance: 500)
let simulatedTargetContentOffset = simulateHorizontalScroll(distance: 500)
XCTAssertEqual(simulatedTargetContentOffset.pointee.x, 260)
}

//The number of cells that will be scrolled depends on the distance scrolled and the max scroll items specified by the implementation
func test_ScrollDistanceIsLarge_MaxIsSet_ShouldScrollProperly() {
collectionView.frame = CGRect(x: 0, y: 0, width: 320, height: 200)
sut = MSPeekCollectionViewDelegateImplementation(cellSpacing: 20, cellPeekWidth: 20, scrollThreshold: 50, maximumItemsToScroll: 2)
let simulatedTargetContentOffset = simulateVerticalScroll(distance: 640)
let simulatedTargetContentOffset = simulateHorizontalScroll(distance: 640)
XCTAssertEqual(simulatedTargetContentOffset.pointee.x, 520)
}

Expand All @@ -135,7 +135,7 @@ class Tests: XCTestCase {

}

extension Tests: UICollectionViewDataSource {
extension HorizontalScrollDirectionTests: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
Expand Down
153 changes: 153 additions & 0 deletions Example/Tests/VerticalScrollDirectionTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import XCTest
@testable import MSPeekCollectionViewDelegateImplementation_Example
@testable import MSPeekCollectionViewDelegateImplementation

class VerticalScrollDirectionTests: XCTestCase {

var sut: MSPeekCollectionViewDelegateImplementation!
var collectionView: UICollectionView!
var collectionViewFlowLayout: UICollectionViewFlowLayout!
override func setUp() {
super.setUp()
sut = MSPeekCollectionViewDelegateImplementation(scrollDirection: .vertical)
collectionViewFlowLayout = UICollectionViewFlowLayout()
collectionViewFlowLayout.scrollDirection = .vertical
collectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: collectionViewFlowLayout)
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
collectionView.dataSource = self
}

override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}

private func simulateVerticalScroll(distance: CGFloat) -> UnsafeMutablePointer<CGPoint> {
sut.scrollViewWillBeginDragging(collectionView)
let simulatedTargetContentOffset = UnsafeMutablePointer<CGPoint>.allocate(capacity: 1)
simulatedTargetContentOffset.pointee = CGPoint(x: 0, y: collectionView.contentOffset.y + distance)
sut.scrollViewWillEndDragging(collectionView, withVelocity: CGPoint.zero, targetContentOffset: simulatedTargetContentOffset)
return simulatedTargetContentOffset
}

func test_minimumLineSpacing_ShouldBeEqualToCellSpacing() {
sut = MSPeekCollectionViewDelegateImplementation(cellSpacing: 20, scrollDirection: .vertical)
let expectedLineSpacing = sut.collectionView(collectionView, layout: collectionViewFlowLayout, minimumLineSpacingForSectionAt: 0)
XCTAssertEqual(expectedLineSpacing, 20)
}

//Left and Right Insets should be equal to the cell spacing plus the cell peek width
func test_LeftAndRightEdgeInsets_ShouldBeSetCorrectly() {
sut = MSPeekCollectionViewDelegateImplementation(cellSpacing: 20, cellPeekWidth: 30, scrollDirection: .vertical)
let expectedEdgeInsets = sut.collectionView(collectionView, layout: collectionViewFlowLayout, insetForSectionAt: 0)
XCTAssertEqual(expectedEdgeInsets.top, 50)
XCTAssertEqual(expectedEdgeInsets.bottom, 50)
}

func test_minimumInteritemSpacing_ShouldBe0() {
let expectedSpacing = sut.collectionView(collectionView, layout: collectionViewFlowLayout, minimumInteritemSpacingForSectionAt: 0)
XCTAssertEqual(expectedSpacing, 0)
}
//Item width should not become negative in edge case
func test_sizeForItemAtIndexPath_collectionViewSizeLessThanArgs_ShouldReturnSizeCorrectly() {
sut = MSPeekCollectionViewDelegateImplementation(cellSpacing: 20, cellPeekWidth: 30, scrollDirection: .vertical)
let testIndexPath = IndexPath(row: 0, section: 0)
let expectedSize = sut.collectionView(collectionView, layout: collectionViewFlowLayout, sizeForItemAt: testIndexPath)
XCTAssertEqual(expectedSize.height, 0)
XCTAssertEqual(expectedSize.width, 0)
}

//Item width should be collection view width minus double the cell spacing with the cell peek width because there's peeking and spacing on both sides
func test_sizeForItemAtIndexPath_ShouldReturnSizeCorrectly() {
collectionView.frame = CGRect(x: 0, y: 0, width: 320, height: 200)
sut = MSPeekCollectionViewDelegateImplementation(cellSpacing: 20, cellPeekWidth: 30, scrollDirection: .vertical)
let testIndexPath = IndexPath(row: 0, section: 0)
let expectedSize = sut.collectionView(collectionView, layout: collectionViewFlowLayout, sizeForItemAt: testIndexPath)
XCTAssertEqual(expectedSize.height, 100)
XCTAssertEqual(expectedSize.width, 320)
}

func test_ScrollViewWillEndDragging_ViewFrameIs0_ShouldNotCrash() {
sut = MSPeekCollectionViewDelegateImplementation(cellSpacing: 20, cellPeekWidth: 20, scrollThreshold: 50, scrollDirection: .vertical)
collectionView.contentOffset = CGPoint(x: 0, y: 0)
sut.scrollViewWillBeginDragging(collectionView)
let simulatedTargetContentOffset = UnsafeMutablePointer<CGPoint>.allocate(capacity: 1)
simulatedTargetContentOffset.pointee = CGPoint(x: 0, y: 49)
sut.scrollViewWillEndDragging(collectionView, withVelocity: CGPoint.zero, targetContentOffset: simulatedTargetContentOffset)
XCTAssertEqual(simulatedTargetContentOffset.pointee.x, 0)
}

func test_ScrollViewWillEndDragging_ScrollLessThanThreshold_ShouldNotScrollToAdjacentItem() {
let initialPosition: CGFloat = 140
collectionView.frame = CGRect(x: 0, y: 0, width: 320, height: 200)
sut = MSPeekCollectionViewDelegateImplementation(cellSpacing: 20, cellPeekWidth: 20, scrollThreshold: 50, scrollDirection: .vertical)
collectionView.contentOffset = CGPoint(x: 0, y: initialPosition)
sut.scrollViewWillBeginDragging(collectionView)
let simulatedTargetContentOffset = UnsafeMutablePointer<CGPoint>.allocate(capacity: 1)
simulatedTargetContentOffset.pointee = CGPoint(x: 0, y: initialPosition + 49)
sut.scrollViewWillEndDragging(collectionView, withVelocity: CGPoint.zero, targetContentOffset: simulatedTargetContentOffset)
XCTAssertEqual(simulatedTargetContentOffset.pointee.y, initialPosition)

sut.scrollViewWillBeginDragging(collectionView)
simulatedTargetContentOffset.pointee = CGPoint(x: 0, y: initialPosition - 49)
sut.scrollViewWillEndDragging(collectionView, withVelocity: CGPoint.zero, targetContentOffset: simulatedTargetContentOffset)
XCTAssertEqual(simulatedTargetContentOffset.pointee.y, initialPosition)
}

func test_ScrollViewWillEndDragging_ScrollGreaterThanThreshold_DirectionRight_ShouldScrollToNextItem() {
collectionView.frame = CGRect(x: 0, y: 0, width: 320, height: 200)
sut = MSPeekCollectionViewDelegateImplementation(cellSpacing: 20, cellPeekWidth: 20, scrollThreshold: 50, scrollDirection: .vertical)
collectionView.contentOffset = CGPoint(x: 0, y: 0)
sut.scrollViewWillBeginDragging(collectionView)
let simulatedTargetContentOffset = simulateVerticalScroll(distance: 50)
XCTAssertEqual(simulatedTargetContentOffset.pointee.y, 140)
}

func test_ScrollViewWillEndDragging_ScrollGreaterThanThreshold_DirectionLeft_ShouldScrollToPreviousItem() {
collectionView.frame = CGRect(x: 0, y: 0, width: 320, height: 200)
sut = MSPeekCollectionViewDelegateImplementation(cellSpacing: 20, cellPeekWidth: 20, scrollThreshold: 50, scrollDirection: .vertical)
collectionView.contentOffset = CGPoint(x: 0, y: 140)
let simulatedTargetContentOffset = simulateVerticalScroll(distance: -50)
XCTAssertEqual(simulatedTargetContentOffset.pointee.y, 0)
}

func test_ScrollDistanceIsLarge_MaxIsDefault_ShouldScroll1ItemByDefault() {
collectionView.frame = CGRect(x: 0, y: 0, width: 320, height: 200)
sut = MSPeekCollectionViewDelegateImplementation(cellSpacing: 20, cellPeekWidth: 20, scrollThreshold: 50, scrollDirection: .vertical)
let simulatedTargetContentOffset = simulateVerticalScroll(distance: 500)
XCTAssertEqual(simulatedTargetContentOffset.pointee.y, 140)
}

//The number of cells that will be scrolled depends on the distance scrolled and the max scroll items specified by the implementation
func test_ScrollDistanceIsLarge_MaxIsSet_ShouldScrollProperly() {
collectionView.frame = CGRect(x: 0, y: 0, width: 320, height: 200)
sut = MSPeekCollectionViewDelegateImplementation(cellSpacing: 20, cellPeekWidth: 20, scrollThreshold: 50, maximumItemsToScroll: 2, scrollDirection: .vertical)
let simulatedTargetContentOffset = simulateVerticalScroll(distance: 320)
XCTAssertEqual(simulatedTargetContentOffset.pointee.y, 280)
}

func test_contentOffsetAtIndex_ShouldReturnCorrectOffset() {
collectionView.frame = CGRect(x: 0, y: 0, width: 320, height: 200)
sut = MSPeekCollectionViewDelegateImplementation(cellSpacing: 20, cellPeekWidth: 20, scrollThreshold: 50, maximumItemsToScroll: 2, scrollDirection: .vertical)
let offset = sut.scrollView(collectionView, contentOffsetForItemAtIndex: 0)
XCTAssertEqual(offset, 0)
let offset2 = sut.scrollView(collectionView, contentOffsetForItemAtIndex: 1)
XCTAssertEqual(offset2, 140)
}

}

extension VerticalScrollDirectionTests: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 4
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
return cell
}
}
Loading