diff --git a/Sources/YSideMenu/SideMenuController+Appearance.swift b/Sources/YSideMenu/SideMenuController+Appearance.swift index ea648a9..f6c30ef 100644 --- a/Sources/YSideMenu/SideMenuController+Appearance.swift +++ b/Sources/YSideMenu/SideMenuController+Appearance.swift @@ -22,7 +22,9 @@ extension SideMenuController { public var presentAnimation: Animation /// Animation for dismissing the side menu. Default = `.defaultDismiss`. public var dismissAnimation: Animation - + /// Whether the menu can be dismissed by swiping left or tapping on the dimmer. Default is `true`. + public var isDismissAllowed: Bool + /// Default appearance public static let `default` = Appearance() @@ -33,18 +35,21 @@ extension SideMenuController { /// - idealWidthPercentage: Ideal width for the side menu based on screen width. /// - presentAnimation: Animation for presenting the side menu. /// - dismissAnimation: Animation for dismissing the side menu. + /// - isDismissAllowed: Whether the menu can be dismissed by swiping left or tapping on the dimmer. public init( dimmerColor: UIColor = UIColor.black.withAlphaComponent(0.5), maximumWidth: CGFloat = 414, idealWidthPercentage: CGFloat = 0.8, presentAnimation: Animation = .defaultPresent, - dismissAnimation: Animation = .defaultDismiss + dismissAnimation: Animation = .defaultDismiss, + isDismissAllowed: Bool = true ) { self.dimmerColor = dimmerColor self.maximumWidth = maximumWidth self.idealWidthPercentage = idealWidthPercentage self.presentAnimation = presentAnimation self.dismissAnimation = dismissAnimation + self.isDismissAllowed = isDismissAllowed } } } diff --git a/Sources/YSideMenu/SideMenuController.swift b/Sources/YSideMenu/SideMenuController.swift index b9ffb6b..9daae06 100644 --- a/Sources/YSideMenu/SideMenuController.swift +++ b/Sources/YSideMenu/SideMenuController.swift @@ -61,6 +61,7 @@ public class SideMenuController: UIViewController { } internal func didDismiss() { + guard appearance.isDismissAllowed else { return } dismiss(animated: true) } } diff --git a/Tests/YSideMenuTests/SideMenuControllerTests.swift b/Tests/YSideMenuTests/SideMenuControllerTests.swift index a354f85..14b27c0 100644 --- a/Tests/YSideMenuTests/SideMenuControllerTests.swift +++ b/Tests/YSideMenuTests/SideMenuControllerTests.swift @@ -76,6 +76,61 @@ final class SideMenuControllerTests: XCTestCase { XCTAssertEqual(sut.dimmerView.backgroundColor, customAppearance.dimmerColor) XCTAssertLessThanOrEqual(sut.contentView.bounds.width, customAppearance.maximumWidth) } + + func test_presentAnimator_returnsTheCorrectAnimator() throws { + let sut = makeSpy(rootViewController: UIViewController()) + let parent = UIViewController() + let animator = try XCTUnwrap(sut.animationController(forPresented: sut, presenting: parent, source: parent)) + XCTAssertTrue(animator.isKind(of: SideMenuPresentAnimator.self)) + } + + func test_dismissAnimator_returnsTheCorrectAnimator() throws { + let sut = makeSpy(rootViewController: UIViewController()) + let animator = try XCTUnwrap(sut.animationController(forDismissed: sut)) + XCTAssertTrue(animator.isKind(of: SideMenuDismissAnimator.self)) + } + + func test_onDimmer() { + let sut = makeSpy(rootViewController: UIViewController()) + + XCTAssertFalse(sut.onDimmerTapped) + XCTAssertFalse(sut.isDismissed) + + sut.simulateOnDimmerTap() + + XCTAssertTrue(sut.onDimmerTapped) + XCTAssertTrue(sut.isDismissed) + } + + func test_onSwipeLeft() { + let sut = makeSpy(rootViewController: UIViewController()) + sut.loadViewIfNeeded() + + XCTAssertFalse(sut.onMenuSwiped) + XCTAssertFalse(sut.isDismissed) + + sut.simulateSwipeToDismiss() + + XCTAssertTrue(sut.onMenuSwiped) + XCTAssertTrue(sut.isDismissed) + } + + func test_forbidDismiss() { + let sut = makeSpy(rootViewController: UIViewController()) + sut.appearance.isDismissAllowed = false + sut.loadViewIfNeeded() + + XCTAssertFalse(sut.onMenuSwiped) + XCTAssertFalse(sut.onDimmerTapped) + XCTAssertFalse(sut.isDismissed) + + sut.simulateOnDimmerTap() + sut.simulateSwipeToDismiss() + _ = sut.accessibilityPerformEscape() + + XCTAssertFalse(sut.onMenuSwiped) + XCTAssertFalse(sut.onDimmerTapped) + } } private extension SideMenuControllerTests { @@ -112,11 +167,15 @@ final class SpySideMenuController: SideMenuController { override func simulateOnDimmerTap() { super.simulateOnDimmerTap() - onDimmerTapped = true + if appearance.isDismissAllowed { + onDimmerTapped = true + } } override func simulateSwipeToDismiss() { super.simulateSwipeToDismiss() - onMenuSwiped = true + if appearance.isDismissAllowed { + onMenuSwiped = true + } } }