Home | History | Annotate | Download | only in webdriver
      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