Skip to content

Commit

Permalink
gesture unit tests
Browse files Browse the repository at this point in the history
Reviewers: O4 Material Motion Apple platform reviewers, O2 Material Motion, featherless

Reviewed By: O4 Material Motion Apple platform reviewers, O2 Material Motion, featherless

Subscribers: featherless

Tags: #material_motion

Differential Revision: http://codereview.cc/D1757
  • Loading branch information
rcameron committed Oct 24, 2016
1 parent b414f2a commit ce18107
Show file tree
Hide file tree
Showing 6 changed files with 401 additions and 12 deletions.
18 changes: 17 additions & 1 deletion examples/apps/Catalog/Catalog.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
73D1CC614139358D78678E9F /* Pods_MaterialMotionDirectManipulationFamily_Catalog.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47AD29C808E6149118D934CA /* Pods_MaterialMotionDirectManipulationFamily_Catalog.framework */; };
DE0294BD1D5CE6E300A5BBA5 /* SimpleGestureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0294BB1D5CE6B400A5BBA5 /* SimpleGestureTests.swift */; };
DE1EFE1A1DB7EA33009939F5 /* ObjectiveCAPITests.m in Sources */ = {isa = PBXBuildFile; fileRef = DE1EFE191DB7EA33009939F5 /* ObjectiveCAPITests.m */; };
DE1EFE1D1DB81FB6009939F5 /* GestureActionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE1EFE1B1DB81F4C009939F5 /* GestureActionTests.swift */; };
DE73309F1D88A188003BBF53 /* ComposedGestureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE73309D1D88A14B003BBF53 /* ComposedGestureTests.swift */; };
DE7330A21D88BD9C003BBF53 /* TestableGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE7330A01D88B9A4003BBF53 /* TestableGestureRecognizer.swift */; };
DE7977851D4FF53900691A95 /* DirectManipulationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE7977841D4FF53900691A95 /* DirectManipulationViewController.swift */; };
DEFA68101DB96A2000C83810 /* AnchorPointTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEFA680E1DB969A700C83810 /* AnchorPointTests.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -46,9 +48,11 @@
DC36123760B2FCBFD565C0E7 /* Pods-MaterialMotionDirectManipulationFamily-UnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MaterialMotionDirectManipulationFamily-UnitTests.debug.xcconfig"; path = "../../../Pods/Target Support Files/Pods-MaterialMotionDirectManipulationFamily-UnitTests/Pods-MaterialMotionDirectManipulationFamily-UnitTests.debug.xcconfig"; sourceTree = "<group>"; };
DE0294BB1D5CE6B400A5BBA5 /* SimpleGestureTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SimpleGestureTests.swift; sourceTree = "<group>"; };
DE1EFE191DB7EA33009939F5 /* ObjectiveCAPITests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjectiveCAPITests.m; sourceTree = "<group>"; };
DE1EFE1B1DB81F4C009939F5 /* GestureActionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GestureActionTests.swift; sourceTree = "<group>"; };
DE73309D1D88A14B003BBF53 /* ComposedGestureTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ComposedGestureTests.swift; sourceTree = "<group>"; };
DE7330A01D88B9A4003BBF53 /* TestableGestureRecognizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestableGestureRecognizer.swift; sourceTree = "<group>"; };
DE7977841D4FF53900691A95 /* DirectManipulationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DirectManipulationViewController.swift; path = apps/Catalog/DirectManipulationViewController.swift; sourceTree = "<group>"; };
DEFA680E1DB969A700C83810 /* AnchorPointTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnchorPointTests.swift; sourceTree = "<group>"; };
F3DF17AC229B9E4FE3049EC8 /* Pods-MaterialMotionDirectManipulationFamily-Catalog.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MaterialMotionDirectManipulationFamily-Catalog.release.xcconfig"; path = "../../../Pods/Target Support Files/Pods-MaterialMotionDirectManipulationFamily-Catalog/Pods-MaterialMotionDirectManipulationFamily-Catalog.release.xcconfig"; sourceTree = "<group>"; };
F4B078EA77710D032C55A942 /* Pods-MaterialMotionDirectManipulationFamily-Catalog.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MaterialMotionDirectManipulationFamily-Catalog.debug.xcconfig"; path = "../../../Pods/Target Support Files/Pods-MaterialMotionDirectManipulationFamily-Catalog/Pods-MaterialMotionDirectManipulationFamily-Catalog.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -108,9 +112,11 @@
666FAA971D384A6B000363DA /* tests */ = {
isa = PBXGroup;
children = (
DE1EFE1E1DB820B3009939F5 /* helpers */,
DE0294BB1D5CE6B400A5BBA5 /* SimpleGestureTests.swift */,
DE73309D1D88A14B003BBF53 /* ComposedGestureTests.swift */,
DE7330A01D88B9A4003BBF53 /* TestableGestureRecognizer.swift */,
DE1EFE1B1DB81F4C009939F5 /* GestureActionTests.swift */,
DEFA680E1DB969A700C83810 /* AnchorPointTests.swift */,
DE1EFE191DB7EA33009939F5 /* ObjectiveCAPITests.m */,
);
name = tests;
Expand Down Expand Up @@ -175,6 +181,14 @@
name = Pods;
sourceTree = "<group>";
};
DE1EFE1E1DB820B3009939F5 /* helpers */ = {
isa = PBXGroup;
children = (
DE7330A01D88B9A4003BBF53 /* TestableGestureRecognizer.swift */,
);
name = helpers;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -386,6 +400,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DE1EFE1D1DB81FB6009939F5 /* GestureActionTests.swift in Sources */,
DEFA68101DB96A2000C83810 /* AnchorPointTests.swift in Sources */,
DE0294BD1D5CE6E300A5BBA5 /* SimpleGestureTests.swift in Sources */,
DE7330A21D88BD9C003BBF53 /* TestableGestureRecognizer.swift in Sources */,
DE1EFE1A1DB7EA33009939F5 /* ObjectiveCAPITests.m in Sources */,
Expand Down
14 changes: 10 additions & 4 deletions src/DirectManipulationMotionFamily.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ public final class Draggable: NSObject, Plan {
}

public func copy(with zone: NSZone? = nil) -> Any {
return Draggable(withGestureRecognizer: panGestureRecognizer)
let draggable = Draggable(withGestureRecognizer: panGestureRecognizer)
draggable.shouldAdjustAnchorPointOnGestureStart = shouldAdjustAnchorPointOnGestureStart
return draggable
}
}

