Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(589)

Side by Side Diff: ios/chrome/browser/ui/omnibox/omnibox_text_field_ios_unittest.mm

Issue 2589803002: Upstream Chrome on iOS source code [6/11]. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2012 The Chromium 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 "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h"
6
7 #include "base/command_line.h"
8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h"
10 #include "base/mac/scoped_nsobject.h"
11 #include "base/path_service.h"
12 #include "base/strings/string_split.h"
13 #include "base/strings/sys_string_conversions.h"
14 #include "ios/chrome/browser/chrome_paths.h"
15 #include "ios/chrome/grit/ios_strings.h"
16 #include "testing/gtest_mac.h"
17 #include "testing/platform_test.h"
18 #include "ui/base/l10n/l10n_util_mac.h"
19
20 // A category for making existing methods visible for use in these tests.
21 @interface OmniboxTextFieldIOS (VisibleForTesting)
22 - (CGRect)rectForDrawTextInRect:(CGRect)rect;
23 @end
24
25 namespace {
26
27 class OmniboxTextFieldIOSTest : public PlatformTest {
28 protected:
29 void SetUp() override {
30 PlatformTest::SetUp();
31 // This rect is fairly arbitrary. The text field just needs a non-zero width
32 // so that the pre-edit label's text alignment can be tested.
33 CGRect rect = CGRectMake(0, 0, 100, 20);
34 textfield_.reset([[OmniboxTextFieldIOS alloc] initWithFrame:rect]);
35 [[[UIApplication sharedApplication] keyWindow] addSubview:textfield_];
36 };
37
38 void TearDown() override { [textfield_ removeFromSuperview]; }
39
40 BOOL IsCopyUrlInMenu() {
41 UIMenuController* menuController = [UIMenuController sharedMenuController];
42 NSString* const kTitle = l10n_util::GetNSString(IDS_IOS_COPY_URL);
43 for (UIMenuItem* item in menuController.menuItems) {
44 if ([item.title isEqual:kTitle])
45 return YES;
46 }
47 return NO;
48 };
49
50 void ExpectRectEqual(CGRect expectedRect, CGRect actualRect) {
51 EXPECT_EQ(expectedRect.origin.x, actualRect.origin.x);
52 EXPECT_EQ(expectedRect.origin.y, actualRect.origin.y);
53 EXPECT_EQ(expectedRect.size.width, actualRect.size.width);
54 EXPECT_EQ(expectedRect.size.height, actualRect.size.height);
55 }
56
57 // Verifies that the |selectedNSRange| function properly converts from opaque
58 // UITextRanges to NSRanges. This function selects blocks of text in the text
59 // field and compares the field's actual selected text to the converted
60 // NSRange.
61 void VerifySelectedNSRanges(NSString* text) {
62 // The NSRange conversion mechanism only works when the field is first
63 // responder.
64 [textfield_ setText:text];
65 [textfield_ becomeFirstResponder];
66 ASSERT_TRUE([textfield_ isFirstResponder]);
67
68 // |i| and |j| hold the start and end offsets of the range that is currently
69 // being tested. This function iterates through all possible combinations
70 // of |i| and |j|.
71 NSInteger i = 0;
72 NSInteger j = i + 1;
73 UITextPosition* beginning = [textfield_ beginningOfDocument];
74 UITextPosition* start =
75 [textfield_ positionFromPosition:[textfield_ beginningOfDocument]
76 offset:i];
77
78 // In order to avoid making any assumptions about the length of the text in
79 // the field, this test operates by incrementing the |i| and |j| offsets and
80 // converting them to opaque UITextPositions. If either |i| or |j| are
81 // invalid offsets for the current field text,
82 // |positionFromPosition:offset:| is documented to return nil. This is used
83 // as a signal to stop incrementing that offset and reset (or end the test).
84 while (start) {
85 UITextPosition* end =
86 [textfield_ positionFromPosition:beginning offset:j];
87 while (end) {
88 [textfield_
89 setSelectedTextRange:[textfield_ textRangeFromPosition:start
90 toPosition:end]];
91
92 // There are two ways to get the selected text:
93 // 1) Ask the field for it directly.
94 // 2) Compute the selected NSRange and use that to extract a substring
95 // from the field's text.
96 // This block of code ensures that the two methods give identical text.
97 NSRange nsrange = [textfield_ selectedNSRange];
98 NSString* nstext = [[textfield_ text] substringWithRange:nsrange];
99 UITextRange* uirange = [textfield_ selectedTextRange];
100 NSString* uitext = [textfield_ textInRange:uirange];
101 EXPECT_NSEQ(nstext, uitext);
102
103 // Increment |j| and |end| for the next iteration of the inner while
104 // loop.
105 ++j;
106 end = [textfield_ positionFromPosition:beginning offset:j];
107 }
108
109 // Increment |i| and |start| for the next iteration of the outer while
110 // loop. This also requires |j| to be reset.
111 ++i;
112 j = i + 1;
113 start = [textfield_ positionFromPosition:beginning offset:i];
114 }
115
116 [textfield_ resignFirstResponder];
117 }
118
119 base::scoped_nsobject<OmniboxTextFieldIOS> textfield_;
120 };
121
122 TEST_F(OmniboxTextFieldIOSTest, BecomeFirstResponderAddsCopyURLMenuItem) {
123 // The 'Copy URL' menu item should not be present before this test runs.
124 EXPECT_FALSE(IsCopyUrlInMenu());
125
126 // Call |becomeFirstResponder| and verify the Copy URL menu item was added.
127 UIMenuController* menuController = [UIMenuController sharedMenuController];
128 NSUInteger expectedItems = [menuController.menuItems count] + 1;
129 [textfield_ becomeFirstResponder];
130 EXPECT_EQ(expectedItems, [menuController.menuItems count]);
131 EXPECT_TRUE(IsCopyUrlInMenu());
132
133 // Call |becomeFirstResponder| again and verify the Copy URL menu item is not
134 // added again.
135 [textfield_ becomeFirstResponder];
136 EXPECT_EQ(expectedItems, [menuController.menuItems count]);
137 EXPECT_TRUE(IsCopyUrlInMenu());
138 }
139
140 TEST_F(OmniboxTextFieldIOSTest, ResignFirstResponderRemovesCopyURLMenuItem) {
141 // Call |becomeFirstResponder| to add the 'Copy URL' menu item so this test
142 // can remove it.
143 [textfield_ becomeFirstResponder];
144
145 UIMenuController* menuController = [UIMenuController sharedMenuController];
146 NSUInteger expectedItems = [menuController.menuItems count] - 1;
147 [textfield_ resignFirstResponder];
148 EXPECT_EQ(expectedItems, [menuController.menuItems count]);
149 EXPECT_FALSE(IsCopyUrlInMenu());
150 }
151
152 TEST_F(OmniboxTextFieldIOSTest, enterPreEditState_preEditTextAlignment_short) {
153 [textfield_ setText:@"s"];
154 [textfield_ becomeFirstResponder];
155 [textfield_ enterPreEditState];
156 UILabel* preEditLabel = [textfield_ preEditStaticLabel];
157 EXPECT_EQ(NSTextAlignmentLeft, preEditLabel.textAlignment);
158 [textfield_ resignFirstResponder];
159 }
160
161 TEST_F(OmniboxTextFieldIOSTest, enterPreEditState_preEditTextAlignment_long) {
162 [textfield_ setText:@"some really long text that is wider than the omnibox"];
163 [textfield_ becomeFirstResponder];
164 [textfield_ enterPreEditState];
165 UILabel* preEditLabel = [textfield_ preEditStaticLabel];
166 EXPECT_EQ(NSTextAlignmentRight, preEditLabel.textAlignment);
167 [textfield_ resignFirstResponder];
168 }
169
170 TEST_F(OmniboxTextFieldIOSTest, enterPreEditState_preEditTextAlignment_change) {
171 [textfield_ setText:@"s"];
172 [textfield_ becomeFirstResponder];
173 [textfield_ enterPreEditState];
174 // Simulate changing the omnibox text while in pre-edit state.
175 [textfield_ setText:@"some really long text that is wider than the omnibox"];
176 [textfield_ layoutSubviews];
177 UILabel* preEditLabel = [textfield_ preEditStaticLabel];
178 EXPECT_EQ(NSTextAlignmentLeft, preEditLabel.textAlignment);
179 [textfield_ resignFirstResponder];
180 }
181
182 TEST_F(OmniboxTextFieldIOSTest, rectForDrawTextInRect_entireURLFits) {
183 NSString* text = @"http://www.google.com";
184 [textfield_ setText:text];
185 CGSize textSize = [[textfield_ attributedText] size];
186 CGFloat widthForEntireURL = ceil(textSize.width) + 10;
187
188 CGRect inputRect = CGRectMake(0, 0, widthForEntireURL, textSize.height);
189 CGRect actualRect = [textfield_ rectForDrawTextInRect:inputRect];
190 ExpectRectEqual(inputRect, actualRect);
191 }
192
193 TEST_F(OmniboxTextFieldIOSTest, rectForDrawTextInRect_clippedPrefix) {
194 NSString* text = @"http://www.google.com";
195 [textfield_ setText:text];
196 CGSize textSize = [[textfield_ attributedText] size];
197 CGFloat clippedWidth = 10;
198 CGFloat widthForPartOfHost = ceil(textSize.width) - clippedWidth;
199
200 CGRect inputRect = CGRectMake(0, 0, widthForPartOfHost, textSize.height);
201 CGRect actualRect = [textfield_ rectForDrawTextInRect:inputRect];
202 CGRect expectedRect =
203 CGRectMake(-1 * clippedWidth, 0, ceil(textSize.width), textSize.height);
204 ExpectRectEqual(expectedRect, actualRect);
205 }
206
207 TEST_F(OmniboxTextFieldIOSTest, rectForDrawTextInRect_clippedSuffix) {
208 NSString* text = @"http://www.google.com/somelongpath";
209 [textfield_ setText:text];
210 CGSize textSize = [[textfield_ attributedText] size];
211 CGFloat widthForPartOfPath = ceil(textSize.width) - 10;
212
213 CGRect inputRect = CGRectMake(0, 0, widthForPartOfPath, textSize.height);
214 CGRect actualRect = [textfield_ rectForDrawTextInRect:inputRect];
215 CGRect expectedRect = CGRectMake(0, 0, ceil(textSize.width), textSize.height);
216 ExpectRectEqual(expectedRect, actualRect);
217 }
218
219 TEST_F(OmniboxTextFieldIOSTest, rectForDrawTextInRect_noScheme) {
220 NSString* text = @"www.google.com";
221 [textfield_ setText:text];
222 CGSize textSize = [[textfield_ attributedText] size];
223
224 CGRect inputRect = CGRectMake(0, 0, ceil(textSize.width), textSize.height);
225 CGRect actualRect = [textfield_ rectForDrawTextInRect:inputRect];
226 ExpectRectEqual(inputRect, actualRect);
227 }
228
229 // When the text doesn't contain a host the method bails early and returns
230 // the |rect| passed in.
231 TEST_F(OmniboxTextFieldIOSTest, rectForDrawTextInRect_noHost) {
232 NSString* text = @"http://";
233 [textfield_ setText:text];
234 CGSize textSize = [[textfield_ attributedText] size];
235
236 CGRect inputRect = CGRectMake(0, 0, ceil(textSize.width), textSize.height);
237 CGRect actualRect = [textfield_ rectForDrawTextInRect:inputRect];
238 ExpectRectEqual(inputRect, actualRect);
239 }
240
241 TEST_F(OmniboxTextFieldIOSTest, SelectedRanges) {
242 base::FilePath test_data_directory;
243 ASSERT_TRUE(PathService::Get(ios::DIR_TEST_DATA, &test_data_directory));
244 base::FilePath test_file = test_data_directory.Append(
245 FILE_PATH_LITERAL("omnibox/selected_ranges.txt"));
246 ASSERT_TRUE(base::PathExists(test_file));
247
248 std::string contents;
249 ASSERT_TRUE(base::ReadFileToString(test_file, &contents));
250 std::vector<std::string> test_strings = base::SplitString(
251 contents, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
252
253 for (size_t i = 0; i < test_strings.size(); ++i) {
254 if (test_strings[i].size() > 0) {
255 VerifySelectedNSRanges(base::SysUTF8ToNSString(test_strings[i]));
256 }
257 }
258 }
259
260 TEST_F(OmniboxTextFieldIOSTest, SelectExitsPreEditState) {
261 [textfield_ enterPreEditState];
262 EXPECT_TRUE([textfield_ isPreEditing]);
263 [textfield_ select:nil];
264 EXPECT_FALSE([textfield_ isPreEditing]);
265 }
266
267 TEST_F(OmniboxTextFieldIOSTest, SelectAllExitsPreEditState) {
268 [textfield_ enterPreEditState];
269 EXPECT_TRUE([textfield_ isPreEditing]);
270 [textfield_ selectAll:nil];
271 EXPECT_FALSE([textfield_ isPreEditing]);
272 }
273
274 } // namespace
OLDNEW
« no previous file with comments | « ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm ('k') | ios/chrome/browser/ui/omnibox/omnibox_view_ios.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698