11cb0ef41Sopenharmony_ciconst t = require('tap')
21cb0ef41Sopenharmony_ciconst tmock = require('../../fixtures/tmock')
31cb0ef41Sopenharmony_ciconst mockNpm = require('../../fixtures/mock-npm')
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ciconst mockOpenUrl = async (t, args, { openerResult, ...config } = {}) => {
61cb0ef41Sopenharmony_ci  let openerUrl = null
71cb0ef41Sopenharmony_ci  let openerOpts = null
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci  const open = async (url, options) => {
101cb0ef41Sopenharmony_ci    openerUrl = url
111cb0ef41Sopenharmony_ci    openerOpts = options
121cb0ef41Sopenharmony_ci    if (openerResult) {
131cb0ef41Sopenharmony_ci      throw openerResult
141cb0ef41Sopenharmony_ci    }
151cb0ef41Sopenharmony_ci  }
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ci  const mock = await mockNpm(t, { config })
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ci  const openUrl = tmock(t, '{LIB}/utils/open-url.js', {
201cb0ef41Sopenharmony_ci    '@npmcli/promise-spawn': { open },
211cb0ef41Sopenharmony_ci  })
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ci  const openWithNpm = (...a) => openUrl(mock.npm, ...a)
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci  if (args) {
261cb0ef41Sopenharmony_ci    await openWithNpm(...args)
271cb0ef41Sopenharmony_ci  }
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci  return {
301cb0ef41Sopenharmony_ci    ...mock,
311cb0ef41Sopenharmony_ci    openUrl: openWithNpm,
321cb0ef41Sopenharmony_ci    openerUrl: () => openerUrl,
331cb0ef41Sopenharmony_ci    openerOpts: () => openerOpts,
341cb0ef41Sopenharmony_ci  }
351cb0ef41Sopenharmony_ci}
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_cit.test('opens a url', async t => {
381cb0ef41Sopenharmony_ci  const { openerUrl, openerOpts, joinedOutput } = await mockOpenUrl(t,
391cb0ef41Sopenharmony_ci    ['https://www.npmjs.com', 'npm home'])
401cb0ef41Sopenharmony_ci  t.equal(openerUrl(), 'https://www.npmjs.com', 'opened the given url')
411cb0ef41Sopenharmony_ci  t.same(openerOpts(), { command: null }, 'passed command as null (the default)')
421cb0ef41Sopenharmony_ci  t.same(joinedOutput(), '', 'printed no output')
431cb0ef41Sopenharmony_ci})
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_cit.test('returns error for non-https url', async t => {
461cb0ef41Sopenharmony_ci  const { openUrl, openerUrl, openerOpts, joinedOutput } = await mockOpenUrl(t)
471cb0ef41Sopenharmony_ci  await t.rejects(
481cb0ef41Sopenharmony_ci    openUrl('ftp://www.npmjs.com', 'npm home'),
491cb0ef41Sopenharmony_ci    /Invalid URL/,
501cb0ef41Sopenharmony_ci    'got the correct error'
511cb0ef41Sopenharmony_ci  )
521cb0ef41Sopenharmony_ci  t.equal(openerUrl(), null, 'did not open')
531cb0ef41Sopenharmony_ci  t.same(openerOpts(), null, 'did not open')
541cb0ef41Sopenharmony_ci  t.same(joinedOutput(), '', 'printed no output')
551cb0ef41Sopenharmony_ci})
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_cit.test('returns error for file url', async t => {
581cb0ef41Sopenharmony_ci  const { openUrl, openerUrl, openerOpts, joinedOutput } = await mockOpenUrl(t)
591cb0ef41Sopenharmony_ci  await t.rejects(
601cb0ef41Sopenharmony_ci    openUrl('file:///usr/local/bin/ls', 'npm home'),
611cb0ef41Sopenharmony_ci    /Invalid URL/,
621cb0ef41Sopenharmony_ci    'got the correct error'
631cb0ef41Sopenharmony_ci  )
641cb0ef41Sopenharmony_ci  t.equal(openerUrl(), null, 'did not open')
651cb0ef41Sopenharmony_ci  t.same(openerOpts(), null, 'did not open')
661cb0ef41Sopenharmony_ci  t.same(joinedOutput(), '', 'printed no output')
671cb0ef41Sopenharmony_ci})
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_cit.test('file url allowed if explicitly asked for', async t => {
701cb0ef41Sopenharmony_ci  const { openerUrl, openerOpts, joinedOutput } = await mockOpenUrl(t,
711cb0ef41Sopenharmony_ci    ['file:///man/page/npm-install', 'npm home', true])
721cb0ef41Sopenharmony_ci  t.equal(openerUrl(), 'file:///man/page/npm-install', 'opened the given url')
731cb0ef41Sopenharmony_ci  t.same(openerOpts(), { command: null }, 'passed command as null (the default)')
741cb0ef41Sopenharmony_ci  t.same(joinedOutput(), '', 'printed no output')
751cb0ef41Sopenharmony_ci})
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_cit.test('returns error for non-parseable url', async t => {
781cb0ef41Sopenharmony_ci  const { openUrl, openerUrl, openerOpts, joinedOutput } = await mockOpenUrl(t)
791cb0ef41Sopenharmony_ci  await t.rejects(
801cb0ef41Sopenharmony_ci    openUrl('git+ssh://user@host:repo.git', 'npm home'),
811cb0ef41Sopenharmony_ci    /Invalid URL/,
821cb0ef41Sopenharmony_ci    'got the correct error'
831cb0ef41Sopenharmony_ci  )
841cb0ef41Sopenharmony_ci  t.equal(openerUrl(), null, 'did not open')
851cb0ef41Sopenharmony_ci  t.same(openerOpts(), null, 'did not open')
861cb0ef41Sopenharmony_ci  t.same(joinedOutput(), '', 'printed no output')
871cb0ef41Sopenharmony_ci})
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_cit.test('encodes non-URL-safe characters in url provided', async t => {
901cb0ef41Sopenharmony_ci  const { openerUrl, openerOpts, joinedOutput } = await mockOpenUrl(t,
911cb0ef41Sopenharmony_ci    ['https://www.npmjs.com/|cat', 'npm home'])
921cb0ef41Sopenharmony_ci  t.equal(openerUrl(), 'https://www.npmjs.com/%7Ccat', 'opened the encoded url')
931cb0ef41Sopenharmony_ci  t.same(openerOpts(), { command: null }, 'passed command as null (the default)')
941cb0ef41Sopenharmony_ci  t.same(joinedOutput(), '', 'printed no output')
951cb0ef41Sopenharmony_ci})
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_cit.test('opens a url with the given browser', async t => {
981cb0ef41Sopenharmony_ci  const { openerUrl, openerOpts, joinedOutput } = await mockOpenUrl(t,
991cb0ef41Sopenharmony_ci    ['https://www.npmjs.com', 'npm home'], { browser: 'chrome' })
1001cb0ef41Sopenharmony_ci  t.equal(openerUrl(), 'https://www.npmjs.com', 'opened the given url')
1011cb0ef41Sopenharmony_ci  // FIXME: browser string is parsed as a boolean in config layer
1021cb0ef41Sopenharmony_ci  // this is a bug that should be fixed or the config should not allow it
1031cb0ef41Sopenharmony_ci  t.same(openerOpts(), { command: null }, 'passed the given browser as command')
1041cb0ef41Sopenharmony_ci  t.same(joinedOutput(), '', 'printed no output')
1051cb0ef41Sopenharmony_ci})
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_cit.test('prints where to go when browser is disabled', async t => {
1081cb0ef41Sopenharmony_ci  const { openerUrl, openerOpts, joinedOutput } = await mockOpenUrl(t,
1091cb0ef41Sopenharmony_ci    ['https://www.npmjs.com', 'npm home'], { browser: false })
1101cb0ef41Sopenharmony_ci  t.equal(openerUrl(), null, 'did not open')
1111cb0ef41Sopenharmony_ci  t.same(openerOpts(), null, 'did not open')
1121cb0ef41Sopenharmony_ci  t.matchSnapshot(joinedOutput(), 'printed expected message')
1131cb0ef41Sopenharmony_ci})
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_cit.test('prints where to go when browser is disabled and json is enabled', async t => {
1161cb0ef41Sopenharmony_ci  const { openerUrl, openerOpts, joinedOutput } = await mockOpenUrl(t,
1171cb0ef41Sopenharmony_ci    ['https://www.npmjs.com', 'npm home'], { browser: false, json: true })
1181cb0ef41Sopenharmony_ci  t.equal(openerUrl(), null, 'did not open')
1191cb0ef41Sopenharmony_ci  t.same(openerOpts(), null, 'did not open')
1201cb0ef41Sopenharmony_ci  t.matchSnapshot(joinedOutput(), 'printed expected message')
1211cb0ef41Sopenharmony_ci})
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_cit.test('prints where to go when given browser does not exist', async t => {
1241cb0ef41Sopenharmony_ci  const { openerUrl, openerOpts, joinedOutput } = await mockOpenUrl(t,
1251cb0ef41Sopenharmony_ci    ['https://www.npmjs.com', 'npm home'],
1261cb0ef41Sopenharmony_ci    {
1271cb0ef41Sopenharmony_ci      openerResult: Object.assign(new Error('failed'), { code: 127 }),
1281cb0ef41Sopenharmony_ci    }
1291cb0ef41Sopenharmony_ci  )
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  t.equal(openerUrl(), 'https://www.npmjs.com', 'tried to open the correct url')
1321cb0ef41Sopenharmony_ci  t.same(openerOpts(), { command: null }, 'tried to use the correct browser')
1331cb0ef41Sopenharmony_ci  t.matchSnapshot(joinedOutput(), 'printed expected message')
1341cb0ef41Sopenharmony_ci})
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_cit.test('handles unknown opener error', async t => {
1371cb0ef41Sopenharmony_ci  const { openUrl } = await mockOpenUrl(t, null, {
1381cb0ef41Sopenharmony_ci    browser: 'firefox',
1391cb0ef41Sopenharmony_ci    openerResult: Object.assign(new Error('failed'), { code: 'ENOBRIAN' }),
1401cb0ef41Sopenharmony_ci  })
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci  await t.rejects(openUrl('https://www.npmjs.com', 'npm home'), 'failed', 'got the correct error')
1431cb0ef41Sopenharmony_ci})
144