@toptal/davinci-cli-shared 2.6.1 → 3.0.1-alpha-ff-79-27a22fcb.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/package.json +5 -4
- package/src/index.js +3 -0
- package/src/utils/files.js +4 -2
- package/src/utils/package.js +11 -6
- package/src/utils/package.test.js +54 -18
- package/src/utils/resolve-bin.js +61 -0
- package/src/utils/resolve-bin.test.js +60 -0
- package/src/utils/yarn-adapter.js +0 -47
- package/src/utils/yarn-adapter.test.js +0 -58
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 3.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- [#2643](https://github.com/toptal/davinci/pull/2643) [`ab9666f`](https://github.com/toptal/davinci/commit/ab9666f999e7a610f6068e0145200257d8511b46) Thanks [@rocodesign](https://github.com/rocodesign)!
|
|
8
|
+
Migrate package manager from Yarn to pnpm
|
|
9
|
+
**WHAT (breaking change):**
|
|
10
|
+
- switch package manager from Yarn to pnpm across the entire Davinci monorepo
|
|
11
|
+
- add `pnpm-workspace.yaml`, `.npmrc`, and `packageManager` field for corepack support
|
|
12
|
+
- convert Yarn `resolutions` to `pnpm.overrides` in root `package.json`
|
|
13
|
+
- update lerna `npmClient` from `yarn` to `pnpm`
|
|
14
|
+
- replace `yarn` with `pnpm` in root scripts (postinstall, test, test:unit:update)
|
|
15
|
+
**HOW to update:**
|
|
16
|
+
- install pnpm (`corepack enable` or `npm install -g pnpm@10.6.1`)
|
|
17
|
+
- replace `yarn install` with `pnpm install` in local workflows
|
|
18
|
+
- replace `yarn <script>` with `pnpm <script>` when running commands
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- Updated dependencies [[`ab9666f`](https://github.com/toptal/davinci/commit/ab9666f999e7a610f6068e0145200257d8511b46)]:
|
|
23
|
+
- @toptal/davinci-workspace-root@2.0.0
|
|
24
|
+
|
|
3
25
|
## 2.6.1
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toptal/davinci-cli-shared",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1-alpha-ff-79-27a22fcb.1+27a22fcb",
|
|
4
4
|
"description": "Shared CLI code and CLI engine for davinci",
|
|
5
5
|
"author": "Toptal",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE.MD",
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
"CHANGELOG.md"
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|
|
18
|
-
"test": "NODE_OPTIONS='--experimental-vm-modules --no-warnings'
|
|
18
|
+
"test": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' pnpm jest"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@segment/analytics-node": "^2.1.3",
|
|
22
|
-
"@toptal/davinci-workspace-root": "^
|
|
22
|
+
"@toptal/davinci-workspace-root": "^2.0.1-alpha-ff-79-27a22fcb.1+27a22fcb",
|
|
23
23
|
"chalk": "^4.1.2",
|
|
24
24
|
"commander": "^11.0.0",
|
|
25
25
|
"execa": "^5.1.1",
|
|
@@ -39,5 +39,6 @@
|
|
|
39
39
|
},
|
|
40
40
|
"publishConfig": {
|
|
41
41
|
"access": "public"
|
|
42
|
-
}
|
|
42
|
+
},
|
|
43
|
+
"gitHead": "27a22fcb012002a99ab87a4a996721e3ba8a92c4"
|
|
43
44
|
}
|
package/src/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createArgument, createOption } from 'commander'
|
|
|
2
2
|
|
|
3
3
|
import cliPrint from './utils/print.cjs'
|
|
4
4
|
import { run, runSync } from './utils/run.js'
|
|
5
|
+
import { resolveBin } from './utils/resolve-bin.js'
|
|
5
6
|
import { confirm, password, input, checkbox } from './utils/prompt.js'
|
|
6
7
|
import { convertToCLIParameters } from './utils/convert-to-cli-parameters.js'
|
|
7
8
|
import davinciConfig from './utils/davinci-project-config.cjs'
|
|
@@ -39,6 +40,7 @@ export const loadCommands = (
|
|
|
39
40
|
|
|
40
41
|
export {
|
|
41
42
|
davinciProjectConfig,
|
|
43
|
+
resolveBin,
|
|
42
44
|
run,
|
|
43
45
|
runSync,
|
|
44
46
|
convertToCLIParameters,
|
|
@@ -84,6 +86,7 @@ export default {
|
|
|
84
86
|
bootstrap,
|
|
85
87
|
loadCommands,
|
|
86
88
|
print,
|
|
89
|
+
resolveBin,
|
|
87
90
|
run,
|
|
88
91
|
runSync,
|
|
89
92
|
prompt,
|
package/src/utils/files.js
CHANGED
|
@@ -17,7 +17,9 @@ export const getPackageFileContent = async (davinciPackageName, filename) => {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export const getPackageFilePath = (davinciPackageName, filename) => {
|
|
20
|
-
const packageIndexPath = require.resolve(davinciPackageName
|
|
20
|
+
const packageIndexPath = require.resolve(davinciPackageName, {
|
|
21
|
+
paths: [process.cwd()],
|
|
22
|
+
})
|
|
21
23
|
const davinciQARoot = path.join(packageIndexPath, '../..')
|
|
22
24
|
|
|
23
25
|
return path.join(davinciQARoot, filename)
|
|
@@ -31,7 +33,7 @@ export const getProjectRootFilePath = filename => {
|
|
|
31
33
|
|
|
32
34
|
export const projectHasPackage = pkg => {
|
|
33
35
|
try {
|
|
34
|
-
require.resolve(pkg)
|
|
36
|
+
require.resolve(pkg, { paths: [process.cwd()] })
|
|
35
37
|
|
|
36
38
|
return true
|
|
37
39
|
} catch {
|
package/src/utils/package.js
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { createRequire } from 'module'
|
|
1
4
|
import semver from 'semver'
|
|
2
5
|
import readPkgUp from 'read-pkg-up'
|
|
3
6
|
|
|
4
|
-
import yarnAdapter from './yarn-adapter.js'
|
|
5
|
-
|
|
6
7
|
export const getPackagePackageJson = cwd => {
|
|
7
8
|
return readPkgUp.sync({ cwd }).packageJson
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
const getInstalledPackageVersion = packageName => {
|
|
11
|
-
const
|
|
12
|
+
const requireFromCwd = createRequire(path.join(process.cwd(), 'package.json'))
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
const packageEntryPath = requireFromCwd.resolve(packageName)
|
|
16
|
+
const packageJsonPath = readPkgUp.sync({ cwd: packageEntryPath }).path
|
|
17
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
|
|
12
18
|
|
|
13
|
-
|
|
19
|
+
return packageJson.version
|
|
20
|
+
} catch {
|
|
14
21
|
return null
|
|
15
22
|
}
|
|
16
|
-
|
|
17
|
-
return packageInfoList.get(packageName)
|
|
18
23
|
}
|
|
19
24
|
|
|
20
25
|
export const checkPrerequirement = ({ dependencies, packageName }) => {
|
|
@@ -1,23 +1,20 @@
|
|
|
1
|
-
import
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import os from 'os'
|
|
3
|
+
import path from 'path'
|
|
2
4
|
|
|
3
5
|
import { checkPrerequirement } from './package.js'
|
|
4
|
-
import yarnAdapter from './yarn-adapter.js'
|
|
5
|
-
|
|
6
|
-
const yarnAdapterListMock = jest.spyOn(yarnAdapter, 'list')
|
|
7
6
|
|
|
8
7
|
const packageName = '@toptal/davinci-engine'
|
|
9
8
|
const packageValidVersions = [
|
|
10
9
|
'4.0.0',
|
|
11
|
-
'4',
|
|
12
|
-
'
|
|
10
|
+
'4.4.0',
|
|
11
|
+
'5.6.7',
|
|
13
12
|
'4.1.13-alpha-FX-1234-my-branch.1',
|
|
14
|
-
'^3',
|
|
15
|
-
'~5.6.7',
|
|
16
13
|
]
|
|
17
14
|
const packageInvalidVersions = [
|
|
18
15
|
'2.0.0',
|
|
19
|
-
'6',
|
|
20
|
-
'1.4',
|
|
16
|
+
'6.0.0',
|
|
17
|
+
'1.4.0',
|
|
21
18
|
'1.1.13-alpha-FX-1234-my-branch.1',
|
|
22
19
|
]
|
|
23
20
|
const validVersionRange = '3 - 5'
|
|
@@ -25,11 +22,54 @@ const packageJsonDependencies = {
|
|
|
25
22
|
[packageName]: validVersionRange,
|
|
26
23
|
}
|
|
27
24
|
|
|
25
|
+
const createProjectPackageJson = tempDir => {
|
|
26
|
+
fs.writeFileSync(
|
|
27
|
+
path.join(tempDir, 'package.json'),
|
|
28
|
+
JSON.stringify({
|
|
29
|
+
name: 'test-project',
|
|
30
|
+
private: true,
|
|
31
|
+
version: '1.0.0',
|
|
32
|
+
})
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const installPackage = (tempDir, version) => {
|
|
37
|
+
const packageDir = path.join(
|
|
38
|
+
tempDir,
|
|
39
|
+
'node_modules',
|
|
40
|
+
...packageName.split('/')
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
fs.mkdirSync(packageDir, { recursive: true })
|
|
44
|
+
fs.writeFileSync(
|
|
45
|
+
path.join(packageDir, 'package.json'),
|
|
46
|
+
JSON.stringify({
|
|
47
|
+
name: packageName,
|
|
48
|
+
main: 'index.js',
|
|
49
|
+
version,
|
|
50
|
+
})
|
|
51
|
+
)
|
|
52
|
+
fs.writeFileSync(path.join(packageDir, 'index.js'), 'module.exports = {}')
|
|
53
|
+
}
|
|
54
|
+
|
|
28
55
|
describe('package utils', () => {
|
|
56
|
+
let initialCwd
|
|
57
|
+
let tempDir
|
|
58
|
+
|
|
59
|
+
beforeEach(() => {
|
|
60
|
+
initialCwd = process.cwd()
|
|
61
|
+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'davinci-package-test-'))
|
|
62
|
+
createProjectPackageJson(tempDir)
|
|
63
|
+
process.chdir(tempDir)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
afterEach(() => {
|
|
67
|
+
process.chdir(initialCwd)
|
|
68
|
+
fs.rmSync(tempDir, { force: true, recursive: true })
|
|
69
|
+
})
|
|
70
|
+
|
|
29
71
|
describe('checkPrerequirement', () => {
|
|
30
72
|
it('should return an error when package is not installed', () => {
|
|
31
|
-
yarnAdapterListMock.mockReturnValueOnce(new Map())
|
|
32
|
-
|
|
33
73
|
const result = checkPrerequirement({
|
|
34
74
|
dependencies: packageJsonDependencies,
|
|
35
75
|
packageName,
|
|
@@ -41,9 +81,7 @@ describe('package utils', () => {
|
|
|
41
81
|
it.each(packageValidVersions)(
|
|
42
82
|
`should return no errors for version %s in range ${validVersionRange}`,
|
|
43
83
|
packageValidVersion => {
|
|
44
|
-
|
|
45
|
-
new Map([[packageName, packageValidVersion]])
|
|
46
|
-
)
|
|
84
|
+
installPackage(tempDir, packageValidVersion)
|
|
47
85
|
|
|
48
86
|
const result = checkPrerequirement({
|
|
49
87
|
dependencies: packageJsonDependencies,
|
|
@@ -57,9 +95,7 @@ describe('package utils', () => {
|
|
|
57
95
|
it.each(packageInvalidVersions)(
|
|
58
96
|
`should return an error for version %s in range ${validVersionRange}`,
|
|
59
97
|
packageInvalidVersion => {
|
|
60
|
-
|
|
61
|
-
new Map([[packageName, packageInvalidVersion]])
|
|
62
|
-
)
|
|
98
|
+
installPackage(tempDir, packageInvalidVersion)
|
|
63
99
|
|
|
64
100
|
const result = checkPrerequirement({
|
|
65
101
|
dependencies: packageJsonDependencies,
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { createRequire } from 'module'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { readFileSync } from 'fs'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Resolves a binary from a package's own dependencies.
|
|
7
|
+
*
|
|
8
|
+
* Under pnpm, transitive dependency binaries are not hoisted to the
|
|
9
|
+
* consumer's node_modules/.bin. This function uses the caller's
|
|
10
|
+
* import.meta.url so that require.resolve looks up from the Davinci
|
|
11
|
+
* package that actually declares the dependency, not from the consumer.
|
|
12
|
+
*
|
|
13
|
+
* @param {string} packageName npm package that owns the binary (e.g. 'eslint', '@sentry/cli')
|
|
14
|
+
* @param {string} callerUrl pass import.meta.url from the calling module
|
|
15
|
+
* @param {string} [binName] name of the binary when it differs from the package's unscoped name
|
|
16
|
+
* @returns {string} absolute path to the binary
|
|
17
|
+
*/
|
|
18
|
+
export const resolveBin = (packageName, callerUrl, binName) => {
|
|
19
|
+
const req = createRequire(callerUrl)
|
|
20
|
+
|
|
21
|
+
let pkgJsonPath
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
pkgJsonPath = req.resolve(`${packageName}/package.json`)
|
|
25
|
+
} catch {
|
|
26
|
+
// Some packages (e.g. lerna) have an exports map that doesn't expose
|
|
27
|
+
// package.json. Fall back to resolving the main entry and walking up.
|
|
28
|
+
const mainEntry = req.resolve(packageName)
|
|
29
|
+
const nodeModulesSegment = `node_modules/${packageName}`
|
|
30
|
+
const idx = mainEntry.lastIndexOf(nodeModulesSegment)
|
|
31
|
+
|
|
32
|
+
pkgJsonPath = path.join(
|
|
33
|
+
mainEntry.slice(0, idx + nodeModulesSegment.length),
|
|
34
|
+
'package.json'
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const pkgDir = path.dirname(pkgJsonPath)
|
|
39
|
+
const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf8'))
|
|
40
|
+
|
|
41
|
+
const target = binName || packageName.split('/').pop()
|
|
42
|
+
const binField = pkgJson.bin
|
|
43
|
+
|
|
44
|
+
let binRelPath
|
|
45
|
+
|
|
46
|
+
if (typeof binField === 'string') {
|
|
47
|
+
binRelPath = binField
|
|
48
|
+
} else if (binField && binField[target]) {
|
|
49
|
+
binRelPath = binField[target]
|
|
50
|
+
} else if (binField) {
|
|
51
|
+
binRelPath = Object.values(binField)[0]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!binRelPath) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
`Cannot resolve bin "${target}" from package "${packageName}"`
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return path.resolve(pkgDir, binRelPath)
|
|
61
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import { fileURLToPath, pathToFileURL } from 'url'
|
|
3
|
+
|
|
4
|
+
import { resolveBin } from './resolve-bin.js'
|
|
5
|
+
|
|
6
|
+
// Build a caller URL that resolves from @toptal/davinci-monorepo's context
|
|
7
|
+
// Use direct path instead of require.resolve since pnpm doesn't hoist workspace siblings
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
9
|
+
const monorepoDir = path.resolve(__dirname, '../../../monorepo')
|
|
10
|
+
const monorepoCallerUrl = pathToFileURL(
|
|
11
|
+
path.join(monorepoDir, 'src/index.js')
|
|
12
|
+
).href
|
|
13
|
+
|
|
14
|
+
describe('resolveBin', () => {
|
|
15
|
+
describe('when package exposes package.json in exports', () => {
|
|
16
|
+
it('resolves the binary path for a package with object bin field', () => {
|
|
17
|
+
// semver is a dependency of cli-shared and has bin: { semver: "bin/semver.js" }
|
|
18
|
+
const result = resolveBin('semver', import.meta.url)
|
|
19
|
+
|
|
20
|
+
expect(result).toContain('semver')
|
|
21
|
+
expect(result).toMatch(/bin\/semver\.js$/)
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
describe('when package does not expose package.json in exports', () => {
|
|
26
|
+
it('falls back to resolving via main entry', () => {
|
|
27
|
+
// lerna has an exports map that blocks package.json access
|
|
28
|
+
const result = resolveBin('lerna', monorepoCallerUrl)
|
|
29
|
+
|
|
30
|
+
expect(result).toContain('lerna')
|
|
31
|
+
expect(result).toMatch(/cli\.js$/)
|
|
32
|
+
})
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
describe('when custom binName is provided', () => {
|
|
36
|
+
it('resolves the correct binary', () => {
|
|
37
|
+
const result = resolveBin('npm-check-updates', monorepoCallerUrl, 'ncu')
|
|
38
|
+
|
|
39
|
+
expect(result).toContain('npm-check-updates')
|
|
40
|
+
expect(result).toMatch(/cli\.js$/)
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
describe('when package is not installed', () => {
|
|
45
|
+
it('throws an error', () => {
|
|
46
|
+
expect(() =>
|
|
47
|
+
resolveBin('nonexistent-package-xyz', import.meta.url)
|
|
48
|
+
).toThrow()
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
describe('when package has no bin field', () => {
|
|
53
|
+
it('throws with a descriptive error', () => {
|
|
54
|
+
// ramda has no bin field
|
|
55
|
+
expect(() => resolveBin('ramda', monorepoCallerUrl)).toThrow(
|
|
56
|
+
/Cannot resolve bin/
|
|
57
|
+
)
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
})
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { runSync } from './run.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
* @param {string} treeName
|
|
6
|
-
* @example '@toptal/davinci-engine@7.5.2'
|
|
7
|
-
* @returns {Array} Pair package name and version, ex. ['@toptal/davinci-engine', '16.0.2']
|
|
8
|
-
*/
|
|
9
|
-
const splitNameAndVersion = treeName => {
|
|
10
|
-
const atPos = treeName.lastIndexOf('@')
|
|
11
|
-
|
|
12
|
-
return [treeName.slice(0, atPos), treeName.slice(atPos + 1)]
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export const createList = syncRun => packageName => {
|
|
16
|
-
const { stdout } = syncRun(
|
|
17
|
-
'yarn',
|
|
18
|
-
[
|
|
19
|
-
'list',
|
|
20
|
-
'--json',
|
|
21
|
-
'--no-progress',
|
|
22
|
-
'--non-interactive',
|
|
23
|
-
'--depth=0',
|
|
24
|
-
'--pattern',
|
|
25
|
-
packageName,
|
|
26
|
-
],
|
|
27
|
-
{
|
|
28
|
-
stdio: undefined,
|
|
29
|
-
}
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
const listInfo = JSON.parse(stdout)
|
|
33
|
-
const packagesFound = listInfo?.data?.trees || []
|
|
34
|
-
|
|
35
|
-
if (packagesFound.length <= 0) {
|
|
36
|
-
return new Map()
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return new Map(packagesFound.map(pkg => splitNameAndVersion(pkg.name)))
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export const list = createList(runSync)
|
|
43
|
-
|
|
44
|
-
export default {
|
|
45
|
-
list,
|
|
46
|
-
createList,
|
|
47
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { jest } from '@jest/globals'
|
|
2
|
-
|
|
3
|
-
import { createList } from './yarn-adapter.js'
|
|
4
|
-
import run from './run.js'
|
|
5
|
-
|
|
6
|
-
const packageName = 'find-up'
|
|
7
|
-
const packageVersion = '5.0.0'
|
|
8
|
-
const existingPackageResponseMock = `{"type":"tree","data":{"type":"list","trees":[{"name":"${packageName}@${packageVersion}","children":[],"hint":null,"color":null,"depth":0}]}}`
|
|
9
|
-
const nonExistingPackageResponseMock = `{"type":"tree","data":{"type":"list","trees":[]}}`
|
|
10
|
-
const invalidResponseMock = 'invalid-response'
|
|
11
|
-
|
|
12
|
-
const runSyncMock = jest.spyOn(run, 'runSync')
|
|
13
|
-
const yarnListInjected = createList(runSyncMock)
|
|
14
|
-
|
|
15
|
-
describe('yarnAdapter', () => {
|
|
16
|
-
describe('list', () => {
|
|
17
|
-
it('should return a version for the existing package', () => {
|
|
18
|
-
runSyncMock.mockReturnValueOnce({
|
|
19
|
-
stdout: existingPackageResponseMock,
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
const result = yarnListInjected(packageName)
|
|
23
|
-
|
|
24
|
-
expect(result.size).toBe(1)
|
|
25
|
-
expect(result.get(packageName)).toBe(packageVersion)
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
it('should return empty map for non-existing package', () => {
|
|
29
|
-
runSyncMock.mockImplementationOnce(() => ({
|
|
30
|
-
stdout: nonExistingPackageResponseMock,
|
|
31
|
-
}))
|
|
32
|
-
|
|
33
|
-
const result = yarnListInjected(packageName)
|
|
34
|
-
|
|
35
|
-
expect(result.size).toBe(0)
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('should throw an error for invalid response', () => {
|
|
39
|
-
runSyncMock.mockReturnValueOnce({
|
|
40
|
-
stdout: invalidResponseMock,
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
expect(() => {
|
|
44
|
-
yarnListInjected(packageName)
|
|
45
|
-
}).toThrow()
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
it('should throw an error for empty response', () => {
|
|
49
|
-
runSyncMock.mockReturnValueOnce({
|
|
50
|
-
stdout: '',
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
expect(() => {
|
|
54
|
-
yarnListInjected(packageName)
|
|
55
|
-
}).toThrow()
|
|
56
|
-
})
|
|
57
|
-
})
|
|
58
|
-
})
|