11cb0ef41Sopenharmony_ciconst t = require('tap')
21cb0ef41Sopenharmony_ciconst log = require('../../../lib/utils/log-shim')
31cb0ef41Sopenharmony_ciconst mockLogs = require('../../fixtures/mock-logs')
41cb0ef41Sopenharmony_ciconst mockGlobals = require('@npmcli/mock-globals')
51cb0ef41Sopenharmony_ciconst tmock = require('../../fixtures/tmock')
61cb0ef41Sopenharmony_ciconst util = require('util')
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ciconst mockDisplay = (t, mocks) => {
91cb0ef41Sopenharmony_ci  const { logs, logMocks } = mockLogs(mocks)
101cb0ef41Sopenharmony_ci  const Display = tmock(t, '{LIB}/utils/display', {
111cb0ef41Sopenharmony_ci    ...mocks,
121cb0ef41Sopenharmony_ci    ...logMocks,
131cb0ef41Sopenharmony_ci  })
141cb0ef41Sopenharmony_ci  const display = new Display()
151cb0ef41Sopenharmony_ci  t.teardown(() => display.off())
161cb0ef41Sopenharmony_ci  return { display, logs }
171cb0ef41Sopenharmony_ci}
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_cit.test('setup', async (t) => {
201cb0ef41Sopenharmony_ci  const { display } = mockDisplay(t)
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci  display.load({ timing: true, loglevel: 'notice' })
231cb0ef41Sopenharmony_ci  t.equal(log.level, 'notice')
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci  display.load({ timing: false, loglevel: 'notice' })
261cb0ef41Sopenharmony_ci  t.equal(log.level, 'notice')
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci  display.load({ color: true })
291cb0ef41Sopenharmony_ci  t.equal(log.useColor(), true)
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci  display.load({ unicode: true })
321cb0ef41Sopenharmony_ci  t.equal(log.gauge._theme.hasUnicode, true)
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci  display.load({ unicode: false })
351cb0ef41Sopenharmony_ci  t.equal(log.gauge._theme.hasUnicode, false)
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci  mockGlobals(t, { 'process.stderr.isTTY': true })
381cb0ef41Sopenharmony_ci  display.load({ progress: true })
391cb0ef41Sopenharmony_ci  t.equal(log.progressEnabled, true)
401cb0ef41Sopenharmony_ci})
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_cit.test('can log cleanly', async (t) => {
431cb0ef41Sopenharmony_ci  const explains = []
441cb0ef41Sopenharmony_ci  const { display, logs } = mockDisplay(t, {
451cb0ef41Sopenharmony_ci    npmlog: {
461cb0ef41Sopenharmony_ci      error: (...args) => logs.push(['error', ...args]),
471cb0ef41Sopenharmony_ci      warn: (...args) => logs.push(['warn', ...args]),
481cb0ef41Sopenharmony_ci    },
491cb0ef41Sopenharmony_ci    '{LIB}/utils/explain-eresolve.js': {
501cb0ef41Sopenharmony_ci      explain: (...args) => {
511cb0ef41Sopenharmony_ci        explains.push(args)
521cb0ef41Sopenharmony_ci        return 'explanation'
531cb0ef41Sopenharmony_ci      },
541cb0ef41Sopenharmony_ci    },
551cb0ef41Sopenharmony_ci  })
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  display.log('error', 'test\x00message')
581cb0ef41Sopenharmony_ci  t.match(logs.error, [['test^@message']])
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  display.log('warn', 'ERESOLVE', 'hello', { some: 'object' })
611cb0ef41Sopenharmony_ci  t.match(logs.warn, [['ERESOLVE', 'hello']])
621cb0ef41Sopenharmony_ci  t.match(explains, [[{ some: 'object' }, null, 2]])
631cb0ef41Sopenharmony_ci})
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_cit.test('handles log throwing', async (t) => {
661cb0ef41Sopenharmony_ci  const errors = []
671cb0ef41Sopenharmony_ci  mockGlobals(t, {
681cb0ef41Sopenharmony_ci    'console.error': (...args) => errors.push(args),
691cb0ef41Sopenharmony_ci  })
701cb0ef41Sopenharmony_ci  const { display } = mockDisplay(t, {
711cb0ef41Sopenharmony_ci    npmlog: {
721cb0ef41Sopenharmony_ci      verbose: () => {
731cb0ef41Sopenharmony_ci        throw new Error('verbose')
741cb0ef41Sopenharmony_ci      },
751cb0ef41Sopenharmony_ci    },
761cb0ef41Sopenharmony_ci    '{LIB}/utils/explain-eresolve.js': {
771cb0ef41Sopenharmony_ci      explain: () => {
781cb0ef41Sopenharmony_ci        throw new Error('explain')
791cb0ef41Sopenharmony_ci      },
801cb0ef41Sopenharmony_ci    },
811cb0ef41Sopenharmony_ci  })
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci  display.log('warn', 'ERESOLVE', 'hello', { some: 'object' })
841cb0ef41Sopenharmony_ci  t.match(errors, [
851cb0ef41Sopenharmony_ci    [/attempt to log .* crashed/, Error('explain'), Error('verbose')],
861cb0ef41Sopenharmony_ci  ])
871cb0ef41Sopenharmony_ci})
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ciclass CustomObj {
901cb0ef41Sopenharmony_ci  [util.inspect.custom] () {
911cb0ef41Sopenharmony_ci    return this.inspected
921cb0ef41Sopenharmony_ci  }
931cb0ef41Sopenharmony_ci}
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_cit.test('Display.clean', async (t) => {
961cb0ef41Sopenharmony_ci  const Display = require('../../../lib/utils/display')
971cb0ef41Sopenharmony_ci  const customNaN = new CustomObj()
981cb0ef41Sopenharmony_ci  const customNull = new CustomObj()
991cb0ef41Sopenharmony_ci  const customNumber = new CustomObj()
1001cb0ef41Sopenharmony_ci  const customObject = new CustomObj()
1011cb0ef41Sopenharmony_ci  const customString = new CustomObj()
1021cb0ef41Sopenharmony_ci  const customUndefined = new CustomObj()
1031cb0ef41Sopenharmony_ci  customNaN.inspected = NaN
1041cb0ef41Sopenharmony_ci  customNull.inspected = null
1051cb0ef41Sopenharmony_ci  customNumber.inspected = 477
1061cb0ef41Sopenharmony_ci  customObject.inspected = { custom: 'rend\x00ering' }
1071cb0ef41Sopenharmony_ci  customString.inspected = 'custom\x00rendering'
1081cb0ef41Sopenharmony_ci  customUndefined.inspected = undefined
1091cb0ef41Sopenharmony_ci  t.test('strings', async (t) => {
1101cb0ef41Sopenharmony_ci    const tests = [
1111cb0ef41Sopenharmony_ci      [477, '477'],
1121cb0ef41Sopenharmony_ci      [null, 'null'],
1131cb0ef41Sopenharmony_ci      [NaN, 'NaN'],
1141cb0ef41Sopenharmony_ci      [true, 'true'],
1151cb0ef41Sopenharmony_ci      [undefined, 'undefined'],
1161cb0ef41Sopenharmony_ci      ['�', '�'],
1171cb0ef41Sopenharmony_ci      // Cover the bounds of each range and a few characters from inside each range
1181cb0ef41Sopenharmony_ci      // \x00 through \x1f
1191cb0ef41Sopenharmony_ci      ['hello\x00world', 'hello^@world'],
1201cb0ef41Sopenharmony_ci      ['hello\x07world', 'hello^Gworld'],
1211cb0ef41Sopenharmony_ci      ['hello\x1bworld', 'hello^[world'],
1221cb0ef41Sopenharmony_ci      ['hello\x1eworld', 'hello^^world'],
1231cb0ef41Sopenharmony_ci      ['hello\x1fworld', 'hello^_world'],
1241cb0ef41Sopenharmony_ci      // \x7f is C0
1251cb0ef41Sopenharmony_ci      ['hello\x7fworld', 'hello^?world'],
1261cb0ef41Sopenharmony_ci      // \x80 through \x9f
1271cb0ef41Sopenharmony_ci      ['hello\x80world', 'hello^@world'],
1281cb0ef41Sopenharmony_ci      ['hello\x87world', 'hello^Gworld'],
1291cb0ef41Sopenharmony_ci      ['hello\x9eworld', 'hello^^world'],
1301cb0ef41Sopenharmony_ci      ['hello\x9fworld', 'hello^_world'],
1311cb0ef41Sopenharmony_ci      // Allowed C0
1321cb0ef41Sopenharmony_ci      ['hello\tworld', 'hello\tworld'],
1331cb0ef41Sopenharmony_ci      ['hello\nworld', 'hello\nworld'],
1341cb0ef41Sopenharmony_ci      ['hello\vworld', 'hello\vworld'],
1351cb0ef41Sopenharmony_ci      ['hello\rworld', 'hello\rworld'],
1361cb0ef41Sopenharmony_ci      // Allowed SGR
1371cb0ef41Sopenharmony_ci      ['hello\x1b[38;5;254mworld', 'hello\x1b[38;5;254mworld'],
1381cb0ef41Sopenharmony_ci      ['hello\x1b[mworld', 'hello\x1b[mworld'],
1391cb0ef41Sopenharmony_ci      // Unallowed CSI / OSC
1401cb0ef41Sopenharmony_ci      ['hello\x1b[2Aworld', 'hello^[[2Aworld'],
1411cb0ef41Sopenharmony_ci      ['hello\x9b[2Aworld', 'hello^[[2Aworld'],
1421cb0ef41Sopenharmony_ci      ['hello\x9decho goodbye\x9cworld', 'hello^]echo goodbye^\\world'],
1431cb0ef41Sopenharmony_ci      // This is done twice to ensure we define inspect.custom as writable
1441cb0ef41Sopenharmony_ci      [{ test: 'object' }, "{ test: 'object' }"],
1451cb0ef41Sopenharmony_ci      [{ test: 'object' }, "{ test: 'object' }"],
1461cb0ef41Sopenharmony_ci      // Make sure custom util.inspect doesn't bypass our cleaning
1471cb0ef41Sopenharmony_ci      [customNaN, 'NaN'],
1481cb0ef41Sopenharmony_ci      [customNull, 'null'],
1491cb0ef41Sopenharmony_ci      [customNumber, '477'],
1501cb0ef41Sopenharmony_ci      [customObject, "{ custom: 'rend\\x00ering' }"],
1511cb0ef41Sopenharmony_ci      [customString, 'custom^@rendering'],
1521cb0ef41Sopenharmony_ci      [customUndefined, 'undefined'],
1531cb0ef41Sopenharmony_ci      // UTF-16 form of 8-bit C1
1541cb0ef41Sopenharmony_ci      ['hello\xc2\x9bworld', 'hello\xc2^[world'],
1551cb0ef41Sopenharmony_ci    ]
1561cb0ef41Sopenharmony_ci    for (const [dirty, clean] of tests) {
1571cb0ef41Sopenharmony_ci      const cleaned = Display.clean(dirty)
1581cb0ef41Sopenharmony_ci      t.equal(util.format(cleaned), clean)
1591cb0ef41Sopenharmony_ci    }
1601cb0ef41Sopenharmony_ci  })
1611cb0ef41Sopenharmony_ci})
162