2021-04-15 21:53:45 -04:00
|
|
|
const t = require('tap')
|
2023-01-16 22:38:23 -05:00
|
|
|
const mockNpm = require('../../fixtures/mock-npm')
|
2020-10-02 17:52:19 -04:00
|
|
|
|
|
|
|
const version = '1.0.0'
|
2023-01-16 22:38:23 -05:00
|
|
|
|
2020-10-02 17:52:19 -04:00
|
|
|
const funding = {
|
|
|
|
type: 'individual',
|
2020-11-17 15:37:44 -05:00
|
|
|
url: 'http://example.com/donate',
|
2020-10-02 17:52:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
const maintainerOwnsAllDeps = {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'maintainer-owns-all-deps',
|
|
|
|
version,
|
|
|
|
funding,
|
|
|
|
dependencies: {
|
|
|
|
'dep-foo': '*',
|
2020-11-17 15:37:44 -05:00
|
|
|
'dep-bar': '*',
|
|
|
|
},
|
2020-10-02 17:52:19 -04:00
|
|
|
}),
|
|
|
|
node_modules: {
|
|
|
|
'dep-foo': {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'dep-foo',
|
|
|
|
version,
|
|
|
|
funding,
|
|
|
|
dependencies: {
|
2020-11-17 15:37:44 -05:00
|
|
|
'dep-sub-foo': '*',
|
|
|
|
},
|
2020-10-02 17:52:19 -04:00
|
|
|
}),
|
|
|
|
node_modules: {
|
|
|
|
'dep-sub-foo': {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'dep-sub-foo',
|
|
|
|
version,
|
2020-11-17 15:37:44 -05:00
|
|
|
funding,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
},
|
2020-10-02 17:52:19 -04:00
|
|
|
},
|
|
|
|
'dep-bar': {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'dep-bar',
|
|
|
|
version,
|
2020-11-17 15:37:44 -05:00
|
|
|
funding,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
},
|
2020-10-02 17:52:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
const nestedNoFundingPackages = {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'nested-no-funding-packages',
|
|
|
|
version,
|
|
|
|
dependencies: {
|
2020-11-17 15:37:44 -05:00
|
|
|
foo: '*',
|
2020-10-02 17:52:19 -04:00
|
|
|
},
|
|
|
|
devDependencies: {
|
2020-11-17 15:37:44 -05:00
|
|
|
lorem: '*',
|
|
|
|
},
|
2020-10-02 17:52:19 -04:00
|
|
|
}),
|
|
|
|
node_modules: {
|
|
|
|
foo: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'foo',
|
|
|
|
version,
|
|
|
|
dependencies: {
|
2020-11-17 15:37:44 -05:00
|
|
|
bar: '*',
|
|
|
|
},
|
2020-10-02 17:52:19 -04:00
|
|
|
}),
|
|
|
|
node_modules: {
|
|
|
|
bar: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'bar',
|
|
|
|
version,
|
2020-11-17 15:37:44 -05:00
|
|
|
funding,
|
2020-10-02 17:52:19 -04:00
|
|
|
}),
|
|
|
|
node_modules: {
|
|
|
|
'sub-bar': {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'sub-bar',
|
|
|
|
version,
|
2020-11-17 15:37:44 -05:00
|
|
|
funding: 'https://example.com/sponsor',
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2020-10-02 17:52:19 -04:00
|
|
|
},
|
|
|
|
lorem: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'lorem',
|
|
|
|
version,
|
|
|
|
funding: {
|
2020-11-17 15:37:44 -05:00
|
|
|
url: 'https://example.com/lorem',
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
},
|
2020-10-02 17:52:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
const nestedMultipleFundingPackages = {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'nested-multiple-funding-packages',
|
|
|
|
version,
|
2021-11-18 20:58:02 +00:00
|
|
|
funding: ['https://one.example.com', 'https://two.example.com'],
|
2020-10-02 17:52:19 -04:00
|
|
|
dependencies: {
|
2020-11-17 15:37:44 -05:00
|
|
|
foo: '*',
|
2020-10-02 17:52:19 -04:00
|
|
|
},
|
|
|
|
devDependencies: {
|
2020-11-17 15:37:44 -05:00
|
|
|
bar: '*',
|
|
|
|
},
|
2020-10-02 17:52:19 -04:00
|
|
|
}),
|
|
|
|
node_modules: {
|
|
|
|
foo: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'foo',
|
|
|
|
version,
|
|
|
|
funding: [
|
|
|
|
'http://example.com',
|
|
|
|
{ url: 'http://sponsors.example.com/me' },
|
2020-11-17 15:37:44 -05:00
|
|
|
'http://collective.example.com',
|
|
|
|
],
|
|
|
|
}),
|
2020-10-02 17:52:19 -04:00
|
|
|
},
|
|
|
|
bar: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'bar',
|
|
|
|
version,
|
2021-11-18 20:58:02 +00:00
|
|
|
funding: ['http://collective.example.com', { url: 'http://sponsors.example.com/you' }],
|
2020-11-17 15:37:44 -05:00
|
|
|
}),
|
|
|
|
},
|
|
|
|
},
|
2020-10-02 17:52:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
const conflictingFundingPackages = {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'conflicting-funding-packages',
|
|
|
|
version,
|
|
|
|
dependencies: {
|
2020-11-17 15:37:44 -05:00
|
|
|
foo: '1.0.0',
|
2020-10-02 17:52:19 -04:00
|
|
|
},
|
|
|
|
devDependencies: {
|
2020-11-17 15:37:44 -05:00
|
|
|
bar: '1.0.0',
|
|
|
|
},
|
2020-10-02 17:52:19 -04:00
|
|
|
}),
|
|
|
|
node_modules: {
|
|
|
|
foo: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'foo',
|
|
|
|
version: '1.0.0',
|
2020-11-17 15:37:44 -05:00
|
|
|
funding: 'http://example.com/1',
|
|
|
|
}),
|
2020-10-02 17:52:19 -04:00
|
|
|
},
|
|
|
|
bar: {
|
|
|
|
node_modules: {
|
|
|
|
foo: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'foo',
|
|
|
|
version: '2.0.0',
|
2020-11-17 15:37:44 -05:00
|
|
|
funding: 'http://example.com/2',
|
|
|
|
}),
|
|
|
|
},
|
2020-10-02 17:52:19 -04:00
|
|
|
},
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'bar',
|
|
|
|
version: '1.0.0',
|
|
|
|
dependencies: {
|
2020-11-17 15:37:44 -05:00
|
|
|
foo: '2.0.0',
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
},
|
2020-10-02 17:52:19 -04:00
|
|
|
}
|
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
const setup = async (t, { openUrl, ...opts } = {}) => {
|
|
|
|
const openedUrls = []
|
|
|
|
|
|
|
|
const res = await mockNpm(t, {
|
|
|
|
...opts,
|
|
|
|
mocks: {
|
|
|
|
'@npmcli/promise-spawn': { open: openUrl || (async url => openedUrls.push(url)) },
|
|
|
|
pacote: {
|
|
|
|
manifest: arg =>
|
|
|
|
arg.name === 'ntl'
|
|
|
|
? Promise.resolve({ funding: 'http://example.com/pacote' })
|
|
|
|
: Promise.reject(new Error('ERROR')),
|
|
|
|
},
|
|
|
|
...opts.mocks,
|
|
|
|
},
|
|
|
|
})
|
2021-03-04 17:40:28 -05:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
return {
|
|
|
|
...res,
|
|
|
|
openedUrls: () => openedUrls,
|
|
|
|
fund: (...args) => res.npm.exec('fund', args),
|
2021-11-18 20:58:02 +00:00
|
|
|
}
|
2020-10-02 17:52:19 -04:00
|
|
|
}
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund with no package containing funding', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund, joinedOutput } = await setup(t, {
|
|
|
|
prefixDir: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'no-funding-package',
|
|
|
|
version: '0.0.0',
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
config: {},
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund()
|
|
|
|
t.matchSnapshot(joinedOutput(), 'should print empty funding info')
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund in which same maintainer owns all its deps', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund, joinedOutput } = await setup(t, {
|
|
|
|
prefixDir: maintainerOwnsAllDeps,
|
|
|
|
config: {},
|
|
|
|
})
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund()
|
|
|
|
t.matchSnapshot(joinedOutput(), 'should print stack packages together')
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund in which same maintainer owns all its deps, using --json option', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund, joinedOutput } = await setup(t, {
|
|
|
|
prefixDir: maintainerOwnsAllDeps,
|
|
|
|
config: { json: true },
|
|
|
|
})
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund()
|
2021-11-04 20:42:47 +00:00
|
|
|
t.same(
|
2023-01-16 22:38:23 -05:00
|
|
|
JSON.parse(joinedOutput()),
|
2021-11-04 20:42:47 +00:00
|
|
|
{
|
|
|
|
length: 3,
|
|
|
|
name: 'maintainer-owns-all-deps',
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: { type: 'individual', url: 'http://example.com/donate' },
|
|
|
|
dependencies: {
|
|
|
|
'dep-bar': {
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: { type: 'individual', url: 'http://example.com/donate' },
|
|
|
|
},
|
|
|
|
'dep-foo': {
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: { type: 'individual', url: 'http://example.com/donate' },
|
|
|
|
dependencies: {
|
|
|
|
'dep-sub-foo': {
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: { type: 'individual', url: 'http://example.com/donate' },
|
2020-11-17 15:37:44 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2020-10-02 17:52:19 -04:00
|
|
|
},
|
2021-11-04 20:42:47 +00:00
|
|
|
},
|
|
|
|
'should print stack packages together'
|
|
|
|
)
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund containing multi-level nested deps with no funding', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund, joinedOutput } = await setup(t, {
|
|
|
|
prefixDir: nestedNoFundingPackages,
|
|
|
|
config: {},
|
|
|
|
})
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund()
|
|
|
|
t.matchSnapshot(joinedOutput(), 'should omit dependencies with no funding declared')
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund containing multi-level nested deps with no funding, using --json option', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund, joinedOutput } = await setup(t, {
|
|
|
|
prefixDir: nestedNoFundingPackages,
|
|
|
|
config: { json: true },
|
|
|
|
})
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund()
|
2021-11-04 20:42:47 +00:00
|
|
|
t.same(
|
2023-01-16 22:38:23 -05:00
|
|
|
JSON.parse(joinedOutput()),
|
2021-11-04 20:42:47 +00:00
|
|
|
{
|
|
|
|
length: 2,
|
|
|
|
name: 'nested-no-funding-packages',
|
|
|
|
version: '1.0.0',
|
|
|
|
dependencies: {
|
|
|
|
lorem: {
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: { url: 'https://example.com/lorem' },
|
|
|
|
},
|
|
|
|
bar: {
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: { type: 'individual', url: 'http://example.com/donate' },
|
2020-11-17 15:37:44 -05:00
|
|
|
},
|
2020-10-02 17:52:19 -04:00
|
|
|
},
|
2021-11-04 20:42:47 +00:00
|
|
|
},
|
|
|
|
'should omit dependencies with no funding declared in json output'
|
|
|
|
)
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund containing multi-level nested deps with no funding, using --json option', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund, joinedOutput } = await setup(t, {
|
|
|
|
prefixDir: nestedMultipleFundingPackages,
|
|
|
|
config: { json: true },
|
|
|
|
})
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund()
|
2021-11-04 20:42:47 +00:00
|
|
|
t.same(
|
2023-01-16 22:38:23 -05:00
|
|
|
JSON.parse(joinedOutput()),
|
2021-11-04 20:42:47 +00:00
|
|
|
{
|
|
|
|
length: 2,
|
|
|
|
name: 'nested-multiple-funding-packages',
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: [
|
|
|
|
{
|
|
|
|
url: 'https://one.example.com',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
url: 'https://two.example.com',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
dependencies: {
|
|
|
|
bar: {
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: [
|
|
|
|
{
|
|
|
|
url: 'http://collective.example.com',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
url: 'http://sponsors.example.com/you',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
foo: {
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: [
|
|
|
|
{
|
|
|
|
url: 'http://example.com',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
url: 'http://sponsors.example.com/me',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
url: 'http://collective.example.com',
|
|
|
|
},
|
|
|
|
],
|
2020-11-17 15:37:44 -05:00
|
|
|
},
|
2020-10-02 17:52:19 -04:00
|
|
|
},
|
2021-11-04 20:42:47 +00:00
|
|
|
},
|
|
|
|
'should list multiple funding entries in json output'
|
|
|
|
)
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund does not support global', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund } = await setup(t, {
|
|
|
|
config: { global: true },
|
|
|
|
})
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await t.rejects(fund(), { code: 'EFUNDGLOBAL' }, 'should throw EFUNDGLOBAL error')
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund using package argument', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund, openedUrls, joinedOutput } = await setup(t, {
|
|
|
|
prefixDir: maintainerOwnsAllDeps,
|
|
|
|
config: {},
|
|
|
|
})
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund('.')
|
|
|
|
t.equal(joinedOutput(), '')
|
|
|
|
t.strictSame(openedUrls(), ['http://example.com/donate'], 'should open funding url')
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund does not support global, using --json option', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund } = await setup(t, {
|
|
|
|
prefixDir: {},
|
|
|
|
config: { global: true, json: true },
|
|
|
|
})
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
await t.rejects(
|
2023-01-16 22:38:23 -05:00
|
|
|
fund(),
|
2021-11-04 20:42:47 +00:00
|
|
|
{ code: 'EFUNDGLOBAL', message: '`npm fund` does not support global packages' },
|
|
|
|
'should use expected error msg'
|
|
|
|
)
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund using string shorthand', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund, openedUrls } = await setup(t, {
|
|
|
|
prefixDir: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'funding-string-shorthand',
|
|
|
|
version: '0.0.0',
|
|
|
|
funding: 'https://example.com/sponsor',
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
config: {},
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund('.')
|
|
|
|
t.strictSame(openedUrls(), ['https://example.com/sponsor'], 'should open string-only url')
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund using nested packages with multiple sources', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund, joinedOutput } = await setup(t, {
|
|
|
|
prefixDir: nestedMultipleFundingPackages,
|
|
|
|
config: {},
|
|
|
|
})
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund('.')
|
|
|
|
t.matchSnapshot(joinedOutput(), 'should prompt with all available URLs')
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund using symlink ref', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const f = 'http://example.com/a'
|
|
|
|
const { fund, openedUrls } = await setup(t, {
|
|
|
|
prefixDir: {
|
2020-10-02 17:52:19 -04:00
|
|
|
'package.json': JSON.stringify({
|
2023-01-16 22:38:23 -05:00
|
|
|
name: 'using-symlink-ref',
|
2020-10-02 17:52:19 -04:00
|
|
|
version: '1.0.0',
|
2020-11-17 15:37:44 -05:00
|
|
|
}),
|
2023-01-16 22:38:23 -05:00
|
|
|
a: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'a',
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: f,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
node_modules: {
|
|
|
|
a: t.fixture('symlink', '../a'),
|
|
|
|
},
|
2020-10-02 17:52:19 -04:00
|
|
|
},
|
2023-01-16 22:38:23 -05:00
|
|
|
config: {},
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
|
|
|
// using symlinked ref
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund('./node_modules/a')
|
|
|
|
t.strictSame(openedUrls(), [f], 'should retrieve funding url from symlink')
|
2021-11-04 20:42:47 +00:00
|
|
|
|
|
|
|
// using target ref
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund('./a')
|
|
|
|
t.strictSame(openedUrls(), [f, f], 'should retrieve funding url from symlink target')
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund using data from actual tree', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund, openedUrls } = await setup(t, {
|
|
|
|
prefixDir: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'using-actual-tree',
|
|
|
|
version: '1.0.0',
|
|
|
|
}),
|
|
|
|
node_modules: {
|
|
|
|
a: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'a',
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: 'http://example.com/a',
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
b: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'a',
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: 'http://example.com/b',
|
|
|
|
}),
|
|
|
|
node_modules: {
|
|
|
|
a: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'a',
|
|
|
|
version: '1.0.1',
|
|
|
|
funding: 'http://example.com/_AAA',
|
|
|
|
}),
|
|
|
|
},
|
2020-11-17 15:37:44 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2023-01-16 22:38:23 -05:00
|
|
|
config: {},
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
|
|
|
// using symlinked ref
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund('a')
|
|
|
|
t.strictSame(
|
|
|
|
openedUrls(),
|
|
|
|
['http://example.com/_AAA'],
|
2021-11-04 20:42:47 +00:00
|
|
|
'should retrieve fund info from actual tree, using greatest version found'
|
|
|
|
)
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund using nested packages with multiple sources, with a source number', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund, openedUrls } = await setup(t, {
|
|
|
|
prefixDir: nestedMultipleFundingPackages,
|
|
|
|
config: { which: '1' },
|
|
|
|
})
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund('.')
|
|
|
|
t.strictSame(openedUrls(), ['https://one.example.com'], 'should open the numbered URL')
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund using pkg name while having conflicting versions', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund, openedUrls } = await setup(t, {
|
|
|
|
prefixDir: conflictingFundingPackages,
|
|
|
|
config: { which: '1' },
|
|
|
|
})
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund('foo')
|
|
|
|
t.strictSame(openedUrls(), ['http://example.com/2'], 'should open greatest version')
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('fund using bad which value: index too high', async t => {
|
|
|
|
const { fund, joinedOutput } = await setup(t, {
|
|
|
|
prefixDir: nestedMultipleFundingPackages,
|
|
|
|
config: { which: '100' },
|
|
|
|
})
|
|
|
|
|
|
|
|
await fund('foo')
|
|
|
|
t.match(joinedOutput(), 'not a valid index')
|
|
|
|
t.matchSnapshot(joinedOutput(), 'should print message about invalid which')
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund using package argument with no browser, using --json option', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund, openedUrls, joinedOutput } = await setup(t, {
|
|
|
|
prefixDir: maintainerOwnsAllDeps,
|
|
|
|
config: { json: true },
|
|
|
|
})
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund('.')
|
|
|
|
t.equal(joinedOutput(), '', 'no output')
|
2021-11-04 20:42:47 +00:00
|
|
|
t.same(
|
2023-01-16 22:38:23 -05:00
|
|
|
openedUrls(),
|
|
|
|
['http://example.com/donate'],
|
2021-11-04 20:42:47 +00:00
|
|
|
'should open funding url using json output'
|
|
|
|
)
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund using package info fetch from registry', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund, openedUrls } = await setup(t, {
|
|
|
|
prefixDir: {},
|
|
|
|
config: {},
|
|
|
|
})
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund('ntl')
|
2021-11-04 20:42:47 +00:00
|
|
|
t.match(
|
2023-01-16 22:38:23 -05:00
|
|
|
openedUrls(),
|
2021-11-04 20:42:47 +00:00
|
|
|
/http:\/\/example.com\/pacote/,
|
|
|
|
'should open funding url that was loaded from registry manifest'
|
|
|
|
)
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund tries to use package info fetch from registry but registry has nothing', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund } = await setup(t, {
|
|
|
|
prefixDir: {},
|
|
|
|
config: {},
|
|
|
|
})
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
await t.rejects(
|
2023-01-16 22:38:23 -05:00
|
|
|
fund('foo'),
|
2021-11-04 20:42:47 +00:00
|
|
|
{ code: 'ENOFUND', message: 'No valid funding method available for: foo' },
|
|
|
|
'should have no valid funding message'
|
|
|
|
)
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund but target module has no funding info', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund } = await setup(t, {
|
|
|
|
prefixDir: nestedNoFundingPackages,
|
|
|
|
config: {},
|
|
|
|
})
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
await t.rejects(
|
2023-01-16 22:38:23 -05:00
|
|
|
fund('foo'),
|
2021-11-04 20:42:47 +00:00
|
|
|
{ code: 'ENOFUND', message: 'No valid funding method available for: foo' },
|
|
|
|
'should have no valid funding message'
|
|
|
|
)
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund using bad which value', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund } = await setup(t, {
|
|
|
|
prefixDir: nestedMultipleFundingPackages,
|
|
|
|
config: { which: '0' },
|
|
|
|
})
|
2020-10-02 17:52:19 -04:00
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
await t.rejects(
|
2023-01-16 22:38:23 -05:00
|
|
|
fund('bar'),
|
2021-11-18 20:58:02 +00:00
|
|
|
{
|
|
|
|
code: 'EFUNDNUMBER',
|
2023-01-16 22:38:23 -05:00
|
|
|
message: /must be given a positive integer/,
|
2021-11-18 20:58:02 +00:00
|
|
|
},
|
2021-11-04 20:42:47 +00:00
|
|
|
'should have bad which option error message'
|
|
|
|
)
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund pkg missing version number', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund, joinedOutput } = await setup(t, {
|
|
|
|
prefixDir: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'foo',
|
|
|
|
funding: 'http://example.com/foo',
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
config: {},
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund()
|
|
|
|
t.matchSnapshot(joinedOutput(), 'should print name only')
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund a package throws on openUrl', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund } = await setup(t, {
|
|
|
|
prefixDir: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'foo',
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: 'http://npmjs.org',
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
config: {},
|
|
|
|
openUrl: () => {
|
|
|
|
throw new Error('ERROR')
|
|
|
|
},
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await t.rejects(fund('.'), { message: 'ERROR' }, 'should throw unknown error')
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('fund a package with type and multiple sources', async t => {
|
2023-01-16 22:38:23 -05:00
|
|
|
const { fund, joinedOutput } = await setup(t, {
|
|
|
|
prefixDir: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'foo',
|
|
|
|
funding: [
|
|
|
|
{
|
|
|
|
type: 'Foo',
|
|
|
|
url: 'http://example.com/foo',
|
2020-11-17 15:37:44 -05:00
|
|
|
},
|
2023-01-16 22:38:23 -05:00
|
|
|
{
|
|
|
|
type: 'Lorem',
|
|
|
|
url: 'http://example.com/foo-lorem',
|
2020-11-17 15:37:44 -05:00
|
|
|
},
|
2023-01-16 22:38:23 -05:00
|
|
|
],
|
|
|
|
}),
|
2020-11-17 15:37:44 -05:00
|
|
|
},
|
2023-01-16 22:38:23 -05:00
|
|
|
config: {},
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund('.')
|
|
|
|
t.matchSnapshot(joinedOutput(), 'should print prompt select message')
|
2020-10-02 17:52:19 -04:00
|
|
|
})
|
2021-05-13 16:18:53 -04:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
t.test('fund colors', async t => {
|
|
|
|
const { fund, joinedOutput } = await setup(t, {
|
|
|
|
prefixDir: {
|
2021-05-13 16:18:53 -04:00
|
|
|
'package.json': JSON.stringify({
|
2023-01-16 22:38:23 -05:00
|
|
|
name: 'test-fund-colors',
|
2021-05-13 16:18:53 -04:00
|
|
|
version: '1.0.0',
|
|
|
|
dependencies: {
|
2023-01-16 22:38:23 -05:00
|
|
|
a: '^1.0.0',
|
|
|
|
b: '^1.0.0',
|
|
|
|
c: '^1.0.0',
|
2021-05-13 16:18:53 -04:00
|
|
|
},
|
|
|
|
}),
|
|
|
|
node_modules: {
|
2023-01-16 22:38:23 -05:00
|
|
|
a: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'a',
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: 'http://example.com/a',
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
b: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'b',
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: 'http://example.com/b',
|
|
|
|
dependencies: {
|
|
|
|
d: '^1.0.0',
|
|
|
|
e: '^1.0.0',
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
},
|
2021-05-13 16:18:53 -04:00
|
|
|
c: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'c',
|
|
|
|
version: '1.0.0',
|
2023-01-16 22:38:23 -05:00
|
|
|
funding: 'http://example.com/b',
|
2021-05-13 16:18:53 -04:00
|
|
|
}),
|
|
|
|
},
|
|
|
|
d: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'd',
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: 'http://example.com/d',
|
|
|
|
}),
|
|
|
|
},
|
2023-01-16 22:38:23 -05:00
|
|
|
e: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'e',
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: 'http://example.com/e',
|
|
|
|
}),
|
|
|
|
},
|
2021-05-13 16:18:53 -04:00
|
|
|
},
|
2023-01-16 22:38:23 -05:00
|
|
|
},
|
|
|
|
config: { color: 'always' },
|
|
|
|
})
|
|
|
|
|
|
|
|
await fund()
|
|
|
|
t.matchSnapshot(joinedOutput(), 'should print output with color info')
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('sub dep with fund info and a parent with no funding info', async t => {
|
|
|
|
const { fund, joinedOutput } = await setup(t, {
|
|
|
|
prefixDir: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'test-multiple-funding-sources',
|
|
|
|
version: '1.0.0',
|
|
|
|
dependencies: {
|
|
|
|
a: '^1.0.0',
|
|
|
|
b: '^1.0.0',
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
node_modules: {
|
2021-05-13 16:18:53 -04:00
|
|
|
a: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'a',
|
|
|
|
version: '1.0.0',
|
|
|
|
dependencies: {
|
|
|
|
c: '^1.0.0',
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
b: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'b',
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: 'http://example.com/b',
|
2023-01-16 22:38:23 -05:00
|
|
|
}),
|
|
|
|
},
|
|
|
|
c: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'c',
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: ['http://example.com/c', 'http://example.com/c-other'],
|
2021-05-13 16:18:53 -04:00
|
|
|
}),
|
|
|
|
},
|
|
|
|
},
|
2023-01-16 22:38:23 -05:00
|
|
|
},
|
|
|
|
config: {},
|
|
|
|
})
|
2021-05-13 16:18:53 -04:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund()
|
|
|
|
t.matchSnapshot(joinedOutput(), 'should nest sub dep as child of root')
|
|
|
|
})
|
2021-05-13 16:18:53 -04:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
t.test('workspaces', async t => {
|
|
|
|
const wsPrefixDir = {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'workspaces-support',
|
|
|
|
version: '1.0.0',
|
|
|
|
workspaces: ['packages/*'],
|
|
|
|
dependencies: {
|
|
|
|
d: '^1.0.0',
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
node_modules: {
|
|
|
|
a: t.fixture('symlink', '../packages/a'),
|
|
|
|
b: t.fixture('symlink', '../packages/b'),
|
|
|
|
c: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'c',
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: ['http://example.com/c', 'http://example.com/c-other'],
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
d: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'd',
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: 'http://example.com/d',
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
packages: {
|
|
|
|
a: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'a',
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: 'https://example.com/a',
|
|
|
|
dependencies: {
|
|
|
|
c: '^1.0.0',
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
b: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'b',
|
|
|
|
version: '1.0.0',
|
|
|
|
funding: 'http://example.com/b',
|
|
|
|
dependencies: {
|
|
|
|
d: '^1.0.0',
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2021-05-13 16:18:53 -04:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
t.test('filter funding info by a specific workspace name', async t => {
|
|
|
|
const { fund, joinedOutput } = await setup(t, {
|
|
|
|
prefixDir: wsPrefixDir,
|
|
|
|
config: {
|
|
|
|
workspace: 'a',
|
|
|
|
},
|
|
|
|
})
|
2021-05-13 16:18:53 -04:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund()
|
|
|
|
t.matchSnapshot(joinedOutput(), 'should display only filtered workspace name and its deps')
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('filter funding info by a specific workspace path', async t => {
|
|
|
|
const { fund, joinedOutput } = await setup(t, {
|
|
|
|
prefixDir: wsPrefixDir,
|
|
|
|
config: {
|
|
|
|
workspace: './packages/a',
|
|
|
|
},
|
|
|
|
})
|
2021-05-13 16:18:53 -04:00
|
|
|
|
2023-01-16 22:38:23 -05:00
|
|
|
await fund()
|
|
|
|
t.matchSnapshot(joinedOutput(), 'should display only filtered workspace name and its deps')
|
2021-05-13 16:18:53 -04:00
|
|
|
})
|
|
|
|
})
|