shared-head.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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. "use strict";
  5. /* eslint no-unused-vars: [2, {"vars": "local"}] */
  6. /* globals registerTestActor, getTestActor, Task, openToolboxForTab, gBrowser */
  7. // This file contains functions related to the inspector that are also of interest to
  8. // other test directores as well.
  9. /**
  10. * Open the toolbox, with the inspector tool visible.
  11. * @param {String} hostType Optional hostType, as defined in Toolbox.HostType
  12. * @return a promise that resolves when the inspector is ready
  13. */
  14. var openInspector = Task.async(function* (hostType) {
  15. info("Opening the inspector");
  16. let toolbox = yield openToolboxForTab(gBrowser.selectedTab, "inspector",
  17. hostType);
  18. let inspector = toolbox.getPanel("inspector");
  19. if (inspector._updateProgress) {
  20. info("Need to wait for the inspector to update");
  21. yield inspector.once("inspector-updated");
  22. }
  23. info("Waiting for actor features to be detected");
  24. yield inspector._detectingActorFeatures;
  25. yield registerTestActor(toolbox.target.client);
  26. let testActor = yield getTestActor(toolbox);
  27. return {toolbox, inspector, testActor};
  28. });
  29. /**
  30. * Open the toolbox, with the inspector tool visible, and the one of the sidebar
  31. * tabs selected.
  32. *
  33. * @param {String} id
  34. * The ID of the sidebar tab to be opened
  35. * @return a promise that resolves when the inspector is ready and the tab is
  36. * visible and ready
  37. */
  38. var openInspectorSidebarTab = Task.async(function* (id) {
  39. let {toolbox, inspector, testActor} = yield openInspector();
  40. info("Selecting the " + id + " sidebar");
  41. inspector.sidebar.select(id);
  42. return {
  43. toolbox,
  44. inspector,
  45. testActor
  46. };
  47. });
  48. /**
  49. * Open the toolbox, with the inspector tool visible, and the rule-view
  50. * sidebar tab selected.
  51. *
  52. * @return a promise that resolves when the inspector is ready and the rule view
  53. * is visible and ready
  54. */
  55. function openRuleView() {
  56. return openInspectorSidebarTab("ruleview").then(data => {
  57. // Replace the view to use a custom throttle function that can be triggered manually
  58. // through an additional ".flush()" property.
  59. data.inspector.ruleview.view.throttle = manualThrottle();
  60. return {
  61. toolbox: data.toolbox,
  62. inspector: data.inspector,
  63. testActor: data.testActor,
  64. view: data.inspector.ruleview.view
  65. };
  66. });
  67. }
  68. /**
  69. * Open the toolbox, with the inspector tool visible, and the computed-view
  70. * sidebar tab selected.
  71. *
  72. * @return a promise that resolves when the inspector is ready and the computed
  73. * view is visible and ready
  74. */
  75. function openComputedView() {
  76. return openInspectorSidebarTab("computedview").then(data => {
  77. return {
  78. toolbox: data.toolbox,
  79. inspector: data.inspector,
  80. testActor: data.testActor,
  81. view: data.inspector.computedview.computedView
  82. };
  83. });
  84. }
  85. /**
  86. * Select the rule view sidebar tab on an already opened inspector panel.
  87. *
  88. * @param {InspectorPanel} inspector
  89. * The opened inspector panel
  90. * @return {CssRuleView} the rule view
  91. */
  92. function selectRuleView(inspector) {
  93. inspector.sidebar.select("ruleview");
  94. return inspector.ruleview.view;
  95. }
  96. /**
  97. * Select the computed view sidebar tab on an already opened inspector panel.
  98. *
  99. * @param {InspectorPanel} inspector
  100. * The opened inspector panel
  101. * @return {CssComputedView} the computed view
  102. */
  103. function selectComputedView(inspector) {
  104. inspector.sidebar.select("computedview");
  105. return inspector.computedview.computedView;
  106. }
  107. /**
  108. * Get the NodeFront for a node that matches a given css selector, via the
  109. * protocol.
  110. * @param {String|NodeFront} selector
  111. * @param {InspectorPanel} inspector The instance of InspectorPanel currently
  112. * loaded in the toolbox
  113. * @return {Promise} Resolves to the NodeFront instance
  114. */
  115. function getNodeFront(selector, {walker}) {
  116. if (selector._form) {
  117. return selector;
  118. }
  119. return walker.querySelector(walker.rootNode, selector);
  120. }
  121. /**
  122. * Set the inspector's current selection to the first match of the given css
  123. * selector
  124. * @param {String|NodeFront} selector
  125. * @param {InspectorPanel} inspector The instance of InspectorPanel currently
  126. * loaded in the toolbox
  127. * @param {String} reason Defaults to "test" which instructs the inspector not
  128. * to highlight the node upon selection
  129. * @return {Promise} Resolves when the inspector is updated with the new node
  130. */
  131. var selectNode = Task.async(function* (selector, inspector, reason = "test") {
  132. info("Selecting the node for '" + selector + "'");
  133. let nodeFront = yield getNodeFront(selector, inspector);
  134. let updated = inspector.once("inspector-updated");
  135. inspector.selection.setNodeFront(nodeFront, reason);
  136. yield updated;
  137. });
  138. /**
  139. * Create a throttling function that can be manually "flushed". This is to replace the
  140. * use of the `throttle` function from `devtools/client/inspector/shared/utils.js`, which
  141. * has a setTimeout that can cause intermittents.
  142. * @return {Function} This function has the same function signature as throttle, but
  143. * the property `.flush()` has been added for flushing out any
  144. * throttled calls.
  145. */
  146. function manualThrottle() {
  147. let calls = [];
  148. function throttle(func, wait, scope) {
  149. return function () {
  150. let existingCall = calls.find(call => call.func === func);
  151. if (existingCall) {
  152. existingCall.args = arguments;
  153. } else {
  154. calls.push({ func, wait, scope, args: arguments });
  155. }
  156. };
  157. }
  158. throttle.flush = function () {
  159. calls.forEach(({func, scope, args}) => func.apply(scope, args));
  160. calls = [];
  161. };
  162. return throttle;
  163. }