summaryrefslogtreecommitdiffstats
path: root/browser/components/places/tests/marionette/test_reopen_from_library.py
blob: 28f6ff3cd6cb5a229f3d664e2600be56a8d04f75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import textwrap

from marionette_driver import Wait
from marionette_harness import MarionetteTestCase, WindowManagerMixin


class TestReopenFromLibrary(WindowManagerMixin, MarionetteTestCase):
    def setUp(self):
        super(TestReopenFromLibrary, self).setUp()

        self.original_showForNewBookmarks_pref = self.marionette.get_pref(
            "browser.bookmarks.editDialog.showForNewBookmarks"
        )
        self.original_loadBookmarksInTabs_pref = self.marionette.get_pref(
            "browser.tabs.loadBookmarksInTabs"
        )

        self.marionette.set_pref(
            "browser.bookmarks.editDialog.showForNewBookmarks", False
        )
        self.marionette.set_pref("browser.tabs.loadBookmarksInTabs", True)

    def tearDown(self):
        self.close_all_windows()

        self.marionette.restart(in_app=False, clean=True)

        super(TestReopenFromLibrary, self).tearDown()

    def test_open_bookmark_from_library_with_no_browser_window_open(self):
        bookmark_url = self.marionette.absolute_url("empty.html")
        self.marionette.navigate(bookmark_url)

        self.marionette.set_context(self.marionette.CONTEXT_CHROME)

        star_button = self.marionette.find_element("id", "star-button-box")

        # Await for async updates to the star button before clicking on it, as
        # clicks are ignored during status updates.
        script = """\
          return window.BookmarkingUI.status != window.BookmarkingUI.STATUS_UPDATING;
        """
        Wait(self.marionette).until(
            lambda _: self.marionette.execute_script(textwrap.dedent(script)),
            message="Failed waiting for star updates",
        )

        star_button.click()

        star_image = self.marionette.find_element("id", "star-button")

        def check(_):
            return "true" in star_image.get_attribute("starred")

        Wait(self.marionette).until(check, message="Failed to star the page")

        win = self.open_chrome_window(
            "chrome://browser/content/places/places.xhtml", False
        )

        self.marionette.close_chrome_window()

        self.marionette.switch_to_window(win)

        # Tree elements can't be accessed in the same way as regular elements,
        # so this uses some code from the places tests and EventUtils.js to
        # select the bookmark in the tree and then double-click it.
        script = """\
          window.PlacesOrganizer.selectLeftPaneContainerByHierarchy(
            PlacesUtils.bookmarks.virtualToolbarGuid
          );

          // Bookmarks may be imported and shift the expected one, so search
          // for it.
          let node;
          for (let i = 1; i < window.ContentTree.view.result.root.childCount; ++i) {
            node = window.ContentTree.view.view.nodeForTreeIndex(i);
            if (node.uri.endsWith("empty.html")) {
              break;
            }
          }

          window.ContentTree.view.selectNode(node);

          // Based on synthesizeDblClickOnSelectedTreeCell
          let tree = window.ContentTree.view;

          if (tree.view.selection.count < 1) {
            throw new Error("The test node should be successfully selected");
          }
          // Get selection rowID.
          let min = {};
          let max = {};
          tree.view.selection.getRangeAt(0, min, max);
          let rowID = min.value;
          tree.ensureRowIsVisible(rowID);
          // Calculate the click coordinates.
          let rect = tree.getCoordsForCellItem(rowID, tree.columns[0], "text");
          let x = rect.x + rect.width / 2;
          let y = rect.y + rect.height / 2;
          let treeBodyRect = tree.body.getBoundingClientRect();
          return [treeBodyRect.left + x, treeBodyRect.top + y]
        """

        position = self.marionette.execute_script(textwrap.dedent(script))
        # These must be integers for pointer_move
        x = round(position[0])
        y = round(position[1])

        self.marionette.actions.sequence(
            "pointer", "pointer_id", {"pointerType": "mouse"}
        ).pointer_move(x, y).click().click().perform()

        def window_with_url_open(_):
            urls_in_windows = self.get_urls_for_windows()

            for urls in urls_in_windows:
                if bookmark_url in urls:
                    return True
            return False

        Wait(self.marionette).until(
            window_with_url_open,
            message="Failed to open the browser window from the library",
        )

        # Closes the library window.
        self.marionette.close_chrome_window()

    def get_urls_for_windows(self):
        # There's no guarantee that Marionette will return us an
        # iterator for the opened windows that will match the
        # order within our window list. Instead, we'll convert
        # the list of URLs within each open window to a set of
        # tuples that will allow us to do a direct comparison
        # while allowing the windows to be in any order.
        opened_urls = set()
        for win in self.marionette.chrome_window_handles:
            urls = tuple(self.get_urls_for_window(win))
            opened_urls.add(urls)

        return opened_urls

    def get_urls_for_window(self, win):
        orig_handle = self.marionette.current_chrome_window_handle

        try:
            self.marionette.switch_to_window(win)
            return self.marionette.execute_script(
                """
              if (!window?.gBrowser) {
                return [];
              }
              return window.gBrowser.tabs.map(tab => {
                return tab.linkedBrowser.currentURI.spec;
              });
            """
            )
        finally:
            self.marionette.switch_to_window(orig_handle)