ime_menu_tray_unittest.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. // Copyright 2016 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. #include "ash/system/ime_menu/ime_menu_tray.h"
  5. #include "ash/accelerators/accelerator_controller_impl.h"
  6. #include "ash/ime/ime_controller_impl.h"
  7. #include "ash/ime/test_ime_controller_client.h"
  8. #include "ash/public/cpp/ime_info.h"
  9. #include "ash/session/session_controller_impl.h"
  10. #include "ash/shell.h"
  11. #include "ash/system/ime_menu/ime_list_view.h"
  12. #include "ash/system/status_area_widget.h"
  13. #include "ash/system/status_area_widget_test_helper.h"
  14. #include "ash/test/ash_test_base.h"
  15. #include "base/containers/contains.h"
  16. #include "base/run_loop.h"
  17. #include "base/strings/utf_string_conversions.h"
  18. #include "ui/accessibility/ax_enums.mojom.h"
  19. #include "ui/accessibility/ax_node_data.h"
  20. #include "ui/base/emoji/emoji_panel_helper.h"
  21. #include "ui/base/ime/ash/ime_bridge.h"
  22. #include "ui/base/ime/text_input_flags.h"
  23. #include "ui/display/test/display_manager_test_api.h"
  24. #include "ui/events/devices/device_data_manager_test_api.h"
  25. #include "ui/events/devices/input_device.h"
  26. #include "ui/events/devices/touchscreen_device.h"
  27. #include "ui/events/event.h"
  28. #include "ui/views/controls/label.h"
  29. using base::UTF8ToUTF16;
  30. namespace ash {
  31. namespace {
  32. const int kEmojiButtonId = 1;
  33. const int kSettingsButtonId = 2;
  34. ImeMenuTray* GetTray() {
  35. return StatusAreaWidgetTestHelper::GetStatusAreaWidget()->ime_menu_tray();
  36. }
  37. void SetCurrentIme(const std::string& current_ime_id,
  38. const std::vector<ImeInfo>& available_imes) {
  39. std::vector<ImeInfo> available_ime_ptrs;
  40. for (const auto& ime : available_imes)
  41. available_ime_ptrs.push_back(ime);
  42. Shell::Get()->ime_controller()->RefreshIme(current_ime_id,
  43. std::move(available_ime_ptrs),
  44. std::vector<ImeMenuItem>());
  45. }
  46. } // namespace
  47. class ImeMenuTrayTest : public AshTestBase {
  48. public:
  49. ImeMenuTrayTest() = default;
  50. ImeMenuTrayTest(const ImeMenuTrayTest&) = delete;
  51. ImeMenuTrayTest& operator=(const ImeMenuTrayTest&) = delete;
  52. ~ImeMenuTrayTest() override = default;
  53. protected:
  54. // Returns true if the IME menu tray is visible.
  55. bool IsVisible() { return GetTray()->GetVisible(); }
  56. // Returns the label text of the tray.
  57. const std::u16string& GetTrayText() { return GetTray()->label_->GetText(); }
  58. // Returns true if the background color of the tray is active.
  59. bool IsTrayBackgroundActive() { return GetTray()->is_active(); }
  60. // Returns true if the IME menu bubble has been shown.
  61. bool IsBubbleShown() { return GetTray()->GetBubbleView() != nullptr; }
  62. // Returns true if emoji palatte is enabled for the current keyboard.
  63. bool IsEmojiEnabled() { return GetTray()->is_emoji_enabled_; }
  64. // Returns true if handwirting input is enabled for the current keyboard.
  65. bool IsHandwritingEnabled() { return GetTray()->is_handwriting_enabled_; }
  66. // Returns true if voice input is enabled for the current keyboard.
  67. bool IsVoiceEnabled() { return GetTray()->is_voice_enabled_; }
  68. views::Button* GetEmojiButton() const {
  69. return static_cast<views::Button*>(
  70. GetTray()->bubble_->bubble_view()->GetViewByID(kEmojiButtonId));
  71. }
  72. views::View* GetSettingsButton() const {
  73. return static_cast<views::View*>(
  74. GetTray()->bubble_->bubble_view()->GetViewByID(kSettingsButtonId));
  75. }
  76. void SetUpKioskSession() {
  77. SessionInfo info;
  78. info.is_running_in_app_mode = true;
  79. Shell::Get()->session_controller()->SetSessionInfo(info);
  80. }
  81. // Verifies the IME menu list has been updated with the right IME list.
  82. void ExpectValidImeList(const std::vector<ImeInfo>& expected_imes,
  83. const ImeInfo& expected_current_ime) {
  84. const std::map<views::View*, std::string>& ime_map =
  85. ImeListViewTestApi(GetTray()->ime_list_view_).ime_map();
  86. EXPECT_EQ(expected_imes.size(), ime_map.size());
  87. std::vector<std::string> expected_ime_ids;
  88. for (const auto& ime : expected_imes) {
  89. expected_ime_ids.push_back(ime.id);
  90. }
  91. for (const auto& ime : ime_map) {
  92. // Tests that all the IMEs on the view is in the list of selected IMEs.
  93. EXPECT_TRUE(base::Contains(expected_ime_ids, ime.second));
  94. // Tests that the checked IME is the current IME.
  95. ui::AXNodeData node_data;
  96. ime.first->GetAccessibleNodeData(&node_data);
  97. const auto checked_state = static_cast<ax::mojom::CheckedState>(
  98. node_data.GetIntAttribute(ax::mojom::IntAttribute::kCheckedState));
  99. if (checked_state == ax::mojom::CheckedState::kTrue)
  100. EXPECT_EQ(expected_current_ime.id, ime.second);
  101. }
  102. }
  103. // Focuses in the given type of input context.
  104. void FocusInInputContext(ui::TextInputType input_type) {
  105. ui::IMEEngineHandlerInterface::InputContext input_context(
  106. input_type, ui::TEXT_INPUT_MODE_DEFAULT, ui::TEXT_INPUT_FLAG_NONE,
  107. ui::TextInputClient::FOCUS_REASON_OTHER,
  108. false /* should_do_learning */);
  109. ui::IMEBridge::Get()->SetCurrentInputContext(input_context);
  110. }
  111. bool MenuHasOnScreenKeyboardToggle() const {
  112. if (!GetTray()->ime_list_view_)
  113. return false;
  114. return ImeListViewTestApi(GetTray()->ime_list_view_).GetToggleView();
  115. }
  116. };
  117. // Tests that visibility of IME menu tray should be consistent with the
  118. // activation of the IME menu.
  119. TEST_F(ImeMenuTrayTest, ImeMenuTrayVisibility) {
  120. ASSERT_FALSE(IsVisible());
  121. Shell::Get()->ime_controller()->ShowImeMenuOnShelf(true);
  122. EXPECT_TRUE(IsVisible());
  123. Shell::Get()->ime_controller()->ShowImeMenuOnShelf(false);
  124. EXPECT_FALSE(IsVisible());
  125. }
  126. // Tests that IME menu tray shows the right info of the current IME.
  127. TEST_F(ImeMenuTrayTest, TrayLabelTest) {
  128. Shell::Get()->ime_controller()->ShowImeMenuOnShelf(true);
  129. ASSERT_TRUE(IsVisible());
  130. ImeInfo info1;
  131. info1.id = "ime1";
  132. info1.name = u"English";
  133. info1.short_name = u"US";
  134. info1.third_party = false;
  135. ImeInfo info2;
  136. info2.id = "ime2";
  137. info2.name = u"English UK";
  138. info2.short_name = u"UK";
  139. info2.third_party = true;
  140. // Changes the input method to "ime1".
  141. SetCurrentIme("ime1", {info1, info2});
  142. EXPECT_EQ(u"US", GetTrayText());
  143. // Changes the input method to a third-party IME extension.
  144. SetCurrentIme("ime2", {info1, info2});
  145. EXPECT_EQ(u"UK*", GetTrayText());
  146. }
  147. TEST_F(ImeMenuTrayTest, TrayLabelExludesDictation) {
  148. Shell::Get()->ime_controller()->ShowImeMenuOnShelf(true);
  149. ASSERT_TRUE(IsVisible());
  150. ImeInfo info1;
  151. info1.id = "ime1";
  152. info1.name = u"English";
  153. info1.short_name = u"US";
  154. info1.third_party = false;
  155. ImeInfo info2;
  156. info2.id = "ime2";
  157. info2.name = u"English UK";
  158. info2.short_name = u"UK";
  159. info2.third_party = true;
  160. ImeInfo dictation;
  161. dictation.id = "_ext_ime_egfdjlfmgnehecnclamagfafdccgfndpdictation";
  162. dictation.name = u"Dictation";
  163. // Changes the input method to "ime1".
  164. SetCurrentIme("ime1", {info1, dictation, info2});
  165. EXPECT_EQ(u"US", GetTrayText());
  166. // Changes the input method to a third-party IME extension.
  167. SetCurrentIme("ime2", {info1, dictation, info2});
  168. EXPECT_EQ(u"UK*", GetTrayText());
  169. // Sets to "dictation", which shouldn't be shown.
  170. SetCurrentIme(dictation.id, {info1, dictation, info2});
  171. EXPECT_EQ(u"", GetTrayText());
  172. }
  173. // Tests that IME menu tray changes background color when tapped/clicked. And
  174. // tests that the background color becomes 'inactive' when disabling the IME
  175. // menu feature. Also makes sure that the shelf won't autohide as long as the
  176. // IME menu is open.
  177. TEST_F(ImeMenuTrayTest, PerformAction) {
  178. Shell::Get()->ime_controller()->ShowImeMenuOnShelf(true);
  179. ASSERT_TRUE(IsVisible());
  180. ASSERT_FALSE(IsTrayBackgroundActive());
  181. StatusAreaWidget* status = StatusAreaWidgetTestHelper::GetStatusAreaWidget();
  182. EXPECT_FALSE(status->ShouldShowShelf());
  183. ui::GestureEvent tap(0, 0, 0, base::TimeTicks(),
  184. ui::GestureEventDetails(ui::ET_GESTURE_TAP));
  185. GetTray()->PerformAction(tap);
  186. EXPECT_TRUE(IsTrayBackgroundActive());
  187. EXPECT_TRUE(IsBubbleShown());
  188. // Auto-hidden shelf would be forced to be visible as long as the bubble is
  189. // open.
  190. EXPECT_TRUE(status->ShouldShowShelf());
  191. GetTray()->PerformAction(tap);
  192. EXPECT_FALSE(IsTrayBackgroundActive());
  193. EXPECT_FALSE(IsBubbleShown());
  194. // If disabling the IME menu feature when the menu tray is activated, the tray
  195. // element will be deactivated.
  196. GetTray()->PerformAction(tap);
  197. EXPECT_TRUE(IsTrayBackgroundActive());
  198. Shell::Get()->ime_controller()->ShowImeMenuOnShelf(false);
  199. EXPECT_FALSE(IsVisible());
  200. EXPECT_FALSE(IsBubbleShown());
  201. EXPECT_FALSE(IsTrayBackgroundActive());
  202. EXPECT_FALSE(status->ShouldShowShelf());
  203. }
  204. // Tests that IME menu list updates when changing the current IME. This should
  205. // only happen by using shortcuts (Ctrl + Space / Ctrl + Shift + Space) to
  206. // switch IMEs.
  207. TEST_F(ImeMenuTrayTest, RefreshImeWithListViewCreated) {
  208. ui::GestureEvent tap(0, 0, 0, base::TimeTicks(),
  209. ui::GestureEventDetails(ui::ET_GESTURE_TAP));
  210. GetTray()->PerformAction(tap);
  211. EXPECT_TRUE(IsTrayBackgroundActive());
  212. EXPECT_TRUE(IsBubbleShown());
  213. ImeInfo info1, info2, info3;
  214. info1.id = "ime1";
  215. info1.name = u"English";
  216. info1.short_name = u"US";
  217. info1.third_party = false;
  218. info2.id = "ime2";
  219. info2.name = u"English UK";
  220. info2.short_name = u"UK";
  221. info2.third_party = true;
  222. info3.id = "ime3";
  223. info3.name = u"Pinyin";
  224. info3.short_name = u"拼";
  225. info3.third_party = false;
  226. std::vector<ImeInfo> ime_info_list{info1, info2, info3};
  227. // Switch to ime1.
  228. SetCurrentIme("ime1", ime_info_list);
  229. EXPECT_EQ(u"US", GetTrayText());
  230. ExpectValidImeList(ime_info_list, info1);
  231. // Switch to ime3.
  232. SetCurrentIme("ime3", ime_info_list);
  233. EXPECT_EQ(u"拼", GetTrayText());
  234. ExpectValidImeList(ime_info_list, info3);
  235. // Closes the menu before quitting.
  236. GetTray()->PerformAction(tap);
  237. EXPECT_FALSE(IsTrayBackgroundActive());
  238. EXPECT_FALSE(IsBubbleShown());
  239. }
  240. // Tests that quits Chrome with IME menu openned will not crash.
  241. TEST_F(ImeMenuTrayTest, QuitChromeWithMenuOpen) {
  242. Shell::Get()->ime_controller()->ShowImeMenuOnShelf(true);
  243. ASSERT_TRUE(IsVisible());
  244. ASSERT_FALSE(IsTrayBackgroundActive());
  245. ui::GestureEvent tap(0, 0, 0, base::TimeTicks(),
  246. ui::GestureEventDetails(ui::ET_GESTURE_TAP));
  247. GetTray()->PerformAction(tap);
  248. EXPECT_TRUE(IsTrayBackgroundActive());
  249. EXPECT_TRUE(IsBubbleShown());
  250. }
  251. // Tests using 'Alt+Shift+K' to open the menu.
  252. TEST_F(ImeMenuTrayTest, TestAccelerator) {
  253. Shell::Get()->ime_controller()->ShowImeMenuOnShelf(true);
  254. ASSERT_TRUE(IsVisible());
  255. ASSERT_FALSE(IsTrayBackgroundActive());
  256. Shell::Get()->accelerator_controller()->PerformActionIfEnabled(
  257. TOGGLE_IME_MENU_BUBBLE, {});
  258. EXPECT_TRUE(IsTrayBackgroundActive());
  259. EXPECT_TRUE(IsBubbleShown());
  260. ui::GestureEvent tap(0, 0, 0, base::TimeTicks(),
  261. ui::GestureEventDetails(ui::ET_GESTURE_TAP));
  262. GetTray()->PerformAction(tap);
  263. EXPECT_FALSE(IsTrayBackgroundActive());
  264. EXPECT_FALSE(IsBubbleShown());
  265. }
  266. TEST_F(ImeMenuTrayTest, ShowingEmojiKeysetHidesBubble) {
  267. Shell::Get()->ime_controller()->ShowImeMenuOnShelf(true);
  268. ASSERT_TRUE(IsVisible());
  269. ASSERT_FALSE(IsTrayBackgroundActive());
  270. ui::GestureEvent tap(0, 0, 0, base::TimeTicks(),
  271. ui::GestureEventDetails(ui::ET_GESTURE_TAP));
  272. GetTray()->PerformAction(tap);
  273. EXPECT_TRUE(IsTrayBackgroundActive());
  274. EXPECT_TRUE(IsBubbleShown());
  275. TestImeControllerClient client;
  276. Shell::Get()->ime_controller()->SetClient(&client);
  277. GetTray()->ShowKeyboardWithKeyset(input_method::ImeKeyset::kEmoji);
  278. // The menu should be hidden.
  279. EXPECT_FALSE(IsBubbleShown());
  280. }
  281. // Tests that the IME menu accelerator toggles the bubble on and off.
  282. TEST_F(ImeMenuTrayTest, ImeBubbleAccelerator) {
  283. Shell::Get()->ime_controller()->ShowImeMenuOnShelf(true);
  284. ASSERT_TRUE(IsVisible());
  285. EXPECT_FALSE(IsBubbleShown());
  286. PressAndReleaseKey(ui::VKEY_K, ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN);
  287. base::RunLoop().RunUntilIdle();
  288. EXPECT_TRUE(IsBubbleShown());
  289. PressAndReleaseKey(ui::VKEY_K, ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN);
  290. base::RunLoop().RunUntilIdle();
  291. EXPECT_FALSE(IsBubbleShown());
  292. }
  293. // Tests that tapping the emoji button does not crash. http://crbug.com/739630
  294. TEST_F(ImeMenuTrayTest, TapEmojiButton) {
  295. int callCount = 0;
  296. ui::SetShowEmojiKeyboardCallback(
  297. base::BindRepeating([](int* count) { (*count)++; }, (&callCount)));
  298. Shell::Get()->ime_controller()->ShowImeMenuOnShelf(true);
  299. Shell::Get()->ime_controller()->SetExtraInputOptionsEnabledState(
  300. true /* ui enabled */, true /* emoji input enabled */,
  301. true /* hanwriting input enabled */, true /* voice input enabled */);
  302. // Open the menu.
  303. ui::GestureEvent tap(0, 0, 0, base::TimeTicks(),
  304. ui::GestureEventDetails(ui::ET_GESTURE_TAP));
  305. GetTray()->PerformAction(tap);
  306. // Tap the emoji button.
  307. views::Button* emoji_button = GetEmojiButton();
  308. ASSERT_TRUE(emoji_button);
  309. emoji_button->OnGestureEvent(&tap);
  310. // The callback should have been called.
  311. EXPECT_EQ(callCount, 1);
  312. // Cleanup.
  313. ui::SetShowEmojiKeyboardCallback(base::DoNothing());
  314. }
  315. TEST_F(ImeMenuTrayTest, ShouldShowBottomButtons) {
  316. Shell::Get()->ime_controller()->SetExtraInputOptionsEnabledState(
  317. true /* ui enabled */, true /* emoji input enabled */,
  318. true /* hanwriting input enabled */, true /* voice input enabled */);
  319. FocusInInputContext(ui::TEXT_INPUT_TYPE_TEXT);
  320. EXPECT_TRUE(GetTray()->ShouldShowBottomButtons());
  321. EXPECT_TRUE(IsEmojiEnabled());
  322. EXPECT_TRUE(IsHandwritingEnabled());
  323. EXPECT_TRUE(IsVoiceEnabled());
  324. FocusInInputContext(ui::TEXT_INPUT_TYPE_PASSWORD);
  325. EXPECT_FALSE(GetTray()->ShouldShowBottomButtons());
  326. EXPECT_FALSE(IsEmojiEnabled());
  327. EXPECT_FALSE(IsHandwritingEnabled());
  328. EXPECT_FALSE(IsVoiceEnabled());
  329. }
  330. TEST_F(ImeMenuTrayTest, ShouldShowBottomButtonsSeperate) {
  331. FocusInInputContext(ui::TEXT_INPUT_TYPE_TEXT);
  332. // Sets emoji disabled.
  333. Shell::Get()->ime_controller()->SetExtraInputOptionsEnabledState(
  334. true /* ui enabled */, false /* emoji input disabled */,
  335. true /* hanwriting input enabled */, true /* voice input enabled */);
  336. EXPECT_TRUE(GetTray()->ShouldShowBottomButtons());
  337. EXPECT_FALSE(IsEmojiEnabled());
  338. EXPECT_TRUE(IsHandwritingEnabled());
  339. EXPECT_TRUE(IsVoiceEnabled());
  340. // Sets emoji enabled, but voice and handwriting disabled.
  341. Shell::Get()->ime_controller()->SetExtraInputOptionsEnabledState(
  342. true /* ui enabled */, true /* emoji input enabled */,
  343. false /* hanwriting input disabled */, false /* voice input disabled */);
  344. EXPECT_TRUE(GetTray()->ShouldShowBottomButtons());
  345. EXPECT_TRUE(IsEmojiEnabled());
  346. EXPECT_FALSE(IsHandwritingEnabled());
  347. EXPECT_FALSE(IsVoiceEnabled());
  348. }
  349. TEST_F(ImeMenuTrayTest, KioskImeTraySettingsButton) {
  350. SetUpKioskSession();
  351. Shell::Get()->ime_controller()->ShowImeMenuOnShelf(true);
  352. ASSERT_TRUE(IsVisible());
  353. // Open the menu.
  354. ui::GestureEvent tap(0, 0, 0, base::TimeTicks(),
  355. ui::GestureEventDetails(ui::ET_GESTURE_TAP));
  356. GetTray()->PerformAction(tap);
  357. views::View* settings_button = GetSettingsButton();
  358. EXPECT_FALSE(settings_button);
  359. }
  360. TEST_F(ImeMenuTrayTest, UserSessionImeTraySettingsButton) {
  361. Shell::Get()->ime_controller()->ShowImeMenuOnShelf(true);
  362. ASSERT_TRUE(IsVisible());
  363. // Open the menu.
  364. ui::GestureEvent tap(0, 0, 0, base::TimeTicks(),
  365. ui::GestureEventDetails(ui::ET_GESTURE_TAP));
  366. GetTray()->PerformAction(tap);
  367. views::View* settings_button = GetSettingsButton();
  368. EXPECT_TRUE(settings_button);
  369. }
  370. TEST_F(ImeMenuTrayTest, ShowOnScreenKeyboardToggle) {
  371. Shell::Get()->ime_controller()->ShowImeMenuOnShelf(true);
  372. ASSERT_TRUE(IsVisible());
  373. ASSERT_FALSE(IsTrayBackgroundActive());
  374. ui::GestureEvent tap(0, 0, 0, base::TimeTicks(),
  375. ui::GestureEventDetails(ui::ET_GESTURE_TAP));
  376. GetTray()->PerformAction(tap);
  377. EXPECT_TRUE(IsTrayBackgroundActive());
  378. EXPECT_TRUE(IsBubbleShown());
  379. EXPECT_FALSE(MenuHasOnScreenKeyboardToggle());
  380. // The on-screen keyboard toggle should show if the device has a touch
  381. // screen, and does not have an internal keyboard.
  382. std::vector<ui::TouchscreenDevice> screens;
  383. screens.push_back(
  384. ui::TouchscreenDevice(1, ui::InputDeviceType::INPUT_DEVICE_INTERNAL,
  385. "Touchscreen", gfx::Size(1024, 768), 0));
  386. ui::DeviceDataManagerTestApi().SetTouchscreenDevices(screens);
  387. std::vector<ui::InputDevice> keyboard_devices;
  388. keyboard_devices.push_back(ui::InputDevice(
  389. 1, ui::InputDeviceType::INPUT_DEVICE_USB, "external keyboard"));
  390. ui::DeviceDataManagerTestApi().SetKeyboardDevices(keyboard_devices);
  391. // Bubble gets closed when the keyboard suppression state changes.
  392. EXPECT_FALSE(IsBubbleShown());
  393. GetTray()->PerformAction(ui::GestureEvent(
  394. 0, 0, 0, base::TimeTicks(), ui::GestureEventDetails(ui::ET_GESTURE_TAP)));
  395. EXPECT_TRUE(IsBubbleShown());
  396. EXPECT_TRUE(MenuHasOnScreenKeyboardToggle());
  397. // The toggle should not be removed on IME device refresh.
  398. ImeInfo info;
  399. info.id = "ime";
  400. info.name = u"English UK";
  401. info.short_name = u"UK";
  402. info.third_party = true;
  403. SetCurrentIme("ime", {info});
  404. EXPECT_TRUE(MenuHasOnScreenKeyboardToggle());
  405. // The toggle should be hidden with internal keyboard.
  406. keyboard_devices.push_back(ui::InputDevice(
  407. 1, ui::InputDeviceType::INPUT_DEVICE_USB, "external keyboard"));
  408. keyboard_devices.push_back(ui::InputDevice(
  409. 1, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, "internal keyboard"));
  410. ui::DeviceDataManagerTestApi().SetKeyboardDevices(keyboard_devices);
  411. // Bubble gets closed when the keyboard suppression state changes.
  412. EXPECT_FALSE(IsBubbleShown());
  413. GetTray()->PerformAction(ui::GestureEvent(
  414. 0, 0, 0, base::TimeTicks(), ui::GestureEventDetails(ui::ET_GESTURE_TAP)));
  415. EXPECT_TRUE(IsBubbleShown());
  416. EXPECT_FALSE(MenuHasOnScreenKeyboardToggle());
  417. }
  418. } // namespace ash