blob: 10a8472d4e3a676a98dfa863d3dfeffa6e38a1b7 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ui/base/cocoa/hover_button.h"
#import <Cocoa/Cocoa.h>
#import "ui/base/test/cocoa_helper.h"
#import "ui/events/test/cocoa_test_event_utils.h"
@interface TestHoverButton : HoverButtonCocoa
@property(readwrite, nonatomic) NSRect hitbox;
@end
@implementation TestHoverButton
@synthesize hitbox = hitbox_;
- (void)setHitbox:(NSRect)hitbox {
hitbox_ = hitbox;
[self updateTrackingAreas];
}
@end
@interface HoverButtonTestTarget : NSObject
@property(nonatomic, copy) void (^actionHandler)(id);
@end
@implementation HoverButtonTestTarget
@synthesize actionHandler = actionHandler_;
- (void)dealloc {
[actionHandler_ release];
[super dealloc];
}
- (IBAction)action:(id)sender {
actionHandler_(sender);
}
@end
@interface HoverButtonTestDragDelegate : NSObject<HoverButtonDragDelegate>
@property(nonatomic, copy) void (^dragHandler)(HoverButtonCocoa*, NSEvent*);
@end
@implementation HoverButtonTestDragDelegate
@synthesize dragHandler = dragHandler_;
- (void)dealloc {
[dragHandler_ release];
[super dealloc];
}
- (void)beginDragFromHoverButton:(HoverButtonCocoa*)button
event:(NSEvent*)event {
dragHandler_(button, event);
}
@end
namespace {
class HoverButtonTest : public ui::CocoaTest {
public:
HoverButtonTest() {
NSRect frame = NSMakeRect(0, 0, 20, 20);
base::scoped_nsobject<TestHoverButton> button(
[[TestHoverButton alloc] initWithFrame:frame]);
button_ = button;
target_.reset([[HoverButtonTestTarget alloc] init]);
button_.target = target_;
button_.action = @selector(action:);
[[test_window() contentView] addSubview:button_];
}
protected:
void HoverAndExpect(CloseButtonHoverState hoverState) {
EXPECT_EQ(kHoverStateNone, button_.hoverState);
[button_ mouseEntered:cocoa_test_event_utils::EnterEvent()];
EXPECT_EQ(hoverState, button_.hoverState);
[button_ mouseExited:cocoa_test_event_utils::ExitEvent()];
EXPECT_EQ(kHoverStateNone, button_.hoverState);
}
bool HandleMouseDown(NSEvent* mouseDownEvent) {
__block bool action_sent = false;
target_.get().actionHandler = ^(id sender) {
action_sent = true;
EXPECT_EQ(kHoverStateMouseDown, button_.hoverState);
};
[NSApp sendEvent:mouseDownEvent];
target_.get().actionHandler = nil;
return action_sent;
}
TestHoverButton* button_; // Weak, owned by test_window().
base::scoped_nsobject<HoverButtonTestTarget> target_;
};
TEST_VIEW(HoverButtonTest, button_)
TEST_F(HoverButtonTest, Hover) {
EXPECT_EQ(kHoverStateNone, button_.hoverState);
// Default
HoverAndExpect(kHoverStateMouseOver);
// Tracking disabled
button_.trackingEnabled = NO;
HoverAndExpect(kHoverStateNone);
button_.trackingEnabled = YES;
// Button disabled
button_.enabled = NO;
HoverAndExpect(kHoverStateNone);
button_.enabled = YES;
// Back to normal
HoverAndExpect(kHoverStateMouseOver);
}
TEST_F(HoverButtonTest, Click) {
EXPECT_EQ(kHoverStateNone, button_.hoverState);
const auto click = cocoa_test_event_utils::MouseClickInView(button_, 1);
[NSApp postEvent:click.second atStart:YES];
EXPECT_TRUE(HandleMouseDown(click.first));
button_.enabled = NO;
EXPECT_FALSE(HandleMouseDown(click.first));
EXPECT_EQ(kHoverStateNone, button_.hoverState);
}
TEST_F(HoverButtonTest, CustomHitbox) {
NSRect hitbox = button_.frame;
hitbox.size.width += 10;
NSPoint inside_hit_point =
NSMakePoint(NSMaxX(button_.frame) + 5, NSMidY(button_.frame));
NSPoint outside_hit_point =
NSMakePoint(inside_hit_point.x + 10, inside_hit_point.y);
{
NSRect trackingRect = button_.trackingAreas[0].rect;
EXPECT_FALSE(NSPointInRect(inside_hit_point, trackingRect));
EXPECT_FALSE(NSPointInRect(outside_hit_point, trackingRect));
EXPECT_NE(button_, [button_ hitTest:inside_hit_point]);
EXPECT_EQ(nil, [button_ hitTest:outside_hit_point]);
}
button_.hitbox = hitbox;
{
NSRect trackingRect = button_.trackingAreas[0].rect;
EXPECT_TRUE(NSPointInRect(inside_hit_point, trackingRect));
EXPECT_FALSE(NSPointInRect(outside_hit_point, trackingRect));
EXPECT_EQ(button_, [button_ hitTest:inside_hit_point]);
EXPECT_EQ(nil, [button_ hitTest:outside_hit_point]);
}
button_.hitbox = NSZeroRect;
{
NSRect trackingRect = button_.trackingAreas[0].rect;
EXPECT_FALSE(NSPointInRect(inside_hit_point, trackingRect));
EXPECT_FALSE(NSPointInRect(outside_hit_point, trackingRect));
EXPECT_NE(button_, [button_ hitTest:inside_hit_point]);
EXPECT_EQ(nil, [button_ hitTest:outside_hit_point]);
}
}
TEST_F(HoverButtonTest, DragDelegate) {
base::scoped_nsobject<HoverButtonTestDragDelegate> dragDelegate(
[[HoverButtonTestDragDelegate alloc] init]);
__block bool dragged = false;
dragDelegate.get().dragHandler = ^(HoverButtonCocoa* button, NSEvent* event) {
dragged = true;
};
button_.dragDelegate = dragDelegate;
const auto click = cocoa_test_event_utils::MouseClickInView(button_, 1);
NSPoint targetPoint = click.first.locationInWindow;
targetPoint.x += 5; // *Not* enough to trigger a drag.
[NSApp postEvent:cocoa_test_event_utils::MouseEventAtPointInWindow(
targetPoint, NSEventTypeLeftMouseDragged,
[button_ window], 1)
atStart:NO];
[NSApp postEvent:click.second atStart:NO];
EXPECT_TRUE(HandleMouseDown(click.first));
EXPECT_FALSE(dragged);
targetPoint.x += 1; // Now it's enough to trigger a drag.
[NSApp postEvent:cocoa_test_event_utils::MouseEventAtPointInWindow(
targetPoint, NSEventTypeLeftMouseDragged,
[button_ window], 1)
atStart:NO];
[NSApp postEvent:click.second atStart:NO];
EXPECT_FALSE(HandleMouseDown(click.first));
EXPECT_TRUE(dragged);
}
} // namespace