Back to index

unity  6.0.0
test_hud.py
Go to the documentation of this file.
00001 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
00002 # Copyright 2012 Canonical
00003 # Author: Alex Launi,
00004 #         Marco Trevisan
00005 #
00006 # This program is free software: you can redistribute it and/or modify it
00007 # under the terms of the GNU General Public License version 3, as published
00008 # by the Free Software Foundation.
00009 
00010 from __future__ import absolute_import
00011 
00012 from autopilot.matchers import Eventually
00013 from autopilot.emulators.X11 import ScreenGeometry
00014 from autopilot.testcase import multiply_scenarios
00015 from os import remove
00016 from testtools.matchers import (
00017     Equals,
00018     EndsWith,
00019     GreaterThan,
00020     LessThan,
00021     NotEquals,
00022     )
00023 from time import sleep
00024 
00025 from unity.emulators.icons import HudLauncherIcon
00026 from unity.tests import UnityTestCase
00027 
00028 
00029 def _make_monitor_scenarios():
00030     num_monitors = ScreenGeometry().get_num_monitors()
00031     scenarios = []
00032 
00033     if num_monitors == 1:
00034         scenarios = [('Single Monitor', {'hud_monitor': 0})]
00035     else:
00036         for i in range(num_monitors):
00037             scenarios += [('Monitor %d' % (i), {'hud_monitor': i})]
00038 
00039     return scenarios
00040 
00041 
00042 class HudTestsBase(UnityTestCase):
00043 
00044     def setUp(self):
00045         super(HudTestsBase, self).setUp()
00046 
00047     def tearDown(self):
00048         self.hud.ensure_hidden()
00049         super(HudTestsBase, self).tearDown()
00050 
00051     def get_num_active_launcher_icons(self):
00052         num_active = 0
00053         for icon in self.launcher.model.get_launcher_icons():
00054             if icon.active and icon.visible:
00055                 num_active += 1
00056         return num_active
00057 
00058 
00059 class HudBehaviorTests(HudTestsBase):
00060 
00061     def setUp(self):
00062         super(HudBehaviorTests, self).setUp()
00063 
00064         self.hud_monitor = self.screen_geo.get_primary_monitor()
00065         self.screen_geo.move_mouse_to_monitor(self.hud_monitor)
00066 
00067     def test_no_initial_values(self):
00068         self.hud.ensure_visible()
00069         self.assertThat(self.hud.num_buttons, Equals(0))
00070         self.assertThat(self.hud.selected_button, Equals(0))
00071 
00072     def test_check_a_values(self):
00073         self.hud.ensure_visible()
00074         self.keyboard.type('a')
00075         self.assertThat(self.hud.search_string, Eventually(Equals('a')))
00076         self.assertThat(self.hud.num_buttons, Eventually(Equals(5)))
00077         self.assertThat(self.hud.selected_button, Eventually(Equals(1)))
00078 
00079     def test_up_down_arrows(self):
00080         self.hud.ensure_visible()
00081         self.keyboard.type('a')
00082         self.assertThat(self.hud.search_string, Eventually(Equals('a')))
00083         self.keyboard.press_and_release('Down')
00084         self.assertThat(self.hud.selected_button, Eventually(Equals(2)))
00085         self.keyboard.press_and_release('Down')
00086         self.assertThat(self.hud.selected_button, Eventually(Equals(3)))
00087         self.keyboard.press_and_release('Down')
00088         self.assertThat(self.hud.selected_button, Eventually(Equals(4)))
00089         self.keyboard.press_and_release('Down')
00090         self.assertThat(self.hud.selected_button, Eventually(Equals(5)))
00091         # Down again stays on 5.
00092         self.keyboard.press_and_release('Down')
00093         self.assertThat(self.hud.selected_button, Eventually(Equals(5)))
00094         self.keyboard.press_and_release('Up')
00095         self.assertThat(self.hud.selected_button, Eventually(Equals(4)))
00096         self.keyboard.press_and_release('Up')
00097         self.assertThat(self.hud.selected_button, Eventually(Equals(3)))
00098         self.keyboard.press_and_release('Up')
00099         self.assertThat(self.hud.selected_button, Eventually(Equals(2)))
00100         self.keyboard.press_and_release('Up')
00101         self.assertThat(self.hud.selected_button, Eventually(Equals(1)))
00102         # Up again stays on 1.
00103         self.keyboard.press_and_release('Up')
00104         self.assertThat(self.hud.selected_button, Eventually(Equals(1)))
00105 
00106     def test_no_reset_selected_button(self):
00107         """Hud must not change selected button when results update over time."""
00108         # TODO - this test doesn't test anything. Onmy system the results never update.
00109         # ideally we'd send artificial results to the hud from the test.
00110         self.hud.ensure_visible()
00111         self.keyboard.type('is')
00112         self.assertThat(self.hud.search_string, Eventually(Equals('is')))
00113         self.keyboard.press_and_release('Down')
00114         self.assertThat(self.hud.selected_button, Eventually(Equals(2)))
00115         # long sleep to let the service send updated results
00116         sleep(10)
00117         self.assertThat(self.hud.selected_button, Equals(2))
00118 
00119     def test_slow_tap_not_reveal_hud(self):
00120         """A slow tap must not reveal the HUD."""
00121         self.keybinding("hud/reveal", 0.3)
00122         # need a long sleep to ensure that we test after the hud controller has
00123         # seen the keypress.
00124         sleep(5)
00125         self.assertThat(self.hud.visible, Equals(False))
00126 
00127     def test_alt_f4_doesnt_show_hud(self):
00128         self.start_app('Calculator')
00129         sleep(1)
00130         # Do a very fast Alt+F4
00131         self.keyboard.press_and_release("Alt+F4", 0.05)
00132         sleep(1)
00133         self.assertFalse(self.hud.visible)
00134 
00135     def test_reveal_hud_with_no_apps(self):
00136         """Hud must show even with no visible applications.
00137 
00138         This used to cause unity to crash (hence the lack of assertion in this test).
00139 
00140         """
00141         self.window_manager.enter_show_desktop()
00142         self.addCleanup(self.window_manager.leave_show_desktop)
00143 
00144         self.hud.ensure_visible()
00145         self.hud.ensure_hidden()
00146 
00147     def test_restore_focus(self):
00148         """Ensures that once the hud is dismissed, the same application
00149         that was focused before hud invocation is refocused.
00150         """
00151         calc = self.start_app("Calculator")
00152 
00153         # first ensure that the application has started and is focused
00154         self.assertEqual(calc.is_active, True)
00155 
00156         self.hud.ensure_visible()
00157         self.hud.ensure_hidden()
00158 
00159         # again ensure that the application we started is focused
00160         self.assertEqual(calc.is_active, True)
00161 
00162         self.hud.ensure_visible()
00163         self.hud.ensure_hidden()
00164         # why do we do this: ???
00165         self.keyboard.press_and_release('Return')
00166         sleep(1)
00167 
00168         self.assertEqual(calc.is_active, True)
00169 
00170     def test_gedit_undo(self):
00171         """Test that the 'undo' action in the Hud works with GEdit."""
00172 
00173         self.addCleanup(remove, '/tmp/autopilot_gedit_undo_test_temp_file.txt')
00174         self.start_app('Text Editor', files=['/tmp/autopilot_gedit_undo_test_temp_file.txt'], locale='C')
00175 
00176         self.keyboard.type("0")
00177         self.keyboard.type(" ")
00178         self.keyboard.type("1")
00179 
00180         self.hud.ensure_visible()
00181 
00182         self.keyboard.type("undo")
00183         hud_query_check = lambda: self.hud.selected_hud_button.label_no_formatting
00184         self.assertThat(hud_query_check,
00185                         Eventually(Equals("Edit > Undo")))
00186         self.keyboard.press_and_release('Return')
00187         self.assertThat(self.hud.visible, Eventually(Equals(False)))
00188         self.keyboard.press_and_release("Ctrl+s")
00189         sleep(1)
00190 
00191         contents = open("/tmp/autopilot_gedit_undo_test_temp_file.txt").read().strip('\n')
00192         self.assertEqual("0 ", contents)
00193 
00194     def test_hud_to_dash_has_key_focus(self):
00195         """When switching from the hud to the dash you don't lose key focus."""
00196         self.hud.ensure_visible()
00197         self.dash.ensure_visible()
00198         self.addCleanup(self.dash.ensure_hidden)
00199         self.keyboard.type('focus1')
00200         self.assertThat(self.dash.search_string, Eventually(Equals('focus1')))
00201 
00202     def test_dash_to_hud_has_key_focus(self):
00203         """When switching from the dash to the hud you don't lose key focus."""
00204         self.dash.ensure_visible()
00205         self.hud.ensure_visible()
00206         self.keyboard.type('focus2')
00207         self.assertThat(self.hud.search_string, Eventually(Equals('focus2')))
00208 
00209     def test_hud_closes_on_workspace_switch(self):
00210         """This test shows that when you switch to another workspace the hud closes."""
00211         initial_workspace = self.workspace.current_workspace
00212         self.addCleanup(self.workspace.switch_to, initial_workspace)
00213         self.hud.ensure_visible()
00214         self.workspace.switch_to(1)
00215         self.workspace.switch_to(2)
00216         self.assertThat(self.hud.visible, Eventually(Equals(False)))
00217 
00218     def test_hud_closes_on_spread(self):
00219         """This test shows that when the spread is initiated, the hud closes."""
00220         self.hud.ensure_visible()
00221         self.addCleanup(self.keybinding, "spread/cancel")
00222         self.keybinding("spread/start")
00223         self.assertThat(self.window_manager.scale_active, Eventually(Equals(True)))
00224         self.assertThat(self.hud.visible, Eventually(Equals(False)))
00225 
00226     def test_hud_closes_click_outside_geo_shrunk(self):
00227         """
00228         Clicking outside the hud when it is shurnk will make it close.
00229         Shurnk is when the hud has no results and is much smaller then normal.
00230         """
00231 
00232         self.hud.ensure_visible()
00233         (x,y,w,h) = self.hud.view.geometry
00234         self.mouse.move(w/2, h-50)
00235         self.mouse.click()
00236 
00237         self.assertThat(self.hud.visible, Eventually(Equals(False)))
00238 
00239     def test_hud_closes_click_outside_geo(self):
00240         """Clicking outside of the hud will make it close."""
00241 
00242         self.hud.ensure_visible()
00243         self.keyboard.type("Test")
00244 
00245         (x,y,w,h) = self.hud.view.geometry
00246         self.mouse.move(w/2, h+50)
00247         self.mouse.click()
00248 
00249         self.assertThat(self.hud.visible, Eventually(Equals(False)))
00250 
00251     def test_alt_f4_close_hud(self):
00252         """Hud must close on alt+F4."""
00253         self.hud.ensure_visible()
00254         self.keyboard.press_and_release("Alt+F4")
00255         self.assertThat(self.hud.visible, Eventually(Equals(False)))
00256 
00257 
00258 class HudLauncherInteractionsTests(HudTestsBase):
00259 
00260     launcher_modes = [('Launcher autohide', {'launcher_autohide': False}),
00261                       ('Launcher never hide', {'launcher_autohide': True})]
00262 
00263     scenarios = multiply_scenarios(_make_monitor_scenarios(), launcher_modes)
00264 
00265     def setUp(self):
00266         super(HudLauncherInteractionsTests, self).setUp()
00267         # Launchers on all monitors
00268         self.set_unity_option('num_launchers', 0)
00269         self.set_unity_option('launcher_hide_mode', int(self.launcher_autohide))
00270 
00271         self.screen_geo.move_mouse_to_monitor(self.hud_monitor)
00272         sleep(0.5)
00273 
00274     def test_multiple_hud_reveal_does_not_break_launcher(self):
00275         """Multiple Hud reveals must not cause the launcher to set multiple
00276         apps as active.
00277 
00278         """
00279         launcher = self.launcher.get_launcher_for_monitor(self.hud_monitor)
00280 
00281         # We need an app to switch to:
00282         self.start_app('Character Map')
00283         # We need an application to play with - I'll use the calculator.
00284         self.start_app('Calculator')
00285         sleep(1)
00286 
00287         # before we start, make sure there's zero or one active icon:
00288         num_active = self.get_num_active_launcher_icons()
00289         self.assertThat(num_active, LessThan(2), "Invalid number of launcher icons active before test has run!")
00290 
00291         # reveal and hide hud several times over:
00292         for i in range(3):
00293             self.hud.ensure_visible()
00294             self.hud.ensure_hidden()
00295 
00296         # click application icons for running apps in the launcher:
00297         icon = self.launcher.model.get_icon_by_desktop_id("gucharmap.desktop")
00298         launcher.click_launcher_icon(icon)
00299 
00300         # see how many apps are marked as being active:
00301         num_active = self.get_num_active_launcher_icons()
00302         self.assertLessEqual(num_active, 1, "More than one launcher icon active after test has run!")
00303 
00304     def test_hud_does_not_change_launcher_status(self):
00305         """Opening the HUD must not change the launcher visibility."""
00306 
00307         launcher = self.launcher.get_launcher_for_monitor(self.hud_monitor)
00308 
00309         launcher_shows_pre = launcher.is_showing
00310         self.hud.ensure_visible()
00311         launcher_shows_post = launcher.is_showing
00312         self.assertThat(launcher_shows_pre, Equals(launcher_shows_post))
00313 
00314 
00315 class HudLockedLauncherInteractionsTests(HudTestsBase):
00316 
00317     scenarios = _make_monitor_scenarios()
00318 
00319     def setUp(self):
00320         super(HudLockedLauncherInteractionsTests, self).setUp()
00321         # Locked Launchers on all monitors
00322         self.set_unity_option('num_launchers', 0)
00323         self.set_unity_option('launcher_hide_mode', 0)
00324 
00325         self.screen_geo.move_mouse_to_monitor(self.hud_monitor)
00326         sleep(0.5)
00327 
00328     def test_hud_launcher_icon_hides_bfb(self):
00329         """BFB icon must be hidden when the HUD launcher icon is shown."""
00330 
00331         hud_icon = self.hud.get_launcher_icon()
00332         bfb_icon = self.launcher.model.get_bfb_icon()
00333 
00334         self.assertThat(bfb_icon.visible, Eventually(Equals(True)))
00335         self.assertTrue(bfb_icon.is_on_monitor(self.hud_monitor))
00336         self.assertThat(hud_icon.visible, Eventually(Equals(False)))
00337 
00338         self.hud.ensure_visible()
00339 
00340         self.assertThat(hud_icon.visible, Eventually(Equals(True)))
00341         self.assertTrue(hud_icon.is_on_monitor(self.hud_monitor))
00342         # For some reason the BFB icon is always visible :-/
00343         #bfb_icon.visible, Eventually(Equals(False)
00344 
00345     def test_hud_desaturates_launcher_icons(self):
00346         """Launcher icons must desaturate when the HUD is opened."""
00347 
00348         self.hud.ensure_visible()
00349 
00350         for icon in self.launcher.model.get_launcher_icons_for_monitor(self.hud_monitor):
00351             if isinstance(icon, HudLauncherIcon):
00352                 self.assertFalse(icon.desaturated)
00353             else:
00354                 self.assertTrue(icon.desaturated)
00355 
00356     def test_hud_launcher_icon_click_hides_hud(self):
00357         """Clicking the Hud Icon should hide the HUD"""
00358 
00359         hud_icon = self.hud.get_launcher_icon()
00360         self.hud.ensure_visible()
00361 
00362         launcher = self.launcher.get_launcher_for_monitor(self.hud_monitor)
00363         launcher.click_launcher_icon(hud_icon)
00364 
00365         self.assertThat(self.hud.visible, Eventually(Equals(False)))
00366         self.assertThat(hud_icon.visible, Eventually(Equals(False)))
00367 
00368 
00369 class HudVisualTests(HudTestsBase):
00370 
00371     launcher_modes = [('Launcher autohide', {'launcher_autohide': False}),
00372                       ('Launcher never hide', {'launcher_autohide': True})]
00373 
00374     launcher_screen = [('Launcher on primary monitor', {'launcher_primary_only': False}),
00375                        ('Launcher on all monitors', {'launcher_primary_only': True})]
00376 
00377     scenarios = multiply_scenarios(_make_monitor_scenarios(), launcher_modes, launcher_screen)
00378 
00379     def setUp(self):
00380         super(HudVisualTests, self).setUp()
00381         self.screen_geo.move_mouse_to_monitor(self.hud_monitor)
00382         self.set_unity_option('launcher_hide_mode', int(self.launcher_autohide))
00383         self.set_unity_option('num_launchers', int(self.launcher_primary_only))
00384         self.hud_monitor_is_primary = (self.screen_geo.get_primary_monitor() == self.hud_monitor)
00385         self.hud_locked = (not self.launcher_autohide and (not self.launcher_primary_only or self.hud_monitor_is_primary))
00386         sleep(0.5)
00387 
00388     def test_initially_hidden(self):
00389         self.assertFalse(self.hud.visible)
00390 
00391     def test_hud_is_on_right_monitor(self):
00392         """HUD must be drawn on the monitor where the mouse is."""
00393         self.hud.ensure_visible()
00394         self.assertThat(self.hud.monitor, Eventually(Equals(self.hud_monitor)))
00395         self.assertTrue(self.screen_geo.is_rect_on_monitor(self.hud.monitor, self.hud.geometry))
00396 
00397     def test_hud_geometries(self):
00398         """Tests the HUD geometries for the given monitor and status."""
00399         self.hud.ensure_visible()
00400         monitor_geo = self.screen_geo.get_monitor_geometry(self.hud_monitor)
00401         monitor_x = monitor_geo[0]
00402         monitor_w = monitor_geo[2]
00403         hud_x = self.hud.geometry[0]
00404         hud_w = self.hud.geometry[2]
00405 
00406         if self.hud_locked:
00407             self.assertThat(hud_x, GreaterThan(monitor_x))
00408             self.assertThat(hud_x, LessThan(monitor_x + monitor_w))
00409             self.assertThat(hud_w, Equals(monitor_x + monitor_w - hud_x))
00410         else:
00411             self.assertThat(hud_x, Equals(monitor_x))
00412             self.assertThat(hud_w, Equals(monitor_w))
00413 
00414     def test_hud_is_locked_to_launcher(self):
00415         """Tests if the HUD is locked to launcher as we expect or not."""
00416         self.hud.ensure_visible()
00417         self.assertThat(self.hud.is_locked_launcher, Eventually(Equals(self.hud_locked)))
00418 
00419     def test_hud_icon_is_shown(self):
00420         """Tests that the correct HUD icon is shown."""
00421         self.hud.ensure_visible()
00422         hud_launcher_icon = self.hud.get_launcher_icon()
00423         hud_embedded_icon = self.hud.get_embedded_icon()
00424 
00425         if self.hud.is_locked_launcher:
00426             self.assertThat(hud_launcher_icon.visible, Eventually(Equals(True)))
00427             self.assertTrue(hud_launcher_icon.is_on_monitor(self.hud_monitor))
00428             self.assertTrue(hud_launcher_icon.active)
00429             self.assertThat(hud_launcher_icon.monitor, Equals(self.hud_monitor))
00430             self.assertFalse(hud_launcher_icon.desaturated)
00431             self.assertThat(hud_embedded_icon, Equals(None))
00432         else:
00433             self.assertThat(hud_launcher_icon.visible, Eventually(Equals(False)))
00434             self.assertFalse(hud_launcher_icon.active)
00435             # the embedded icon has no visible property.
00436             self.assertThat(hud_embedded_icon, NotEquals(None))
00437 
00438     def test_hud_icon_shows_the_focused_application_emblem(self):
00439         """Tests that the correct HUD icon is shown."""
00440         self.close_all_app("Calculator")
00441         calc = self.start_app("Calculator")
00442         self.assertTrue(calc.is_active)
00443         self.hud.ensure_visible()
00444 
00445         self.assertThat(self.hud.icon.icon_name, Eventually(Equals(calc.icon)))
00446 
00447     def test_hud_icon_shows_the_ubuntu_emblem_on_empty_desktop(self):
00448         """When in 'show desktop' mode the hud icon must be the BFB icon."""
00449         self.window_manager.enter_show_desktop()
00450         self.addCleanup(self.window_manager.leave_show_desktop)
00451         self.hud.ensure_visible()
00452 
00453         self.assertThat(self.hud.icon.icon_name, Eventually(EndsWith("launcher_bfb.png")))
00454 
00455     def test_switch_dash_hud_does_not_break_the_focused_application_emblem(self):
00456         """Switching from Dash to HUD must still show the correct HUD icon."""
00457         self.close_all_app("Calculator")
00458         calc = self.start_app("Calculator")
00459         self.assertTrue(calc.is_active)
00460 
00461         self.dash.ensure_visible()
00462         self.hud.ensure_visible()
00463 
00464         self.assertThat(self.hud.icon.icon_name, Eventually(Equals(calc.icon)))
00465 
00466     def test_switch_hud_dash_does_not_break_the_focused_application_emblem(self):
00467         """Switching from HUD to Dash and back must still show the correct HUD icon."""
00468         self.close_all_app("Calculator")
00469         calc = self.start_app("Calculator")
00470         self.assertTrue(calc.is_active)
00471 
00472         self.hud.ensure_visible()
00473         self.dash.ensure_visible()
00474         self.hud.ensure_visible()
00475         self.assertThat(self.hud.icon.icon_name, Eventually(Equals(calc.icon)))
00476 
00477     def test_dash_hud_only_uses_icon_from_current_desktop(self):
00478         """
00479         Switching from the dash to Hud must pick an icon from applications
00480         from the current desktop. As the Hud must go through the entire window
00481         stack to find the top most window.
00482         """
00483         initial_workspace = self.workspace.current_workspace
00484         self.addCleanup(self.workspace.switch_to, initial_workspace)
00485         self.workspace.switch_to(0)
00486         calc = self.start_app("Calculator")
00487         self.assertTrue(calc.is_active)
00488         self.workspace.switch_to(2)
00489         self.dash.ensure_visible()
00490         self.hud.ensure_visible()
00491 
00492         self.assertThat(self.hud.icon.icon_name, Eventually(EndsWith("launcher_bfb.png")))
00493 
00494 
00495 class HudAlternativeKeybindingTests(HudTestsBase):
00496 
00497     def test_super_h(self):
00498         """Test hud reveal on <Super>h."""
00499         self.set_unity_option("show_hud", "<Super>h")
00500         # Don't use reveal_hud, but be explicit in the keybindings.
00501         self.keyboard.press_and_release("Super+h")
00502         self.assertThat(self.hud.visible, Eventually(Equals(True)))
00503 
00504     def test_ctrl_alt_h(self):
00505         """Test hud reveal on <Contrl><Alt>h."""
00506         self.set_unity_option("show_hud", "<Control><Alt>h")
00507         # Don't use reveal_hud, but be explicit in the keybindings.
00508         self.keyboard.press_and_release("Ctrl+Alt+h")
00509         self.assertThat(self.hud.visible, Eventually(Equals(True)))