blob: 7994bd5056ed49c2a0c99b954a91777c1bbe9c09 [file] [log] [blame]
/*
* Copyright 2015 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <algorithm>
#include <vector>
#include "cobalt/dom/keyboard_event.h"
#include "cobalt/dom/keycode.h"
#include "cobalt/webdriver/keyboard.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::Each;
using testing::ElementsAre;
using testing::Eq;
namespace cobalt {
namespace webdriver {
namespace {
int32 GetKeyCode(const dom::KeyboardEvent::Data& event) {
scoped_refptr<dom::KeyboardEvent> keyboard_event(
new dom::KeyboardEvent(event));
return keyboard_event->key_code();
}
int32 GetCharCode(const dom::KeyboardEvent::Data& event) {
scoped_refptr<dom::KeyboardEvent> keyboard_event(
new dom::KeyboardEvent(event));
return keyboard_event->char_code();
}
uint32 GetModifierBitfield(const dom::KeyboardEvent::Data& event) {
scoped_refptr<dom::KeyboardEvent> keyboard_event(
new dom::KeyboardEvent(event));
return keyboard_event->modifiers();
}
std::string GetType(const dom::KeyboardEvent::Data& event) {
scoped_refptr<dom::KeyboardEvent> keyboard_event(
new dom::KeyboardEvent(event));
return keyboard_event->type().c_str();
}
int GetLocation(const dom::KeyboardEvent::Data& event) {
scoped_refptr<dom::KeyboardEvent> keyboard_event(
new dom::KeyboardEvent(event));
return keyboard_event->location();
}
class KeyboardTest : public ::testing::Test {
protected:
// Less verbose redefinitions.
const int kNoModifier = dom::UIEventWithKeyState::kNoModifier;
const int kShift = dom::UIEventWithKeyState::kShiftKey;
const int kAlt = dom::UIEventWithKeyState::kAltKey;
const int kAltAndShift = kAlt | kShift;
const int kLocationStandard = dom::KeyboardEvent::kDomKeyLocationStandard;
const int kLocationLeft = dom::KeyboardEvent::kDomKeyLocationLeft;
std::vector<int32> GetKeyCodes() {
std::vector<int32> key_codes(events_.size());
std::transform(events_.begin(), events_.end(), key_codes.begin(),
GetKeyCode);
return key_codes;
}
std::vector<int32> GetCharCodes() {
std::vector<int32> char_codes(events_.size());
std::transform(events_.begin(), events_.end(), char_codes.begin(),
GetCharCode);
return char_codes;
}
std::vector<uint32> GetModifiers() {
std::vector<uint32> modifiers(events_.size());
std::transform(events_.begin(), events_.end(), modifiers.begin(),
GetModifierBitfield);
return modifiers;
}
std::vector<int> GetLocations() {
std::vector<int> locations(events_.size());
std::transform(events_.begin(), events_.end(), locations.begin(),
GetLocation);
return locations;
}
std::vector<std::string> GetTypes() {
std::vector<std::string> types(events_.size());
std::transform(events_.begin(), events_.end(), types.begin(), GetType);
return types;
}
Keyboard::KeyboardEventVector events_;
};
} // namespace
TEST_F(KeyboardTest, LowerCaseCharacter) {
std::string keys = "r";
Keyboard::TranslateToKeyEvents(keys, Keyboard::kKeepModifiers, &events_);
ASSERT_EQ(events_.size(), 3);
EXPECT_THAT(GetTypes(), ElementsAre("keydown", "keypress", "keyup"));
EXPECT_THAT(GetKeyCodes(), ElementsAre('R', 0, 'R'));
EXPECT_THAT(GetCharCodes(), ElementsAre(0, 'r', 0));
EXPECT_THAT(GetModifiers(), Each(Eq(kNoModifier)));
EXPECT_THAT(GetLocations(), Each(Eq(kLocationStandard)));
}
TEST_F(KeyboardTest, UpperCaseCharacter) {
std::string keys = "R";
Keyboard::TranslateToKeyEvents(keys, Keyboard::kKeepModifiers, &events_);
// keydown(shift)
// keydown(R), keypress(R), keyup(R)
// keyup(shift)
ASSERT_EQ(events_.size(), 5);
EXPECT_THAT(GetTypes(),
ElementsAre("keydown", "keydown", "keypress", "keyup", "keyup"));
EXPECT_THAT(GetKeyCodes(), ElementsAre(dom::keycode::kShift, 'R', 0, 'R',
dom::keycode::kShift));
EXPECT_THAT(GetCharCodes(), ElementsAre(0, 0, 'R', 0, 0));
EXPECT_THAT(GetModifiers(),
ElementsAre(kShift, kShift, kShift, kShift, kNoModifier));
EXPECT_THAT(GetLocations(),
ElementsAre(kLocationLeft, kLocationStandard, kLocationStandard,
kLocationStandard, kLocationLeft));
}
TEST_F(KeyboardTest, ShiftedCharacter) {
std::string keys = "&";
Keyboard::TranslateToKeyEvents(keys, Keyboard::kKeepModifiers, &events_);
// keydown(shift)
// keydown(7), keypress(&), keyup(7)
// keyup(shift)
ASSERT_EQ(events_.size(), 5);
EXPECT_THAT(GetTypes(),
ElementsAre("keydown", "keydown", "keypress", "keyup", "keyup"));
EXPECT_THAT(GetKeyCodes(), ElementsAre(dom::keycode::kShift, '7', 0, '7',
dom::keycode::kShift));
EXPECT_THAT(GetCharCodes(), ElementsAre(0, 0, '&', 0, 0));
EXPECT_THAT(GetModifiers(),
ElementsAre(kShift, kShift, kShift, kShift, kNoModifier));
EXPECT_THAT(GetLocations(),
ElementsAre(kLocationLeft, kLocationStandard, kLocationStandard,
kLocationStandard, kLocationLeft));
}
TEST_F(KeyboardTest, Modifier) {
// \uE00A is the Alt-key modifier.
std::string keys = "\uE00A";
Keyboard::TranslateToKeyEvents(keys, Keyboard::kKeepModifiers, &events_);
ASSERT_EQ(events_.size(), 1);
EXPECT_THAT(GetTypes(), ElementsAre("keydown"));
EXPECT_THAT(GetKeyCodes(), ElementsAre(dom::keycode::kMenu));
EXPECT_THAT(GetCharCodes(), ElementsAre(0));
EXPECT_THAT(GetModifiers(), ElementsAre(kAlt));
EXPECT_THAT(GetLocations(), ElementsAre(kLocationLeft));
}
TEST_F(KeyboardTest, ModifiersAreKept) {
// \uE00A is the Alt-key modifier.
// \uE008 is the Shift-key modifier.
std::string keys = "\uE00A\uE008";
Keyboard::TranslateToKeyEvents(keys, Keyboard::kKeepModifiers, &events_);
ASSERT_EQ(events_.size(), 2);
EXPECT_THAT(GetTypes(), ElementsAre("keydown", "keydown"));
EXPECT_THAT(GetKeyCodes(),
ElementsAre(dom::keycode::kMenu, dom::keycode::kShift));
EXPECT_THAT(GetCharCodes(), Each(Eq(0)));
EXPECT_THAT(GetModifiers(), ElementsAre(kAlt, kAltAndShift));
EXPECT_THAT(GetLocations(), Each(Eq(kLocationLeft)));
}
TEST_F(KeyboardTest, ModifiersAreReleased) {
// \uE00A is the Alt-key modifier.
// \uE008 is the Shift-key modifier.
std::string keys = "\uE00A\uE008";
Keyboard::TranslateToKeyEvents(keys, Keyboard::kReleaseModifiers, &events_);
ASSERT_EQ(events_.size(), 4);
EXPECT_THAT(GetTypes(), ElementsAre("keydown", "keydown", "keyup", "keyup"));
EXPECT_THAT(GetKeyCodes(),
ElementsAre(dom::keycode::kMenu, dom::keycode::kShift,
dom::keycode::kMenu, dom::keycode::kShift));
EXPECT_THAT(GetCharCodes(), Each(Eq(0)));
EXPECT_THAT(GetModifiers(),
ElementsAre(kAlt, kAltAndShift, kShift, kNoModifier));
EXPECT_THAT(GetLocations(), Each(Eq(kLocationLeft)));
}
TEST_F(KeyboardTest, SpecialCharacter) {
// \uE012 is the Left-arrow key.
std::string keys = "\uE012";
Keyboard::TranslateToKeyEvents(keys, Keyboard::kKeepModifiers, &events_);
ASSERT_EQ(events_.size(), 2);
EXPECT_THAT(GetTypes(), ElementsAre("keydown", "keyup"));
EXPECT_THAT(GetKeyCodes(), Each(Eq(dom::keycode::kLeft)));
EXPECT_THAT(GetCharCodes(), Each(Eq(0)));
EXPECT_THAT(GetModifiers(), Each(Eq(kNoModifier)));
EXPECT_THAT(GetLocations(), Each(Eq(kLocationStandard)));
}
TEST_F(KeyboardTest, ModifierIsSticky) {
// \uE00A is the Alt-key modifier. Corresponds to the kMenu key code.
std::string keys = "\uE00AaB";
Keyboard::TranslateToKeyEvents(keys, Keyboard::kKeepModifiers, &events_);
// keydown(alt)
// keydown(A), keypress(a), keyup(A),
// keydown(shift)
// keydown(B), keypress(B), keyup(B)
// keyup(shift)
ASSERT_EQ(events_.size(), 9);
EXPECT_THAT(GetTypes(),
ElementsAre("keydown", "keydown", "keypress", "keyup", "keydown",
"keydown", "keypress", "keyup", "keyup"));
EXPECT_THAT(GetKeyCodes(), ElementsAre(dom::keycode::kMenu, 'A', 0, 'A',
dom::keycode::kShift, 'B', 0, 'B',
dom::keycode::kShift));
EXPECT_THAT(GetCharCodes(), ElementsAre(0, 0, 'a', 0, 0, 0, 'B', 0, 0));
EXPECT_THAT(GetModifiers(),
ElementsAre(kAlt, kAlt, kAlt, kAlt, kAltAndShift, kAltAndShift,
kAltAndShift, kAltAndShift, kAlt));
EXPECT_THAT(GetLocations(),
ElementsAre(kLocationLeft, kLocationStandard, kLocationStandard,
kLocationStandard, kLocationLeft, kLocationStandard,
kLocationStandard, kLocationStandard, kLocationLeft));
}
TEST_F(KeyboardTest, ToggleModifier) {
// \uE008 is the Shift-key modifier.
std::string keys = "\uE008a\uE008a";
Keyboard::TranslateToKeyEvents(keys, Keyboard::kKeepModifiers, &events_);
// keydown(shift)
// keydown(A), keypress(A), keyup(A)
// keyup(shift)
// keydown(A), keypress(a), keyup(A)
ASSERT_EQ(events_.size(), 8);
EXPECT_THAT(GetTypes(), ElementsAre("keydown", "keydown", "keypress", "keyup",
"keyup", "keydown", "keypress", "keyup"));
EXPECT_THAT(GetKeyCodes(), ElementsAre(dom::keycode::kShift, 'A', 0, 'A',
dom::keycode::kShift, 'A', 0, 'A'));
EXPECT_THAT(GetCharCodes(), ElementsAre(0, 0, 'A', 0, 0, 0, 'a', 0));
EXPECT_THAT(GetModifiers(),
ElementsAre(kShift, kShift, kShift, kShift, kNoModifier,
kNoModifier, kNoModifier, kNoModifier));
EXPECT_THAT(GetLocations(),
ElementsAre(kLocationLeft, kLocationStandard, kLocationStandard,
kLocationStandard, kLocationLeft, kLocationStandard,
kLocationStandard, kLocationStandard));
}
TEST_F(KeyboardTest, NullClearsModifiers) {
std::string keys = "\uE008\uE00A\uE000a";
Keyboard::TranslateToKeyEvents(keys, Keyboard::kKeepModifiers, &events_);
// keydown(shift)
// keydown(alt)
// keyup(alt)
// keyup(shift)
// keydown(A), keypress(a), keyup(A)
ASSERT_EQ(events_.size(), 7);
EXPECT_THAT(GetTypes(), ElementsAre("keydown", "keydown", "keyup", "keyup",
"keydown", "keypress", "keyup"));
EXPECT_THAT(
GetKeyCodes(),
ElementsAre(dom::keycode::kShift, dom::keycode::kMenu,
dom::keycode::kMenu, dom::keycode::kShift, 'A', 0, 'A'));
EXPECT_THAT(GetCharCodes(), ElementsAre(0, 0, 0, 0, 0, 'a', 0));
EXPECT_THAT(GetModifiers(),
ElementsAre(kShift, kAltAndShift, kShift, kNoModifier,
kNoModifier, kNoModifier, kNoModifier));
EXPECT_THAT(
GetLocations(),
ElementsAre(kLocationLeft, kLocationLeft, kLocationLeft, kLocationLeft,
kLocationStandard, kLocationStandard, kLocationStandard));
}
} // namespace webdriver
} // namespace cobalt