11cb0ef41Sopenharmony_ciconst t = require('tap')
21cb0ef41Sopenharmony_ciconst { load: _loadMockNpm } = require('../../fixtures/mock-npm')
31cb0ef41Sopenharmony_ciconst MockRegistry = require('@npmcli/mock-registry')
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ciconst path = require('path')
61cb0ef41Sopenharmony_ciconst fs = require('fs')
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci// t.cleanSnapshot = str => str.replace(/ in [0-9ms]+/g, ' in {TIME}')
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ciconst loadMockNpm = async (t, opts) => {
111cb0ef41Sopenharmony_ci  const mock = await _loadMockNpm(t, opts)
121cb0ef41Sopenharmony_ci  const registry = new MockRegistry({
131cb0ef41Sopenharmony_ci    tap: t,
141cb0ef41Sopenharmony_ci    registry: mock.npm.config.get('registry'),
151cb0ef41Sopenharmony_ci  })
161cb0ef41Sopenharmony_ci  return { registry, ...mock }
171cb0ef41Sopenharmony_ci}
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ciconst packageJson = {
201cb0ef41Sopenharmony_ci  name: 'test-package',
211cb0ef41Sopenharmony_ci  version: '1.0.0',
221cb0ef41Sopenharmony_ci  dependencies: {
231cb0ef41Sopenharmony_ci    abbrev: '^1.0.0',
241cb0ef41Sopenharmony_ci  },
251cb0ef41Sopenharmony_ci}
261cb0ef41Sopenharmony_ciconst packageLock = {
271cb0ef41Sopenharmony_ci  name: 'test-package',
281cb0ef41Sopenharmony_ci  version: '1.0.0',
291cb0ef41Sopenharmony_ci  lockfileVersion: 2,
301cb0ef41Sopenharmony_ci  requires: true,
311cb0ef41Sopenharmony_ci  packages: {
321cb0ef41Sopenharmony_ci    '': {
331cb0ef41Sopenharmony_ci      name: 'test-package',
341cb0ef41Sopenharmony_ci      version: '1.0.0',
351cb0ef41Sopenharmony_ci      dependencies: {
361cb0ef41Sopenharmony_ci        abbrev: '^1.0.0',
371cb0ef41Sopenharmony_ci      },
381cb0ef41Sopenharmony_ci    },
391cb0ef41Sopenharmony_ci    'node_modules/abbrev': {
401cb0ef41Sopenharmony_ci      version: '1.0.0',
411cb0ef41Sopenharmony_ci      resolved: 'https://registry.npmjs.org/abbrev/-/abbrev-1.0.0.tgz',
421cb0ef41Sopenharmony_ci      // integrity changes w/ each test cause the path is different?
431cb0ef41Sopenharmony_ci    },
441cb0ef41Sopenharmony_ci  },
451cb0ef41Sopenharmony_ci  dependencies: {
461cb0ef41Sopenharmony_ci    abbrev: {
471cb0ef41Sopenharmony_ci      version: '1.0.0',
481cb0ef41Sopenharmony_ci      resolved: 'https://registry.npmjs.org/abbrev/-/abbrev-1.0.0.tgz',
491cb0ef41Sopenharmony_ci      // integrity changes w/ each test cause the path is different?
501cb0ef41Sopenharmony_ci    },
511cb0ef41Sopenharmony_ci  },
521cb0ef41Sopenharmony_ci}
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ciconst abbrev = {
551cb0ef41Sopenharmony_ci  'package.json': '{"name": "abbrev", "version": "1.0.0"}',
561cb0ef41Sopenharmony_ci  test: 'test file',
571cb0ef41Sopenharmony_ci}
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_cit.test('reifies, audits, removes node_modules', async t => {
601cb0ef41Sopenharmony_ci  const { npm, joinedOutput, registry } = await loadMockNpm(t, {
611cb0ef41Sopenharmony_ci    prefixDir: {
621cb0ef41Sopenharmony_ci      abbrev: abbrev,
631cb0ef41Sopenharmony_ci      'package.json': JSON.stringify(packageJson),
641cb0ef41Sopenharmony_ci      'package-lock.json': JSON.stringify(packageLock),
651cb0ef41Sopenharmony_ci      node_modules: { test: 'test file that will be removed' },
661cb0ef41Sopenharmony_ci    },
671cb0ef41Sopenharmony_ci  })
681cb0ef41Sopenharmony_ci  const manifest = registry.manifest({ name: 'abbrev' })
691cb0ef41Sopenharmony_ci  await registry.tarball({
701cb0ef41Sopenharmony_ci    manifest: manifest.versions['1.0.0'],
711cb0ef41Sopenharmony_ci    tarball: path.join(npm.prefix, 'abbrev'),
721cb0ef41Sopenharmony_ci  })
731cb0ef41Sopenharmony_ci  registry.nock.post('/-/npm/v1/security/advisories/bulk').reply(200, {})
741cb0ef41Sopenharmony_ci  await npm.exec('ci', [])
751cb0ef41Sopenharmony_ci  t.match(joinedOutput(), 'added 1 package, and audited 2 packages in')
761cb0ef41Sopenharmony_ci  const nmTest = path.join(npm.prefix, 'node_modules', 'test')
771cb0ef41Sopenharmony_ci  t.equal(fs.existsSync(nmTest), false, 'existing node_modules is removed')
781cb0ef41Sopenharmony_ci  const nmAbbrev = path.join(npm.prefix, 'node_modules', 'abbrev')
791cb0ef41Sopenharmony_ci  t.equal(fs.existsSync(nmAbbrev), true, 'installs abbrev')
801cb0ef41Sopenharmony_ci})
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_cit.test('reifies, audits, removes node_modules on repeat run', async t => {
831cb0ef41Sopenharmony_ci  const { npm, joinedOutput, registry } = await loadMockNpm(t, {
841cb0ef41Sopenharmony_ci    prefixDir: {
851cb0ef41Sopenharmony_ci      abbrev: abbrev,
861cb0ef41Sopenharmony_ci      'package.json': JSON.stringify(packageJson),
871cb0ef41Sopenharmony_ci      'package-lock.json': JSON.stringify(packageLock),
881cb0ef41Sopenharmony_ci      node_modules: { test: 'test file that will be removed' },
891cb0ef41Sopenharmony_ci    },
901cb0ef41Sopenharmony_ci  })
911cb0ef41Sopenharmony_ci  const manifest = registry.manifest({ name: 'abbrev' })
921cb0ef41Sopenharmony_ci  await registry.tarball({
931cb0ef41Sopenharmony_ci    manifest: manifest.versions['1.0.0'],
941cb0ef41Sopenharmony_ci    tarball: path.join(npm.prefix, 'abbrev'),
951cb0ef41Sopenharmony_ci  })
961cb0ef41Sopenharmony_ci  registry.nock.post('/-/npm/v1/security/advisories/bulk').reply(200, {})
971cb0ef41Sopenharmony_ci  await npm.exec('ci', [])
981cb0ef41Sopenharmony_ci  await npm.exec('ci', [])
991cb0ef41Sopenharmony_ci  t.match(joinedOutput(), 'added 1 package, and audited 2 packages in')
1001cb0ef41Sopenharmony_ci  const nmTest = path.join(npm.prefix, 'node_modules', 'test')
1011cb0ef41Sopenharmony_ci  t.equal(fs.existsSync(nmTest), false, 'existing node_modules is removed')
1021cb0ef41Sopenharmony_ci  const nmAbbrev = path.join(npm.prefix, 'node_modules', 'abbrev')
1031cb0ef41Sopenharmony_ci  t.equal(fs.existsSync(nmAbbrev), true, 'installs abbrev')
1041cb0ef41Sopenharmony_ci})
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_cit.test('--no-audit and --ignore-scripts', async t => {
1071cb0ef41Sopenharmony_ci  const { npm, joinedOutput, registry } = await loadMockNpm(t, {
1081cb0ef41Sopenharmony_ci    config: {
1091cb0ef41Sopenharmony_ci      'ignore-scripts': true,
1101cb0ef41Sopenharmony_ci      audit: false,
1111cb0ef41Sopenharmony_ci    },
1121cb0ef41Sopenharmony_ci    prefixDir: {
1131cb0ef41Sopenharmony_ci      abbrev: {
1141cb0ef41Sopenharmony_ci        'package.json': '{"name": "abbrev", "version": "1.0.0"}',
1151cb0ef41Sopenharmony_ci        test: 'test-file',
1161cb0ef41Sopenharmony_ci      },
1171cb0ef41Sopenharmony_ci      'package.json': JSON.stringify({
1181cb0ef41Sopenharmony_ci        ...packageJson,
1191cb0ef41Sopenharmony_ci        // Would make install fail
1201cb0ef41Sopenharmony_ci        scripts: { install: 'echo "SHOULD NOT RUN" && exit 1' },
1211cb0ef41Sopenharmony_ci      }),
1221cb0ef41Sopenharmony_ci      'package-lock.json': JSON.stringify(packageLock),
1231cb0ef41Sopenharmony_ci    },
1241cb0ef41Sopenharmony_ci  })
1251cb0ef41Sopenharmony_ci  require('nock').emitter.on('no match', req => {
1261cb0ef41Sopenharmony_ci    t.fail('Should not audit')
1271cb0ef41Sopenharmony_ci  })
1281cb0ef41Sopenharmony_ci  const manifest = registry.manifest({ name: 'abbrev' })
1291cb0ef41Sopenharmony_ci  await registry.tarball({
1301cb0ef41Sopenharmony_ci    manifest: manifest.versions['1.0.0'],
1311cb0ef41Sopenharmony_ci    tarball: path.join(npm.prefix, 'abbrev'),
1321cb0ef41Sopenharmony_ci  })
1331cb0ef41Sopenharmony_ci  await npm.exec('ci', [])
1341cb0ef41Sopenharmony_ci  t.match(joinedOutput(), 'added 1 package in', 'would fail if install script ran')
1351cb0ef41Sopenharmony_ci})
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_cit.test('lifecycle scripts', async t => {
1381cb0ef41Sopenharmony_ci  const scripts = []
1391cb0ef41Sopenharmony_ci  const { npm, registry } = await loadMockNpm(t, {
1401cb0ef41Sopenharmony_ci    prefixDir: {
1411cb0ef41Sopenharmony_ci      abbrev: abbrev,
1421cb0ef41Sopenharmony_ci      'package.json': JSON.stringify(packageJson),
1431cb0ef41Sopenharmony_ci      'package-lock.json': JSON.stringify(packageLock),
1441cb0ef41Sopenharmony_ci    },
1451cb0ef41Sopenharmony_ci    mocks: {
1461cb0ef41Sopenharmony_ci      '@npmcli/run-script': (opts) => {
1471cb0ef41Sopenharmony_ci        t.ok(opts.banner)
1481cb0ef41Sopenharmony_ci        scripts.push(opts.event)
1491cb0ef41Sopenharmony_ci      },
1501cb0ef41Sopenharmony_ci    },
1511cb0ef41Sopenharmony_ci  })
1521cb0ef41Sopenharmony_ci  const manifest = registry.manifest({ name: 'abbrev' })
1531cb0ef41Sopenharmony_ci  await registry.tarball({
1541cb0ef41Sopenharmony_ci    manifest: manifest.versions['1.0.0'],
1551cb0ef41Sopenharmony_ci    tarball: path.join(npm.prefix, 'abbrev'),
1561cb0ef41Sopenharmony_ci  })
1571cb0ef41Sopenharmony_ci  registry.nock.post('/-/npm/v1/security/advisories/bulk').reply(200, {})
1581cb0ef41Sopenharmony_ci  await npm.exec('ci', [])
1591cb0ef41Sopenharmony_ci  t.same(scripts, [
1601cb0ef41Sopenharmony_ci    'preinstall',
1611cb0ef41Sopenharmony_ci    'install',
1621cb0ef41Sopenharmony_ci    'postinstall',
1631cb0ef41Sopenharmony_ci    'prepublish',
1641cb0ef41Sopenharmony_ci    'preprepare',
1651cb0ef41Sopenharmony_ci    'prepare',
1661cb0ef41Sopenharmony_ci    'postprepare',
1671cb0ef41Sopenharmony_ci  ], 'runs appropriate scripts, in order')
1681cb0ef41Sopenharmony_ci})
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_cit.test('should throw if package-lock.json or npm-shrinkwrap missing', async t => {
1711cb0ef41Sopenharmony_ci  const { npm } = await loadMockNpm(t, {
1721cb0ef41Sopenharmony_ci    prefixDir: {
1731cb0ef41Sopenharmony_ci      'package.json': JSON.stringify(packageJson),
1741cb0ef41Sopenharmony_ci      node_modules: {
1751cb0ef41Sopenharmony_ci        'test-file': 'should not be removed',
1761cb0ef41Sopenharmony_ci      },
1771cb0ef41Sopenharmony_ci    },
1781cb0ef41Sopenharmony_ci  })
1791cb0ef41Sopenharmony_ci  await t.rejects(npm.exec('ci', []), { code: 'EUSAGE', message: /package-lock.json/ })
1801cb0ef41Sopenharmony_ci  const nmTestFile = path.join(npm.prefix, 'node_modules', 'test-file')
1811cb0ef41Sopenharmony_ci  t.equal(fs.existsSync(nmTestFile), true, 'does not remove node_modules')
1821cb0ef41Sopenharmony_ci})
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_cit.test('should throw ECIGLOBAL', async t => {
1851cb0ef41Sopenharmony_ci  const { npm } = await loadMockNpm(t, {
1861cb0ef41Sopenharmony_ci    config: { global: true },
1871cb0ef41Sopenharmony_ci  })
1881cb0ef41Sopenharmony_ci  await t.rejects(npm.exec('ci', []), { code: 'ECIGLOBAL' })
1891cb0ef41Sopenharmony_ci})
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_cit.test('should throw error when ideal inventory mismatches virtual', async t => {
1921cb0ef41Sopenharmony_ci  const { npm, registry } = await loadMockNpm(t, {
1931cb0ef41Sopenharmony_ci    prefixDir: {
1941cb0ef41Sopenharmony_ci      abbrev: abbrev,
1951cb0ef41Sopenharmony_ci      'package.json': JSON.stringify({
1961cb0ef41Sopenharmony_ci        ...packageJson,
1971cb0ef41Sopenharmony_ci        dependencies: { notabbrev: '^1.0.0' },
1981cb0ef41Sopenharmony_ci      }),
1991cb0ef41Sopenharmony_ci      'package-lock.json': JSON.stringify(packageLock),
2001cb0ef41Sopenharmony_ci      node_modules: {
2011cb0ef41Sopenharmony_ci        'test-file': 'should not be removed',
2021cb0ef41Sopenharmony_ci      },
2031cb0ef41Sopenharmony_ci    },
2041cb0ef41Sopenharmony_ci  })
2051cb0ef41Sopenharmony_ci  const manifest = registry.manifest({ name: 'notabbrev' })
2061cb0ef41Sopenharmony_ci  await registry.package({ manifest })
2071cb0ef41Sopenharmony_ci  await t.rejects(
2081cb0ef41Sopenharmony_ci    npm.exec('ci', []),
2091cb0ef41Sopenharmony_ci    { code: 'EUSAGE', message: /in sync/ }
2101cb0ef41Sopenharmony_ci  )
2111cb0ef41Sopenharmony_ci  const nmTestFile = path.join(npm.prefix, 'node_modules', 'test-file')
2121cb0ef41Sopenharmony_ci  t.equal(fs.existsSync(nmTestFile), true, 'does not remove node_modules')
2131cb0ef41Sopenharmony_ci})
214