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 |