browser_rules_style-editor-link.js (8275B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 // Test the links from the rule-view to the styleeditor 7 8 const STYLESHEET_DATA_URL_CONTENTS = `#first { 9 color: blue 10 }`; 11 const STYLESHEET_DATA_URL = `data:text/css,${encodeURIComponent( 12 STYLESHEET_DATA_URL_CONTENTS 13 )}`; 14 15 const EXTERNAL_STYLESHEET_FILE_NAME = "doc_style_editor_link.css"; 16 const EXTERNAL_STYLESHEET_URL = URL_ROOT_SSL + EXTERNAL_STYLESHEET_FILE_NAME; 17 18 const DOCUMENT_HTML = encodeURIComponent(` 19 <html> 20 <head> 21 <title>Rule view style editor link test</title> 22 <style type="text/css"> 23 html { color: #000000; } 24 div { font-variant: small-caps; color: #000000; } 25 .nomatches {color: #ff0000;} 26 </style> 27 <style> 28 div { font-weight: bold; } 29 </style> 30 <link rel="stylesheet" type="text/css" href="${STYLESHEET_DATA_URL}"> 31 <link rel="stylesheet" type="text/css" href="${EXTERNAL_STYLESHEET_URL}"> 32 </head> 33 <body> 34 <div id="first" style="margin: 10em;font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA"> 35 <h1>Some header text</h1> 36 <p id="salutation" style="font-size: 12pt">hi.</p> 37 <p id="body" style="font-size: 12pt">I am a test-case. This text exists 38 solely to provide some things to 39 <span style="color: yellow" class="highlight"> 40 highlight</span> and <span style="font-weight: bold">count</span> 41 style list-items in the box at right. If you are reading this, 42 you should go do something else instead. Maybe read a book. Or better 43 yet, write some test-cases for another bit of code. 44 <span style="font-style: italic">some text</span></p> 45 <p id="closing">more text</p> 46 <p>even more text</p> 47 </div> 48 </body> 49 </html> 50 `); 51 52 const DOCUMENT_DATA_URL = "data:text/html;charset=utf-8," + DOCUMENT_HTML; 53 const EXAMPLE_ORG_DOCUMENT_URL = 54 "https://example.org/document-builder.sjs?html=" + DOCUMENT_HTML; 55 56 add_task(async function () { 57 await addTab(DOCUMENT_DATA_URL); 58 const { toolbox, inspector, view } = await openRuleView(); 59 60 await testAllStylesheets(inspector, view, toolbox); 61 62 info("Navigate to the example.org document"); 63 await navigateTo(EXAMPLE_ORG_DOCUMENT_URL); 64 await testAllStylesheets(inspector, view, toolbox); 65 }); 66 67 add_task(async function () { 68 info("Check that link to the style editor works after tab reload"); 69 await addTab(EXAMPLE_ORG_DOCUMENT_URL); 70 const { toolbox, inspector, view } = await openRuleView(); 71 72 info("Reload the example.org document"); 73 // Use navigateTo as it waits for the inspector to be ready. 74 await navigateTo(EXAMPLE_ORG_DOCUMENT_URL); 75 await testAllStylesheets(inspector, view, toolbox); 76 }); 77 78 async function testAllStylesheets(inspector, view, toolbox) { 79 await selectNode("div", inspector); 80 await testRuleViewLinkLabel(view); 81 await testDisabledStyleEditor(view, toolbox); 82 await testFirstInlineStyleSheet(view, toolbox); 83 await testSecondInlineStyleSheet(view, toolbox); 84 await testExternalStyleSheet(view, toolbox); 85 86 info("Switch back to the inspector panel"); 87 await toolbox.selectTool("inspector"); 88 await selectNode("body", inspector); 89 } 90 91 async function testFirstInlineStyleSheet(view, toolbox) { 92 info("Testing inline stylesheet"); 93 94 info("Listening for toolbox switch to the styleeditor"); 95 const onSwitch = waitForStyleEditor(toolbox); 96 97 info("Clicking an inline stylesheet"); 98 clickLinkByIndex(view, 4); 99 const editor = await onSwitch; 100 101 ok(true, "Switched to the style-editor panel in the toolbox"); 102 103 await validateStyleEditorSheet(toolbox, editor, 0); 104 } 105 106 async function testSecondInlineStyleSheet(view, toolbox) { 107 info("Testing second inline stylesheet"); 108 109 const styleEditorPanel = toolbox.getCurrentPanel(); 110 const onEditorSelected = styleEditorPanel.UI.once("editor-selected"); 111 112 info("Switching back to the inspector panel in the toolbox"); 113 await toolbox.selectTool("inspector"); 114 const onToolSelected = toolbox.once("styleeditor-selected"); 115 116 info("Clicking on second inline stylesheet link"); 117 clickLinkByIndex(view, 3); 118 119 info("Wait for the stylesheet editor to be selected"); 120 const editor = await onEditorSelected; 121 await onToolSelected; 122 123 is( 124 toolbox.currentToolId, 125 "styleeditor", 126 "The style editor is selected again" 127 ); 128 await validateStyleEditorSheet(toolbox, editor, 1); 129 } 130 131 async function testExternalStyleSheet(view, toolbox) { 132 info("Testing external stylesheet"); 133 const styleEditorPanel = toolbox.getCurrentPanel(); 134 const onEditorSelected = styleEditorPanel.UI.once("editor-selected"); 135 136 info("Switching back to the inspector panel in the toolbox"); 137 await toolbox.selectTool("inspector"); 138 const onToolSelected = toolbox.once("styleeditor-selected"); 139 140 info("Clicking on an external stylesheet link"); 141 clickLinkByIndex(view, 1); 142 143 info("Wait for the stylesheet editor to be selected"); 144 const editor = await onEditorSelected; 145 await onToolSelected; 146 147 is( 148 toolbox.currentToolId, 149 "styleeditor", 150 "The style editor is selected again" 151 ); 152 await validateStyleEditorSheet(toolbox, editor, 2); 153 } 154 155 async function validateStyleEditorSheet(toolbox, editor, expectedSheetIndex) { 156 info("validating style editor stylesheet"); 157 is( 158 editor.styleSheet.styleSheetIndex, 159 expectedSheetIndex, 160 "loaded stylesheet index matches document stylesheet" 161 ); 162 163 const href = editor.styleSheet.href || editor.styleSheet.nodeHref; 164 165 const expectedHref = await SpecialPowers.spawn( 166 gBrowser.selectedBrowser, 167 [expectedSheetIndex], 168 _expectedSheetIndex => { 169 return ( 170 content.document.styleSheets[_expectedSheetIndex].href || 171 content.document.location.href 172 ); 173 } 174 ); 175 176 is(href, expectedHref, "loaded stylesheet href matches document stylesheet"); 177 } 178 179 async function testDisabledStyleEditor(view, toolbox) { 180 info("Testing with the style editor disabled"); 181 182 info("Switching to the inspector panel in the toolbox"); 183 await toolbox.selectTool("inspector"); 184 185 info("Disabling the style editor"); 186 Services.prefs.setBoolPref("devtools.styleeditor.enabled", false); 187 gDevTools.emit("tool-unregistered", "styleeditor"); 188 189 info("Clicking on a link"); 190 testUnselectableRuleViewLink(view, 1); 191 clickLinkByIndex(view, 1); 192 // Wait for a bit just to make sure the click didn't had an impact 193 await wait(2000); 194 195 is(toolbox.currentToolId, "inspector", "The click should have no effect"); 196 197 info("Enabling the style editor"); 198 Services.prefs.setBoolPref("devtools.styleeditor.enabled", true); 199 gDevTools.emit("tool-registered", "styleeditor"); 200 201 Services.prefs.clearUserPref("devtools.styleeditor.enabled"); 202 } 203 204 async function testRuleViewLinkLabel(view) { 205 info("Checking the data URL link label"); 206 let link = await waitFor(() => getRuleViewLinkByIndex(view, 1)); 207 let labelElem = link.querySelector(".ruleview-rule-source-label"); 208 let value = labelElem.textContent; 209 let tooltipText = labelElem.getAttribute("title"); 210 211 is( 212 value, 213 STYLESHEET_DATA_URL_CONTENTS + ":1", 214 "Rule view data URL stylesheet display value matches contents" 215 ); 216 is( 217 tooltipText, 218 `View source in Style Editor → ${STYLESHEET_DATA_URL}:1`, 219 "Rule view data URL stylesheet tooltip text matches the full URI path" 220 ); 221 222 info("Checking the external link label"); 223 link = await waitFor(() => getRuleViewLinkByIndex(view, 2)); 224 labelElem = link.querySelector(".ruleview-rule-source-label"); 225 value = labelElem.textContent; 226 tooltipText = labelElem.getAttribute("title"); 227 228 is( 229 value, 230 `${EXTERNAL_STYLESHEET_FILE_NAME}:1`, 231 "Rule view external stylesheet display value matches filename and line number" 232 ); 233 is( 234 tooltipText, 235 `View source in Style Editor → ${EXTERNAL_STYLESHEET_URL}:1`, 236 "Rule view external stylesheet tooltip text matches the full URI path" 237 ); 238 } 239 240 function testUnselectableRuleViewLink(view, index) { 241 const link = getRuleViewLinkByIndex(view, index); 242 const unselectable = link.hasAttribute("unselectable"); 243 244 ok(unselectable, "Rule view is unselectable"); 245 } 246 247 function clickLinkByIndex(view, index) { 248 const link = getRuleViewLinkByIndex(view, index); 249 link.scrollIntoView(); 250 link.click(); 251 }