Chromium Code Reviews| Index: ui/views/cocoa/desktop_drag_drop_client_mac_unittest.mm |
| diff --git a/ui/views/cocoa/desktop_drag_drop_client_mac_unittest.mm b/ui/views/cocoa/desktop_drag_drop_client_mac_unittest.mm |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..b2ae52e249b0fcf81b9816f6103d2f5260daa178 |
| --- /dev/null |
| +++ b/ui/views/cocoa/desktop_drag_drop_client_mac_unittest.mm |
| @@ -0,0 +1,291 @@ |
| +// Copyright 2016 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 <Cocoa/Cocoa.h> |
| + |
| +#include "base/strings/utf_string_conversions.h" |
| +#import "ui/gfx/test/ui_cocoa_test_helper.h" |
| +#import "ui/views/cocoa/bridged_content_view.h" |
| +#import "ui/views/cocoa/bridged_native_widget.h" |
| +#include "ui/views/cocoa/drag_drop_client_mac.h" |
|
tapted
2016/05/24 08:06:01
nit: This should be at the top of the file (and #i
spqchan
2016/05/26 01:56:53
Done.
|
| +#include "ui/views/view.h" |
| +#include "ui/views/widget/native_widget_mac.h" |
| +#include "ui/views/widget/root_view.h" |
| +#include "ui/views/widget/widget.h" |
| + |
| +using base::ASCIIToUTF16; |
| + |
| +// Mocks the NSDraggingInfo sent to the DragDropClientMac's DragUpdate() and |
| +// Drop() methods. Out of the required methods of NSDraggingInfo, only |
| +// draggingLocation and draggingPasteboard are used. |
| +@interface MockDraggingInfo : NSObject<NSDraggingInfo> { |
| + NSPasteboard* pasteboard_; |
| +} |
| + |
| +@property BOOL animatesToDestination; |
| +@property NSInteger numberOfValidItemsForDrop; |
| +@property NSDraggingFormation draggingFormation; |
|
tapted
2016/05/24 08:06:01
looks like the 10.11 SDK "requires" this to implem
spqchan
2016/05/26 01:56:53
Done.
|
| + |
| +@end |
| + |
| +@implementation MockDraggingInfo |
| + |
| +@synthesize animatesToDestination; |
| +@synthesize numberOfValidItemsForDrop; |
| +@synthesize draggingFormation; |
| + |
| +- (id)initWithPasteboard:(NSPasteboard*)pasteboard { |
| + if ((self = [super init])) { |
| + pasteboard_ = pasteboard; |
| + } |
| + return self; |
| +} |
| + |
| +- (NSPoint)draggingLocation { |
| + return NSMakePoint(50, 50); |
| +} |
| + |
|
tapted
2016/05/24 08:06:01
let's squish all these together by removing these
spqchan
2016/05/26 01:56:53
Done.
|
| +- (NSPasteboard*)draggingPasteboard { |
| + return pasteboard_; |
| +} |
| + |
| +- (NSInteger)draggingSequenceNumber { |
| + return 0; |
| +} |
| + |
| +- (id)draggingSource { |
| + return nil; |
| +} |
| + |
| +- (NSDragOperation)draggingSourceOperationMask { |
| + return NSDragOperationNone; |
| +} |
| + |
| +- (NSWindow*)draggingDestinationWindow { |
| + return nil; |
| +} |
| + |
| +- (NSArray*)namesOfPromisedFilesDroppedAtDestination:(NSURL*)dropDestination { |
| + return nil; |
| +} |
| + |
| +- (NSImage*)draggedImage { |
| + return nil; |
| +} |
| + |
| +- (NSPoint)draggedImageLocation { |
| + return NSZeroPoint; |
| +} |
| + |
| +- (void)slideDraggedImageTo:(NSPoint)aPoint { |
| +} |
| + |
| +- (void) |
| +enumerateDraggingItemsWithOptions:(NSDraggingItemEnumerationOptions)enumOpts |
| + forView:(NSView*)view |
| + classes:(NSArray*)classArray |
| + searchOptions:(NSDictionary*)searchOptions |
| + usingBlock:(void (^)(NSDraggingItem* draggingItem, |
| + NSInteger idx, |
| + BOOL* stop))block { |
| +} |
| + |
| +- (void)resetSpringLoading { |
| +} |
| + |
| +@end |
| + |
| +namespace views { |
| +namespace test { |
| + |
| +// Provides the |parent| argument to construct a BridgedNativeWidget. |
| +class DragDropTestNativeWidgetMac : public NativeWidgetMac { |
|
tapted
2016/05/24 08:06:01
I think we won't need this
spqchan
2016/05/26 01:56:54
Done.
|
| + public: |
| + DragDropTestNativeWidgetMac(Widget* delegate) : NativeWidgetMac(delegate) {} |
| + |
| + DragDropClientMac* drag_drop_client() { return bridge_->drag_drop_client(); } |
| + |
| + BridgedNativeWidget* bridge() { return bridge_.get(); } |
| + |
| + // internal::NativeWidgetPrivate: |
| + void InitNativeWidget(const Widget::InitParams& params) override { |
| + ownership_ = params.ownership; |
| + } |
| + |
| + void ReorderNativeViews() override { |
| + // Called via Widget::Init to set the content view. No-op in these tests. |
| + } |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(DragDropTestNativeWidgetMac); |
| +}; |
| + |
| +// View object that will receive and process dropped data from the test. |
| +class DragDropView : public View { |
| + public: |
| + bool GetDropFormats( |
|
tapted
2016/05/24 08:06:01
// View:
(i.e. to indicate overrides)
spqchan
2016/05/26 01:56:54
Done.
|
| + int* formats, |
| + std::set<ui::Clipboard::FormatType>* format_types) override { |
| + *formats |= formats_; |
| + return true; |
| + } |
| + |
| + bool CanDrop(const OSExchangeData& data) override { return true; } |
| + |
|
tapted
2016/05/24 08:06:01
nit: these overrides can be squished together too
spqchan
2016/05/26 01:56:54
The line will be > 80 characters if I squish them
tapted
2016/05/26 12:31:41
Ah, I just meant remove the blank lines between th
|
| + int OnDragUpdated(const ui::DropTargetEvent& event) override { |
| + return ui::DragDropTypes::DRAG_COPY; |
| + } |
| + |
| + int OnPerformDrop(const ui::DropTargetEvent& event) override { |
| + return ui::DragDropTypes::DRAG_COPY; |
| + } |
| + |
| + void SetDropFormats(int formats) { formats_ = formats; } |
|
tapted
2016/05/24 08:06:01
nit: move this above the overrides, and call it se
|
| + |
| + private: |
| + // Drop formats accepted by this View object. |
| + int formats_; |
|
tapted
2016/05/24 08:06:01
= 0;
(needs to be initialized)
spqchan
2016/05/26 01:56:54
Done.
|
| +}; |
|
tapted
2016/05/24 08:06:01
nit: DISALLOW_COPY_AND_ASSIGN(..)
spqchan
2016/05/26 01:56:54
Done.
|
| + |
| +class CocoaDragDropTest : public ui::CocoaTest { |
|
tapted
2016/05/24 08:06:01
hopefuly inheriting from WidgetTest will get us be
spqchan
2016/05/26 01:56:54
Done.
|
| + public: |
| + CocoaDragDropTest() |
| + : widget_(new Widget), |
| + native_widget_mac_(new DragDropTestNativeWidgetMac(widget_.get())) {} |
| + |
| + DragDropClientMac* drag_drop_client() { |
| + return native_widget_mac_->drag_drop_client(); |
| + } |
| + |
| + // Overridden from testing::Test: |
| + void SetUp() override { |
| + ui::CocoaTest::SetUp(); |
| + |
| + init_params_.native_widget = native_widget_mac_; |
| + |
| + // Use a frameless window, otherwise Widget will try to center the window |
| + // before the tests covering the Init() flow are ready to do that. |
| + init_params_.type = Widget::InitParams::TYPE_WINDOW_FRAMELESS; |
| + |
| + // To control the lifetime without an actual window that must be closed, |
| + // tests in this file need to use WIDGET_OWNS_NATIVE_WIDGET. |
| + init_params_.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| + |
| + init_params_.bounds = gfx::Rect(100, 100, 100, 100); |
| + native_widget_mac_->GetWidget()->Init(init_params_); |
| + |
| + view_.reset(new views::internal::RootView(widget_.get())); |
| + base::scoped_nsobject<NSWindow> window([test_window() retain]); |
| + |
| + BridgedNativeWidget* bridge = native_widget_mac_->bridge(); |
| + |
| + // BridgedNativeWidget expects to be initialized with a hidden (deferred) |
| + // window. |
| + [window orderOut:nil]; |
| + EXPECT_FALSE([window delegate]); |
| + bridge->Init(window, init_params_); |
| + |
| + // The delegate should exist before setting the root view. |
| + EXPECT_TRUE([window delegate]); |
| + bridge->SetRootView(view_.get()); |
| + ns_view_ = bridge->ns_view(); |
| + |
| + // Add target view |
| + target_.reset(new DragDropView()); |
| + target_->SetBounds(0, 0, 100, 100); |
| + view_->AddChildView(target_.get()); |
| + |
| + drag_drop_client()->operation_ = ui::DragDropTypes::DRAG_COPY; |
| + } |
| + |
| + void TearDown() override { |
| + BridgedNativeWidget* bridge = native_widget_mac_->bridge(); |
| + if (bridge) |
| + bridge->SetRootView(nullptr); |
| + target_.reset(); |
| + view_.reset(); |
| + CocoaTest::TearDown(); |
| + } |
| + |
| + NSDragOperation DragUpdate(NSPasteboard* pasteboard) { |
| + DragDropClientMac* client = drag_drop_client(); |
| + MockDraggingInfo* info = |
| + [[MockDraggingInfo alloc] initWithPasteboard:pasteboard]; |
| + return client->DragUpdate(info); |
| + } |
| + |
| + NSDragOperation Drop(NSPasteboard* pasteboard) { |
| + DragDropClientMac* client = drag_drop_client(); |
| + MockDraggingInfo* info = |
| + [[MockDraggingInfo alloc] initWithPasteboard:pasteboard]; |
| + return client->Drop(info); |
| + } |
| + |
| + void SetData(OSExchangeData& data) { |
| + drag_drop_client()->data_source_.reset( |
| + [[CocoaDragDropDataProvider alloc] initWithData:data]); |
| + } |
| + |
| + protected: |
| + std::unique_ptr<views::View> view_; |
|
tapted
2016/05/24 08:06:01
normally views are owned by the Widget* (via its R
spqchan
2016/05/26 01:56:54
Done.
|
| + BridgedContentView* ns_view_; |
|
tapted
2016/05/24 08:06:01
This can be retrieved from widget_->GetNativeView(
spqchan
2016/05/26 01:56:54
Done.
|
| + std::unique_ptr<Widget> widget_; |
|
tapted
2016/05/24 08:06:01
It's more common for NativeWidgets to own themselv
spqchan
2016/05/26 01:56:53
Done.
spqchan
2016/05/26 01:56:54
Done.
|
| + DragDropTestNativeWidgetMac* native_widget_mac_; // Weak. Owned by |widget_|. |
| + std::unique_ptr<DragDropView> target_; |
| + |
| + // Make the InitParams available to tests to cover initialization codepaths. |
| + Widget::InitParams init_params_; |
| +}; |
|
tapted
2016/05/24 08:06:01
nit: private: DISALLOW_COPY_AND_ASSIGN(..)
spqchan
2016/05/26 01:56:54
Done.
|
| + |
| +// Tests if the drag and drop target receives the dropped data. |
| +TEST_F(CocoaDragDropTest, BasicDragDrop) { |
| + // Create the drop data |
| + OSExchangeData data; |
| + const base::string16& text = ASCIIToUTF16("text"); |
| + data.SetString(text); |
| + SetData(data); |
| + |
| + target_->SetDropFormats(ui::OSExchangeData::STRING | ui::OSExchangeData::URL); |
| + |
| + // Check if the target receives the data from a drop and returns the expected |
| + // operation. |
| + EXPECT_NE(DragUpdate(nil), NSDragOperationNone); |
| + EXPECT_NE(Drop(nil), NSDragOperationNone); |
| +} |
| + |
| +// Tests if the drag and drop target rejects the dropped data with the |
| +// incorrect format. |
| +TEST_F(CocoaDragDropTest, InvalidFormatDragDrop) { |
| + OSExchangeData data; |
| + const base::string16& text = ASCIIToUTF16("text"); |
| + data.SetString(text); |
| + SetData(data); |
| + |
| + target_->SetDropFormats(ui::OSExchangeData::URL); |
| + |
| + // Check if the target receives the data from a drop and returns the expected |
| + // operation. |
| + EXPECT_EQ(DragUpdate(nil), NSDragOperationNone); |
| + EXPECT_EQ(Drop(nil), NSDragOperationNone); |
| +} |
| + |
| +// Tests if the drag and drop target can accept data without an OSExchangeData |
| +// object. |
| +TEST_F(CocoaDragDropTest, PasteboardToOSExchangeTest) { |
| + target_->SetDropFormats(ui::OSExchangeData::STRING); |
| + |
| + NSPasteboard* pasteboard = [NSPasteboard pasteboardWithUniqueName]; |
| + |
| + EXPECT_EQ(DragUpdate(pasteboard), NSDragOperationNone); |
| + EXPECT_EQ(Drop(pasteboard), NSDragOperationNone); |
| + drag_drop_client()->EndDrag(); |
| + |
| + [pasteboard setString:@"text" forType:NSPasteboardTypeString]; |
| + |
| + EXPECT_NE(DragUpdate(pasteboard), NSDragOperationNone); |
| + EXPECT_NE(Drop(pasteboard), NSDragOperationNone); |
| +} |
| + |
| +} // namespace test |
| +} // namespace views |