@tarojs/cli
Version:
cli tool for taro
325 lines (286 loc) • 8.43 kB
text/typescript
import * as path from 'node:path'
import {
chalk,
fs,
PROJECT_CONFIG,
shouldUseCnpm,
shouldUseYarn
} from '@tarojs/helper'
import { exec } from 'child_process'
import { getPkgVersion } from '../util'
import { run } from './utils'
const runUpdate = run('update', ['commands/update'])
const lastestVersion = getPkgVersion()
jest.mock('child_process', () => {
const exec = jest.fn()
exec.mockReturnValue({
stdout: {
on () {}
},
stderr: {
on () {}
}
})
return {
__esModule: true,
exec
}
})
jest.mock('ora', () => {
const ora = jest.fn()
ora.mockReturnValue({
start () {
return {
stop () {},
warn () {},
succeed () {}
}
}
})
return ora
})
jest.mock('@tarojs/helper', () => {
const helper = jest.requireActual('@tarojs/helper')
const fs = helper.fs
return {
__esModule: true,
...helper,
shouldUseCnpm: jest.fn(),
shouldUseYarn: jest.fn(),
chalk: {
red: jest.fn(),
green () {}
},
fs: {
...fs,
writeJson: jest.fn()
}
}
})
jest.mock('latest-version', () => () => lastestVersion)
function updatePkg (pkgPath: string, version: string) {
let packageMap = require(pkgPath)
packageMap = {
...packageMap,
dependencies: {
...packageMap.dependencies,
'@tarojs/shared': version,
'@tarojs/taro': version,
'@tarojs/cli': version,
'@tarojs/components': version,
'@tarojs/api': version,
'@tarojs/taro-h5': version,
'@tarojs/helper': version,
'@tarojs/taro-loader': version,
'@tarojs/react': version,
'@tarojs/router': version,
'@tarojs/runner-utils': version,
'@tarojs/runtime': version,
'@tarojs/service': version,
'@tarojs/with-weapp': version,
'@tarojs/taroize': version,
'@tarojs/plugin-platform-weapp': version,
'@tarojs/plugin-platform-alipay': version,
'@tarojs/plugin-platform-swan': version,
'@tarojs/plugin-platform-tt': version,
'@tarojs/plugin-platform-jd': version,
'@tarojs/plugin-platform-qq': version,
'@tarojs/plugin-platform-h5': version
},
devDependencies: {
...packageMap.devDependencies,
'babel-preset-taro': version,
'eslint-config-taro': version,
'babel-plugin-transform-taroapi': version,
'postcss-plugin-constparse': version,
'postcss-pxtransform': version
}
}
return packageMap
}
describe('update', () => {
const execMocked = (exec as unknown) as jest.Mock<any>
const shouldUseCnpmMocked = shouldUseCnpm as jest.Mock<any>
const shouldUseYarnMocked = shouldUseYarn as jest.Mock<any>
const writeJson = fs.writeJson as jest.Mock<any>
beforeEach(() => {
shouldUseCnpmMocked.mockReturnValue(false)
shouldUseYarnMocked.mockReturnValue(false)
})
afterEach(() => {
execMocked.mockClear()
shouldUseCnpmMocked.mockReset()
shouldUseYarnMocked.mockReset()
writeJson.mockClear()
})
it('should log errors', async () => {
const spy = jest.spyOn(console, 'log')
spy.mockImplementation(() => {})
await runUpdate('', {
options: {
npm: 'npm',
disableGlobalConfig: true
}
})
expect(spy).toBeCalledTimes(3)
spy.mockRestore()
})
it('should update self', async () => {
await runUpdate('', {
args: ['self'],
options: {
npm: 'npm',
disableGlobalConfig: true
}
})
expect(execMocked).toBeCalledWith(`npm i -g @tarojs/cli@${lastestVersion}`)
})
it('should update self using yarn', async () => {
shouldUseCnpmMocked.mockReturnValue(true)
await runUpdate('', {
args: ['self'],
options: {
npm: 'yarn',
disableGlobalConfig: true
}
})
expect(execMocked).toBeCalledWith(`yarn global add @tarojs/cli@${lastestVersion}`)
})
it('should update self using pnpm', async () => {
shouldUseCnpmMocked.mockReturnValue(true)
await runUpdate('', {
args: ['self'],
options: {
npm: 'pnpm',
disableGlobalConfig: true
}
})
expect(execMocked).toBeCalledWith(`pnpm add -g @tarojs/cli@${lastestVersion}`)
})
it('should update self using cnpm', async () => {
shouldUseCnpmMocked.mockReturnValue(true)
await runUpdate('', {
args: ['self'],
options: {
npm: 'cnpm',
disableGlobalConfig: true
}
})
expect(execMocked).toBeCalledWith(`cnpm i -g @tarojs/cli@${lastestVersion}`)
})
it('should update self to specific version', async () => {
const version = '3.0.0-beta.0'
await runUpdate('', {
args: ['self', version],
options: {
npm: 'npm',
disableGlobalConfig: true
}
})
expect(execMocked).toBeCalledWith(`npm i -g @tarojs/cli@${version}`)
})
it('should throw when there isn\'t a Taro project', async () => {
const chalkMocked = (chalk.red as unknown) as jest.Mock<any>
const exitSpy = jest.spyOn(process, 'exit')
const logSpy = jest.spyOn(console, 'log')
exitSpy.mockImplementation(() => {
throw new Error()
})
logSpy.mockImplementation(() => {})
try {
await runUpdate('', {
args: ['project'],
options: {
npm: 'npm',
disableGlobalConfig: true
}
})
} catch (error) {} // eslint-disable-line no-empty
expect(exitSpy).toBeCalledWith(1)
expect(chalkMocked).toBeCalledWith(`找不到项目配置文件 ${PROJECT_CONFIG},请确定当前目录是 Taro 项目根目录!`)
exitSpy.mockRestore()
logSpy.mockRestore()
})
it('should update project', async () => {
const appPath = path.resolve(__dirname, 'fixtures/default')
const pkgPath = path.join(appPath, 'package.json')
const packageMap = updatePkg(pkgPath, lastestVersion)
const logSpy = jest.spyOn(console, 'log')
logSpy.mockImplementation(() => {})
await runUpdate(appPath, {
args: ['project'],
options: {
npm: 'npm',
disableGlobalConfig: true
}
})
expect(writeJson.mock.calls[0][0]).toEqual(pkgPath)
expect(writeJson.mock.calls[0][1]).toEqual(packageMap)
expect(execMocked).toBeCalledWith('npm install')
logSpy.mockRestore()
})
it('should update project to specific version', async () => {
const version = '3.0.0-beta.4'
const appPath = path.resolve(__dirname, 'fixtures/default')
const pkgPath = path.join(appPath, 'package.json')
const packageMap = updatePkg(pkgPath, version)
const logSpy = jest.spyOn(console, 'log')
logSpy.mockImplementation(() => {})
await runUpdate(appPath, {
args: ['project', version],
options: {
npm: 'npm',
disableGlobalConfig: true
}
})
expect(writeJson.mock.calls[0][0]).toEqual(pkgPath)
expect(writeJson.mock.calls[0][1]).toEqual(packageMap)
expect(execMocked).toBeCalledWith('npm install')
logSpy.mockRestore()
})
it('should update project with yarn', async () => {
const appPath = path.resolve(__dirname, 'fixtures/default')
const logSpy = jest.spyOn(console, 'log')
logSpy.mockImplementation(() => {})
shouldUseYarnMocked.mockReturnValue(true)
await runUpdate(appPath, {
args: ['project'],
options: {
npm: 'yarn',
disableGlobalConfig: true
}
})
expect(execMocked).toBeCalledWith('yarn install')
logSpy.mockRestore()
})
it('should update project with pnpm', async () => {
const appPath = path.resolve(__dirname, 'fixtures/default')
const logSpy = jest.spyOn(console, 'log')
logSpy.mockImplementation(() => {})
shouldUseCnpmMocked.mockReturnValue(true)
await runUpdate(appPath, {
args: ['project'],
options: {
npm: 'pnpm',
disableGlobalConfig: true
}
})
expect(execMocked).toBeCalledWith('pnpm install')
logSpy.mockRestore()
})
it('should update project with cnpm', async () => {
const appPath = path.resolve(__dirname, 'fixtures/default')
const logSpy = jest.spyOn(console, 'log')
logSpy.mockImplementation(() => {})
shouldUseCnpmMocked.mockReturnValue(true)
await runUpdate(appPath, {
args: ['project'],
options: {
npm: 'cnpm',
disableGlobalConfig: true
}
})
expect(execMocked).toBeCalledWith('cnpm install')
logSpy.mockRestore()
})
})