From c5503a4b397d72fc8381bca6ea42c9eee228622d Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Thu, 19 Sep 2019 23:51:21 +0800 Subject: [PATCH 1/2] refactor: move jest configs into a preset This could significantly reduce the size of default boilerplate, and gives us more control on the internal config details, thus potentially making future upgrades easier. --- .../__tests__/jestGenerator.spec.js | 19 --- .../__tests__/jestPlugin.spec.js | 10 ++ .../cli-plugin-unit-jest/generator/index.js | 127 +++--------------- .../@vue/cli-plugin-unit-jest/package.json | 17 ++- .../preset/jest-preset.js | 35 +++++ .../preset/no-babel/esmoduleTransformer.js | 7 + .../preset/no-babel/jest-preset.js | 21 +++ .../typescript-and-babel/jest-preset.js | 13 ++ .../preset/typescript/jest-preset.js | 12 ++ 9 files changed, 130 insertions(+), 131 deletions(-) create mode 100644 packages/@vue/cli-plugin-unit-jest/preset/jest-preset.js create mode 100644 packages/@vue/cli-plugin-unit-jest/preset/no-babel/esmoduleTransformer.js create mode 100644 packages/@vue/cli-plugin-unit-jest/preset/no-babel/jest-preset.js create mode 100644 packages/@vue/cli-plugin-unit-jest/preset/typescript-and-babel/jest-preset.js create mode 100644 packages/@vue/cli-plugin-unit-jest/preset/typescript/jest-preset.js diff --git a/packages/@vue/cli-plugin-unit-jest/__tests__/jestGenerator.spec.js b/packages/@vue/cli-plugin-unit-jest/__tests__/jestGenerator.spec.js index 62814dd174..dcc581a68f 100644 --- a/packages/@vue/cli-plugin-unit-jest/__tests__/jestGenerator.spec.js +++ b/packages/@vue/cli-plugin-unit-jest/__tests__/jestGenerator.spec.js @@ -23,29 +23,10 @@ test('base', async () => { expect(pkg.scripts['test:unit']).toBe('vue-cli-service test:unit') expect(pkg.devDependencies).toHaveProperty('@vue/test-utils') - // should inject babel-jest - expect(pkg.devDependencies).toHaveProperty('babel-jest') - expect(pkg.devDependencies).toHaveProperty('@babel/core') - // eslint - expect(files['tests/unit/.eslintrc.js']).toMatch('jest: true') - const spec = files['tests/unit/example.spec.js'] expect(spec).toMatch(`expect(wrapper.text()).toMatch(msg)`) }) -test('without babel/eslint', async () => { - const { pkg, files } = await generateWithPlugin([ - { - id: 'unit-jest', - apply: require('../generator'), - options: {} - } - ]) - - expect(pkg.devDependencies).not.toHaveProperty('babel-jest') - expect(files['tests/unit/.eslintrc.js']).toBeUndefined() -}) - test('with TS', async () => { const { files } = await generateWithPlugin([ { diff --git a/packages/@vue/cli-plugin-unit-jest/__tests__/jestPlugin.spec.js b/packages/@vue/cli-plugin-unit-jest/__tests__/jestPlugin.spec.js index 33387a779b..c873d71547 100644 --- a/packages/@vue/cli-plugin-unit-jest/__tests__/jestPlugin.spec.js +++ b/packages/@vue/cli-plugin-unit-jest/__tests__/jestPlugin.spec.js @@ -111,3 +111,13 @@ test('should work with tsx', async () => { await run(`vue-cli-service test:unit`) }) + +test('should correctly configured eslint', async () => { + const project = await create('unit-jest-eslint', { + plugins: { + '@vue/cli-plugin-eslint': {}, + '@vue/cli-plugin-unit-jest': {} + } + }) + await project.run(`vue-cli-service lint`) +}) diff --git a/packages/@vue/cli-plugin-unit-jest/generator/index.js b/packages/@vue/cli-plugin-unit-jest/generator/index.js index 998bf8b805..e40dbc04d1 100644 --- a/packages/@vue/cli-plugin-unit-jest/generator/index.js +++ b/packages/@vue/cli-plugin-unit-jest/generator/index.js @@ -3,6 +3,21 @@ module.exports = (api, _, __, invoking) => { hasTS: api.hasPlugin('typescript') }) + let jestPresetPath + if (api.hasPlugin('babel')) { + if (api.hasPlugin('typescript')) { + jestPresetPath = '@vue/cli-plugin-unit-jest/preset/typescript-and-babel' + } else { + jestPresetPath = '@vue/cli-plugin-unit-jest/preset' + } + } else { + if (api.hasPlugin('typescript')) { + jestPresetPath = '@vue/cli-plugin-unit-jest/preset/typescript' + } else { + jestPresetPath = '@vue/cli-plugin-unit-jest/preset/no-babel' + } + } + api.extendPackage({ scripts: { 'test:unit': 'vue-cli-service test:unit' @@ -11,78 +26,19 @@ module.exports = (api, _, __, invoking) => { '@vue/test-utils': '1.0.0-beta.29' }, jest: { - moduleFileExtensions: [ - 'js', - 'jsx', - 'json', - // tell Jest to handle *.vue files - 'vue' - ], - transform: { - // process *.vue files with vue-jest - '^.+\\.vue$': 'vue-jest', - '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': - 'jest-transform-stub' - }, - 'transformIgnorePatterns': ['/node_modules/'], - // support the same @ -> src alias mapping in source code - moduleNameMapper: { - '^@/(.*)$': '/src/$1' - }, - // serializer for snapshots - snapshotSerializers: ['jest-serializer-vue'], - testMatch: [ - '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)' - ], - // https://github.com/facebook/jest/issues/6766 - testURL: 'http://localhost/', - watchPlugins: [ - 'jest-watch-typeahead/filename', - 'jest-watch-typeahead/testname' - ] + preset: jestPresetPath } }) - if (!api.hasPlugin('typescript')) { - api.extendPackage({ - jest: { - transform: { - '^.+\\.jsx?$': 'babel-jest' - } - } - }) - if (api.hasPlugin('babel')) { - api.extendPackage({ - devDependencies: { - 'babel-jest': '^24.8.0', - '@babel/core': '^7.4.5' - } - }) - } else { - // ts-jest still does not support babel.config.js - // https://github.com/kulshekhar/ts-jest/issues/933 - api.render(files => { - files['.babelrc'] = JSON.stringify( - { - plugins: ['@babel/plugin-transform-modules-commonjs'] - }, - null, - 2 - ) - }) - } - } else { - applyTS(api, invoking) - } - if (api.hasPlugin('eslint')) { - applyESLint(api) - api.extendPackage({ eslintConfig: { overrides: [ { - files: ['**/__tests__/*.{j,t}s?(x)'], + files: [ + '**/__tests__/*.{j,t}s?(x)', + '**/tests/unit/**/*.spec.{j,t}s?(x)' + ], env: { jest: true } @@ -91,40 +47,9 @@ module.exports = (api, _, __, invoking) => { } }) } -} -const applyTS = (module.exports.applyTS = (api, invoking) => { - api.extendPackage({ - jest: { - moduleFileExtensions: ['ts', 'tsx'], - transform: { - '^.+\\.tsx?$': 'ts-jest' - } - }, - devDependencies: { - '@types/jest': '^24.0.11', - 'ts-jest': '^24.0.2' - } - }) - if (api.hasPlugin('babel')) { - api.extendPackage({ - jest: { - globals: { - 'ts-jest': { - // we need babel to transpile JSX - babelConfig: true - } - } - }, - devDependencies: { - // this is for now necessary to force ts-jest and vue-jest to use babel 7 - '@babel/core': '^7.4.5', - 'babel-core': '7.0.0-bridge.0' - } - }) - } // inject jest type to tsconfig.json - if (invoking) { + if (api.hasPlugin('typescript') && invoking) { api.render(files => { const tsconfig = files['tsconfig.json'] if (tsconfig) { @@ -139,12 +64,4 @@ const applyTS = (module.exports.applyTS = (api, invoking) => { } }) } -}) - -const applyESLint = (module.exports.applyESLint = api => { - api.render(files => { - files['tests/unit/.eslintrc.js'] = api.genJSConfig({ - env: { jest: true } - }) - }) -}) +} diff --git a/packages/@vue/cli-plugin-unit-jest/package.json b/packages/@vue/cli-plugin-unit-jest/package.json index b5daa2af78..882cf6deb5 100644 --- a/packages/@vue/cli-plugin-unit-jest/package.json +++ b/packages/@vue/cli-plugin-unit-jest/package.json @@ -23,20 +23,23 @@ "access": "public" }, "dependencies": { - "@babel/core": "^7.4.5", + "@babel/core": "^7.0.0", "@babel/plugin-transform-modules-commonjs": "^7.4.4", + "@types/jest": "^24.0.18", "@vue/cli-shared-utils": "^4.0.0-rc.3", - "babel-core": "7.0.0-bridge.0", - "babel-jest": "^24.8.0", + "babel-core": "^7.0.0-bridge.0", + "babel-jest": "^24.9.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2", + "deepmerge": "^4.0.0", "jest": "^24.8.0", "jest-serializer-vue": "^2.0.2", "jest-transform-stub": "^2.0.0", - "jest-watch-typeahead": "^0.3.1", - "vue-jest": "^3.0.4" + "jest-watch-typeahead": "^0.4.0", + "ts-jest": "^24.1.0", + "vue-jest": "^3.0.5" }, "devDependencies": { - "@vue/test-utils": "1.0.0-beta.29", - "ts-jest": "^24.0.2" + "@vue/test-utils": "1.0.0-beta.29" }, "peerDependencies": { "@vue/cli-service": "^3.0.0 || ^4.0.0-0" diff --git a/packages/@vue/cli-plugin-unit-jest/preset/jest-preset.js b/packages/@vue/cli-plugin-unit-jest/preset/jest-preset.js new file mode 100644 index 0000000000..6d965ed088 --- /dev/null +++ b/packages/@vue/cli-plugin-unit-jest/preset/jest-preset.js @@ -0,0 +1,35 @@ +module.exports = { + moduleFileExtensions: [ + 'js', + 'jsx', + 'json', + // tell Jest to handle *.vue files + 'vue' + ], + transform: { + // process *.vue files with vue-jest + '^.+\\.vue$': require.resolve('vue-jest'), + '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': + require.resolve('jest-transform-stub'), + '^.+\\.jsx?$': require.resolve('babel-jest') + }, + transformIgnorePatterns: ['/node_modules/'], + // support the same @ -> src alias mapping in source code + moduleNameMapper: { + '^@/(.*)$': '/src/$1' + }, + // serializer for snapshots + snapshotSerializers: [ + 'jest-serializer-vue' + ], + testMatch: [ + '**/tests/unit/**/*.spec.[jt]s?(x)', + '**/__tests__/*.[jt]s?(x)' + ], + // https://github.com/facebook/jest/issues/6766 + testURL: 'http://localhost/', + watchPlugins: [ + require.resolve('jest-watch-typeahead/filename'), + require.resolve('jest-watch-typeahead/testname') + ] +} diff --git a/packages/@vue/cli-plugin-unit-jest/preset/no-babel/esmoduleTransformer.js b/packages/@vue/cli-plugin-unit-jest/preset/no-babel/esmoduleTransformer.js new file mode 100644 index 0000000000..6b8c671f14 --- /dev/null +++ b/packages/@vue/cli-plugin-unit-jest/preset/no-babel/esmoduleTransformer.js @@ -0,0 +1,7 @@ +const babelJest = require('babel-jest') + +module.exports = babelJest.createTransformer({ + plugins: ['@babel/plugin-transform-modules-commonjs'], + babelrc: false, + configFile: false +}) diff --git a/packages/@vue/cli-plugin-unit-jest/preset/no-babel/jest-preset.js b/packages/@vue/cli-plugin-unit-jest/preset/no-babel/jest-preset.js new file mode 100644 index 0000000000..a65cf7ed86 --- /dev/null +++ b/packages/@vue/cli-plugin-unit-jest/preset/no-babel/jest-preset.js @@ -0,0 +1,21 @@ +const deepmerge = require('deepmerge') +const defaultPreset = require('../jest-preset') + +// If no default babel preset exists, +// we need to use a customized babel transformer to deal with es modules + +module.exports = deepmerge( + defaultPreset, + { + transform: { + '^.+\\.jsx?$': require.resolve('./esmoduleTransformer') + }, + globals: { + 'vue-jest': { + babelConfig: { + plugins: [require('babel-plugin-transform-es2015-modules-commonjs')] + } + } + } + } +) diff --git a/packages/@vue/cli-plugin-unit-jest/preset/typescript-and-babel/jest-preset.js b/packages/@vue/cli-plugin-unit-jest/preset/typescript-and-babel/jest-preset.js new file mode 100644 index 0000000000..bece3ebd1c --- /dev/null +++ b/packages/@vue/cli-plugin-unit-jest/preset/typescript-and-babel/jest-preset.js @@ -0,0 +1,13 @@ +const deepmerge = require('deepmerge') +const defaultTsPreset = require('../typescript/jest-preset') + +module.exports = deepmerge( + defaultTsPreset, + { + globals: { + 'ts-jest': { + babelConfig: true + } + } + } +) diff --git a/packages/@vue/cli-plugin-unit-jest/preset/typescript/jest-preset.js b/packages/@vue/cli-plugin-unit-jest/preset/typescript/jest-preset.js new file mode 100644 index 0000000000..7aa3b81f62 --- /dev/null +++ b/packages/@vue/cli-plugin-unit-jest/preset/typescript/jest-preset.js @@ -0,0 +1,12 @@ +const deepmerge = require('deepmerge') +const defaultPreset = require('../jest-preset') + +module.exports = deepmerge( + defaultPreset, + { + moduleFileExtensions: ['ts', 'tsx'], + transform: { + '^.+\\.tsx?$': require.resolve('ts-jest') + } + } +) From 0ed0d4cb58b8f428c172fabfd2b13a1459201269 Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Fri, 20 Sep 2019 00:09:32 +0800 Subject: [PATCH 2/2] fix: add back applyTS --- .../cli-plugin-unit-jest/generator/index.js | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/packages/@vue/cli-plugin-unit-jest/generator/index.js b/packages/@vue/cli-plugin-unit-jest/generator/index.js index e40dbc04d1..42af529b11 100644 --- a/packages/@vue/cli-plugin-unit-jest/generator/index.js +++ b/packages/@vue/cli-plugin-unit-jest/generator/index.js @@ -3,21 +3,6 @@ module.exports = (api, _, __, invoking) => { hasTS: api.hasPlugin('typescript') }) - let jestPresetPath - if (api.hasPlugin('babel')) { - if (api.hasPlugin('typescript')) { - jestPresetPath = '@vue/cli-plugin-unit-jest/preset/typescript-and-babel' - } else { - jestPresetPath = '@vue/cli-plugin-unit-jest/preset' - } - } else { - if (api.hasPlugin('typescript')) { - jestPresetPath = '@vue/cli-plugin-unit-jest/preset/typescript' - } else { - jestPresetPath = '@vue/cli-plugin-unit-jest/preset/no-babel' - } - } - api.extendPackage({ scripts: { 'test:unit': 'vue-cli-service test:unit' @@ -26,7 +11,9 @@ module.exports = (api, _, __, invoking) => { '@vue/test-utils': '1.0.0-beta.29' }, jest: { - preset: jestPresetPath + preset: api.hasPlugin('babel') + ? '@vue/cli-plugin-unit-jest/preset' + : '@vue/cli-plugin-unit-jest/preset/no-babel' } }) @@ -48,8 +35,25 @@ module.exports = (api, _, __, invoking) => { }) } - // inject jest type to tsconfig.json - if (api.hasPlugin('typescript') && invoking) { + if (api.hasPlugin('typescript')) { + applyTS(api, invoking) + } +} + +const applyTS = (module.exports.applyTS = (api, invoking) => { + api.extendPackage({ + jest: { + preset: api.hasPlugin('babel') + ? '@vue/cli-plugin-unit-jest/preset/typescript-and-babel' + : '@vue/cli-plugin-unit-jest/preset/typescript' + }, + devDependencies: { + '@types/jest': '^24.0.11' + } + }) + + if (invoking) { + // inject jest type to tsconfig.json api.render(files => { const tsconfig = files['tsconfig.json'] if (tsconfig) { @@ -64,4 +68,4 @@ module.exports = (api, _, __, invoking) => { } }) } -} +})