Skip to content

Commit

Permalink
refactor for testing
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Jan 3, 2018
1 parent 82d2471 commit 267ce74
Show file tree
Hide file tree
Showing 13 changed files with 116 additions and 65 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ design
packages/test
dist
yarn.lock
.vuerc
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
24 changes: 19 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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"
}
}
3 changes: 3 additions & 0 deletions packages/@vue/cli-plugin-eslint/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
3 changes: 3 additions & 0 deletions packages/@vue/cli-plugin-unit-jest/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
4 changes: 4 additions & 0 deletions packages/@vue/cli-plugin-unit-mocha-webpack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
Expand Down
19 changes: 6 additions & 13 deletions packages/@vue/cli-shared-utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -71,6 +61,9 @@ exports.hasYarn = (() => {
})()

exports.hasGit = () => {
if (process.env.VUE_CLI_TEST) {
return true
}
try {
execSync('git --version', { stdio: 'ignore' })
return true
Expand Down
89 changes: 47 additions & 42 deletions packages/@vue/cli/lib/Creator.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -52,39 +52,7 @@ module.exports = class Creator {
async create () {
const name = this.name
const targetDir = process.env.VUE_CLI_CONTEXT = this.context

// prompt
clearConsole()
const answers = await inquirer.prompt(this.resolveFinalPrompts())
debug('vue:cli-answers')(answers)

let options
if (answers.mode === 'saved') {
options = this.savedOptions // this is loaded when resolving prompts
} else if (answers.mode === 'default') {
options = defaults
} else {
// manual
options = {
useTaobaoRegistry: null,
packageManager: answers.packageManager,
plugins: {}
}
// run cb registered by prompt modules to finalize the options
this.promptCompleteCbs.forEach(cb => cb(answers, options))
}

// save options
if (answers.mode === 'manual' && answers.save) {
saveOptions(options)
}

// inject core service
options.plugins['@vue/cli-service'] = {
projectName: name
}

debug('vue:cli-ptions')(options)
const options = await this.promptAndResolveOptions()

// write base package.json to disk
clearConsole()
Expand All @@ -106,10 +74,9 @@ module.exports = class Creator {
// 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)
if (process.env.VUE_CLI_TEST) {
// in development, avoid installation process
setupDevProject(targetDir, deps)
} else {
await installDeps(targetDir, options, deps)
}
Expand All @@ -121,7 +88,9 @@ module.exports = class Creator {

// install additional deps (injected by generators)
logWithSpinner('📦', `Installing additional dependencies...`)
await installDeps(targetDir, options)
if (!process.env.VUE_CLI_TEST) {
await installDeps(targetDir, options)
}

// run complete cbs if any
for (const cb of this.createCompleteCbs) {
Expand All @@ -130,8 +99,8 @@ module.exports = class Creator {

// commit initial state
if (hasGit) {
await exec('git add -A', { cwd: targetDir })
await exec('git commit -m init', { cwd: targetDir })
await exec('git add -A', { cwd: targetDir, stdio: 'ignore' })
await exec('git commit -m init', { cwd: targetDir, stdio: 'ignore' })
}

// log instructions
Expand All @@ -141,11 +110,47 @@ module.exports = class Creator {
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'}`)
chalk.cyan(` ${chalk.gray('$')} ${options.packageManager === 'yarn' ? 'yarn serve' : 'npm run serve'}`)
)
log()
}

async promptAndResolveOptions () {
// prompt
clearConsole()
const answers = await inquirer.prompt(this.resolveFinalPrompts())
debug('vue:cli-answers')(answers)

let options
if (answers.mode === 'saved') {
options = this.savedOptions // this is loaded when resolving prompts
} else if (answers.mode === 'default') {
options = defaults
} else {
// manual
options = {
useTaobaoRegistry: null,
packageManager: answers.packageManager,
plugins: {}
}
// run cb registered by prompt modules to finalize the options
this.promptCompleteCbs.forEach(cb => cb(answers, options))
}

// save options
if (answers.mode === 'manual' && answers.save) {
saveOptions(options)
}

// inject core service
options.plugins['@vue/cli-service'] = {
projectName: this.name
}

debug('vue:cli-ptions')(options)
return options
}

resolveIntroPrompts () {
const defualtFeatures = formatFeatures(defaults.plugins)
const modePrompt = {
Expand Down
7 changes: 5 additions & 2 deletions packages/@vue/cli/lib/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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})`
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand All @@ -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 changes: 2 additions & 0 deletions test/__setup__.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
process.env.VUE_CLI_TEST = true
process.env.VUE_CLI_CONFIG_PATH = require('path').join(__dirname, '.vuerc')
6 changes: 6 additions & 0 deletions test/unit/__mocks__/fs.js
Original file line number Diff line number Diff line change
@@ -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
8 changes: 7 additions & 1 deletion test/unit/options.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
it('should pass', () => {
jest.mock('fs')

const { saveOptions } = require('@vue/cli/lib/options')

it('should pass', () => {
saveOptions({
useTaobaoRegistry: true
})
})

0 comments on commit 267ce74

Please sign in to comment.