Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 3c9308f

Browse files
authored
hasStrings Mac (#20531)
Adds the hasStrings method for Mac, and improves the state of unit testing on Mac.
1 parent 2a26bfb commit 3c9308f

File tree

5 files changed

+104
-4
lines changed

5 files changed

+104
-4
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,7 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterTextI
10351035
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h
10361036
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterView.mm
10371037
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm
1038+
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm
10381039
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h
10391040
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/fixtures/flutter_desktop_test.dart
10401041
FILE: ../../../flutter/shell/platform/darwin/macos/framework/module.modulemap

shell/platform/darwin/macos/BUILD.gn

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,10 @@ test_fixtures("flutter_desktop_darwin_fixtures") {
101101
executable("flutter_desktop_darwin_unittests") {
102102
testonly = true
103103

104-
sources = [ "framework/Source/FlutterEngineUnittests.mm" ]
104+
sources = [
105+
"framework/Source/FlutterEngineUnittests.mm",
106+
"framework/Source/FlutterViewControllerTest.mm",
107+
]
105108

106109
cflags_objcc = [ "-fobjc-arc" ]
107110

@@ -114,6 +117,7 @@ executable("flutter_desktop_darwin_unittests") {
114117
"//flutter/testing:dart",
115118
"//flutter/testing:skia",
116119
"//flutter/testing:testing_lib",
120+
"//third_party/ocmock:ocmock",
117121
]
118122
}
119123

shell/platform/darwin/macos/framework/Source/FlutterViewController.mm

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ - (NSDictionary*)getClipboardData:(NSString*)format;
173173
*/
174174
- (void)setClipboardData:(NSDictionary*)data;
175175

176+
/**
177+
* Returns true iff the clipboard contains nonempty string data.
178+
*/
179+
- (BOOL)clipboardHasStrings;
180+
176181
@end
177182

178183
#pragma mark - FlutterViewController implementation.
@@ -505,6 +510,8 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
505510
} else if ([call.method isEqualToString:@"Clipboard.setData"]) {
506511
[self setClipboardData:call.arguments];
507512
result(nil);
513+
} else if ([call.method isEqualToString:@"Clipboard.hasStrings"]) {
514+
result(@{@"value" : @([self clipboardHasStrings])});
508515
} else {
509516
result(FlutterMethodNotImplemented);
510517
}
@@ -517,7 +524,7 @@ - (void)playSystemSound:(NSString*)soundType {
517524
}
518525

519526
- (NSDictionary*)getClipboardData:(NSString*)format {
520-
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
527+
NSPasteboard* pasteboard = self.pasteboard;
521528
if ([format isEqualToString:@(kTextPlainFormat)]) {
522529
NSString* stringInPasteboard = [pasteboard stringForType:NSPasteboardTypeString];
523530
return stringInPasteboard == nil ? nil : @{@"text" : stringInPasteboard};
@@ -526,14 +533,22 @@ - (NSDictionary*)getClipboardData:(NSString*)format {
526533
}
527534

528535
- (void)setClipboardData:(NSDictionary*)data {
529-
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
536+
NSPasteboard* pasteboard = self.pasteboard;
530537
NSString* text = data[@"text"];
538+
[pasteboard clearContents];
531539
if (text && ![text isEqual:[NSNull null]]) {
532-
[pasteboard clearContents];
533540
[pasteboard setString:text forType:NSPasteboardTypeString];
534541
}
535542
}
536543

544+
- (BOOL)clipboardHasStrings {
545+
return [self.pasteboard stringForType:NSPasteboardTypeString].length > 0;
546+
}
547+
548+
- (NSPasteboard*)pasteboard {
549+
return [NSPasteboard generalPasteboard];
550+
}
551+
537552
#pragma mark - FlutterViewReshapeListener
538553

539554
/**
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h"
6+
7+
#include "flutter/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h"
8+
#include "flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h"
9+
#include "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h"
10+
#include "flutter/testing/testing.h"
11+
#import "third_party/ocmock/Source/OCMock/OCMock.h"
12+
13+
namespace flutter::testing {
14+
15+
// Returns a mock FlutterViewController that is able to work in environments
16+
// without a real pasteboard.
17+
id mockViewController(NSString* pasteboardString) {
18+
NSString* fixtures = @(testing::GetFixturesPath());
19+
FlutterDartProject* project = [[FlutterDartProject alloc]
20+
initWithAssetsPath:fixtures
21+
ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
22+
FlutterViewController* viewController = [[FlutterViewController alloc] initWithProject:project];
23+
24+
// Mock pasteboard so that this test will work in environments without a
25+
// real pasteboard.
26+
id pasteboardMock = OCMClassMock([NSPasteboard class]);
27+
OCMExpect([pasteboardMock stringForType:[OCMArg any]]).andDo(^(NSInvocation* invocation) {
28+
NSString* returnValue = pasteboardString.length > 0 ? pasteboardString : nil;
29+
[invocation setReturnValue:&returnValue];
30+
});
31+
id viewControllerMock = OCMPartialMock(viewController);
32+
OCMStub([viewControllerMock pasteboard]).andReturn(pasteboardMock);
33+
return viewControllerMock;
34+
}
35+
36+
TEST(FlutterViewControllerTest, HasStringsWhenPasteboardEmpty) {
37+
// Mock FlutterViewController so that it behaves like the pasteboard is empty.
38+
id viewControllerMock = mockViewController(nil);
39+
40+
// Call hasStrings and expect it to be false.
41+
__block bool calledAfterClear = false;
42+
__block bool valueAfterClear;
43+
FlutterResult resultAfterClear = ^(id result) {
44+
calledAfterClear = true;
45+
NSNumber* valueNumber = [result valueForKey:@"value"];
46+
valueAfterClear = [valueNumber boolValue];
47+
};
48+
FlutterMethodCall* methodCallAfterClear =
49+
[FlutterMethodCall methodCallWithMethodName:@"Clipboard.hasStrings" arguments:nil];
50+
[viewControllerMock handleMethodCall:methodCallAfterClear result:resultAfterClear];
51+
ASSERT_TRUE(calledAfterClear);
52+
ASSERT_FALSE(valueAfterClear);
53+
}
54+
55+
TEST(FlutterViewControllerTest, HasStringsWhenPasteboardFull) {
56+
// Mock FlutterViewController so that it behaves like the pasteboard has a
57+
// valid string.
58+
id viewControllerMock = mockViewController(@"some string");
59+
60+
// Call hasStrings and expect it to be true.
61+
__block bool called = false;
62+
__block bool value;
63+
FlutterResult result = ^(id result) {
64+
called = true;
65+
NSNumber* valueNumber = [result valueForKey:@"value"];
66+
value = [valueNumber boolValue];
67+
};
68+
FlutterMethodCall* methodCall =
69+
[FlutterMethodCall methodCallWithMethodName:@"Clipboard.hasStrings" arguments:nil];
70+
[viewControllerMock handleMethodCall:methodCall result:result];
71+
ASSERT_TRUE(called);
72+
ASSERT_TRUE(value);
73+
}
74+
75+
} // flutter::testing

shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
// The FlutterView for this view controller.
1212
@property(nonatomic, readonly, nullable) FlutterView* flutterView;
1313

14+
/**
15+
* This just returns the NSPasteboard so that it can be mocked in the tests.
16+
*/
17+
@property(nonatomic, readonly, nonnull) NSPasteboard* pasteboard;
18+
1419
/**
1520
* Adds a responder for keyboard events. Key up and key down events are forwarded to all added
1621
* responders.

0 commit comments

Comments
 (0)