refactor for testing

This commit is contained in:
Evan You
2018-01-02 20:16:01 -05:00
parent 82d24718bc
commit 267ce7442a
13 changed files with 135 additions and 84 deletions
+1
View File
@@ -5,3 +5,4 @@ design
packages/test
dist
yarn.lock
.vuerc
+5 -1
View File
@@ -16,7 +16,7 @@ cd packages/@vue/cli
yarn link
# create test projects in /packages/test
export VUE_CLI_DEBUG=true # necessary for local tests to work
export VUE_CLI_TEST=true # necessary for manual tests to work
cd -
cd packages/test
vue create test-app
@@ -87,6 +87,10 @@ module.exports = (api, options) => {
}
```
#### Important Development Note
A plugin with a generator that injects additional dependencies other than packages in this repo (e.g. `chai` is conditionally injected by `@vue/cli-plugin-unit-mocha-webpack/generator/index.js`) should have those dependencies listed in its "devDependencies" field. This ensures that the package always exist in this repo's root `node_modules` so that we don't have to reinstall them on every test.
[1]: https://github.com/vuejs/vue-cli/tree/next/packages/@vue/cli/lib/Creator.js
[3]: https://github.com/vuejs/vue-cli/tree/next/packages/@vue/cli/lib/GeneratorAPI.js
[4]: https://github.com/vuejs/vue-cli/tree/next/packages/@vue/cli-service/lib/Service.js
+19 -5
View File
@@ -10,16 +10,29 @@
"precommit": "lint-staged"
},
"jest": {
"testMatch": ["<rootDir>/test/**/*.js"],
"testMatch": [
"<rootDir>/test/**/*.js"
],
"testEnvironment": "node",
"setupFiles": [
"<rootDir>/test/__setup__.js"
],
"testPathIgnorePatterns": [
"/node_modules/",
"/packages/"
"/packages/",
"/__mocks__/",
"__setup__.js"
]
},
"lint-staged": {
"*.js": ["eslint --fix", "git add"],
"packages/**/bin/*": ["eslint --fix", "git add"]
"*.js": [
"eslint --fix",
"git add"
],
"packages/**/bin/*": [
"eslint --fix",
"git add"
]
},
"devDependencies": {
"debug": "^3.1.0",
@@ -29,6 +42,7 @@
"husky": "^0.14.3",
"jest": "^22.0.4",
"lerna": "^2.5.1",
"lint-staged": "^6.0.0"
"lint-staged": "^6.0.0",
"memfs": "^2.6.0"
}
}
@@ -25,5 +25,8 @@
"babel-eslint": "^8.1.2",
"eslint": "^4.14.0",
"eslint-loader": "^1.9.0"
},
"devDependencies": {
"eslint-plugin-vue": "^4.0.0"
}
}
@@ -26,5 +26,8 @@
"jest": "^22.0.4",
"jest-serializer-vue": "^0.3.0",
"vue-jest": "^1.4.0"
},
"devDependencies": {
"vue-test-utils": "^1.0.0-beta.9"
}
}
@@ -27,6 +27,10 @@
"mocha-webpack": "^1.0.1",
"webpack-node-externals": "^1.6.0"
},
"devDependencies": {
"chai": "^4.1.2",
"vue-test-utils": "^1.0.0-beta.9"
},
"publishConfig": {
"access": "public"
}
+6 -13
View File
@@ -4,14 +4,6 @@ const { execSync } = require('child_process')
const padStart = require('string.prototype.padstart')
const { logWithSpinner, stopSpinner } = require('./spinner')
const wrapForTest = fn => {
return (...args) => {
if (!process.env.VUE_CLI_TEST) {
return fn.apply(null, args)
}
}
}
const format = (label, msg) => {
return msg.split('\n').map((line, i) => {
return i === 0
@@ -56,12 +48,10 @@ exports.clearConsole = title => {
}
}
// wrap all log utils for tests
Object.keys(exports).forEach(key => {
exports[key] = wrapForTest(exports[key])
})
exports.hasYarn = (() => {
if (process.env.VUE_CLI_TEST) {
return true
}
try {
execSync('yarnpkg --version', { stdio: 'ignore' })
return true
@@ -71,6 +61,9 @@ exports.hasYarn = (() => {
})()
exports.hasGit = () => {
if (process.env.VUE_CLI_TEST) {
return true
}
try {
execSync('git --version', { stdio: 'ignore' })
return true
+66 -61
View File
@@ -9,7 +9,7 @@ const clearConsole = require('./util/clearConsole')
const PromptModuleAPI = require('./PromptModuleAPI')
const writeFileTree = require('./util/writeFileTree')
const formatFeatures = require('./util/formatfeatures')
const updatePackageForDev = require('./util/updatePackageForDev')
const setupDevProject = require('./util/setupDevProject')
const exec = require('util').promisify(require('child_process').exec)
const {
@@ -52,7 +52,70 @@ module.exports = class Creator {
async create () {
const name = this.name
const targetDir = process.env.VUE_CLI_CONTEXT = this.context
const options = await this.promptAndResolveOptions()
// write base package.json to disk
clearConsole()
logWithSpinner('✨', `Creating project in ${chalk.yellow(targetDir)}.`)
writeFileTree(targetDir, {
'package.json': JSON.stringify({
name,
version: '0.1.0',
private: true
}, null, 2)
})
// intilaize git repository
if (hasGit) {
logWithSpinner('🗃', `Initializing git repository...`)
await exec('git init', { cwd: targetDir })
}
// install plugins
logWithSpinner('⚙', `Installing CLI plugins. This might take a while...`)
const deps = Object.keys(options.plugins)
if (process.env.VUE_CLI_TEST) {
// in development, avoid installation process
setupDevProject(targetDir, deps)
} else {
await installDeps(targetDir, options, deps)
}
// run generator
logWithSpinner('🚀', `Invoking generators...`)
const generator = new Generator(targetDir, options, this)
await generator.generate()
// install additional deps (injected by generators)
logWithSpinner('📦', `Installing additional dependencies...`)
if (!process.env.VUE_CLI_TEST) {
await installDeps(targetDir, options)
}
// run complete cbs if any
for (const cb of this.createCompleteCbs) {
await cb()
}
// commit initial state
if (hasGit) {
await exec('git add -A', { cwd: targetDir, stdio: 'ignore' })
await exec('git commit -m init', { cwd: targetDir, stdio: 'ignore' })
}
// log instructions
stopSpinner()
log()
log(`🎉 Successfully created project ${chalk.yellow(name)}.`)
log(
`👉 Get started with the following commands:\n\n` +
chalk.cyan(` ${chalk.gray('$')} cd ${name}\n`) +
chalk.cyan(` ${chalk.gray('$')} ${options.packageManager === 'yarn' ? 'yarn serve' : 'npm run serve'}`)
)
log()
}
async promptAndResolveOptions () {
// prompt
clearConsole()
const answers = await inquirer.prompt(this.resolveFinalPrompts())
@@ -81,69 +144,11 @@ module.exports = class Creator {
// inject core service
options.plugins['@vue/cli-service'] = {
projectName: name
projectName: this.name
}
debug('vue:cli-ptions')(options)
// write base package.json to disk
clearConsole()
logWithSpinner('✨', `Creating project in ${chalk.yellow(targetDir)}.`)
writeFileTree(targetDir, {
'package.json': JSON.stringify({
name,
version: '0.1.0',
private: true
}, null, 2)
})
// intilaize git repository
if (hasGit) {
logWithSpinner('🗃', `Initializing git repository...`)
await exec('git init', { cwd: targetDir })
}
// install plugins
logWithSpinner('⚙', `Installing CLI plugins. This might take a while...`)
const deps = Object.keys(options.plugins)
if (process.env.VUE_CLI_DEBUG) {
// in development, use linked packages
updatePackageForDev(targetDir, deps)
await installDeps(targetDir, options)
} else {
await installDeps(targetDir, options, deps)
}
// run generator
logWithSpinner('🚀', `Invoking generators...`)
const generator = new Generator(targetDir, options, this)
await generator.generate()
// install additional deps (injected by generators)
logWithSpinner('📦', `Installing additional dependencies...`)
await installDeps(targetDir, options)
// run complete cbs if any
for (const cb of this.createCompleteCbs) {
await cb()
}
// commit initial state
if (hasGit) {
await exec('git add -A', { cwd: targetDir })
await exec('git commit -m init', { cwd: targetDir })
}
// log instructions
stopSpinner()
log()
log(`🎉 Successfully created project ${chalk.yellow(name)}.`)
log(
`👉 Get started with the following commands:\n\n` +
chalk.cyan(` ${chalk.gray('$')} cd ${name}\n`) +
chalk.cyan(` ${chalk.gray('$')} ${options.packageManager === 'yarn' ? 'yarn dev' : 'npm run dev'}`)
)
log()
return options
}
resolveIntroPrompts () {
+5 -2
View File
@@ -3,7 +3,10 @@ const os = require('os')
const path = require('path')
const { error, hasYarn } = require('@vue/cli-shared-utils')
const rcPath = exports.rcPath = path.join(os.homedir(), '.vuerc')
const rcPath = exports.rcPath = (
process.env.VUE_CLI_CONFIG_PATH ||
path.join(os.homedir(), '.vuerc')
)
exports.defaults = {
useTaobaoRegistry: null,
@@ -45,7 +48,7 @@ exports.saveOptions = options => {
} catch (e) {
error(
`Error saving preferences: ` +
`make sure you have write access to ~/.vuerc.\n` +
`make sure you have write access to ${rcPath}.\n` +
`(${e.message})`
)
}
@@ -2,8 +2,9 @@
const fs = require('fs')
const path = require('path')
const mkdirp = require('mkdirp')
module.exports = function updatePackageForDev (targetDir, deps) {
module.exports = function setupDevProject (targetDir, deps) {
const pkg = require(path.resolve(targetDir, 'package.json'))
pkg.devDependencies = {}
deps.forEach(dep => {
@@ -18,4 +19,10 @@ module.exports = function updatePackageForDev (targetDir, deps) {
path.resolve(targetDir, 'package.json'),
JSON.stringify(pkg, null, 2)
)
const binPath = path.join(targetDir, 'node_modules', '.bin')
mkdirp.sync(binPath)
fs.symlinkSync(
require.resolve('@vue/cli-service/bin/vue-cli-service'),
path.join(binPath, 'vue-cli-service')
)
}
+2
View File
@@ -0,0 +1,2 @@
process.env.VUE_CLI_TEST = true
process.env.VUE_CLI_CONFIG_PATH = require('path').join(__dirname, '.vuerc')
+6
View File
@@ -0,0 +1,6 @@
const { fs } = require('memfs')
// overwrite config path when fs is mocked
process.env.VUE_CLI_CONFIG_PATH = '/.vuerc'
module.exports = fs
+7 -1
View File
@@ -1,3 +1,9 @@
it('should pass', () => {
jest.mock('fs')
const { saveOptions } = require('@vue/cli/lib/options')
it('should pass', () => {
saveOptions({
useTaobaoRegistry: true
})
})