helpers.js (5073B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const reduxActions = require("resource://devtools/client/webconsole/actions/index.js"); 7 const { 8 configureStore, 9 } = require("resource://devtools/client/webconsole/store.js"); 10 const { 11 IdGenerator, 12 } = require("resource://devtools/client/webconsole/utils/id-generator.js"); 13 const { 14 stubPackets, 15 } = require("resource://devtools/client/webconsole/test/node/fixtures/stubs/index.js"); 16 const { 17 getMutableMessagesById, 18 } = require("resource://devtools/client/webconsole/selectors/messages.js"); 19 const { 20 getPrefsService, 21 } = require("resource://devtools/client/webconsole/utils/prefs.js"); 22 const prefsService = getPrefsService({}); 23 const { PREFS } = require("resource://devtools/client/webconsole/constants.js"); 24 const Telemetry = require("resource://devtools/client/shared/test-helpers/jest-fixtures/telemetry.js"); 25 const { 26 getSerializedPacket, 27 parsePacketAndCreateFronts, 28 } = require("resource://devtools/client/webconsole/test/browser/stub-generator-helpers.js"); 29 30 /** 31 * Prepare actions for use in testing. 32 */ 33 function setupActions() { 34 // Some actions use dependency injection. This helps them avoid using state in 35 // a hard-to-test way. We need to inject stubbed versions of these dependencies. 36 const wrappedActions = Object.assign({}, reduxActions); 37 38 const idGenerator = new IdGenerator(); 39 wrappedActions.messagesAdd = packets => { 40 return reduxActions.messagesAdd(packets, idGenerator); 41 }; 42 43 return { 44 ...reduxActions, 45 messagesAdd: packets => reduxActions.messagesAdd(packets, idGenerator), 46 }; 47 } 48 49 /** 50 * Prepare the store for use in testing. 51 */ 52 function setupStore( 53 input = [], 54 { storeOptions = {}, actions, webConsoleUI } = {} 55 ) { 56 if (!webConsoleUI) { 57 webConsoleUI = getWebConsoleUiMock(); 58 } 59 const store = configureStore(webConsoleUI, { 60 ...storeOptions, 61 thunkArgs: { toolbox: {}, webConsoleUI }, 62 telemetry: new Telemetry(), 63 }); 64 65 // Add the messages from the input commands to the store. 66 const messagesAdd = actions ? actions.messagesAdd : reduxActions.messagesAdd; 67 store.dispatch(messagesAdd(input.map(cmd => stubPackets.get(cmd)))); 68 69 return store; 70 } 71 72 /** 73 * Create deep copy of given packet object. 74 */ 75 function clonePacket(packet) { 76 const strPacket = getSerializedPacket(packet); 77 return parsePacketAndCreateFronts(JSON.parse(strPacket)); 78 } 79 80 /** 81 * Return the message in the store at the given index. 82 * 83 * @param {object} state - The redux state of the console. 84 * @param {int} index - The index of the message in the map. 85 * @return {Message} - The message, or undefined if the index does not exists in the map. 86 */ 87 function getMessageAt(state, index) { 88 const messageMap = getMutableMessagesById(state); 89 return messageMap.get(state.messages.mutableMessagesOrder[index]); 90 } 91 92 /** 93 * Return the first message in the store. 94 * 95 * @param {object} state - The redux state of the console. 96 * @return {Message} - The last message, or undefined if there are no message in store. 97 */ 98 function getFirstMessage(state) { 99 return getMessageAt(state, 0); 100 } 101 102 /** 103 * Return the last message in the store. 104 * 105 * @param {object} state - The redux state of the console. 106 * @return {Message} - The last message, or undefined if there are no message in store. 107 */ 108 function getLastMessage(state) { 109 const lastIndex = state.messages.mutableMessagesOrder.length - 1; 110 return getMessageAt(state, lastIndex); 111 } 112 113 function getFiltersPrefs() { 114 return Object.values(PREFS.FILTER).reduce((res, pref) => { 115 res[pref] = prefsService.getBoolPref(pref); 116 return res; 117 }, {}); 118 } 119 120 function clearPrefs() { 121 [ 122 "devtools.hud.loglimit", 123 ...Object.values(PREFS.FILTER), 124 ...Object.values(PREFS.UI), 125 ].forEach(prefsService.clearUserPref); 126 } 127 128 function getPrivatePacket(key) { 129 const packet = clonePacket(stubPackets.get(key)); 130 packet.private = true; 131 if (packet.pageError) { 132 packet.pageError.private = true; 133 } 134 if (Object.getOwnPropertyNames(packet).includes("private")) { 135 packet.private = true; 136 } 137 return packet; 138 } 139 140 function getWebConsoleUiMock(hud) { 141 return { 142 emit: () => {}, 143 emitForTests: () => {}, 144 hud: { 145 commands: { 146 client: { 147 mainRoot: {}, 148 }, 149 objectCommand: { 150 releaseObjects: async () => {}, 151 }, 152 }, 153 ...hud, 154 }, 155 clearNetworkRequests: () => {}, 156 clearMessagesCache: () => {}, 157 inspectObjectActor: () => {}, 158 toolbox: {}, 159 watchCssMessages: () => {}, 160 }; 161 } 162 163 function formatErrorTextWithCausedBy(text) { 164 // The component text does not append new line character before 165 // the "Caused by" label, so add it here to make the assertions 166 // look more legible 167 return text.replace(/Caused by/g, "\nCaused by"); 168 } 169 170 module.exports = { 171 clearPrefs, 172 clonePacket, 173 formatErrorTextWithCausedBy, 174 getFiltersPrefs, 175 getFirstMessage, 176 getLastMessage, 177 getMessageAt, 178 getPrivatePacket, 179 getWebConsoleUiMock, 180 prefsService, 181 setupActions, 182 setupStore, 183 };