Back to index

unity  6.0.0
test_dash.py
Go to the documentation of this file.
00001 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
00002 # Copyright 2010 Canonical
00003 # Author: Alex Launi
00004 #
00005 # This program is free software: you can redistribute it and/or modify it
00006 # under the terms of the GNU General Public License version 3, as published
00007 # by the Free Software Foundation.
00008 
00009 from __future__ import absolute_import
00010 
00011 from time import sleep
00012 
00013 from autopilot.matchers import Eventually
00014 from gtk import Clipboard
00015 from testtools.matchers import Equals, NotEquals
00016 
00017 from unity.tests import UnityTestCase
00018 
00019 
00020 class DashTestCase(UnityTestCase):
00021     def setUp(self):
00022         super(DashTestCase, self).setUp()
00023         self.set_unity_log_level("unity.shell", "DEBUG")
00024         self.set_unity_log_level("unity.launcher", "DEBUG")
00025         self.dash.ensure_hidden()
00026         # On shutdown, ensure hidden too.  Also add a delay.  Cleanup is LIFO.
00027         self.addCleanup(self.dash.ensure_hidden)
00028         self.addCleanup(sleep, 1)
00029 
00030 
00031 class DashRevealTests(DashTestCase):
00032     """Test the Unity dash Reveal."""
00033 
00034     def test_dash_reveal(self):
00035         """Ensure we can show and hide the dash."""
00036         self.dash.ensure_visible()
00037         self.dash.ensure_hidden()
00038 
00039     def test_application_lens_shortcut(self):
00040         """Application lense must reveal when Super+a is pressed."""
00041         self.dash.reveal_application_lens()
00042         self.assertThat(self.dash.active_lens, Eventually(Equals('applications.lens')))
00043 
00044     def test_music_lens_shortcut(self):
00045         """Music lense must reveal when Super+w is pressed."""
00046         self.dash.reveal_music_lens()
00047         self.assertThat(self.dash.active_lens, Eventually(Equals('music.lens')))
00048 
00049     def test_file_lens_shortcut(self):
00050         """File lense must reveal when Super+f is pressed."""
00051         self.dash.reveal_file_lens()
00052         self.assertThat(self.dash.active_lens, Eventually(Equals('files.lens')))
00053 
00054     def test_command_lens_shortcut(self):
00055         """Run Command lens must reveat on alt+F2."""
00056         self.dash.reveal_command_lens()
00057         self.assertThat(self.dash.active_lens, Eventually(Equals('commands.lens')))
00058 
00059     def test_alt_f4_close_dash(self):
00060         """Dash must close on alt+F4."""
00061         self.dash.ensure_visible()
00062         self.keyboard.press_and_release("Alt+F4")
00063         self.assertThat(self.dash.visible, Eventually(Equals(False)))
00064 
00065     def test_dash_closes_on_spread(self):
00066         """This test shows that when the spread is initiated, the dash closes."""
00067         self.dash.ensure_visible()
00068         self.addCleanup(self.keybinding, "spread/cancel")
00069         self.keybinding("spread/start")
00070         self.assertThat(self.window_manager.scale_active, Eventually(Equals(True)))
00071         self.assertThat(self.dash.visible, Eventually(Equals(False)))
00072 
00073     def test_dash_opens_when_in_spread(self):
00074         """This test shows the dash opens when in spread mode."""
00075         self.keybinding("spread/start")
00076         self.assertThat(self.window_manager.scale_active, Eventually(Equals(True)))
00077 
00078         self.dash.ensure_visible()
00079         self.assertThat(self.dash.visible, Eventually(Equals(True)))
00080 
00081     def test_command_lens_opens_when_in_spread(self):
00082         """This test shows the command lens opens when in spread mode."""
00083         self.keybinding("spread/start")
00084         self.assertThat(self.window_manager.scale_active, Eventually(Equals(True)))
00085 
00086         self.dash.reveal_command_lens()
00087         self.assertThat(self.dash.active_lens, Eventually(Equals('commands.lens')))
00088 
00089     def test_lens_opens_when_in_spread(self):
00090         """This test shows that any lens opens when in spread mode."""
00091         self.keybinding("spread/start")
00092         self.assertThat(self.window_manager.scale_active, Eventually(Equals(True)))
00093 
00094         self.dash.reveal_application_lens()
00095         self.assertThat(self.dash.active_lens, Eventually(Equals('applications.lens')))
00096 
00097 
00098 class DashSearchInputTests(DashTestCase):
00099     """Test features involving input to the dash search"""
00100 
00101     def assertSearchText(self, text):
00102         self.assertThat(self.dash.search_string, Eventually(Equals(text)))
00103 
00104     def test_search_keyboard_focus(self):
00105         """Dash must put keyboard focus on the search bar at all times."""
00106         self.dash.ensure_visible()
00107         self.keyboard.type("Hello")
00108         self.assertSearchText("Hello")
00109 
00110 
00111 class DashMultiKeyTests(DashSearchInputTests):
00112     def setUp(self):
00113         # set the multi key first so that we're not getting a new _DISPLAY while keys are held down.
00114         old_value = self.call_gsettings_cmd('get', 'org.gnome.libgnomekbd.keyboard', 'options')
00115         self.addCleanup(self.call_gsettings_cmd, 'set', 'org.gnome.libgnomekbd.keyboard', 'options', old_value)
00116         self.call_gsettings_cmd('set', 'org.gnome.libgnomekbd.keyboard', 'options', "['Compose key\tcompose:caps']")
00117 
00118         super(DashMultiKeyTests, self).setUp()
00119 
00120     def test_multi_key(self):
00121         """Pressing 'Multi_key' must not add any characters to the search."""
00122         self.dash.reveal_application_lens()
00123         self.keyboard.press_and_release('Multi_key')
00124         self.keyboard.type("o")
00125         self.assertSearchText("")
00126 
00127     def test_multi_key_o(self):
00128         """Pressing the sequences 'Multi_key' + '^' + 'o' must produce 'ô'."""
00129         self.dash.reveal_application_lens()
00130         self.keyboard.press_and_release('Multi_key')
00131         self.keyboard.type("^o")
00132         self.assertSearchText("ô")
00133 
00134     def test_multi_key_copyright(self):
00135         """Pressing the sequences 'Multi_key' + 'c' + 'o' must produce '©'."""
00136         self.dash.reveal_application_lens()
00137         self.keyboard.press_and_release('Multi_key')
00138         self.keyboard.type("oc")
00139         self.assertSearchText("©")
00140 
00141     def test_multi_key_delete(self):
00142         """Pressing 'Multi_key' must not get stuck looking for a sequence."""
00143         self.dash.reveal_application_lens()
00144         self.keyboard.type("dd")
00145         self.keyboard.press_and_release('Multi_key')
00146         self.keyboard.press_and_release('BackSpace')
00147         self.keyboard.press_and_release('BackSpace')
00148         self.assertSearchText("d")
00149 
00150 
00151 class DashKeyNavTests(DashTestCase):
00152     """Test the unity Dash keyboard navigation."""
00153 
00154     def test_lensbar_gets_keyfocus(self):
00155         """Test that the lensbar gets key focus after using Down keypresses."""
00156         self.dash.ensure_visible()
00157 
00158         # Make sure that the lens bar can get the focus
00159         for i in range(self.dash.get_num_rows()):
00160             self.keyboard.press_and_release("Down")
00161         lensbar = self.dash.view.get_lensbar()
00162         self.assertThat(lensbar.focused_lens_icon, Eventually(NotEquals('')))
00163 
00164     def test_lensbar_focus_changes(self):
00165         """Lensbar focused icon should change with Left and Right keypresses."""
00166         self.dash.ensure_visible()
00167 
00168         for i in range(self.dash.get_num_rows()):
00169             self.keyboard.press_and_release("Down")
00170         lensbar = self.dash.view.get_lensbar()
00171 
00172         current_focused_icon = lensbar.focused_lens_icon
00173 
00174         self.keyboard.press_and_release("Right");
00175         self.assertThat(lensbar.focused_lens_icon, Eventually(NotEquals(current_focused_icon)))
00176 
00177         self.keyboard.press_and_release("Left")
00178         self.assertThat(lensbar.focused_lens_icon, Eventually(Equals(current_focused_icon)))
00179 
00180     def test_lensbar_enter_activation(self):
00181         """Must be able to activate LensBar icons that have focus with an Enter keypress."""
00182         self.dash.ensure_visible()
00183 
00184         for i in range(self.dash.get_num_rows()):
00185             self.keyboard.press_and_release("Down")
00186         self.keyboard.press_and_release("Right");
00187         lensbar = self.dash.view.get_lensbar()
00188         focused_icon = lensbar.focused_lens_icon
00189         self.keyboard.press_and_release("Enter");
00190 
00191         self.assertThat(lensbar.active_lens, Eventually(Equals(focused_icon)))
00192 
00193         # lensbar should lose focus after activation.
00194         # TODO this should be a different test to make sure focus
00195         # returns to the correct place.
00196         self.assertThat(lensbar.focused_lens_icon, Eventually(Equals("")))
00197 
00198     def test_category_header_keynav(self):
00199         """ Tests that a category header gets focus when 'down' is pressed after the
00200         dash is opened
00201 
00202         OK important to note that this test only tests that A category is
00203         focused, not the first and from doing this it seems that it's common
00204         for a header other than the first to get focus.
00205         """
00206         self.dash.ensure_visible()
00207         # Make sure that a category have the focus.
00208         self.keyboard.press_and_release("Down")
00209         lens = self.dash.get_current_lens()
00210         category = lens.get_focused_category()
00211         self.assertIsNot(category, None)
00212         # Make sure that the category is highlighted.
00213         self.assertTrue(category.header_is_highlighted)
00214 
00215     def test_control_tab_lens_cycle(self):
00216         """This test makes sure that Ctrl+Tab cycles lenses."""
00217         self.dash.ensure_visible()
00218 
00219         self.keyboard.press('Control')
00220         self.keyboard.press_and_release('Tab')
00221         self.keyboard.release('Control')
00222 
00223         lensbar = self.dash.view.get_lensbar()
00224         self.assertEqual(lensbar.active_lens, u'applications.lens')
00225 
00226         self.keyboard.press('Control')
00227         self.keyboard.press('Shift')
00228         self.keyboard.press_and_release('Tab')
00229         self.keyboard.release('Control')
00230         self.keyboard.release('Shift')
00231 
00232         self.assertThat(lensbar.active_lens, Eventually(Equals('home.lens')))
00233 
00234     def test_tab_cycle_category_headers(self):
00235         """ Makes sure that pressing tab cycles through the category headers"""
00236         self.dash.ensure_visible()
00237         lens = self.dash.get_current_lens()
00238 
00239         # Test that tab cycles through the categories.
00240         # + 1 is to cycle back to first header
00241         for i in range(lens.get_num_visible_categories() + 1):
00242             self.keyboard.press_and_release('Tab')
00243             category = lens.get_focused_category()
00244             self.assertIsNot(category, None)
00245 
00246     def test_tab_with_filter_bar(self):
00247         """ This test makes sure that Tab works well with the filter bara."""
00248         self.dash.reveal_application_lens()
00249         lens = self.dash.get_current_lens()
00250 
00251         # Tabs to last category
00252         for i in range(lens.get_num_visible_categories()):
00253             self.keyboard.press_and_release('Tab')
00254 
00255         self.keyboard.press_and_release('Tab')
00256         self.assertThat(self.dash.searchbar.expander_has_focus, Eventually(Equals(True)))
00257 
00258         filter_bar = lens.get_filterbar()
00259         if not self.dash.searchbar.showing_filters:
00260             self.keyboard.press_and_release('Enter')
00261             self.assertThat(self.dash.searchbar.showing_filters, Eventually(Equals(True)))
00262             self.addCleanup(filter_bar.ensure_collapsed)
00263 
00264         for i in range(filter_bar.get_num_filters()):
00265             self.keyboard.press_and_release('Tab')
00266             new_focused_filter = filter_bar.get_focused_filter()
00267             self.assertIsNotNone(new_focused_filter)
00268 
00269         # Ensure that tab cycles back to a category header
00270         self.keyboard.press_and_release('Tab')
00271         category = lens.get_focused_category()
00272         self.assertIsNot(category, None)
00273 
00274 
00275 class DashClipboardTests(DashTestCase):
00276     """Test the Unity clipboard"""
00277 
00278     def test_ctrl_a(self):
00279         """ This test if ctrl+a selects all text """
00280         self.dash.ensure_visible()
00281 
00282         self.keyboard.type("SelectAll")
00283         self.assertThat(self.dash.search_string, Eventually(Equals("SelectAll")))
00284 
00285         self.keyboard.press_and_release("Ctrl+a")
00286         self.keyboard.press_and_release("Delete")
00287         self.assertThat(self.dash.search_string, Eventually(Equals('')))
00288 
00289     def test_ctrl_c(self):
00290         """ This test if ctrl+c copies text into the clipboard """
00291         self.dash.ensure_visible()
00292 
00293         self.keyboard.type("Copy")
00294         self.assertThat(self.dash.search_string, Eventually(Equals("Copy")))
00295 
00296         self.keyboard.press_and_release("Ctrl+a")
00297         self.keyboard.press_and_release("Ctrl+c")
00298 
00299         cb = Clipboard(selection="CLIPBOARD")
00300         self.assertThat(self.dash.search_string, Eventually(Equals(cb.wait_for_text())))
00301 
00302     def test_ctrl_x(self):
00303         """ This test if ctrl+x deletes all text and copys it """
00304         self.dash.ensure_visible()
00305 
00306         self.keyboard.type("Cut")
00307         self.assertThat(self.dash.search_string, Eventually(Equals("Cut")))
00308 
00309         self.keyboard.press_and_release("Ctrl+a")
00310         self.keyboard.press_and_release("Ctrl+x")
00311         self.assertThat(self.dash.search_string, Eventually(Equals("")))
00312 
00313         cb = Clipboard(selection="CLIPBOARD")
00314         self.assertEqual(cb.wait_for_text(), u'Cut')
00315 
00316     def test_ctrl_c_v(self):
00317         """ This test if ctrl+c and ctrl+v copies and pastes text"""
00318         self.dash.ensure_visible()
00319 
00320         self.keyboard.type("CopyPaste")
00321         self.assertThat(self.dash.search_string, Eventually(Equals("CopyPaste")))
00322 
00323         self.keyboard.press_and_release("Ctrl+a")
00324         self.keyboard.press_and_release("Ctrl+c")
00325         self.keyboard.press_and_release("Ctrl+v")
00326         self.keyboard.press_and_release("Ctrl+v")
00327 
00328         self.assertThat(self.dash.search_string, Eventually(Equals('CopyPasteCopyPaste')))
00329 
00330     def test_ctrl_x_v(self):
00331         """ This test if ctrl+x and ctrl+v cuts and pastes text"""
00332         self.dash.ensure_visible()
00333 
00334         self.keyboard.type("CutPaste")
00335         self.assertThat(self.dash.search_string, Eventually(Equals("CutPaste")))
00336 
00337         self.keyboard.press_and_release("Ctrl+a")
00338         self.keyboard.press_and_release("Ctrl+x")
00339         self.keyboard.press_and_release("Ctrl+v")
00340         self.keyboard.press_and_release("Ctrl+v")
00341 
00342         self.assertThat(self.dash.search_string, Eventually(Equals('CutPasteCutPaste')))
00343 
00344 
00345 class DashKeyboardFocusTests(DashTestCase):
00346     """Tests that keyboard focus works."""
00347 
00348     def test_filterbar_expansion_leaves_kb_focus(self):
00349         """Expanding or collapsing the filterbar must keave keyboard focus in the
00350         search bar.
00351         """
00352         self.dash.reveal_application_lens()
00353         filter_bar = self.dash.get_current_lens().get_filterbar()
00354         filter_bar.ensure_collapsed()
00355 
00356         self.keyboard.type("hello")
00357         filter_bar.ensure_expanded()
00358         self.addCleanup(filter_bar.ensure_collapsed)
00359         self.keyboard.type(" world")
00360         self.assertThat(self.dash.search_string, Eventually(Equals("hello world")))
00361 
00362 
00363 class DashLensResultsTests(DashTestCase):
00364     """Tests results from the lens view."""
00365 
00366     def test_results_message_empty_search(self):
00367         """This tests a message is not shown when there is no text."""
00368         self.dash.reveal_application_lens()
00369         lens = self.dash.get_current_lens()
00370         self.assertThat(lens.no_results_active, Eventually(Equals(False)))
00371 
00372     def test_results_message(self):
00373         """This test no mesage will be shown when results are there."""
00374         self.dash.reveal_application_lens()
00375         self.keyboard.type("Terminal")
00376         self.assertThat(self.dash.search_string, Eventually(Equals("Terminal")))
00377         lens = self.dash.get_current_lens()
00378         self.assertThat(lens.no_results_active, Eventually(Equals(False)))
00379 
00380     def test_no_results_message(self):
00381         """This test shows a message will appear in the lens."""
00382         self.dash.reveal_application_lens()
00383         self.keyboard.type("qwerlkjzvxc")
00384         self.assertThat(self.dash.search_string, Eventually(Equals("qwerlkjzvxc")))
00385         lens = self.dash.get_current_lens()
00386         self.assertThat(lens.no_results_active, Eventually(Equals(True)))
00387 
00388     def test_results_update_on_filter_changed(self):
00389         """This test makes sure the results change when filters change."""
00390         self.dash.reveal_application_lens()
00391         lens = self.dash.get_current_lens()
00392         self.keyboard.type(" ")
00393         self.assertThat(self.dash.search_string, Eventually(Equals(" ")))
00394         results_category = lens.get_category_by_name("Installed")
00395         old_results = results_category.get_results()
00396 
00397         # FIXME: This should be a method on the dash emulator perhaps, or
00398         # maybe a proper method of this class. It should NOT be an inline
00399         # function that is only called once!
00400         def activate_filter(add_cleanup = False):
00401             # Tabs to last category
00402             for i in range(lens.get_num_visible_categories()):
00403                 self.keyboard.press_and_release('Tab')
00404 
00405             self.keyboard.press_and_release('Tab')
00406             self.assertThat(self.dash.searchbar.expander_has_focus, Eventually(Equals(True)))
00407 
00408             filter_bar = lens.get_filterbar()
00409             if not self.dash.searchbar.showing_filters:
00410                 self.keyboard.press_and_release('Enter')
00411                 self.assertThat(self.dash.searchbar.showing_filters, Eventually(Equals(True)))
00412                 if add_cleanup:
00413                     self.addCleanup(filter_bar.ensure_collapsed)
00414 
00415             # Tab to the "Type" filter in apps lens
00416             self.keyboard.press_and_release('Tab')
00417             new_focused_filter = filter_bar.get_focused_filter()
00418             self.assertIsNotNone(new_focused_filter)
00419 
00420             self.keyboard.press_and_release("Down")
00421             self.keyboard.press_and_release("Down")
00422             self.keyboard.press_and_release("Down")
00423             # We should be on the Education category
00424             self.keyboard.press_and_release('Enter')
00425 
00426         activate_filter(True)
00427         self.addCleanup(activate_filter)
00428 
00429         results_category = lens.get_category_by_name("Installed")
00430         results = results_category.get_results()
00431         self.assertIsNot(results, old_results)
00432 
00433         # so we can clean up properly
00434         self.keyboard.press_and_release('BackSpace')
00435 
00436 
00437 class DashVisualTests(DashTestCase):
00438     """Tests that the dash visual is correct."""
00439 
00440     def test_see_more_result_alignment(self):
00441         """The see more results label should be baseline aligned
00442         with the category name label.
00443         """
00444         self.dash.reveal_application_lens()
00445 
00446         lens = self.dash.get_current_lens()
00447         groups = lens.get_groups()
00448 
00449         for group in groups:
00450             if (group.is_visible and group.expand_label_is_visible):
00451                 expand_label_y = group.expand_label_y + group.expand_label_baseline
00452                 name_label_y = group.name_label_y + group.name_label_baseline
00453                 self.assertThat(expand_label_y, Equals(name_label_y))
00454 
00455 
00456 class DashLensBarTests(DashTestCase):
00457     """Tests that the lensbar works well."""
00458 
00459     def setUp(self):
00460         super(DashLensBarTests, self).setUp()
00461         self.dash.ensure_visible()
00462         self.lensbar = self.dash.view.get_lensbar()
00463 
00464     def test_click_inside_highlight(self):
00465         """Lens selection should work when clicking in
00466         the rectangle outside of the icon.
00467         """
00468         app_icon = self.lensbar.get_icon_by_name(u'applications.lens')
00469 
00470         self.mouse.move(app_icon.x + (app_icon.width / 2),
00471                         app_icon.y + (app_icon.height / 2))
00472         self.mouse.click()
00473 
00474         self.assertThat(self.lensbar.active_lens, Eventually(Equals('applications.lens')))
00475 
00476 
00477 class DashBorderTests(DashTestCase):
00478     """Tests that the dash border works well.
00479     """
00480     def setUp(self):
00481         super(DashBorderTests, self).setUp()
00482         self.dash.ensure_visible()
00483 
00484     def test_click_right_border(self):
00485         """Clicking on the right dash border should do nothing,
00486         *NOT* close the dash.
00487         """
00488         if (self.dash.view.form_factor != "desktop"):
00489             self.skip("Not in desktop form-factor.")
00490 
00491         x = self.dash.view.x + self.dash.view.width + self.dash.view.right_border_width / 2;
00492         y = self.dash.view.y + self.dash.view.height / 2;
00493 
00494         self.mouse.move(x, y)
00495         self.mouse.click()
00496 
00497         self.assertThat(self.dash.visible, Eventually(Equals(True)))
00498 
00499     def test_click_bottom_border(self):
00500         """Clicking on the bottom dash border should do nothing,
00501         *NOT* close the dash.
00502         """
00503         if (self.dash.view.form_factor != "desktop"):
00504             self.skip("Not in desktop form-factor.")
00505 
00506         x = self.dash.view.x + self.dash.view.width / 2;
00507         y = self.dash.view.y + self.dash.view.height + self.dash.view.bottom_border_height / 2;
00508 
00509         self.mouse.move(x, y)
00510         self.mouse.click()
00511 
00512         self.assertThat(self.dash.visible, Eventually(Equals(True)))
00513 
00514 
00515 class CategoryHeaderTests(DashTestCase):
00516     """Tests that category headers work.
00517     """
00518     def test_click_inside_highlight(self):
00519         """Clicking into a category highlight must expand/collapse
00520         the view.
00521         """
00522         lens = self.dash.reveal_file_lens()
00523         self.addCleanup(self.dash.ensure_hidden)
00524 
00525         category = lens.get_category_by_name("Folders")
00526         is_expanded = category.is_expanded
00527 
00528         self.mouse.move(self.dash.view.x + self.dash.view.width / 2,
00529                         category.header_y + category.header_height / 2)
00530 
00531         self.mouse.click()
00532         self.assertThat(category.is_expanded, Eventually(Equals(not is_expanded)))
00533 
00534         self.mouse.click()
00535         self.assertThat(category.is_expanded, Eventually(Equals(is_expanded)))
00536