1 // Copyright (c) 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.
8 #include "base/string16.h"
9 #include "base/utf_string_conversions.h"
10 #include "chrome/test/automation/automation_json_requests.h"
11 #include "chrome/test/webdriver/webdriver_key_converter.h"
12 #include "chrome/test/webdriver/webdriver_test_util.h"
13 #include "testing/gtest/include/gtest/gtest.h"
17 void CheckEvents(const string16
& keys
,
18 WebKeyEvent expected_events
[],
19 bool release_modifiers
,
21 int expected_modifiers
) {
23 std::vector
<WebKeyEvent
> events
;
24 std::string error_msg
;
25 EXPECT_TRUE(ConvertKeysToWebKeyEvents(keys
, Logger(),
27 &modifiers
, &events
, &error_msg
));
28 EXPECT_EQ(expected_size
, events
.size());
29 for (size_t i
= 0; i
< events
.size() && i
< expected_size
; ++i
) {
30 EXPECT_EQ(expected_events
[i
].type
, events
[i
].type
);
31 EXPECT_EQ(expected_events
[i
].key_code
, events
[i
].key_code
);
32 EXPECT_EQ(expected_events
[i
].unmodified_text
, events
[i
].unmodified_text
);
33 EXPECT_EQ(expected_events
[i
].modified_text
, events
[i
].modified_text
);
34 EXPECT_EQ(expected_events
[i
].modifiers
, events
[i
].modifiers
);
36 EXPECT_EQ(expected_modifiers
, modifiers
);
39 void CheckEventsReleaseModifiers(const string16
& keys
,
40 WebKeyEvent expected_events
[],
41 size_t expected_size
) {
42 CheckEvents(keys
, expected_events
, true /* release_modifier */,
43 expected_size
, 0 /* expected_modifiers */);
46 void CheckEventsReleaseModifiers(const std::string
& keys
,
47 WebKeyEvent expected_events
[],
48 size_t expected_size
) {
49 CheckEventsReleaseModifiers(UTF8ToUTF16(keys
),
50 expected_events
, expected_size
);
53 void CheckNonShiftChar(ui::KeyboardCode key_code
, char character
) {
55 std::string char_string
;
56 char_string
.push_back(character
);
57 std::vector
<WebKeyEvent
> events
;
58 std::string error_msg
;
59 EXPECT_TRUE(ConvertKeysToWebKeyEvents(ASCIIToUTF16(char_string
), Logger(),
60 true /* release_modifiers*/,
61 &modifiers
, &events
, &error_msg
));
62 ASSERT_EQ(3u, events
.size()) << "Char: " << character
;
63 EXPECT_EQ(key_code
, events
[0].key_code
) << "Char: " << character
;
64 ASSERT_EQ(1u, events
[1].modified_text
.length()) << "Char: " << character
;
65 ASSERT_EQ(1u, events
[1].unmodified_text
.length()) << "Char: " << character
;
66 EXPECT_EQ(character
, events
[1].modified_text
[0]) << "Char: " << character
;
67 EXPECT_EQ(character
, events
[1].unmodified_text
[0]) << "Char: " << character
;
68 EXPECT_EQ(key_code
, events
[2].key_code
) << "Char: " << character
;
71 void CheckShiftChar(ui::KeyboardCode key_code
, char character
, char lower
) {
73 std::string char_string
;
74 char_string
.push_back(character
);
75 std::vector
<WebKeyEvent
> events
;
76 std::string error_msg
;
77 EXPECT_TRUE(ConvertKeysToWebKeyEvents(ASCIIToUTF16(char_string
), Logger(),
78 true /* release_modifiers*/,
79 &modifiers
, &events
, &error_msg
));
80 ASSERT_EQ(5u, events
.size()) << "Char: " << character
;
81 EXPECT_EQ(ui::VKEY_SHIFT
, events
[0].key_code
) << "Char: " << character
;
82 EXPECT_EQ(key_code
, events
[1].key_code
) << "Char: " << character
;
83 ASSERT_EQ(1u, events
[2].modified_text
.length()) << "Char: " << character
;
84 ASSERT_EQ(1u, events
[2].unmodified_text
.length()) << "Char: " << character
;
85 EXPECT_EQ(character
, events
[2].modified_text
[0]) << "Char: " << character
;
86 EXPECT_EQ(lower
, events
[2].unmodified_text
[0]) << "Char: " << character
;
87 EXPECT_EQ(key_code
, events
[3].key_code
) << "Char: " << character
;
88 EXPECT_EQ(ui::VKEY_SHIFT
, events
[4].key_code
) << "Char: " << character
;
91 TEST(WebDriverKeyConverter
, SingleChar
) {
92 WebKeyEvent event_array
[] = {
93 CreateKeyDownEvent(ui::VKEY_H
, 0),
94 CreateCharEvent("h", "h", 0),
95 CreateKeyUpEvent(ui::VKEY_H
, 0)};
96 CheckEventsReleaseModifiers("h", event_array
, arraysize(event_array
));
99 TEST(WebDriverKeyConverter
, SingleNumber
) {
100 WebKeyEvent event_array
[] = {
101 CreateKeyDownEvent(ui::VKEY_1
, 0),
102 CreateCharEvent("1", "1", 0),
103 CreateKeyUpEvent(ui::VKEY_1
, 0)};
104 CheckEventsReleaseModifiers("1", event_array
, arraysize(event_array
));
107 TEST(WebDriverKeyConverter
, MultipleChars
) {
108 WebKeyEvent event_array
[] = {
109 CreateKeyDownEvent(ui::VKEY_H
, 0),
110 CreateCharEvent("h", "h", 0),
111 CreateKeyUpEvent(ui::VKEY_H
, 0),
112 CreateKeyDownEvent(ui::VKEY_E
, 0),
113 CreateCharEvent("e", "e", 0),
114 CreateKeyUpEvent(ui::VKEY_E
, 0),
115 CreateKeyDownEvent(ui::VKEY_Y
, 0),
116 CreateCharEvent("y", "y", 0),
117 CreateKeyUpEvent(ui::VKEY_Y
, 0)};
118 CheckEventsReleaseModifiers("hey", event_array
, arraysize(event_array
));
121 TEST(WebDriverKeyConverter
, WebDriverSpecialChar
) {
122 WebKeyEvent event_array
[] = {
123 CreateKeyDownEvent(ui::VKEY_SPACE
, 0),
124 CreateCharEvent(" ", " ", 0),
125 CreateKeyUpEvent(ui::VKEY_SPACE
, 0)};
127 keys
.push_back(static_cast<char16
>(0xE00DU
));
128 CheckEventsReleaseModifiers(keys
, event_array
, arraysize(event_array
));
131 TEST(WebDriverKeyConverter
, WebDriverSpecialNonCharKey
) {
132 WebKeyEvent event_array
[] = {
133 CreateKeyDownEvent(ui::VKEY_F1
, 0),
134 CreateKeyUpEvent(ui::VKEY_F1
, 0)};
136 keys
.push_back(static_cast<char16
>(0xE031U
));
137 CheckEventsReleaseModifiers(keys
, event_array
, arraysize(event_array
));
140 TEST(WebDriverKeyConverter
, FrenchKeyOnEnglishLayout
) {
141 WebKeyEvent event_array
[] = {
142 CreateKeyDownEvent(ui::VKEY_UNKNOWN
, 0),
143 CreateCharEvent(WideToUTF8(L
"\u00E9"), WideToUTF8(L
"\u00E9"), 0),
144 CreateKeyUpEvent(ui::VKEY_UNKNOWN
, 0)};
145 CheckEventsReleaseModifiers(WideToUTF16(L
"\u00E9"),
146 event_array
, arraysize(event_array
));
150 TEST(WebDriverKeyConverter
, NeedsCtrlAndAlt
) {
151 RestoreKeyboardLayoutOnDestruct restore
;
152 int ctrl_and_alt
= automation::kControlKeyMask
| automation::kAltKeyMask
;
153 WebKeyEvent event_array
[] = {
154 CreateKeyDownEvent(ui::VKEY_CONTROL
, 0),
155 CreateKeyDownEvent(ui::VKEY_MENU
, 0),
156 CreateKeyDownEvent(ui::VKEY_Q
, ctrl_and_alt
),
157 CreateCharEvent("q", "@", ctrl_and_alt
),
158 CreateKeyUpEvent(ui::VKEY_Q
, ctrl_and_alt
),
159 CreateKeyUpEvent(ui::VKEY_MENU
, 0),
160 CreateKeyUpEvent(ui::VKEY_CONTROL
, 0)};
161 ASSERT_TRUE(SwitchKeyboardLayout("00000407"));
162 CheckEventsReleaseModifiers("@", event_array
, arraysize(event_array
));
166 TEST(WebDriverKeyConverter
, UppercaseCharDoesShift
) {
167 WebKeyEvent event_array
[] = {
168 CreateKeyDownEvent(ui::VKEY_SHIFT
, 0),
169 CreateKeyDownEvent(ui::VKEY_A
, automation::kShiftKeyMask
),
170 CreateCharEvent("a", "A", automation::kShiftKeyMask
),
171 CreateKeyUpEvent(ui::VKEY_A
, automation::kShiftKeyMask
),
172 CreateKeyUpEvent(ui::VKEY_SHIFT
, 0)};
173 CheckEventsReleaseModifiers("A", event_array
, arraysize(event_array
));
176 TEST(WebDriverKeyConverter
, UppercaseSymbolCharDoesShift
) {
177 WebKeyEvent event_array
[] = {
178 CreateKeyDownEvent(ui::VKEY_SHIFT
, 0),
179 CreateKeyDownEvent(ui::VKEY_1
, automation::kShiftKeyMask
),
180 CreateCharEvent("1", "!", automation::kShiftKeyMask
),
181 CreateKeyUpEvent(ui::VKEY_1
, automation::kShiftKeyMask
),
182 CreateKeyUpEvent(ui::VKEY_SHIFT
, 0)};
183 CheckEventsReleaseModifiers("!", event_array
, arraysize(event_array
));
186 TEST(WebDriverKeyConverter
, UppercaseCharUsesShiftOnlyIfNecessary
) {
187 WebKeyEvent event_array
[] = {
188 CreateKeyDownEvent(ui::VKEY_SHIFT
, automation::kShiftKeyMask
),
189 CreateKeyDownEvent(ui::VKEY_A
, automation::kShiftKeyMask
),
190 CreateCharEvent("a", "A", automation::kShiftKeyMask
),
191 CreateKeyUpEvent(ui::VKEY_A
, automation::kShiftKeyMask
),
192 CreateKeyDownEvent(ui::VKEY_B
, automation::kShiftKeyMask
),
193 CreateCharEvent("b", "B", automation::kShiftKeyMask
),
194 CreateKeyUpEvent(ui::VKEY_B
, automation::kShiftKeyMask
),
195 CreateKeyDownEvent(ui::VKEY_C
, automation::kShiftKeyMask
),
196 CreateCharEvent("c", "C", automation::kShiftKeyMask
),
197 CreateKeyUpEvent(ui::VKEY_C
, automation::kShiftKeyMask
),
198 CreateKeyUpEvent(ui::VKEY_SHIFT
, 0)};
200 keys
.push_back(static_cast<char16
>(0xE008U
));
201 keys
.append(UTF8ToUTF16("aBc"));
202 CheckEventsReleaseModifiers(keys
, event_array
, arraysize(event_array
));
205 TEST(WebDriverKeyConverter
, ToggleModifiers
) {
206 WebKeyEvent event_array
[] = {
207 CreateKeyDownEvent(ui::VKEY_SHIFT
, automation::kShiftKeyMask
),
208 CreateKeyUpEvent(ui::VKEY_SHIFT
, 0),
209 CreateKeyDownEvent(ui::VKEY_CONTROL
, automation::kControlKeyMask
),
210 CreateKeyUpEvent(ui::VKEY_CONTROL
, 0),
211 CreateKeyDownEvent(ui::VKEY_MENU
, automation::kAltKeyMask
),
212 CreateKeyUpEvent(ui::VKEY_MENU
, 0),
213 CreateKeyDownEvent(ui::VKEY_COMMAND
, automation::kMetaKeyMask
),
214 CreateKeyUpEvent(ui::VKEY_COMMAND
, 0)};
216 keys
.push_back(static_cast<char16
>(0xE008U
));
217 keys
.push_back(static_cast<char16
>(0xE008U
));
218 keys
.push_back(static_cast<char16
>(0xE009U
));
219 keys
.push_back(static_cast<char16
>(0xE009U
));
220 keys
.push_back(static_cast<char16
>(0xE00AU
));
221 keys
.push_back(static_cast<char16
>(0xE00AU
));
222 keys
.push_back(static_cast<char16
>(0xE03DU
));
223 keys
.push_back(static_cast<char16
>(0xE03DU
));
224 CheckEventsReleaseModifiers(keys
, event_array
, arraysize(event_array
));
227 TEST(WebDriverKeyConverter
, AllShorthandKeys
) {
228 WebKeyEvent event_array
[] = {
229 CreateKeyDownEvent(ui::VKEY_RETURN
, 0),
230 CreateCharEvent("\r", "\r", 0),
231 CreateKeyUpEvent(ui::VKEY_RETURN
, 0),
232 CreateKeyDownEvent(ui::VKEY_RETURN
, 0),
233 CreateCharEvent("\r", "\r", 0),
234 CreateKeyUpEvent(ui::VKEY_RETURN
, 0),
235 CreateKeyDownEvent(ui::VKEY_TAB
, 0),
236 #if defined(USE_AURA)
237 CreateCharEvent("\t", "\t", 0),
239 CreateKeyUpEvent(ui::VKEY_TAB
, 0),
240 CreateKeyDownEvent(ui::VKEY_BACK
, 0),
241 #if defined(USE_AURA)
242 CreateCharEvent("\b", "\b", 0),
244 CreateKeyUpEvent(ui::VKEY_BACK
, 0),
245 CreateKeyDownEvent(ui::VKEY_SPACE
, 0),
246 CreateCharEvent(" ", " ", 0),
247 CreateKeyUpEvent(ui::VKEY_SPACE
, 0)};
248 CheckEventsReleaseModifiers("\n\r\n\t\b ",
249 event_array
,arraysize(event_array
));
252 TEST(WebDriverKeyConverter
, AllEnglishKeyboardSymbols
) {
254 const ui::KeyboardCode kSymbolKeyCodes
[] = {
266 std::string kLowerSymbols
= "`-=[]\\;',./";
267 std::string kUpperSymbols
= "~_+{}|:\"<>?";
268 for (size_t i
= 0; i
< kLowerSymbols
.length(); ++i
)
269 CheckNonShiftChar(kSymbolKeyCodes
[i
], kLowerSymbols
[i
]);
270 for (size_t i
= 0; i
< kUpperSymbols
.length(); ++i
)
271 CheckShiftChar(kSymbolKeyCodes
[i
], kUpperSymbols
[i
], kLowerSymbols
[i
]);
274 TEST(WebDriverKeyConverter
, AllEnglishKeyboardTextChars
) {
275 std::string kLowerChars
= "0123456789abcdefghijklmnopqrstuvwxyz";
276 std::string kUpperChars
= ")!@#$%^&*(ABCDEFGHIJKLMNOPQRSTUVWXYZ";
277 for (size_t i
= 0; i
< kLowerChars
.length(); ++i
) {
282 offset
= ui::VKEY_0
+ 7;
283 ui::KeyboardCode expected_code
= static_cast<ui::KeyboardCode
>(offset
+ i
);
284 CheckNonShiftChar(expected_code
, kLowerChars
[i
]);
286 for (size_t i
= 0; i
< kUpperChars
.length(); ++i
) {
291 offset
= ui::VKEY_0
+ 7;
292 ui::KeyboardCode expected_code
= static_cast<ui::KeyboardCode
>(offset
+ i
);
293 CheckShiftChar(expected_code
, kUpperChars
[i
], kLowerChars
[i
]);
297 TEST(WebDriverKeyConverter
, AllSpecialWebDriverKeysOnEnglishKeyboard
) {
298 const char kTextForKeys
[] = {
299 #if defined(USE_AURA)
300 0, 0, 0, '\b', '\t', 0, '\r', '\r', 0, 0, 0, 0, 0x1B,
301 ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x7F, ';', '=',
303 0, 0, 0, 0, 0, 0, '\r', '\r', 0, 0, 0, 0, 0,
304 ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ';', '=',
306 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
307 '*', '+', ',', '-', '.', '/'};
308 for (size_t i
= 0; i
<= 0x3D; ++i
) {
309 if (i
> 0x29 && i
< 0x31)
313 keys
.push_back(0xE000U
+ i
);
314 std::vector
<WebKeyEvent
> events
;
315 std::string error_msg
;
317 EXPECT_FALSE(ConvertKeysToWebKeyEvents(keys
, Logger(),
318 true /* release_modifiers*/,
319 &modifiers
, &events
, &error_msg
))
321 EXPECT_EQ(0u, events
.size()) << "Index: " << i
;
323 EXPECT_TRUE(ConvertKeysToWebKeyEvents(keys
, Logger(),
324 true /* release_modifiers */,
325 &modifiers
, &events
, &error_msg
))
328 EXPECT_EQ(0u, events
.size()) << "Index: " << i
;
329 } else if (i
>= arraysize(kTextForKeys
) || kTextForKeys
[i
] == 0) {
330 EXPECT_EQ(2u, events
.size()) << "Index: " << i
;
332 ASSERT_EQ(3u, events
.size()) << "Index: " << i
;
333 ASSERT_EQ(1u, events
[1].unmodified_text
.length()) << "Index: " << i
;
334 EXPECT_EQ(kTextForKeys
[i
], events
[1].unmodified_text
[0])
341 TEST(WebDriverKeyConverter
, ModifiersState
) {
342 int shift_key_modifier
= automation::kShiftKeyMask
;
343 int control_key_modifier
= shift_key_modifier
| automation::kControlKeyMask
;
344 int alt_key_modifier
= control_key_modifier
| automation::kAltKeyMask
;
345 int meta_key_modifier
= alt_key_modifier
| automation::kMetaKeyMask
;
346 WebKeyEvent event_array
[] = {
347 CreateKeyDownEvent(ui::VKEY_SHIFT
, shift_key_modifier
),
348 CreateKeyDownEvent(ui::VKEY_CONTROL
, control_key_modifier
),
349 CreateKeyDownEvent(ui::VKEY_MENU
, alt_key_modifier
),
350 CreateKeyDownEvent(ui::VKEY_COMMAND
, meta_key_modifier
)};
352 keys
.push_back(static_cast<char16
>(0xE008U
));
353 keys
.push_back(static_cast<char16
>(0xE009U
));
354 keys
.push_back(static_cast<char16
>(0xE00AU
));
355 keys
.push_back(static_cast<char16
>(0xE03DU
));
357 CheckEvents(keys
, event_array
, false /* release_modifiers */,
358 arraysize(event_array
), meta_key_modifier
);
361 TEST(WebDriverKeyConverter
, ReleaseModifiers
) {
362 WebKeyEvent event_array
[] = {
363 CreateKeyDownEvent(ui::VKEY_SHIFT
, automation::kShiftKeyMask
),
364 CreateKeyDownEvent(ui::VKEY_CONTROL
,
365 automation::kShiftKeyMask
| automation::kControlKeyMask
),
366 CreateKeyUpEvent(ui::VKEY_SHIFT
, 0),
367 CreateKeyUpEvent(ui::VKEY_CONTROL
, 0)};
369 keys
.push_back(static_cast<char16
>(0xE008U
));
370 keys
.push_back(static_cast<char16
>(0xE009U
));
372 CheckEvents(keys
, event_array
, true /* release_modifiers */,
373 arraysize(event_array
), 0);
376 } // namespace webdriver