Expand Down Expand Up @@ -120,7 +122,9 @@ public final class Pinchable: NSObject, Plan {
}

public func copy(with zone: NSZone? = nil) -> Any {
return Pinchable(withGestureRecognizer: pinchGestureRecognizer)
let pinchable = Pinchable(withGestureRecognizer: pinchGestureRecognizer)
pinchable.shouldAdjustAnchorPointOnGestureStart = shouldAdjustAnchorPointOnGestureStart
return pinchable
}
}

Expand All @@ -137,7 +141,7 @@ final class PinchablePerformer: NSObject, PlanPerforming, ComposablePerforming {

func addPlan(_ plan: Plan) {
guard let plan = plan as? Pinchable else {
fatalError("DraggablePerformer can only add Draggable plans.")
fatalError("PinchablePerformer can only add Pinchable plans.")
}

let recognizer = plan.pinchGestureRecognizer
Expand Down Expand Up @@ -197,7 +201,9 @@ public final class Rotatable: NSObject, Plan {
}

public func copy(with zone: NSZone? = nil) -> Any {
return Rotatable(withGestureRecognizer: rotationGestureRecognizer)
let rotatable = Rotatable(withGestureRecognizer: rotationGestureRecognizer)
rotatable.shouldAdjustAnchorPointOnGestureStart = shouldAdjustAnchorPointOnGestureStart
return rotatable
}
}

Expand Down
76 changes: 76 additions & 0 deletions tests/unit/AnchorPointTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
Copyright 2016-present The Material Motion Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import XCTest
import MaterialMotionRuntime
import MaterialMotionDirectManipulationFamily

class AnchorPointTests: XCTestCase {
func testThatAnchorPointIsModifiedByDraggablePerformer() {
let pan = TestablePanGestureRecognizer()
let draggable = Draggable(withGestureRecognizer: pan)
draggable.shouldAdjustAnchorPointOnGestureStart = true
let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))

let scheduler = Scheduler()
scheduler.addPlan(draggable, to: view)

pan.performTouch(location: CGPoint(x: 10, y: 20), state: .began)

XCTAssertEqual(view.layer.anchorPoint, CGPoint(x: 0.1, y: 0.2))
}

func testThatAnchorPointIsModifiedByPinchablePerformer() {
let pinch = TestablePinchGestureRecognizer()
let pinchable = Pinchable(withGestureRecognizer: pinch)
let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))

let scheduler = Scheduler()
scheduler.addPlan(pinchable, to: view)

pinch.performTouch(location: CGPoint(x: 10, y: 20), state: .began)

XCTAssertEqual(view.layer.anchorPoint, CGPoint(x: 0.1, y: 0.2))
}

func testThatAnchorPointIsModifiedByRotatablePerformer() {
let rotate = TestableRotationGestureRecognizer()
let rotatable = Rotatable(withGestureRecognizer: rotate)
let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))

let scheduler = Scheduler()
scheduler.addPlan(rotatable, to: view)

rotate.performTouch(location: CGPoint(x: 10, y: 20), state: .began)

XCTAssertEqual(view.layer.anchorPoint, CGPoint(x: 0.1, y: 0.2))
}

func testThatPinchableAnchorPointFlagPreventsModification() {
let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))

let pinch = TestablePinchGestureRecognizer()
let pinchable = Pinchable(withGestureRecognizer: pinch)
pinchable.shouldAdjustAnchorPointOnGestureStart = false

let scheduler = Scheduler()
scheduler.addPlan(pinchable, to: view)

