@@ -99,6 +99,11 @@ - (UILabel *)referenceLabelForButton:(TORoundedButton *)button {
9999 return reference;
100100}
101101
102+ // / Reads the button's private `_isTapped` flag via KVC.
103+ - (BOOL )isTappedForButton : (TORoundedButton *)button {
104+ return [[button valueForKey: @" isTapped" ] boolValue ];
105+ }
106+
102107#pragma mark - Layout Regression
103108
104109- (void )testTitleLabelDoesNotWrapWhenButtonIsWideEnough {
@@ -389,4 +394,68 @@ - (void)testGlassStyleRoundTrip {
389394}
390395#endif
391396
397+ #pragma mark - Touch & Animation
398+
399+ - (void )testTouchSequenceTogglesTappedState {
400+ TORoundedButton *button = [[TORoundedButton alloc ] initWithText: @" Tap" ];
401+ XCTAssertFalse ([self isTappedForButton: button]);
402+
403+ [button sendActionsForControlEvents: UIControlEventTouchDown]; // _didTouchDownInside
404+ XCTAssertTrue ([self isTappedForButton: button]);
405+
406+ [button sendActionsForControlEvents: UIControlEventTouchDragExit]; // _didDragOutside
407+ XCTAssertFalse ([self isTappedForButton: button]);
408+
409+ [button sendActionsForControlEvents: UIControlEventTouchDragEnter]; // _didDragInside
410+ XCTAssertTrue ([self isTappedForButton: button]);
411+
412+ [button sendActionsForControlEvents: UIControlEventTouchUpInside]; // _didTouchUpInside:event:
413+ XCTAssertFalse ([self isTappedForButton: button]);
414+ }
415+
416+ - (void )testTouchCancelResetsTappedState {
417+ TORoundedButton *button = [[TORoundedButton alloc ] initWithText: @" Tap" ];
418+ [button sendActionsForControlEvents: UIControlEventTouchDown];
419+ XCTAssertTrue ([self isTappedForButton: button]);
420+ [button sendActionsForControlEvents: UIControlEventTouchCancel]; // _didDragOutside
421+ XCTAssertFalse ([self isTappedForButton: button]);
422+ }
423+
424+ - (void )testTouchDownScalesContainerThenRestoresOnTouchUp {
425+ TORoundedButton *button = [[TORoundedButton alloc ] initWithText: @" Tap" ];
426+ UIView *container = [button valueForKey: @" containerView" ];
427+
428+ [button sendActionsForControlEvents: UIControlEventTouchDown];
429+ // Container scales down to tappedButtonScale (default 0.97); .a is the x-scale factor.
430+ XCTAssertEqualWithAccuracy (container.transform .a , button.tappedButtonScale , 0.0001 );
431+
432+ [button sendActionsForControlEvents: UIControlEventTouchUpInside];
433+ XCTAssertEqualWithAccuracy (container.transform .a , 1.0 , 0.0001 );
434+ }
435+
436+ - (void )testTouchDimsLabelWhenTappedTextAlphaSet {
437+ TORoundedButton *button = [[TORoundedButton alloc ] initWithText: @" Tap" ];
438+ button.tappedTextAlpha = 0.4 ; // a value < 1 enables the alpha-dim path (1.0 disables it)
439+ UILabel *titleLabel = [button valueForKey: @" titleLabel" ];
440+
441+ [button sendActionsForControlEvents: UIControlEventTouchDown];
442+ XCTAssertEqualWithAccuracy (titleLabel.alpha , 0.4 , 0.0001 );
443+
444+ [button sendActionsForControlEvents: UIControlEventTouchUpInside];
445+ XCTAssertEqualWithAccuracy (titleLabel.alpha , 1.0 , 0.0001 );
446+ }
447+
448+ - (void )testTappedBackgroundColorPathForSolidStyle {
449+ TORoundedButton *button = [[TORoundedButton alloc ] initWithText: @" Tap" ];
450+ button.backgroundStyle = TORoundedButtonBackgroundStyleSolid;
451+ button.tappedTintColor = [UIColor redColor ];
452+
453+ // With a tintable (solid) background and an explicit tapped tint, the tap sequence
454+ // exercises the background-color animation path in both directions.
455+ [button sendActionsForControlEvents: UIControlEventTouchDown];
456+ XCTAssertTrue ([self isTappedForButton: button]);
457+ [button sendActionsForControlEvents: UIControlEventTouchUpInside];
458+ XCTAssertFalse ([self isTappedForButton: button]);
459+ }
460+
392461@end
0 commit comments