11cb0ef41Sopenharmony_ci 21cb0ef41Sopenharmony_ciconst NPMLOG = require('npmlog') 31cb0ef41Sopenharmony_ciconst { LEVELS } = require('proc-log') 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ciconst npmEmitLog = NPMLOG.emitLog.bind(NPMLOG) 61cb0ef41Sopenharmony_ciconst npmLog = NPMLOG.log.bind(NPMLOG) 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ciconst merge = (...objs) => objs.reduce((acc, obj) => ({ ...acc, ...obj })) 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ciconst mockLogs = (otherMocks = {}) => { 111cb0ef41Sopenharmony_ci // Return mocks as an array with getters for each level 121cb0ef41Sopenharmony_ci // that return an array of logged properties with the 131cb0ef41Sopenharmony_ci // level removed. This is for convenience throughout tests 141cb0ef41Sopenharmony_ci const logs = Object.defineProperties( 151cb0ef41Sopenharmony_ci [], 161cb0ef41Sopenharmony_ci ['timing', ...LEVELS].reduce((acc, level) => { 171cb0ef41Sopenharmony_ci acc[level] = { 181cb0ef41Sopenharmony_ci get () { 191cb0ef41Sopenharmony_ci return this 201cb0ef41Sopenharmony_ci .filter(([l]) => level === l) 211cb0ef41Sopenharmony_ci .map(([l, ...args]) => args) 221cb0ef41Sopenharmony_ci }, 231cb0ef41Sopenharmony_ci } 241cb0ef41Sopenharmony_ci return acc 251cb0ef41Sopenharmony_ci }, {}) 261cb0ef41Sopenharmony_ci ) 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci // the above logs array is anything logged and it not filtered by level. 291cb0ef41Sopenharmony_ci // this display array is filtered and will not include items that 301cb0ef41Sopenharmony_ci // would not be shown in the terminal 311cb0ef41Sopenharmony_ci const display = Object.defineProperties( 321cb0ef41Sopenharmony_ci [], 331cb0ef41Sopenharmony_ci ['timing', ...LEVELS].reduce((acc, level) => { 341cb0ef41Sopenharmony_ci acc[level] = { 351cb0ef41Sopenharmony_ci get () { 361cb0ef41Sopenharmony_ci return this 371cb0ef41Sopenharmony_ci .filter(([l]) => level === l) 381cb0ef41Sopenharmony_ci .map(([l, ...args]) => args) 391cb0ef41Sopenharmony_ci }, 401cb0ef41Sopenharmony_ci } 411cb0ef41Sopenharmony_ci return acc 421cb0ef41Sopenharmony_ci }, {}) 431cb0ef41Sopenharmony_ci ) 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ci const npmLogBuffer = [] 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci // This returns an object with mocked versions of all necessary 481cb0ef41Sopenharmony_ci // logging modules. It mocks them with methods that add logs 491cb0ef41Sopenharmony_ci // to an array which it also returns. The reason it also returns 501cb0ef41Sopenharmony_ci // the mocks is that in tests the same instance of these mocks 511cb0ef41Sopenharmony_ci // should be passed to multiple calls to t.mock. 521cb0ef41Sopenharmony_ci // XXX: this is messy and fragile and should be removed in favor 531cb0ef41Sopenharmony_ci // of some other way to collect and filter logs across all tests 541cb0ef41Sopenharmony_ci const logMocks = { 551cb0ef41Sopenharmony_ci 'proc-log': merge( 561cb0ef41Sopenharmony_ci { LEVELS }, 571cb0ef41Sopenharmony_ci LEVELS.reduce((acc, l) => { 581cb0ef41Sopenharmony_ci acc[l] = (...args) => { 591cb0ef41Sopenharmony_ci // Re-emit log item for since the log file listens on these 601cb0ef41Sopenharmony_ci process.emit('log', l, ...args) 611cb0ef41Sopenharmony_ci // Dont add pause/resume events to the logs. Those aren't displayed 621cb0ef41Sopenharmony_ci // and emitting them is tested in the display layer 631cb0ef41Sopenharmony_ci if (l !== 'pause' && l !== 'resume') { 641cb0ef41Sopenharmony_ci logs.push([l, ...args]) 651cb0ef41Sopenharmony_ci } 661cb0ef41Sopenharmony_ci } 671cb0ef41Sopenharmony_ci return acc 681cb0ef41Sopenharmony_ci }, {}), 691cb0ef41Sopenharmony_ci otherMocks['proc-log'] 701cb0ef41Sopenharmony_ci ), 711cb0ef41Sopenharmony_ci // Object.assign is important here because we need to assign 721cb0ef41Sopenharmony_ci // mocked properties directly to npmlog and then mock with that 731cb0ef41Sopenharmony_ci // object. This is necessary so tests can still directly set 741cb0ef41Sopenharmony_ci // `log.level = 'silent'` anywhere in the test and have that 751cb0ef41Sopenharmony_ci // that reflected in the npmlog singleton. 761cb0ef41Sopenharmony_ci // XXX: remove with npmlog 771cb0ef41Sopenharmony_ci npmlog: Object.assign(NPMLOG, merge( 781cb0ef41Sopenharmony_ci { 791cb0ef41Sopenharmony_ci log: (level, ...args) => { 801cb0ef41Sopenharmony_ci // timing does not exist on proclog, so if it got logged 811cb0ef41Sopenharmony_ci // with npmlog we need to push it to our logs 821cb0ef41Sopenharmony_ci if (level === 'timing') { 831cb0ef41Sopenharmony_ci logs.push([level, ...args]) 841cb0ef41Sopenharmony_ci } 851cb0ef41Sopenharmony_ci npmLog(level, ...args) 861cb0ef41Sopenharmony_ci }, 871cb0ef41Sopenharmony_ci write: (msg) => { 881cb0ef41Sopenharmony_ci // npmlog.write is what outputs to the terminal. 891cb0ef41Sopenharmony_ci // it writes in chunks so we push each chunk to an 901cb0ef41Sopenharmony_ci // array that we will log and zero out 911cb0ef41Sopenharmony_ci npmLogBuffer.push(msg) 921cb0ef41Sopenharmony_ci }, 931cb0ef41Sopenharmony_ci emitLog: (m) => { 941cb0ef41Sopenharmony_ci // this calls the original emitLog method 951cb0ef41Sopenharmony_ci // which will filter based on loglevel 961cb0ef41Sopenharmony_ci npmEmitLog(m) 971cb0ef41Sopenharmony_ci // if anything was logged then we push to our display 981cb0ef41Sopenharmony_ci // array which we can assert against in tests 991cb0ef41Sopenharmony_ci if (npmLogBuffer.length) { 1001cb0ef41Sopenharmony_ci // first two parts are 'npm' and a single space 1011cb0ef41Sopenharmony_ci display.push(npmLogBuffer.slice(2)) 1021cb0ef41Sopenharmony_ci } 1031cb0ef41Sopenharmony_ci npmLogBuffer.length = 0 1041cb0ef41Sopenharmony_ci }, 1051cb0ef41Sopenharmony_ci newItem: () => { 1061cb0ef41Sopenharmony_ci return { 1071cb0ef41Sopenharmony_ci info: (...p) => { 1081cb0ef41Sopenharmony_ci logs.push(['info', ...p]) 1091cb0ef41Sopenharmony_ci }, 1101cb0ef41Sopenharmony_ci warn: (...p) => { 1111cb0ef41Sopenharmony_ci logs.push(['warn', ...p]) 1121cb0ef41Sopenharmony_ci }, 1131cb0ef41Sopenharmony_ci error: (...p) => { 1141cb0ef41Sopenharmony_ci logs.push(['error', ...p]) 1151cb0ef41Sopenharmony_ci }, 1161cb0ef41Sopenharmony_ci silly: (...p) => { 1171cb0ef41Sopenharmony_ci logs.push(['silly', ...p]) 1181cb0ef41Sopenharmony_ci }, 1191cb0ef41Sopenharmony_ci completeWork: () => {}, 1201cb0ef41Sopenharmony_ci finish: () => {}, 1211cb0ef41Sopenharmony_ci } 1221cb0ef41Sopenharmony_ci }, 1231cb0ef41Sopenharmony_ci }, 1241cb0ef41Sopenharmony_ci otherMocks.npmlog 1251cb0ef41Sopenharmony_ci )), 1261cb0ef41Sopenharmony_ci } 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ci return { logs, logMocks, display } 1291cb0ef41Sopenharmony_ci} 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_cimodule.exports = mockLogs 132