11cb0ef41Sopenharmony_ciconst t = require('tap') 21cb0ef41Sopenharmony_ciconst { resolve } = require('path') 31cb0ef41Sopenharmony_ciconst mockNpm = require('../../fixtures/mock-npm.js') 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ciconst mockExplain = async (t, opts) => { 61cb0ef41Sopenharmony_ci const mock = await mockNpm(t, { 71cb0ef41Sopenharmony_ci command: 'explain', 81cb0ef41Sopenharmony_ci mocks: { 91cb0ef41Sopenharmony_ci // keep the snapshots pared down a bit, since this has its own tests. 101cb0ef41Sopenharmony_ci '{LIB}/utils/explain-dep.js': { 111cb0ef41Sopenharmony_ci explainNode: (expl, depth, chalk) => { 121cb0ef41Sopenharmony_ci const color = chalk.level !== 0 131cb0ef41Sopenharmony_ci return `${expl.name}@${expl.version} depth=${depth} color=${color}` 141cb0ef41Sopenharmony_ci }, 151cb0ef41Sopenharmony_ci }, 161cb0ef41Sopenharmony_ci }, 171cb0ef41Sopenharmony_ci ...opts, 181cb0ef41Sopenharmony_ci }) 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_ci return mock 211cb0ef41Sopenharmony_ci} 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_cit.test('no args throws usage', async t => { 241cb0ef41Sopenharmony_ci const { explain } = await mockExplain(t) 251cb0ef41Sopenharmony_ci await t.rejects( 261cb0ef41Sopenharmony_ci explain.exec([]), 271cb0ef41Sopenharmony_ci explain.usage 281cb0ef41Sopenharmony_ci ) 291cb0ef41Sopenharmony_ci}) 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_cit.test('no match throws not found', async t => { 321cb0ef41Sopenharmony_ci const { explain } = await mockExplain(t) 331cb0ef41Sopenharmony_ci await t.rejects( 341cb0ef41Sopenharmony_ci explain.exec(['foo@1.2.3', 'node_modules/baz']), 351cb0ef41Sopenharmony_ci 'No dependencies found matching foo@1.2.3, node_modules/baz' 361cb0ef41Sopenharmony_ci ) 371cb0ef41Sopenharmony_ci}) 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_cit.test('invalid package name throws not found', async t => { 401cb0ef41Sopenharmony_ci const { explain } = await mockExplain(t) 411cb0ef41Sopenharmony_ci const badName = ' not a valid package name ' 421cb0ef41Sopenharmony_ci await t.rejects( 431cb0ef41Sopenharmony_ci explain.exec([`${badName}@1.2.3`]), 441cb0ef41Sopenharmony_ci `No dependencies found matching ${badName}@1.2.3` 451cb0ef41Sopenharmony_ci ) 461cb0ef41Sopenharmony_ci}) 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_cit.test('explain some nodes', async t => { 491cb0ef41Sopenharmony_ci const mockNodes = async (t, config = {}) => { 501cb0ef41Sopenharmony_ci const mock = await mockExplain(t, { 511cb0ef41Sopenharmony_ci prefixDir: { 521cb0ef41Sopenharmony_ci node_modules: { 531cb0ef41Sopenharmony_ci foo: { 541cb0ef41Sopenharmony_ci 'package.json': JSON.stringify({ 551cb0ef41Sopenharmony_ci name: 'foo', 561cb0ef41Sopenharmony_ci version: '1.2.3', 571cb0ef41Sopenharmony_ci dependencies: { 581cb0ef41Sopenharmony_ci bar: '*', 591cb0ef41Sopenharmony_ci }, 601cb0ef41Sopenharmony_ci }), 611cb0ef41Sopenharmony_ci }, 621cb0ef41Sopenharmony_ci bar: { 631cb0ef41Sopenharmony_ci 'package.json': JSON.stringify({ 641cb0ef41Sopenharmony_ci name: 'bar', 651cb0ef41Sopenharmony_ci version: '1.2.3', 661cb0ef41Sopenharmony_ci }), 671cb0ef41Sopenharmony_ci }, 681cb0ef41Sopenharmony_ci baz: { 691cb0ef41Sopenharmony_ci 'package.json': JSON.stringify({ 701cb0ef41Sopenharmony_ci name: 'baz', 711cb0ef41Sopenharmony_ci version: '1.2.3', 721cb0ef41Sopenharmony_ci dependencies: { 731cb0ef41Sopenharmony_ci foo: '*', 741cb0ef41Sopenharmony_ci bar: '2', 751cb0ef41Sopenharmony_ci }, 761cb0ef41Sopenharmony_ci }), 771cb0ef41Sopenharmony_ci node_modules: { 781cb0ef41Sopenharmony_ci bar: { 791cb0ef41Sopenharmony_ci 'package.json': JSON.stringify({ 801cb0ef41Sopenharmony_ci name: 'bar', 811cb0ef41Sopenharmony_ci version: '2.3.4', 821cb0ef41Sopenharmony_ci }), 831cb0ef41Sopenharmony_ci }, 841cb0ef41Sopenharmony_ci extra: { 851cb0ef41Sopenharmony_ci 'package.json': JSON.stringify({ 861cb0ef41Sopenharmony_ci name: 'extra', 871cb0ef41Sopenharmony_ci version: '99.9999.999999', 881cb0ef41Sopenharmony_ci description: 'extraneous package', 891cb0ef41Sopenharmony_ci }), 901cb0ef41Sopenharmony_ci }, 911cb0ef41Sopenharmony_ci }, 921cb0ef41Sopenharmony_ci }, 931cb0ef41Sopenharmony_ci }, 941cb0ef41Sopenharmony_ci 'package.json': JSON.stringify({ 951cb0ef41Sopenharmony_ci dependencies: { 961cb0ef41Sopenharmony_ci baz: '1', 971cb0ef41Sopenharmony_ci }, 981cb0ef41Sopenharmony_ci }), 991cb0ef41Sopenharmony_ci }, 1001cb0ef41Sopenharmony_ci config: { 1011cb0ef41Sopenharmony_ci color: 'always', 1021cb0ef41Sopenharmony_ci ...config, 1031cb0ef41Sopenharmony_ci }, 1041cb0ef41Sopenharmony_ci }) 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ci return mock 1071cb0ef41Sopenharmony_ci } 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci t.test('works with the location', async t => { 1101cb0ef41Sopenharmony_ci const path = 'node_modules/foo' 1111cb0ef41Sopenharmony_ci const { explain, joinedOutput } = await mockNodes(t) 1121cb0ef41Sopenharmony_ci await explain.exec([path]) 1131cb0ef41Sopenharmony_ci t.strictSame(joinedOutput(), 'foo@1.2.3 depth=Infinity color=true') 1141cb0ef41Sopenharmony_ci }) 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ci t.test('works with a full actual path', async t => { 1171cb0ef41Sopenharmony_ci const { npm, explain, joinedOutput } = await mockNodes(t) 1181cb0ef41Sopenharmony_ci const path = resolve(npm.prefix, 'node_modules/foo') 1191cb0ef41Sopenharmony_ci await explain.exec([path]) 1201cb0ef41Sopenharmony_ci t.strictSame(joinedOutput(), 'foo@1.2.3 depth=Infinity color=true') 1211cb0ef41Sopenharmony_ci }) 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci t.test('finds all nodes by name', async t => { 1241cb0ef41Sopenharmony_ci const { explain, joinedOutput } = await mockNodes(t) 1251cb0ef41Sopenharmony_ci await explain.exec(['bar']) 1261cb0ef41Sopenharmony_ci t.strictSame(joinedOutput(), 1271cb0ef41Sopenharmony_ci 'bar@1.2.3 depth=Infinity color=true\n\n' + 1281cb0ef41Sopenharmony_ci 'bar@2.3.4 depth=Infinity color=true' 1291cb0ef41Sopenharmony_ci ) 1301cb0ef41Sopenharmony_ci }) 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci t.test('finds only nodes that match the spec', async t => { 1331cb0ef41Sopenharmony_ci const { explain, joinedOutput } = await mockNodes(t) 1341cb0ef41Sopenharmony_ci await explain.exec(['bar@1']) 1351cb0ef41Sopenharmony_ci t.strictSame(joinedOutput(), 'bar@1.2.3 depth=Infinity color=true') 1361cb0ef41Sopenharmony_ci }) 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci t.test('finds extraneous nodes', async t => { 1391cb0ef41Sopenharmony_ci const { explain, joinedOutput } = await mockNodes(t) 1401cb0ef41Sopenharmony_ci await explain.exec(['extra']) 1411cb0ef41Sopenharmony_ci t.strictSame(joinedOutput(), 'extra@99.9999.999999 depth=Infinity color=true') 1421cb0ef41Sopenharmony_ci }) 1431cb0ef41Sopenharmony_ci 1441cb0ef41Sopenharmony_ci t.test('json output', async t => { 1451cb0ef41Sopenharmony_ci const { explain, joinedOutput } = await mockNodes(t, { json: true }) 1461cb0ef41Sopenharmony_ci await explain.exec(['node_modules/foo']) 1471cb0ef41Sopenharmony_ci t.match(JSON.parse(joinedOutput()), [{ 1481cb0ef41Sopenharmony_ci name: 'foo', 1491cb0ef41Sopenharmony_ci version: '1.2.3', 1501cb0ef41Sopenharmony_ci dependents: Array, 1511cb0ef41Sopenharmony_ci }]) 1521cb0ef41Sopenharmony_ci }) 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci t.test('report if no nodes found', async t => { 1551cb0ef41Sopenharmony_ci const { explain } = await mockNodes(t) 1561cb0ef41Sopenharmony_ci await t.rejects( 1571cb0ef41Sopenharmony_ci explain.exec(['asdf/foo/bar', 'quux@1.x']), 1581cb0ef41Sopenharmony_ci 'No dependencies found matching asdf/foo/bar, quux@1.x' 1591cb0ef41Sopenharmony_ci ) 1601cb0ef41Sopenharmony_ci }) 1611cb0ef41Sopenharmony_ci}) 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_cit.test('workspaces', async t => { 1641cb0ef41Sopenharmony_ci const mockWorkspaces = async (t, exec = [], workspaces = true) => { 1651cb0ef41Sopenharmony_ci const mock = await mockExplain(t, { 1661cb0ef41Sopenharmony_ci prefixDir: { 1671cb0ef41Sopenharmony_ci 'package.json': JSON.stringify({ 1681cb0ef41Sopenharmony_ci name: 'workspaces-project', 1691cb0ef41Sopenharmony_ci version: '1.0.0', 1701cb0ef41Sopenharmony_ci workspaces: ['packages/*'], 1711cb0ef41Sopenharmony_ci dependencies: { 1721cb0ef41Sopenharmony_ci abbrev: '^1.0.0', 1731cb0ef41Sopenharmony_ci }, 1741cb0ef41Sopenharmony_ci }), 1751cb0ef41Sopenharmony_ci node_modules: { 1761cb0ef41Sopenharmony_ci a: t.fixture('symlink', '../packages/a'), 1771cb0ef41Sopenharmony_ci b: t.fixture('symlink', '../packages/b'), 1781cb0ef41Sopenharmony_ci c: t.fixture('symlink', '../packages/c'), 1791cb0ef41Sopenharmony_ci once: { 1801cb0ef41Sopenharmony_ci 'package.json': JSON.stringify({ 1811cb0ef41Sopenharmony_ci name: 'once', 1821cb0ef41Sopenharmony_ci version: '1.0.0', 1831cb0ef41Sopenharmony_ci dependencies: { 1841cb0ef41Sopenharmony_ci wrappy: '2.0.0', 1851cb0ef41Sopenharmony_ci }, 1861cb0ef41Sopenharmony_ci }), 1871cb0ef41Sopenharmony_ci }, 1881cb0ef41Sopenharmony_ci abbrev: { 1891cb0ef41Sopenharmony_ci 'package.json': JSON.stringify({ 1901cb0ef41Sopenharmony_ci name: 'abbrev', 1911cb0ef41Sopenharmony_ci version: '1.0.0', 1921cb0ef41Sopenharmony_ci }), 1931cb0ef41Sopenharmony_ci }, 1941cb0ef41Sopenharmony_ci wrappy: { 1951cb0ef41Sopenharmony_ci 'package.json': JSON.stringify({ 1961cb0ef41Sopenharmony_ci name: 'wrappy', 1971cb0ef41Sopenharmony_ci version: '2.0.0', 1981cb0ef41Sopenharmony_ci }), 1991cb0ef41Sopenharmony_ci }, 2001cb0ef41Sopenharmony_ci }, 2011cb0ef41Sopenharmony_ci packages: { 2021cb0ef41Sopenharmony_ci a: { 2031cb0ef41Sopenharmony_ci 'package.json': JSON.stringify({ 2041cb0ef41Sopenharmony_ci name: 'a', 2051cb0ef41Sopenharmony_ci version: '1.0.0', 2061cb0ef41Sopenharmony_ci dependencies: { 2071cb0ef41Sopenharmony_ci once: '1.0.0', 2081cb0ef41Sopenharmony_ci }, 2091cb0ef41Sopenharmony_ci }), 2101cb0ef41Sopenharmony_ci }, 2111cb0ef41Sopenharmony_ci b: { 2121cb0ef41Sopenharmony_ci 'package.json': JSON.stringify({ 2131cb0ef41Sopenharmony_ci name: 'b', 2141cb0ef41Sopenharmony_ci version: '1.0.0', 2151cb0ef41Sopenharmony_ci dependencies: { 2161cb0ef41Sopenharmony_ci abbrev: '^1.0.0', 2171cb0ef41Sopenharmony_ci }, 2181cb0ef41Sopenharmony_ci }), 2191cb0ef41Sopenharmony_ci }, 2201cb0ef41Sopenharmony_ci c: { 2211cb0ef41Sopenharmony_ci 'package.json': JSON.stringify({ 2221cb0ef41Sopenharmony_ci name: 'c', 2231cb0ef41Sopenharmony_ci version: '1.0.0', 2241cb0ef41Sopenharmony_ci }), 2251cb0ef41Sopenharmony_ci }, 2261cb0ef41Sopenharmony_ci }, 2271cb0ef41Sopenharmony_ci }, 2281cb0ef41Sopenharmony_ci config: { 2291cb0ef41Sopenharmony_ci ...(typeof workspaces === 'boolean' ? { workspaces } : { workspace: workspaces }), 2301cb0ef41Sopenharmony_ci color: 'always', 2311cb0ef41Sopenharmony_ci }, 2321cb0ef41Sopenharmony_ci }) 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_ci await mock.explain.exec(exec) 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci return mock.joinedOutput() 2371cb0ef41Sopenharmony_ci } 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ci t.test('should explain workspaces deps', async t => { 2401cb0ef41Sopenharmony_ci const OUTPUT = await mockWorkspaces(t, ['wrappy']) 2411cb0ef41Sopenharmony_ci t.strictSame( 2421cb0ef41Sopenharmony_ci OUTPUT, 2431cb0ef41Sopenharmony_ci 'wrappy@2.0.0 depth=Infinity color=true' 2441cb0ef41Sopenharmony_ci ) 2451cb0ef41Sopenharmony_ci }) 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci t.test('should explain deps when filtering to a single ws', async t => { 2481cb0ef41Sopenharmony_ci const OUTPUT = await mockWorkspaces(t, ['wrappy'], ['a']) 2491cb0ef41Sopenharmony_ci t.strictSame( 2501cb0ef41Sopenharmony_ci OUTPUT, 2511cb0ef41Sopenharmony_ci 'wrappy@2.0.0 depth=Infinity color=true' 2521cb0ef41Sopenharmony_ci ) 2531cb0ef41Sopenharmony_ci }) 2541cb0ef41Sopenharmony_ci 2551cb0ef41Sopenharmony_ci t.test('should explain deps of workspaces only', async t => { 2561cb0ef41Sopenharmony_ci const OUTPUT = await mockWorkspaces(t, ['abbrev']) 2571cb0ef41Sopenharmony_ci t.strictSame( 2581cb0ef41Sopenharmony_ci OUTPUT, 2591cb0ef41Sopenharmony_ci 'abbrev@1.0.0 depth=Infinity color=true' 2601cb0ef41Sopenharmony_ci ) 2611cb0ef41Sopenharmony_ci }) 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_ci t.test('should throw usage if dep not found within filtered ws', async t => { 2641cb0ef41Sopenharmony_ci await t.rejects( 2651cb0ef41Sopenharmony_ci mockWorkspaces(t, ['abbrev'], ['a']), 2661cb0ef41Sopenharmony_ci 'No dependencies found matching abbrev' 2671cb0ef41Sopenharmony_ci ) 2681cb0ef41Sopenharmony_ci }) 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_ci t.test('workspaces disabled', async t => { 2711cb0ef41Sopenharmony_ci await t.rejects( 2721cb0ef41Sopenharmony_ci mockWorkspaces(t, ['once'], false), 2731cb0ef41Sopenharmony_ci 'No dependencies found matching once', 2741cb0ef41Sopenharmony_ci 'should throw usage if dep not found when excluding ws' 2751cb0ef41Sopenharmony_ci ) 2761cb0ef41Sopenharmony_ci }) 2771cb0ef41Sopenharmony_ci}) 278