browser_styleeditor_sourcemap_watching.js (4552B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 /* eslint-disable mozilla/no-arbitrary-setTimeout */ 4 5 "use strict"; 6 7 const TESTCASE_URI_HTML = TEST_BASE_HTTP + "sourcemaps-watching.html"; 8 const TESTCASE_URI_CSS = TEST_BASE_HTTP + "sourcemap-css/sourcemaps.css"; 9 const TESTCASE_URI_REG_CSS = TEST_BASE_HTTP + "simple.css"; 10 const TESTCASE_URI_SCSS = TEST_BASE_HTTP + "sourcemap-sass/sourcemaps.scss"; 11 const TESTCASE_URI_MAP = TEST_BASE_HTTP + "sourcemap-css/sourcemaps.css.map"; 12 const TESTCASE_SCSS_NAME = "sourcemaps.scss"; 13 14 const TRANSITIONS_PREF = "devtools.styleeditor.transitions"; 15 16 const CSS_TEXT = "* { color: blue }"; 17 18 add_task(async function () { 19 await new Promise(resolve => { 20 SpecialPowers.pushPrefEnv({ set: [[TRANSITIONS_PREF, false]] }, resolve); 21 }); 22 23 // copy all our files over so we don't screw them up for other tests 24 const HTMLFile = await copy(TESTCASE_URI_HTML, ["sourcemaps.html"]); 25 const CSSFile = await copy(TESTCASE_URI_CSS, [ 26 "sourcemap-css", 27 "sourcemaps.css", 28 ]); 29 await copy(TESTCASE_URI_SCSS, ["sourcemap-sass", "sourcemaps.scss"]); 30 await copy(TESTCASE_URI_MAP, ["sourcemap-css", "sourcemaps.css.map"]); 31 await copy(TESTCASE_URI_REG_CSS, ["simple.css"]); 32 33 const uri = Services.io.newFileURI(HTMLFile); 34 const testcaseURI = uri.resolve(""); 35 36 const { ui } = await openStyleEditorForURL(testcaseURI); 37 38 let editor = ui.editors[1]; 39 if (getStylesheetNameFor(editor) != TESTCASE_SCSS_NAME) { 40 editor = ui.editors[2]; 41 } 42 43 is(getStylesheetNameFor(editor), TESTCASE_SCSS_NAME, "found scss editor"); 44 45 const link = getLinkFor(editor); 46 link.click(); 47 48 await editor.getSourceEditor(); 49 50 let color = await getComputedStyleProperty({ 51 selector: "div", 52 name: "color", 53 }); 54 is(color, "rgb(255, 0, 102)", "div is red before saving file"); 55 56 const styleApplied = editor.once("style-applied"); 57 58 await pauseForTimeChange(); 59 60 // Edit and save Sass in the editor. This will start off a file-watching 61 // process waiting for the CSS file to change. 62 await editSCSS(editor); 63 64 // We can't run Sass or another compiler, so we fake it by just 65 // directly changing the CSS file. 66 await editCSSFile(CSSFile); 67 68 info("wrote to CSS file, waiting for style-applied event"); 69 70 await styleApplied; 71 72 color = await getComputedStyleProperty({ selector: "div", name: "color" }); 73 is(color, "rgb(0, 0, 255)", "div is blue after saving file"); 74 75 // Ensure that the editor didn't revert. Bug 1346662. 76 is(editor.sourceEditor.getText(), CSS_TEXT, "edits remain applied"); 77 }); 78 79 function editSCSS(editor) { 80 return new Promise(resolve => { 81 editor.sourceEditor.setText(CSS_TEXT); 82 83 editor.saveToFile(null, function (file) { 84 ok(file, "Scss file should be saved"); 85 resolve(); 86 }); 87 }); 88 } 89 90 function editCSSFile(CSSFile) { 91 return write(CSS_TEXT, CSSFile); 92 } 93 94 function pauseForTimeChange() { 95 return new Promise(resolve => { 96 // We have to wait for the system time to turn over > 1000 ms so that 97 // our file's last change time will show a change. This reflects what 98 // would happen in real life with a user manually saving the file. 99 setTimeout(resolve, 2000); 100 }); 101 } 102 103 /* Helpers */ 104 105 function getLinkFor(editor) { 106 return editor.summary.querySelector(".stylesheet-name"); 107 } 108 109 function getStylesheetNameFor(editor) { 110 return editor.summary 111 .querySelector(".stylesheet-name > label") 112 .getAttribute("value"); 113 } 114 115 function copy(srcChromeURL, destFilePath) { 116 const destFile = new FileUtils.File( 117 PathUtils.join(PathUtils.profileDir, ...destFilePath) 118 ); 119 return write(read(srcChromeURL), destFile); 120 } 121 122 function read(srcChromeURL) { 123 const scriptableStream = Cc[ 124 "@mozilla.org/scriptableinputstream;1" 125 ].getService(Ci.nsIScriptableInputStream); 126 127 const channel = NetUtil.newChannel({ 128 uri: srcChromeURL, 129 loadUsingSystemPrincipal: true, 130 }); 131 const input = channel.open(); 132 scriptableStream.init(input); 133 134 let data = ""; 135 while (input.available()) { 136 data = data.concat(scriptableStream.read(input.available())); 137 } 138 scriptableStream.close(); 139 input.close(); 140 141 return data; 142 } 143 144 function write(data, file) { 145 return new Promise(resolve => { 146 const istream = getInputStream(data); 147 const ostream = FileUtils.openSafeFileOutputStream(file); 148 149 NetUtil.asyncCopy(istream, ostream, function (status) { 150 if (!Components.isSuccessCode(status)) { 151 info("Coudln't write to " + file.path); 152 return; 153 } 154 resolve(file); 155 }); 156 }); 157 }