text: const { resolve } = require('path')
  
  const Arborist = require('@npmcli/arborist')
  const t = require('tap')
  const requireInject = require('require-inject')
  
  const redactCwd = (path) => {
    const normalizePath = p => p
      .replace(/\\+/g, '/')
      .replace(/\r\n/g, '\n')
    return normalizePath(path)
      .replace(new RegExp(normalizePath(process.cwd()), 'g'), '{CWD}')
  }
  
  t.cleanSnapshot = (str) => redactCwd(str)
  
  let reifyOutput
  const npm = {
    globalDir: null,
    prefix: null,
    flatOptions: {},
    config: {
      get () {
        return false
      },
      find () {},
    },
  }
  const printLinks = async (opts) => {
    let res = ''
    const arb = new Arborist(opts)
    const tree = await arb.loadActual()
    const linkedItems = [...tree.inventory.values()]
      .sort((a, b) => a.pkgid.localeCompare(b.pkgid))
    for (const item of linkedItems) {
      if (item.target)
        res += `${item.path} -> ${item.target.path}\n`
    }
    return res
  }
  
  const mocks = {
    '../../lib/utils/reify-output.js': () => reifyOutput(),
  }
  
  const Link = requireInject('../../lib/link.js', mocks)
  const link = new Link(npm)
  
  t.test('link to globalDir when in current working dir of pkg and no args', (t) => {
    t.plan(2)
  
    const testdir = t.testdir({
      'global-prefix': {
        lib: {
          node_modules: {
            a: {
              'package.json': JSON.stringify({
                name: 'a',
                version: '1.0.0',
              }),
            },
          },
        },
      },
      'test-pkg-link': {
        'package.json': JSON.stringify({
          name: 'test-pkg-link',
          version: '1.0.0',
        }),
      },
    })
    npm.globalDir = resolve(testdir, 'global-prefix', 'lib', 'node_modules')
    npm.prefix = resolve(testdir, 'test-pkg-link')
  
    reifyOutput = async () => {
      reifyOutput = undefined
  
      const links = await printLinks({
        path: resolve(npm.globalDir, '..'),
        global: true,
      })
  
      t.matchSnapshot(links, 'should create a global link to current pkg')
    }
  
    link.exec([], (err) => {
      t.ifError(err, 'should not error out')
    })
  })
  
  t.test('link global linked pkg to local nm when using args', (t) => {
    t.plan(2)
  
    const testdir = t.testdir({
      'global-prefix': {
        lib: {
          node_modules: {
            '@myscope': {
              foo: {
                'package.json': JSON.stringify({
                  name: '@myscope/foo',
                  version: '1.0.0',
                }),
              },
              bar: {
                'package.json': JSON.stringify({
                  name: '@myscope/bar',
                  version: '1.0.0',
                }),
              },
              linked: t.fixture('symlink', '../../../../scoped-linked'),
            },
            a: {
              'package.json': JSON.stringify({
                name: 'a',
                version: '1.0.0',
              }),
            },
            b: {
              'package.json': JSON.stringify({
                name: 'b',
                version: '1.0.0',
              }),
            },
            'test-pkg-link': t.fixture('symlink', '../../../test-pkg-link'),
          },
        },
      },
      'test-pkg-link': {
        'package.json': JSON.stringify({
          name: 'test-pkg-link',
          version: '1.0.0',
        }),
      },
      'link-me-too': {
        'package.json': JSON.stringify({
          name: 'link-me-too',
          version: '1.0.0',
        }),
      },
      'scoped-linked': {
        'package.json': JSON.stringify({
          name: '@myscope/linked',
          version: '1.0.0',
        }),
      },
      'my-project': {
        'package.json': JSON.stringify({
          name: 'my-project',
          version: '1.0.0',
          dependencies: {
            foo: '^1.0.0',
          },
        }),
        node_modules: {
          foo: {
            'package.json': JSON.stringify({
              name: 'foo',
              version: '1.0.0',
            }),
          },
        },
      },
    })
    npm.globalDir = resolve(testdir, 'global-prefix', 'lib', 'node_modules')
    npm.prefix = resolve(testdir, 'my-project')
  
    const _cwd = process.cwd()
    process.chdir(npm.prefix)
  
    reifyOutput = async () => {
      reifyOutput = undefined
      process.chdir(_cwd)
  
      const links = await printLinks({
        path: npm.prefix,
      })
  
      t.matchSnapshot(links, 'should create a local symlink to global pkg')
    }
  
    // installs examples for:
    // - test-pkg-link: pkg linked to globalDir from local fs
    // - @myscope/linked: scoped pkg linked to globalDir from local fs
    // - @myscope/bar: prev installed scoped package available in globalDir
    // - a: prev installed package available in globalDir
    // - file:./link-me-too: pkg that needs to be reified in globalDir first
    link.exec([
      'test-pkg-link',
      '@myscope/linked',
      '@myscope/bar',
      'a',
      'file:../link-me-too',
    ], (err) => {
      t.ifError(err, 'should not error out')
    })
  })
  
  t.test('link pkg already in global space', (t) => {
    t.plan(3)
  
    const testdir = t.testdir({
      'global-prefix': {
        lib: {
          node_modules: {
            '@myscope': {
              linked: t.fixture('symlink', '../../../../scoped-linked'),
            },
          },
        },
      },
      'scoped-linked': {
        'package.json': JSON.stringify({
          name: '@myscope/linked',
          version: '1.0.0',
        }),
      },
      'my-project': {
        'package.json': JSON.stringify({
          name: 'my-project',
          version: '1.0.0',
        }),
      },
    })
    npm.globalDir = resolve(testdir, 'global-prefix', 'lib', 'node_modules')
    npm.prefix = resolve(testdir, 'my-project')
  
    npm.config.find = () => 'default'
  
    const _cwd = process.cwd()
    process.chdir(npm.prefix)
  
    reifyOutput = async () => {
      reifyOutput = undefined
      process.chdir(_cwd)
      npm.config.find = () => null
  
      const links = await printLinks({
        path: npm.prefix,
      })
  
      t.equal(
        require(resolve(testdir, 'my-project', 'package.json')).dependencies,
        undefined,
        'should not save to package.json upon linking'
      )
  
      t.matchSnapshot(links, 'should create a local symlink to global pkg')
    }
  
    // installs examples for:
    // - test-pkg-link: pkg linked to globalDir from local fs
    // - @myscope/linked: scoped pkg linked to globalDir from local fs
    // - @myscope/bar: prev installed scoped package available in globalDir
    // - a: prev installed package available in globalDir
    // - file:./link-me-too: pkg that needs to be reified in globalDir first
    link.exec(['@myscope/linked'], (err) => {
      t.ifError(err, 'should not error out')
    })
  })
  
  t.test('link pkg already in global space when prefix is a symlink', (t) => {
    t.plan(3)
  
    const testdir = t.testdir({
      'global-prefix': t.fixture('symlink', './real-global-prefix'),
      'real-global-prefix': {
        lib: {
          node_modules: {
            '@myscope': {
              linked: t.fixture('symlink', '../../../../scoped-linked'),
            },
          },
        },
      },
      'scoped-linked': {
        'package.json': JSON.stringify({
          name: '@myscope/linked',
          version: '1.0.0',
        }),
      },
      'my-project': {
        'package.json': JSON.stringify({
          name: 'my-project',
          version: '1.0.0',
        }),
      },
    })
    npm.globalDir = resolve(testdir, 'global-prefix', 'lib', 'node_modules')
    npm.prefix = resolve(testdir, 'my-project')
  
    npm.config.find = () => 'default'
  
    const _cwd = process.cwd()
    process.chdir(npm.prefix)
  
    reifyOutput = async () => {
      reifyOutput = undefined
      process.chdir(_cwd)
      npm.config.find = () => null
  
      const links = await printLinks({
        path: npm.prefix,
      })
  
      t.equal(
        require(resolve(testdir, 'my-project', 'package.json')).dependencies,
        undefined,
        'should not save to package.json upon linking'
      )
  
      t.matchSnapshot(links, 'should create a local symlink to global pkg')
    }
  
    link.exec(['@myscope/linked'], (err) => {
      t.ifError(err, 'should not error out')
    })
  })
  
  t.test('completion', async t => {
    const testdir = t.testdir({
      'global-prefix': {
        lib: {
          node_modules: {
            foo: {},
            bar: {},
            lorem: {},
            ipsum: {},
          },
        },
      },
    })
    npm.globalDir = resolve(testdir, 'global-prefix', 'lib', 'node_modules')
  
    const words = await link.completion({})
    t.deepEqual(
      words,
      ['bar', 'foo', 'ipsum', 'lorem'],
      'should list all package names available in globalDir'
    )
    t.end()
  })
  
  t.test('--global option', t => {
    const _config = npm.config
    npm.config = { get () {
      return true
    } }
    link.exec([], (err) => {
      npm.config = _config
      t.match(
        err.message,
        /link should never be --global/,
        'should throw an useful error'
      )
      t.end()
    })
  })
  