OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 #include "ash/ime/candidate_window_view.h" | |
6 | |
7 #include <string> | |
8 | |
9 #include "ash/ime/candidate_view.h" | |
10 #include "base/strings/stringprintf.h" | |
11 #include "base/strings/utf_string_conversions.h" | |
12 #include "testing/gtest/include/gtest/gtest.h" | |
13 #include "ui/views/test/views_test_base.h" | |
14 #include "ui/views/widget/widget.h" | |
15 | |
16 namespace ash { | |
17 namespace ime { | |
18 | |
19 namespace { | |
20 const char* kSampleCandidate[] = { | |
21 "Sample Candidate 1", | |
22 "Sample Candidate 2", | |
23 "Sample Candidate 3" | |
24 }; | |
25 const char* kSampleAnnotation[] = { | |
26 "Sample Annotation 1", | |
27 "Sample Annotation 2", | |
28 "Sample Annotation 3" | |
29 }; | |
30 const char* kSampleDescriptionTitle[] = { | |
31 "Sample Description Title 1", | |
32 "Sample Description Title 2", | |
33 "Sample Description Title 3", | |
34 }; | |
35 const char* kSampleDescriptionBody[] = { | |
36 "Sample Description Body 1", | |
37 "Sample Description Body 2", | |
38 "Sample Description Body 3", | |
39 }; | |
40 | |
41 void InitCandidateWindow(size_t page_size, | |
42 ui::CandidateWindow* candidate_window) { | |
43 candidate_window->set_cursor_position(0); | |
44 candidate_window->set_page_size(page_size); | |
45 candidate_window->mutable_candidates()->clear(); | |
46 candidate_window->set_orientation(ui::CandidateWindow::VERTICAL); | |
47 } | |
48 | |
49 void InitCandidateWindowWithCandidatesFilled( | |
50 size_t page_size, | |
51 ui::CandidateWindow* candidate_window) { | |
52 InitCandidateWindow(page_size, candidate_window); | |
53 for (size_t i = 0; i < page_size; ++i) { | |
54 ui::CandidateWindow::Entry entry; | |
55 entry.value = base::UTF8ToUTF16(base::StringPrintf( | |
56 "value %lld", static_cast<unsigned long long>(i))); | |
57 entry.label = base::UTF8ToUTF16(base::StringPrintf( | |
58 "%lld", static_cast<unsigned long long>(i))); | |
59 candidate_window->mutable_candidates()->push_back(entry); | |
60 } | |
61 } | |
62 | |
63 } // namespace | |
64 | |
65 class CandidateWindowViewTest : public views::ViewsTestBase { | |
66 public: | |
67 CandidateWindowViewTest() {} | |
68 ~CandidateWindowViewTest() override {} | |
69 | |
70 protected: | |
71 void SetUp() override { | |
72 views::ViewsTestBase::SetUp(); | |
73 candidate_window_view_ = new CandidateWindowView(GetContext()); | |
74 candidate_window_view_->InitWidget(); | |
75 } | |
76 | |
77 CandidateWindowView* candidate_window_view() { | |
78 return candidate_window_view_; | |
79 } | |
80 | |
81 int selected_candidate_index_in_page() { | |
82 return candidate_window_view_->selected_candidate_index_in_page_; | |
83 } | |
84 | |
85 size_t GetCandidatesSize() const { | |
86 return candidate_window_view_->candidate_views_.size(); | |
87 } | |
88 | |
89 CandidateView* GetCandidateAt(size_t i) { | |
90 return candidate_window_view_->candidate_views_[i]; | |
91 } | |
92 | |
93 void SelectCandidateAt(int index_in_page) { | |
94 candidate_window_view_->SelectCandidateAt(index_in_page); | |
95 } | |
96 | |
97 void MaybeInitializeCandidateViews( | |
98 const ui::CandidateWindow& candidate_window) { | |
99 candidate_window_view_->MaybeInitializeCandidateViews(candidate_window); | |
100 } | |
101 | |
102 void ExpectLabels(const std::string& shortcut, | |
103 const std::string& candidate, | |
104 const std::string& annotation, | |
105 const CandidateView* row) { | |
106 EXPECT_EQ(shortcut, base::UTF16ToUTF8(row->shortcut_label_->text())); | |
107 EXPECT_EQ(candidate, base::UTF16ToUTF8(row->candidate_label_->text())); | |
108 EXPECT_EQ(annotation, base::UTF16ToUTF8(row->annotation_label_->text())); | |
109 } | |
110 | |
111 private: | |
112 // owned by |parent_|. | |
113 CandidateWindowView* candidate_window_view_; | |
114 | |
115 DISALLOW_COPY_AND_ASSIGN(CandidateWindowViewTest); | |
116 }; | |
117 | |
118 TEST_F(CandidateWindowViewTest, UpdateCandidatesTest_CursorVisibility) { | |
119 // Visible (by default) cursor. | |
120 ui::CandidateWindow candidate_window; | |
121 const int candidate_window_size = 9; | |
122 InitCandidateWindowWithCandidatesFilled(candidate_window_size, | |
123 &candidate_window); | |
124 candidate_window_view()->UpdateCandidates(candidate_window); | |
125 EXPECT_EQ(0, selected_candidate_index_in_page()); | |
126 | |
127 // Invisible cursor. | |
128 candidate_window.set_is_cursor_visible(false); | |
129 candidate_window_view()->UpdateCandidates(candidate_window); | |
130 EXPECT_EQ(-1, selected_candidate_index_in_page()); | |
131 | |
132 // Move the cursor to the end. | |
133 candidate_window.set_cursor_position(candidate_window_size - 1); | |
134 candidate_window_view()->UpdateCandidates(candidate_window); | |
135 EXPECT_EQ(-1, selected_candidate_index_in_page()); | |
136 | |
137 // Change the cursor to visible. The cursor must be at the end. | |
138 candidate_window.set_is_cursor_visible(true); | |
139 candidate_window_view()->UpdateCandidates(candidate_window); | |
140 EXPECT_EQ(candidate_window_size - 1, selected_candidate_index_in_page()); | |
141 } | |
142 | |
143 TEST_F(CandidateWindowViewTest, SelectCandidateAtTest) { | |
144 // Set 9 candidates. | |
145 ui::CandidateWindow candidate_window_large; | |
146 const int candidate_window_large_size = 9; | |
147 InitCandidateWindowWithCandidatesFilled(candidate_window_large_size, | |
148 &candidate_window_large); | |
149 candidate_window_large.set_cursor_position(candidate_window_large_size - 1); | |
150 candidate_window_view()->UpdateCandidates(candidate_window_large); | |
151 | |
152 // Select the last candidate. | |
153 SelectCandidateAt(candidate_window_large_size - 1); | |
154 | |
155 // Reduce the number of candidates to 3. | |
156 ui::CandidateWindow candidate_window_small; | |
157 const int candidate_window_small_size = 3; | |
158 InitCandidateWindowWithCandidatesFilled(candidate_window_small_size, | |
159 &candidate_window_small); | |
160 candidate_window_small.set_cursor_position(candidate_window_small_size - 1); | |
161 // Make sure the test doesn't crash if the candidate window reduced | |
162 // its size. (crbug.com/174163) | |
163 candidate_window_view()->UpdateCandidates(candidate_window_small); | |
164 SelectCandidateAt(candidate_window_small_size - 1); | |
165 } | |
166 | |
167 TEST_F(CandidateWindowViewTest, ShortcutSettingTest) { | |
168 const char* kEmptyLabel = ""; | |
169 const char* kCustomizedLabel[] = { "a", "s", "d" }; | |
170 const char* kExpectedHorizontalCustomizedLabel[] = { "a.", "s.", "d." }; | |
171 | |
172 { | |
173 SCOPED_TRACE("candidate_views allocation test"); | |
174 const size_t kMaxPageSize = 16; | |
175 for (size_t i = 1; i < kMaxPageSize; ++i) { | |
176 ui::CandidateWindow candidate_window; | |
177 InitCandidateWindow(i, &candidate_window); | |
178 candidate_window_view()->UpdateCandidates(candidate_window); | |
179 EXPECT_EQ(i, GetCandidatesSize()); | |
180 } | |
181 } | |
182 { | |
183 SCOPED_TRACE("Empty string for each labels expects empty labels(vertical)"); | |
184 const size_t kPageSize = 3; | |
185 ui::CandidateWindow candidate_window; | |
186 InitCandidateWindow(kPageSize, &candidate_window); | |
187 | |
188 candidate_window.set_orientation(ui::CandidateWindow::VERTICAL); | |
189 for (size_t i = 0; i < kPageSize; ++i) { | |
190 ui::CandidateWindow::Entry entry; | |
191 entry.value = base::UTF8ToUTF16(kSampleCandidate[i]); | |
192 entry.annotation = base::UTF8ToUTF16(kSampleAnnotation[i]); | |
193 entry.description_title = base::UTF8ToUTF16(kSampleDescriptionTitle[i]); | |
194 entry.description_body = base::UTF8ToUTF16(kSampleDescriptionBody[i]); | |
195 entry.label = base::UTF8ToUTF16(kEmptyLabel); | |
196 candidate_window.mutable_candidates()->push_back(entry); | |
197 } | |
198 | |
199 candidate_window_view()->UpdateCandidates(candidate_window); | |
200 | |
201 ASSERT_EQ(kPageSize, GetCandidatesSize()); | |
202 for (size_t i = 0; i < kPageSize; ++i) { | |
203 ExpectLabels(kEmptyLabel, kSampleCandidate[i], kSampleAnnotation[i], | |
204 GetCandidateAt(i)); | |
205 } | |
206 } | |
207 { | |
208 SCOPED_TRACE( | |
209 "Empty string for each labels expect empty labels(horizontal)"); | |
210 const size_t kPageSize = 3; | |
211 ui::CandidateWindow candidate_window; | |
212 InitCandidateWindow(kPageSize, &candidate_window); | |
213 | |
214 candidate_window.set_orientation(ui::CandidateWindow::HORIZONTAL); | |
215 for (size_t i = 0; i < kPageSize; ++i) { | |
216 ui::CandidateWindow::Entry entry; | |
217 entry.value = base::UTF8ToUTF16(kSampleCandidate[i]); | |
218 entry.annotation = base::UTF8ToUTF16(kSampleAnnotation[i]); | |
219 entry.description_title = base::UTF8ToUTF16(kSampleDescriptionTitle[i]); | |
220 entry.description_body = base::UTF8ToUTF16(kSampleDescriptionBody[i]); | |
221 entry.label = base::UTF8ToUTF16(kEmptyLabel); | |
222 candidate_window.mutable_candidates()->push_back(entry); | |
223 } | |
224 | |
225 candidate_window_view()->UpdateCandidates(candidate_window); | |
226 | |
227 ASSERT_EQ(kPageSize, GetCandidatesSize()); | |
228 // Confirm actual labels not containing ".". | |
229 for (size_t i = 0; i < kPageSize; ++i) { | |
230 ExpectLabels(kEmptyLabel, kSampleCandidate[i], kSampleAnnotation[i], | |
231 GetCandidateAt(i)); | |
232 } | |
233 } | |
234 { | |
235 SCOPED_TRACE("Vertical customized label case"); | |
236 const size_t kPageSize = 3; | |
237 ui::CandidateWindow candidate_window; | |
238 InitCandidateWindow(kPageSize, &candidate_window); | |
239 | |
240 candidate_window.set_orientation(ui::CandidateWindow::VERTICAL); | |
241 for (size_t i = 0; i < kPageSize; ++i) { | |
242 ui::CandidateWindow::Entry entry; | |
243 entry.value = base::UTF8ToUTF16(kSampleCandidate[i]); | |
244 entry.annotation = base::UTF8ToUTF16(kSampleAnnotation[i]); | |
245 entry.description_title = base::UTF8ToUTF16(kSampleDescriptionTitle[i]); | |
246 entry.description_body = base::UTF8ToUTF16(kSampleDescriptionBody[i]); | |
247 entry.label = base::UTF8ToUTF16(kCustomizedLabel[i]); | |
248 candidate_window.mutable_candidates()->push_back(entry); | |
249 } | |
250 | |
251 candidate_window_view()->UpdateCandidates(candidate_window); | |
252 | |
253 ASSERT_EQ(kPageSize, GetCandidatesSize()); | |
254 // Confirm actual labels not containing ".". | |
255 for (size_t i = 0; i < kPageSize; ++i) { | |
256 ExpectLabels(kCustomizedLabel[i], | |
257 kSampleCandidate[i], | |
258 kSampleAnnotation[i], | |
259 GetCandidateAt(i)); | |
260 } | |
261 } | |
262 { | |
263 SCOPED_TRACE("Horizontal customized label case"); | |
264 const size_t kPageSize = 3; | |
265 ui::CandidateWindow candidate_window; | |
266 InitCandidateWindow(kPageSize, &candidate_window); | |
267 | |
268 candidate_window.set_orientation(ui::CandidateWindow::HORIZONTAL); | |
269 for (size_t i = 0; i < kPageSize; ++i) { | |
270 ui::CandidateWindow::Entry entry; | |
271 entry.value = base::UTF8ToUTF16(kSampleCandidate[i]); | |
272 entry.annotation = base::UTF8ToUTF16(kSampleAnnotation[i]); | |
273 entry.description_title = base::UTF8ToUTF16(kSampleDescriptionTitle[i]); | |
274 entry.description_body = base::UTF8ToUTF16(kSampleDescriptionBody[i]); | |
275 entry.label = base::UTF8ToUTF16(kCustomizedLabel[i]); | |
276 candidate_window.mutable_candidates()->push_back(entry); | |
277 } | |
278 | |
279 candidate_window_view()->UpdateCandidates(candidate_window); | |
280 | |
281 ASSERT_EQ(kPageSize, GetCandidatesSize()); | |
282 // Confirm actual labels not containing ".". | |
283 for (size_t i = 0; i < kPageSize; ++i) { | |
284 ExpectLabels(kExpectedHorizontalCustomizedLabel[i], | |
285 kSampleCandidate[i], | |
286 kSampleAnnotation[i], | |
287 GetCandidateAt(i)); | |
288 } | |
289 } | |
290 } | |
291 | |
292 TEST_F(CandidateWindowViewTest, DoNotChangeRowHeightWithLabelSwitchTest) { | |
293 const size_t kPageSize = 10; | |
294 ui::CandidateWindow candidate_window; | |
295 ui::CandidateWindow no_shortcut_candidate_window; | |
296 | |
297 const base::string16 kSampleCandidate1 = base::UTF8ToUTF16( | |
298 "Sample String 1"); | |
299 const base::string16 kSampleCandidate2 = base::UTF8ToUTF16( | |
300 "\xE3\x81\x82"); // multi byte string. | |
301 const base::string16 kSampleCandidate3 = base::UTF8ToUTF16("....."); | |
302 | |
303 const base::string16 kSampleShortcut1 = base::UTF8ToUTF16("1"); | |
304 const base::string16 kSampleShortcut2 = base::UTF8ToUTF16("b"); | |
305 const base::string16 kSampleShortcut3 = base::UTF8ToUTF16("C"); | |
306 | |
307 const base::string16 kSampleAnnotation1 = base::UTF8ToUTF16( | |
308 "Sample Annotation 1"); | |
309 const base::string16 kSampleAnnotation2 = base::UTF8ToUTF16( | |
310 "\xE3\x81\x82"); // multi byte string. | |
311 const base::string16 kSampleAnnotation3 = base::UTF8ToUTF16("......"); | |
312 | |
313 // Create CandidateWindow object. | |
314 InitCandidateWindow(kPageSize, &candidate_window); | |
315 | |
316 candidate_window.set_cursor_position(0); | |
317 candidate_window.set_page_size(3); | |
318 candidate_window.mutable_candidates()->clear(); | |
319 candidate_window.set_orientation(ui::CandidateWindow::VERTICAL); | |
320 no_shortcut_candidate_window.CopyFrom(candidate_window); | |
321 | |
322 ui::CandidateWindow::Entry entry; | |
323 entry.value = kSampleCandidate1; | |
324 entry.annotation = kSampleAnnotation1; | |
325 candidate_window.mutable_candidates()->push_back(entry); | |
326 entry.label = kSampleShortcut1; | |
327 no_shortcut_candidate_window.mutable_candidates()->push_back(entry); | |
328 | |
329 entry.value = kSampleCandidate2; | |
330 entry.annotation = kSampleAnnotation2; | |
331 candidate_window.mutable_candidates()->push_back(entry); | |
332 entry.label = kSampleShortcut2; | |
333 no_shortcut_candidate_window.mutable_candidates()->push_back(entry); | |
334 | |
335 entry.value = kSampleCandidate3; | |
336 entry.annotation = kSampleAnnotation3; | |
337 candidate_window.mutable_candidates()->push_back(entry); | |
338 entry.label = kSampleShortcut3; | |
339 no_shortcut_candidate_window.mutable_candidates()->push_back(entry); | |
340 | |
341 int before_height = 0; | |
342 | |
343 // Test for shortcut mode to no-shortcut mode. | |
344 // Initialize with a shortcut mode candidate window. | |
345 MaybeInitializeCandidateViews(candidate_window); | |
346 ASSERT_EQ(3UL, GetCandidatesSize()); | |
347 // Check the selected index is invalidated. | |
348 EXPECT_EQ(-1, selected_candidate_index_in_page()); | |
349 before_height = | |
350 GetCandidateAt(0)->GetContentsBounds().height(); | |
351 // Checks all entry have same row height. | |
352 for (size_t i = 1; i < GetCandidatesSize(); ++i) | |
353 EXPECT_EQ(before_height, GetCandidateAt(i)->GetContentsBounds().height()); | |
354 | |
355 // Initialize with a no shortcut mode candidate window. | |
356 MaybeInitializeCandidateViews(no_shortcut_candidate_window); | |
357 ASSERT_EQ(3UL, GetCandidatesSize()); | |
358 // Check the selected index is invalidated. | |
359 EXPECT_EQ(-1, selected_candidate_index_in_page()); | |
360 EXPECT_EQ(before_height, GetCandidateAt(0)->GetContentsBounds().height()); | |
361 // Checks all entry have same row height. | |
362 for (size_t i = 1; i < GetCandidatesSize(); ++i) | |
363 EXPECT_EQ(before_height, GetCandidateAt(i)->GetContentsBounds().height()); | |
364 | |
365 // Test for no-shortcut mode to shortcut mode. | |
366 // Initialize with a no shortcut mode candidate window. | |
367 MaybeInitializeCandidateViews(no_shortcut_candidate_window); | |
368 ASSERT_EQ(3UL, GetCandidatesSize()); | |
369 // Check the selected index is invalidated. | |
370 EXPECT_EQ(-1, selected_candidate_index_in_page()); | |
371 before_height = GetCandidateAt(0)->GetContentsBounds().height(); | |
372 // Checks all entry have same row height. | |
373 for (size_t i = 1; i < GetCandidatesSize(); ++i) | |
374 EXPECT_EQ(before_height, GetCandidateAt(i)->GetContentsBounds().height()); | |
375 | |
376 // Initialize with a shortcut mode candidate window. | |
377 MaybeInitializeCandidateViews(candidate_window); | |
378 ASSERT_EQ(3UL, GetCandidatesSize()); | |
379 // Check the selected index is invalidated. | |
380 EXPECT_EQ(-1, selected_candidate_index_in_page()); | |
381 EXPECT_EQ(before_height, GetCandidateAt(0)->GetContentsBounds().height()); | |
382 // Checks all entry have same row height. | |
383 for (size_t i = 1; i < GetCandidatesSize(); ++i) | |
384 EXPECT_EQ(before_height, GetCandidateAt(i)->GetContentsBounds().height()); | |
385 } | |
386 | |
387 } // namespace ime | |
388 } // namespace ash | |
OLD | NEW |