11cb0ef41Sopenharmony_ciconst t = require('tap')
21cb0ef41Sopenharmony_ciconst fs = require('fs')
31cb0ef41Sopenharmony_ciconst { resolve } = require('path')
41cb0ef41Sopenharmony_ciconst { load: loadMockNpm } = require('../../fixtures/mock-npm')
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ci// Attempt to parse json values in snapshots before
71cb0ef41Sopenharmony_ci// stringifying to remove escaped values like \\"
81cb0ef41Sopenharmony_ci// This also doesn't reorder the keys of the object
91cb0ef41Sopenharmony_ci// like tap does by default which is nice in this case
101cb0ef41Sopenharmony_cit.formatSnapshot = obj =>
111cb0ef41Sopenharmony_ci  JSON.stringify(
121cb0ef41Sopenharmony_ci    obj,
131cb0ef41Sopenharmony_ci    (k, v) => {
141cb0ef41Sopenharmony_ci      try {
151cb0ef41Sopenharmony_ci        return JSON.parse(v)
161cb0ef41Sopenharmony_ci      } catch {
171cb0ef41Sopenharmony_ci        // leave invalid JSON as a string
181cb0ef41Sopenharmony_ci      }
191cb0ef41Sopenharmony_ci      return v
201cb0ef41Sopenharmony_ci    },
211cb0ef41Sopenharmony_ci    2
221cb0ef41Sopenharmony_ci  )
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci// Run shrinkwrap against a specified prefixDir with config items
251cb0ef41Sopenharmony_ci// and make some assertions that should always be true. Sets
261cb0ef41Sopenharmony_ci// the results on t.context for use in child tests
271cb0ef41Sopenharmony_ciconst shrinkwrap = async (t, prefixDir = {}, config = {}, mocks = {}) => {
281cb0ef41Sopenharmony_ci  const { npm, logs } = await loadMockNpm(t, {
291cb0ef41Sopenharmony_ci    mocks,
301cb0ef41Sopenharmony_ci    config,
311cb0ef41Sopenharmony_ci    prefixDir,
321cb0ef41Sopenharmony_ci  })
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci  await npm.exec('shrinkwrap', [])
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci  const newFile = resolve(npm.prefix, 'npm-shrinkwrap.json')
371cb0ef41Sopenharmony_ci  const oldFile = resolve(npm.prefix, 'package-lock.json')
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci  t.notOk(fs.existsSync(oldFile), 'package-lock is always deleted')
401cb0ef41Sopenharmony_ci  t.same(logs.warn, [], 'no warnings')
411cb0ef41Sopenharmony_ci  t.teardown(() => delete t.context)
421cb0ef41Sopenharmony_ci  t.context = {
431cb0ef41Sopenharmony_ci    localPrefix: prefixDir,
441cb0ef41Sopenharmony_ci    config,
451cb0ef41Sopenharmony_ci    shrinkwrap: JSON.parse(fs.readFileSync(newFile)),
461cb0ef41Sopenharmony_ci    logs: logs.notice.map(([, m]) => m),
471cb0ef41Sopenharmony_ci  }
481cb0ef41Sopenharmony_ci}
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci// Run shrinkwrap against all combinations of existing and config
511cb0ef41Sopenharmony_ci// lockfile versions
521cb0ef41Sopenharmony_ciconst shrinkwrapMatrix = async (t, file, assertions) => {
531cb0ef41Sopenharmony_ci  const ancient = JSON.stringify({ lockfileVersion: 1 })
541cb0ef41Sopenharmony_ci  const existing = JSON.stringify({ lockfileVersion: 2 })
551cb0ef41Sopenharmony_ci  const upgrade = { 'lockfile-version': 3 }
561cb0ef41Sopenharmony_ci  const downgrade = { 'lockfile-version': 1 }
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  let ancientDir = {}
591cb0ef41Sopenharmony_ci  let existingDir = null
601cb0ef41Sopenharmony_ci  if (file === 'package-lock') {
611cb0ef41Sopenharmony_ci    ancientDir = { 'package-lock.json': ancient }
621cb0ef41Sopenharmony_ci    existingDir = { 'package-lock.json': existing }
631cb0ef41Sopenharmony_ci  } else if (file === 'npm-shrinkwrap') {
641cb0ef41Sopenharmony_ci    ancientDir = { 'npm-shrinkwrap.json': ancient }
651cb0ef41Sopenharmony_ci    existingDir = { 'npm-shrinkwrap.json': existing }
661cb0ef41Sopenharmony_ci  } else if (file === 'hidden-lockfile') {
671cb0ef41Sopenharmony_ci    ancientDir = { node_modules: { '.package-lock.json': ancient } }
681cb0ef41Sopenharmony_ci    existingDir = { node_modules: { '.package-lock.json': existing } }
691cb0ef41Sopenharmony_ci  }
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci  await t.test('ancient', async t => {
721cb0ef41Sopenharmony_ci    await shrinkwrap(t, ancientDir)
731cb0ef41Sopenharmony_ci    t.match(t.context, assertions.ancient)
741cb0ef41Sopenharmony_ci    t.matchSnapshot(t.context)
751cb0ef41Sopenharmony_ci  })
761cb0ef41Sopenharmony_ci  await t.test('ancient upgrade', async t => {
771cb0ef41Sopenharmony_ci    await shrinkwrap(t, ancientDir, upgrade)
781cb0ef41Sopenharmony_ci    t.match(t.context, assertions.ancientUpgrade)
791cb0ef41Sopenharmony_ci    t.matchSnapshot(t.context)
801cb0ef41Sopenharmony_ci  })
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  if (existingDir) {
831cb0ef41Sopenharmony_ci    await t.test('existing', async t => {
841cb0ef41Sopenharmony_ci      await shrinkwrap(t, existingDir)
851cb0ef41Sopenharmony_ci      t.match(t.context, assertions.existing)
861cb0ef41Sopenharmony_ci      t.matchSnapshot(t.context)
871cb0ef41Sopenharmony_ci    })
881cb0ef41Sopenharmony_ci    await t.test('existing upgrade', async t => {
891cb0ef41Sopenharmony_ci      await shrinkwrap(t, existingDir, upgrade)
901cb0ef41Sopenharmony_ci      t.match(t.context, assertions.existingUpgrade)
911cb0ef41Sopenharmony_ci      t.matchSnapshot(t.context)
921cb0ef41Sopenharmony_ci    })
931cb0ef41Sopenharmony_ci    await t.test('existing downgrade', async t => {
941cb0ef41Sopenharmony_ci      await shrinkwrap(t, existingDir, downgrade)
951cb0ef41Sopenharmony_ci      t.match(t.context, assertions.existingDowngrade)
961cb0ef41Sopenharmony_ci      t.matchSnapshot(t.context)
971cb0ef41Sopenharmony_ci    })
981cb0ef41Sopenharmony_ci  }
991cb0ef41Sopenharmony_ci}
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ciconst NOTICES = {
1021cb0ef41Sopenharmony_ci  CREATED: (v = '') => [`created a lockfile as npm-shrinkwrap.json${v && ` with version ${v}`}`],
1031cb0ef41Sopenharmony_ci  RENAMED: (v = '') => [
1041cb0ef41Sopenharmony_ci    `package-lock.json has been renamed to npm-shrinkwrap.json${
1051cb0ef41Sopenharmony_ci      v && ` and updated to version ${v}`
1061cb0ef41Sopenharmony_ci    }`,
1071cb0ef41Sopenharmony_ci  ],
1081cb0ef41Sopenharmony_ci  UPDATED: (v = '') => [`npm-shrinkwrap.json updated to version ${v}`],
1091cb0ef41Sopenharmony_ci  SAME: () => [`npm-shrinkwrap.json up to date`],
1101cb0ef41Sopenharmony_ci}
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_cit.test('with nothing', t =>
1131cb0ef41Sopenharmony_ci  shrinkwrapMatrix(t, null, {
1141cb0ef41Sopenharmony_ci    ancient: {
1151cb0ef41Sopenharmony_ci      shrinkwrap: { lockfileVersion: 3 },
1161cb0ef41Sopenharmony_ci      logs: NOTICES.CREATED(3),
1171cb0ef41Sopenharmony_ci    },
1181cb0ef41Sopenharmony_ci    ancientUpgrade: {
1191cb0ef41Sopenharmony_ci      shrinkwrap: { lockfileVersion: 3 },
1201cb0ef41Sopenharmony_ci      logs: NOTICES.CREATED(3),
1211cb0ef41Sopenharmony_ci    },
1221cb0ef41Sopenharmony_ci  })
1231cb0ef41Sopenharmony_ci)
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_cit.test('with package-lock.json', t =>
1261cb0ef41Sopenharmony_ci  shrinkwrapMatrix(t, 'package-lock', {
1271cb0ef41Sopenharmony_ci    ancient: {
1281cb0ef41Sopenharmony_ci      shrinkwrap: { lockfileVersion: 3 },
1291cb0ef41Sopenharmony_ci      logs: NOTICES.RENAMED(3),
1301cb0ef41Sopenharmony_ci    },
1311cb0ef41Sopenharmony_ci    ancientUpgrade: {
1321cb0ef41Sopenharmony_ci      shrinkwrap: { lockfileVersion: 3 },
1331cb0ef41Sopenharmony_ci      logs: NOTICES.RENAMED(3),
1341cb0ef41Sopenharmony_ci    },
1351cb0ef41Sopenharmony_ci    existing: {
1361cb0ef41Sopenharmony_ci      shrinkwrap: { lockfileVersion: 2 },
1371cb0ef41Sopenharmony_ci      logs: NOTICES.RENAMED(),
1381cb0ef41Sopenharmony_ci    },
1391cb0ef41Sopenharmony_ci    existingUpgrade: {
1401cb0ef41Sopenharmony_ci      shrinkwrap: { lockfileVersion: 3 },
1411cb0ef41Sopenharmony_ci      logs: NOTICES.RENAMED(3),
1421cb0ef41Sopenharmony_ci    },
1431cb0ef41Sopenharmony_ci    existingDowngrade: {
1441cb0ef41Sopenharmony_ci      shrinkwrap: { lockfileVersion: 1 },
1451cb0ef41Sopenharmony_ci      logs: NOTICES.RENAMED(1),
1461cb0ef41Sopenharmony_ci    },
1471cb0ef41Sopenharmony_ci  })
1481cb0ef41Sopenharmony_ci)
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_cit.test('with npm-shrinkwrap.json', t =>
1511cb0ef41Sopenharmony_ci  shrinkwrapMatrix(t, 'npm-shrinkwrap', {
1521cb0ef41Sopenharmony_ci    ancient: {
1531cb0ef41Sopenharmony_ci      shrinkwrap: { lockfileVersion: 3 },
1541cb0ef41Sopenharmony_ci      logs: NOTICES.UPDATED(3),
1551cb0ef41Sopenharmony_ci    },
1561cb0ef41Sopenharmony_ci    ancientUpgrade: {
1571cb0ef41Sopenharmony_ci      shrinkwrap: { lockfileVersion: 3 },
1581cb0ef41Sopenharmony_ci      logs: NOTICES.UPDATED(3),
1591cb0ef41Sopenharmony_ci    },
1601cb0ef41Sopenharmony_ci    existing: {
1611cb0ef41Sopenharmony_ci      shrinkwrap: { lockfileVersion: 2 },
1621cb0ef41Sopenharmony_ci      logs: NOTICES.SAME(),
1631cb0ef41Sopenharmony_ci    },
1641cb0ef41Sopenharmony_ci    existingUpgrade: {
1651cb0ef41Sopenharmony_ci      shrinkwrap: { lockfileVersion: 3 },
1661cb0ef41Sopenharmony_ci      logs: NOTICES.UPDATED(3),
1671cb0ef41Sopenharmony_ci    },
1681cb0ef41Sopenharmony_ci    existingDowngrade: {
1691cb0ef41Sopenharmony_ci      shrinkwrap: { lockfileVersion: 1 },
1701cb0ef41Sopenharmony_ci      logs: NOTICES.UPDATED(1),
1711cb0ef41Sopenharmony_ci    },
1721cb0ef41Sopenharmony_ci  })
1731cb0ef41Sopenharmony_ci)
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_cit.test('with hidden lockfile', t =>
1761cb0ef41Sopenharmony_ci  shrinkwrapMatrix(t, 'hidden-lockfile', {
1771cb0ef41Sopenharmony_ci    ancient: {
1781cb0ef41Sopenharmony_ci      shrinkwrap: { lockfileVersion: 1 },
1791cb0ef41Sopenharmony_ci      logs: NOTICES.CREATED(),
1801cb0ef41Sopenharmony_ci    },
1811cb0ef41Sopenharmony_ci    ancientUpgrade: {
1821cb0ef41Sopenharmony_ci      shrinkwrap: { lockfileVersion: 3 },
1831cb0ef41Sopenharmony_ci      logs: NOTICES.CREATED(),
1841cb0ef41Sopenharmony_ci    },
1851cb0ef41Sopenharmony_ci    existing: {
1861cb0ef41Sopenharmony_ci      shrinkwrap: { lockfileVersion: 2 },
1871cb0ef41Sopenharmony_ci      logs: NOTICES.CREATED(),
1881cb0ef41Sopenharmony_ci    },
1891cb0ef41Sopenharmony_ci    existingUpgrade: {
1901cb0ef41Sopenharmony_ci      shrinkwrap: { lockfileVersion: 3 },
1911cb0ef41Sopenharmony_ci      logs: NOTICES.CREATED(3),
1921cb0ef41Sopenharmony_ci    },
1931cb0ef41Sopenharmony_ci    existingDowngrade: {
1941cb0ef41Sopenharmony_ci      shrinkwrap: { lockfileVersion: 1 },
1951cb0ef41Sopenharmony_ci      logs: NOTICES.CREATED(1),
1961cb0ef41Sopenharmony_ci    },
1971cb0ef41Sopenharmony_ci  })
1981cb0ef41Sopenharmony_ci)
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_cit.test('throws in global mode', async t => {
2011cb0ef41Sopenharmony_ci  t.rejects(
2021cb0ef41Sopenharmony_ci    shrinkwrap(
2031cb0ef41Sopenharmony_ci      t,
2041cb0ef41Sopenharmony_ci      {},
2051cb0ef41Sopenharmony_ci      {
2061cb0ef41Sopenharmony_ci        global: true,
2071cb0ef41Sopenharmony_ci      }
2081cb0ef41Sopenharmony_ci    ),
2091cb0ef41Sopenharmony_ci    {
2101cb0ef41Sopenharmony_ci      message: '`npm shrinkwrap` does not work for global packages',
2111cb0ef41Sopenharmony_ci      code: 'ESHRINKWRAPGLOBAL',
2121cb0ef41Sopenharmony_ci    }
2131cb0ef41Sopenharmony_ci  )
2141cb0ef41Sopenharmony_ci})
215