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. 4 5 #include <string> 6 #include <vector> 7 8 #include "base/strings/string16.h" 9 #include "base/strings/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" 14 15 namespace webdriver { 16 17 void CheckEvents(const string16& keys, 18 WebKeyEvent expected_events[], 19 bool release_modifiers, 20 size_t expected_size, 21 int expected_modifiers) { 22 int modifiers = 0; 23 std::vector<WebKeyEvent> events; 24 std::string error_msg; 25 EXPECT_TRUE(ConvertKeysToWebKeyEvents(keys, Logger(), 26 release_modifiers, 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); 35 } 36 EXPECT_EQ(expected_modifiers, modifiers); 37 } 38 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 */); 44 } 45 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); 51 } 52 53 void CheckNonShiftChar(ui::KeyboardCode key_code, char character) { 54 int modifiers = 0; 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; 69 } 70 71 void CheckShiftChar(ui::KeyboardCode key_code, char character, char lower) { 72 int modifiers = 0; 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; 89 } 90 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)); 97 } 98 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)); 105 } 106 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)); 119 } 120 121 TEST(WebDriverKeyConverter, WebDriverSpecialChar) { 122 WebKeyEvent event_array[] = { 123 CreateKeyDownEvent(ui::VKEY_SPACE, 0), 124 CreateCharEvent(" ", " ", 0), 125 CreateKeyUpEvent(ui::VKEY_SPACE, 0)}; 126 string16 keys; 127 keys.push_back(static_cast<char16>(0xE00DU)); 128 CheckEventsReleaseModifiers(keys, event_array, arraysize(event_array)); 129 } 130 131 TEST(WebDriverKeyConverter, WebDriverSpecialNonCharKey) { 132 WebKeyEvent event_array[] = { 133 CreateKeyDownEvent(ui::VKEY_F1, 0), 134 CreateKeyUpEvent(ui::VKEY_F1, 0)}; 135 string16 keys; 136 keys.push_back(static_cast<char16>(0xE031U)); 137 CheckEventsReleaseModifiers(keys, event_array, arraysize(event_array)); 138 } 139 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)); 147 } 148 149 #if defined(OS_WIN) 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)); 163 } 164 #endif 165 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)); 174 } 175 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)); 184 } 185 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)}; 199 string16 keys; 200 keys.push_back(static_cast<char16>(0xE008U)); 201 keys.append(UTF8ToUTF16("aBc")); 202 CheckEventsReleaseModifiers(keys, event_array, arraysize(event_array)); 203 } 204 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)}; 215 string16 keys; 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)); 225 } 226 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), 238 #endif 239 CreateKeyUpEvent(ui::VKEY_TAB, 0), 240 CreateKeyDownEvent(ui::VKEY_BACK, 0), 241 #if defined(USE_AURA) 242 CreateCharEvent("\b", "\b", 0), 243 #endif 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)); 250 } 251 252 TEST(WebDriverKeyConverter, AllEnglishKeyboardSymbols) { 253 string16 keys; 254 const ui::KeyboardCode kSymbolKeyCodes[] = { 255 ui::VKEY_OEM_3, 256 ui::VKEY_OEM_MINUS, 257 ui::VKEY_OEM_PLUS, 258 ui::VKEY_OEM_4, 259 ui::VKEY_OEM_6, 260 ui::VKEY_OEM_5, 261 ui::VKEY_OEM_1, 262 ui::VKEY_OEM_7, 263 ui::VKEY_OEM_COMMA, 264 ui::VKEY_OEM_PERIOD, 265 ui::VKEY_OEM_2}; 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]); 272 } 273 274 TEST(WebDriverKeyConverter, AllEnglishKeyboardTextChars) { 275 std::string kLowerChars = "0123456789abcdefghijklmnopqrstuvwxyz"; 276 std::string kUpperChars = ")!@#$%^&*(ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 277 for (size_t i = 0; i < kLowerChars.length(); ++i) { 278 int offset = 0; 279 if (i < 10) 280 offset = ui::VKEY_0; 281 else 282 offset = ui::VKEY_0 + 7; 283 ui::KeyboardCode expected_code = static_cast<ui::KeyboardCode>(offset + i); 284 CheckNonShiftChar(expected_code, kLowerChars[i]); 285 } 286 for (size_t i = 0; i < kUpperChars.length(); ++i) { 287 int offset = 0; 288 if (i < 10) 289 offset = ui::VKEY_0; 290 else 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]); 294 } 295 } 296 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, ';', '=', 302 #else 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, ';', '=', 305 #endif 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) 310 continue; 311 string16 keys; 312 int modifiers = 0; 313 keys.push_back(0xE000U + i); 314 std::vector<WebKeyEvent> events; 315 std::string error_msg; 316 if (i == 1) { 317 EXPECT_FALSE(ConvertKeysToWebKeyEvents(keys, Logger(), 318 true /* release_modifiers*/, 319 &modifiers, &events, &error_msg)) 320 << "Index: " << i; 321 EXPECT_EQ(0u, events.size()) << "Index: " << i; 322 } else { 323 EXPECT_TRUE(ConvertKeysToWebKeyEvents(keys, Logger(), 324 true /* release_modifiers */, 325 &modifiers, &events, &error_msg)) 326 << "Index: " << i; 327 if (i == 0) { 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; 331 } else { 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]) 335 << "Index: " << i; 336 } 337 } 338 } 339 } 340 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)}; 351 string16 keys; 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)); 356 357 CheckEvents(keys, event_array, false /* release_modifiers */, 358 arraysize(event_array), meta_key_modifier); 359 } 360 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)}; 368 string16 keys; 369 keys.push_back(static_cast<char16>(0xE008U)); 370 keys.push_back(static_cast<char16>(0xE009U)); 371 372 CheckEvents(keys, event_array, true /* release_modifiers */, 373 arraysize(event_array), 0); 374 } 375 376 } // namespace webdriver 377