browser_webconsole_stubs_css_message.js (3491B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const { 7 STUBS_UPDATE_ENV, 8 createCommandsForTab, 9 getCleanedPacket, 10 getSerializedPacket, 11 getStubFile, 12 writeStubsToFile, 13 } = require(`${CHROME_URL_ROOT}stub-generator-helpers`); 14 15 const TEST_URI = 16 "https://example.com/browser/devtools/client/webconsole/test/browser/test-css-message.html"; 17 const STUB_FILE = "cssMessage.js"; 18 19 add_task(async function () { 20 const isStubsUpdate = Services.env.get(STUBS_UPDATE_ENV) == "true"; 21 info(`${isStubsUpdate ? "Update" : "Check"} ${STUB_FILE}`); 22 23 const generatedStubs = await generateCssMessageStubs(); 24 25 if (isStubsUpdate) { 26 await writeStubsToFile(STUB_FILE, generatedStubs); 27 ok(true, `${STUB_FILE} was updated`); 28 return; 29 } 30 31 const existingStubs = getStubFile(STUB_FILE); 32 const FAILURE_MSG = 33 "The cssMessage stubs file needs to be updated by running `" + 34 `mach test ${getCurrentTestFilePath()} --headless --setenv WEBCONSOLE_STUBS_UPDATE=true` + 35 "`"; 36 37 if (generatedStubs.size !== existingStubs.stubPackets.size) { 38 ok(false, FAILURE_MSG); 39 return; 40 } 41 42 let failed = false; 43 for (const [key, packet] of generatedStubs) { 44 const packetStr = getSerializedPacket(packet, { 45 sortKeys: true, 46 replaceActorIds: true, 47 }); 48 const existingPacketStr = getSerializedPacket( 49 existingStubs.rawPackets.get(key), 50 { sortKeys: true, replaceActorIds: true } 51 ); 52 is(packetStr, existingPacketStr, `"${key}" packet has expected value`); 53 failed = failed || packetStr !== existingPacketStr; 54 } 55 56 if (failed) { 57 ok(false, FAILURE_MSG); 58 } else { 59 ok(true, "Stubs are up to date"); 60 } 61 }); 62 63 async function generateCssMessageStubs() { 64 const stubs = new Map(); 65 66 const tab = await addTab(TEST_URI); 67 const commands = await createCommandsForTab(tab); 68 await commands.targetCommand.startListening(); 69 const resourceCommand = commands.resourceCommand; 70 71 // The resource command only supports a single call to watch/unwatch per 72 // instance, so we attach a unique watch callback, which will forward the 73 // resource to `handleErrorMessage`, dynamically updated for each command. 74 let handleCSSMessage = function () {}; 75 76 const onCSSMessageAvailable = resources => { 77 for (const resource of resources) { 78 handleCSSMessage(resource); 79 } 80 }; 81 82 await resourceCommand.watchResources([resourceCommand.TYPES.CSS_MESSAGE], { 83 onAvailable: onCSSMessageAvailable, 84 }); 85 86 for (const code of getCommands()) { 87 const received = new Promise(resolve => { 88 handleCSSMessage = function (packet) { 89 const key = packet.pageError.errorMessage; 90 stubs.set(key, getCleanedPacket(key, packet)); 91 resolve(); 92 }; 93 }); 94 95 await SpecialPowers.spawn( 96 gBrowser.selectedBrowser, 97 [code], 98 function (subCode) { 99 content.docShell.cssErrorReportingEnabled = true; 100 const style = content.document.createElement("style"); 101 style.append(content.document.createTextNode(subCode)); 102 content.document.body.append(style); 103 } 104 ); 105 106 await received; 107 } 108 109 resourceCommand.unwatchResources([resourceCommand.TYPES.CSS_MESSAGE], { 110 onAvailable: onCSSMessageAvailable, 111 }); 112 113 await commands.destroy(); 114 return stubs; 115 } 116 117 function getCommands() { 118 return [ 119 ` 120 p { 121 such-unknown-property: wow; 122 } 123 `, 124 ` 125 p { 126 padding-top: invalid value; 127 } 128 `, 129 ]; 130 }