test_reopen_from_library.py (5809B)
1 # This Source Code Form is subject to the terms of the Mozilla Public 2 # License, v. 2.0. If a copy of the MPL was not distributed with this 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5 import textwrap 6 7 from marionette_driver import Wait 8 from marionette_harness import MarionetteTestCase, WindowManagerMixin 9 10 11 class TestReopenFromLibrary(WindowManagerMixin, MarionetteTestCase): 12 def setUp(self): 13 super().setUp() 14 15 self.original_showForNewBookmarks_pref = self.marionette.get_pref( 16 "browser.bookmarks.editDialog.showForNewBookmarks" 17 ) 18 self.original_loadBookmarksInTabs_pref = self.marionette.get_pref( 19 "browser.tabs.loadBookmarksInTabs" 20 ) 21 22 self.marionette.set_pref( 23 "browser.bookmarks.editDialog.showForNewBookmarks", False 24 ) 25 self.marionette.set_pref("browser.tabs.loadBookmarksInTabs", True) 26 27 def tearDown(self): 28 self.close_all_windows() 29 30 self.marionette.restart(in_app=False, clean=True) 31 32 super().tearDown() 33 34 def test_open_bookmark_from_library_with_no_browser_window_open(self): 35 bookmark_url = self.marionette.absolute_url("empty.html") 36 self.marionette.navigate(bookmark_url) 37 38 self.marionette.set_context(self.marionette.CONTEXT_CHROME) 39 40 star_button = self.marionette.find_element("id", "star-button-box") 41 42 # Await for async updates to the star button before clicking on it, as 43 # clicks are ignored during status updates. 44 script = """\ 45 return window.BookmarkingUI.status != window.BookmarkingUI.STATUS_UPDATING; 46 """ 47 Wait(self.marionette).until( 48 lambda _: self.marionette.execute_script(textwrap.dedent(script)), 49 message="Failed waiting for star updates", 50 ) 51 52 star_button.click() 53 54 star_image = self.marionette.find_element("id", "star-button") 55 56 def check(_): 57 return "" == star_image.get_attribute("starred") 58 59 Wait(self.marionette).until(check, message="Failed to star the page") 60 61 win = self.open_chrome_window( 62 "chrome://browser/content/places/places.xhtml", False 63 ) 64 65 self.marionette.close_chrome_window() 66 67 self.marionette.switch_to_window(win) 68 69 # Tree elements can't be accessed in the same way as regular elements, 70 # so this uses some code from the places tests and EventUtils.js to 71 # select the bookmark in the tree and then double-click it. 72 script = """\ 73 window.PlacesOrganizer.selectLeftPaneContainerByHierarchy( 74 PlacesUtils.bookmarks.virtualToolbarGuid 75 ); 76 77 let node; 78 for (let i = 0; i < window.ContentTree.view.result.root.childCount; ++i) { 79 node = window.ContentTree.view.view.nodeForTreeIndex(i); 80 if (node.uri.endsWith("empty.html")) { 81 break; 82 } 83 } 84 85 window.ContentTree.view.selectNode(node); 86 87 // Based on synthesizeDblClickOnSelectedTreeCell 88 let tree = window.ContentTree.view; 89 90 if (tree.view.selection.count < 1) { 91 throw new Error("The test node should be successfully selected"); 92 } 93 // Get selection rowID. 94 let min = {}; 95 let max = {}; 96 tree.view.selection.getRangeAt(0, min, max); 97 let rowID = min.value; 98 tree.ensureRowIsVisible(rowID); 99 // Calculate the click coordinates. 100 let rect = tree.getCoordsForCellItem(rowID, tree.columns[0], "text"); 101 let x = rect.x + rect.width / 2; 102 let y = rect.y + rect.height / 2; 103 let treeBodyRect = tree.body.getBoundingClientRect(); 104 return [treeBodyRect.left + x, treeBodyRect.top + y] 105 """ 106 107 position = self.marionette.execute_script(textwrap.dedent(script)) 108 # These must be integers for pointer_move 109 x = round(position[0]) 110 y = round(position[1]) 111 112 self.marionette.actions.sequence( 113 "pointer", "pointer_id", {"pointerType": "mouse"} 114 ).pointer_move(x, y).click().click().perform() 115 116 def window_with_url_open(_): 117 urls_in_windows = self.get_urls_for_windows() 118 119 for urls in urls_in_windows: 120 if bookmark_url in urls: 121 return True 122 return False 123 124 Wait(self.marionette).until( 125 window_with_url_open, 126 message="Failed to open the browser window from the library", 127 ) 128 129 # Closes the library window. 130 self.marionette.close_chrome_window() 131 132 def get_urls_for_windows(self): 133 # There's no guarantee that Marionette will return us an 134 # iterator for the opened windows that will match the 135 # order within our window list. Instead, we'll convert 136 # the list of URLs within each open window to a set of 137 # tuples that will allow us to do a direct comparison 138 # while allowing the windows to be in any order. 139 opened_urls = set() 140 for win in self.marionette.chrome_window_handles: 141 urls = tuple(self.get_urls_for_window(win)) 142 opened_urls.add(urls) 143 144 return opened_urls 145 146 def get_urls_for_window(self, win): 147 orig_handle = self.marionette.current_chrome_window_handle 148 149 try: 150 self.marionette.switch_to_window(win) 151 return self.marionette.execute_script( 152 """ 153 if (!window?.gBrowser) { 154 return []; 155 } 156 return window.gBrowser.tabs.map(tab => { 157 return tab.linkedBrowser.currentURI.spec; 158 }); 159 """ 160 ) 161 finally: 162 self.marionette.switch_to_window(orig_handle)