pinch.performTouch(location: CGPoint(x: 10, y: 20), state: .began)

XCTAssertEqual(view.layer.anchorPoint, CGPoint(x: 0.5, y: 0.5))
}
}
79 changes: 79 additions & 0 deletions tests/unit/GestureActionTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
Copyright 2016-present The Material Motion Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import XCTest
import MaterialMotionRuntime
import MaterialMotionDirectManipulationFamily

class GestureActionTests: XCTestCase {
func testThatDraggableDrags() {
let pan = TestablePanGestureRecognizer()
let draggable = Draggable(withGestureRecognizer: pan)
let view = UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))

let scheduler = Scheduler()
scheduler.addPlan(draggable, to: view)

pan.performTouch(state: .began)
pan.performTouch(translation: CGPoint(x: 25, y: -50), state: .changed)

let newCenter = CGPoint(x: 25+25, y: 25-50)
XCTAssertEqual(newCenter, view.center, "View's center (\(view.center.x), \(view.center.y)) should be (\(newCenter.x), \(newCenter.y))")
}

func testThatPinchableScales() {
let pinch = TestablePinchGestureRecognizer()
let pinchable = Pinchable(withGestureRecognizer: pinch)
let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 80))

let scheduler = Scheduler()
scheduler.addPlan(pinchable, to: view)

pinch.performTouch(scale: 1, state: .began)
pinch.performTouch(scale: 0.50, state: .changed)

XCTAssertEqual(view.frame.width, 50, "View's width (\(view.bounds.width)) should equal 50")
XCTAssertEqual(view.frame.height, 40, "View's height (\(view.bounds.height)) should equal 40")
}

func testThatRotatableRotates() {
let rotateGesture = TestableRotationGestureRecognizer()
let rotatable = Rotatable(withGestureRecognizer: rotateGesture)
let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 80))

let scheduler = Scheduler()
scheduler.addPlan(rotatable, to: view)

rotateGesture.performTouch(state: .began)
rotateGesture.performTouch(rotation: CGFloat.pi / 2, state: .changed)

let rotation = atan2(view.transform.b, view.transform.a)

XCTAssertEqual(rotation, CGFloat.pi / 2, "View's rotation (\(rotation) should equal Pi / 2")
}

func testThatAnchorPointIsModified() {
let view = UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
let newAnchorPoint = CGPoint(x: 0.33, y: 0.33)
let changeAnchor = ChangeAnchorPoint(withAnchorPoint: newAnchorPoint)

let scheduler = Scheduler()
scheduler.addPlan(changeAnchor, to: view)

XCTAssertEqual(view.layer.anchorPoint, newAnchorPoint,
"View's anchor point (\(view.layer.anchorPoint.x), \(view.layer.anchorPoint.y)) should be (\(newAnchorPoint.x), \(newAnchorPoint.y))")
}
}
47 changes: 44 additions & 3 deletions tests/unit/SimpleGestureTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,59 @@ class SimpleGestureTests: XCTestCase {
let plan = Draggable(withGestureRecognizer: recognizer)

let scheduler = Scheduler()

scheduler.addPlan(plan, to: targetView)

guard recognizer.target is DraggablePerformer else {
guard recognizer.targets.first is DraggablePerformer else {
XCTFail("Pan gesture recognizer should have a DraggablePerformer target")
return
}

let selector = #selector(DraggablePerformer.handle(gesture:))
guard let action = recognizer.action, action == selector else {
guard recognizer.actions.contains(selector) else {
XCTFail("Pan gesture recognizer should have an action matching 'handle(gesture:)'")
return
}
}

func testThatTargetActionIsAddedToRecognizerUnderPinchablePlan() {
let targetView = UIView()

let recognizer = TestablePinchGestureRecognizer()
let plan = Pinchable(withGestureRecognizer: recognizer)

let scheduler = Scheduler()
scheduler.addPlan(plan, to: targetView)

guard recognizer.targets.first is PinchablePerformer else {
XCTFail("Pinch gesture recognizer should have a PinchablePerformer target")
return
}

let selector = #selector(PinchablePerformer.handle(gesture:))
guard recognizer.actions.contains(selector) else {
XCTFail("Pinch gesture recognizer should have an action matching 'handle(gesture:)'")
return
}
}

func testThatTargetActionIsAddedToRecognizerUnderRotatablePlan() {
let targetView = UIView()

let recognizer = TestableRotationGestureRecognizer()
let plan = Rotatable(withGestureRecognizer: recognizer)

let scheduler = Scheduler()
scheduler.addPlan(plan, to: targetView)

guard recognizer.targets.first is RotatablePerformer else {
XCTFail("Rotation gesture recognizer should have a RotatablePerformer target")
return
}

let selector = #selector(RotatablePerformer.handle(gesture:))
guard recognizer.actions.contains(selector) else {
XCTFail("Rotation gesture recognizer should have an action matching 'handle(gesture:)'")
return
}
}
}
Loading

0 comments on commit ce18107

Please sign in to comment.