Karma 单元测试 Vue.js + Foundation
Karma unit test Vue.js + Foundation
我正在尝试将 Foundation for Sites 添加到我使用 Vue CLI 设置的第一个 Vue.js 项目。
网站运行,但 Karma+Phantomjs 单元测试套件发出此错误:
PhantomJS 2.1.1 (Mac OS X 0.0.0) ERROR
SyntaxError: Invalid character: '`'
at webpack:///~/foundation-sites/js/foundation.util.core.js:24:0 <- index.js:10362
我认为这与 webpack/babel 和 Foundation 的 ES 模块加载有关。我不太确定如何进一步诊断和解决问题。
下面是我所做的代码更改的概述...
Main.js
import jQuery from 'jquery'
window.jQuery = jQuery
window.$ = jQuery
import Foundation from 'foundation-sites'
window.Foundation = Foundation
Hello.vue
<template> ... </template>
<script>
export default {
name: 'hello',
mounted () {
this.dropdownMenu = new Foundation.DropdownMenu($('#dropdown-menu'), {
// These options can be declarative using the data attributes
hoverDelay: 300
})
},
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
destroyed () {
this.dropdownMenu.destroy()
}
}
</script>
test/unit/index.js
import Vue from 'vue'
import Foundation from 'foundation-sites'
window.Foundation = Foundation
// ... auto-generated unit tests
test/unit/karma.conf.js
// This is a karma config file. For more details see
// http://karma-runner.github.io/0.13/config/configuration-file.html
// we are also using it with karma-webpack
// https://github.com/webpack/karma-webpack
var webpackConfig = require('../../build/webpack.test.conf')
module.exports = function (config) {
config.set({
// to run in additional browsers:
// 1. install corresponding karma launcher
// http://karma-runner.github.io/0.13/config/browsers.html
// 2. add it to the `browsers` array below.
browsers: ['PhantomJS'],
frameworks: ['mocha', 'sinon-chai', 'phantomjs-shim'],
reporters: ['spec', 'coverage'],
files: ['./index.js'],
preprocessors: {
'./index.js': ['webpack', 'sourcemap']
},
webpack: webpackConfig,
webpackMiddleware: {
noInfo: true
},
coverageReporter: {
dir: './coverage',
reporters: [
{ type: 'lcov', subdir: '.' },
{ type: 'text-summary' }
]
}
})
}
webpack.base.conf.js
var path = require('path')
var utils = require('./utils')
var config = require('../config')
var vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
module: {
rules: [
{
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter')
}
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
}
}
我猜你正在使用 babel 进行转译并在你的 webpack 配置中定义它。这种转译没有发生是有道理的,因为在 es5 中不可用的内插字符串的反引号似乎失败了。
假设您已经定义了一个 karma.conf.js,您可能只需要将您的 webpack 配置添加到其中。也许 post 你的 karma.conf.js 如果你有的话。
我用的是:
// karma.conf.js
const webpackConfig = require('./build/webpack.base')
delete webpackConfig.entry
webpackConfig.resolve.alias.vue = 'vue/dist/vue.js'
module.exports = function karmaConfig(config) {
config.set({
browsers: ['PhantomJS'],
frameworks: ['mocha', 'chai'],
// this is the entry file for all our tests.
files: ['ui-tests/index.js'],
// we will pass the entry file to webpack for bundling.
preprocessors: {
'ui-tests/index.js': ['webpack'],
},
// use the webpack config
webpack: webpackConfig,
// avoid walls of useless text
webpackMiddleware: {
noInfo: true,
},
singleRun: true,
junitReporter: {
outputDir: '../../build/logs/',
outputFile: 'junit-js-ui-test-report.xml',
suite: 'review',
useBrowserName: false,
nameFormatter: undefined,
classNameFormatter: undefined,
properties: {},
},
})
}
和:
// ui-tests/index.js
const tests = require.context('..', true, /ui-tests\/.*\.spec$/)
tests.keys().forEach(tests)
并且在我的 运行 包脚本中包含以下内容:
./node_modules/.bin/karma start karma.conf.js
******* 更新 *****
不确定你是如何处理你的 babel 预设的,也许你正在使用 babelrc 并且没有找到它(或者无论如何都没有在你的基本 webpack 配置中的某种方式)但是你可以尝试添加类似的东西,但符合您的要求:
babel: {
babelrc: false,
presets: [
['es2015' {modules: false}],
'stage-1'
]
},
到 build/webpack.test.conf 中的 webpack 配置...很难说,因为我不知道你的 test.conf
中有什么
我在另一个包中遇到了类似的问题,我发现是覆盖代码造成的。
在 test/unit 下打开 index.js 并注释这两行:
const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/)
srcContext.keys().forEach(srcContext)
这应该可以解决问题。
我找到的解决方案是通过 Babel 加载 Foundation。
webpack.base.conf.js
{
test: /\.js$/,
loader: 'babel-loader',
include: [
resolve('src'),
resolve('test'),
resolve('node_modules/foundation-sites') // Added this line.
]
},
主要的原因实际上在Foundation docs:
Our JavaScript uses some features of ECMAScript 2015. If you use Foundation with a build system, you'll need to compile our code to ES5. We use Babel in our templates to do this. Babel has plugins for every build system imaginable, so integrating it into an existing setup is easy.
基金会文档继续推荐包括和设置 babel "presets": ["es2015"]
但是 Vue CLI 的设置已经略有不同。
Vue CLI 已经使用了 babel-preset-env
和 babel-preset-stage2
插件,我后来了解到这些插件负责 ES2015 > ES5 的转换。 Vue CLI 使用多个加载器设置 webpack,因此似乎有必要将 Foundation 添加到 babel-loader
配置中。
目前我正在导入 Foundation 并将其从 Vue 的 main.js
入口点添加到全局 window
。接下来我可能会看看我是否可以使用 Expose loader.
公开它
我正在尝试将 Foundation for Sites 添加到我使用 Vue CLI 设置的第一个 Vue.js 项目。
网站运行,但 Karma+Phantomjs 单元测试套件发出此错误:
PhantomJS 2.1.1 (Mac OS X 0.0.0) ERROR
SyntaxError: Invalid character: '`'
at webpack:///~/foundation-sites/js/foundation.util.core.js:24:0 <- index.js:10362
我认为这与 webpack/babel 和 Foundation 的 ES 模块加载有关。我不太确定如何进一步诊断和解决问题。
下面是我所做的代码更改的概述...
Main.js
import jQuery from 'jquery'
window.jQuery = jQuery
window.$ = jQuery
import Foundation from 'foundation-sites'
window.Foundation = Foundation
Hello.vue
<template> ... </template>
<script>
export default {
name: 'hello',
mounted () {
this.dropdownMenu = new Foundation.DropdownMenu($('#dropdown-menu'), {
// These options can be declarative using the data attributes
hoverDelay: 300
})
},
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
destroyed () {
this.dropdownMenu.destroy()
}
}
</script>
test/unit/index.js
import Vue from 'vue'
import Foundation from 'foundation-sites'
window.Foundation = Foundation
// ... auto-generated unit tests
test/unit/karma.conf.js
// This is a karma config file. For more details see
// http://karma-runner.github.io/0.13/config/configuration-file.html
// we are also using it with karma-webpack
// https://github.com/webpack/karma-webpack
var webpackConfig = require('../../build/webpack.test.conf')
module.exports = function (config) {
config.set({
// to run in additional browsers:
// 1. install corresponding karma launcher
// http://karma-runner.github.io/0.13/config/browsers.html
// 2. add it to the `browsers` array below.
browsers: ['PhantomJS'],
frameworks: ['mocha', 'sinon-chai', 'phantomjs-shim'],
reporters: ['spec', 'coverage'],
files: ['./index.js'],
preprocessors: {
'./index.js': ['webpack', 'sourcemap']
},
webpack: webpackConfig,
webpackMiddleware: {
noInfo: true
},
coverageReporter: {
dir: './coverage',
reporters: [
{ type: 'lcov', subdir: '.' },
{ type: 'text-summary' }
]
}
})
}
webpack.base.conf.js
var path = require('path')
var utils = require('./utils')
var config = require('../config')
var vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
module: {
rules: [
{
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter')
}
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
}
}
我猜你正在使用 babel 进行转译并在你的 webpack 配置中定义它。这种转译没有发生是有道理的,因为在 es5 中不可用的内插字符串的反引号似乎失败了。
假设您已经定义了一个 karma.conf.js,您可能只需要将您的 webpack 配置添加到其中。也许 post 你的 karma.conf.js 如果你有的话。
我用的是:
// karma.conf.js
const webpackConfig = require('./build/webpack.base')
delete webpackConfig.entry
webpackConfig.resolve.alias.vue = 'vue/dist/vue.js'
module.exports = function karmaConfig(config) {
config.set({
browsers: ['PhantomJS'],
frameworks: ['mocha', 'chai'],
// this is the entry file for all our tests.
files: ['ui-tests/index.js'],
// we will pass the entry file to webpack for bundling.
preprocessors: {
'ui-tests/index.js': ['webpack'],
},
// use the webpack config
webpack: webpackConfig,
// avoid walls of useless text
webpackMiddleware: {
noInfo: true,
},
singleRun: true,
junitReporter: {
outputDir: '../../build/logs/',
outputFile: 'junit-js-ui-test-report.xml',
suite: 'review',
useBrowserName: false,
nameFormatter: undefined,
classNameFormatter: undefined,
properties: {},
},
})
}
和:
// ui-tests/index.js
const tests = require.context('..', true, /ui-tests\/.*\.spec$/)
tests.keys().forEach(tests)
并且在我的 运行 包脚本中包含以下内容:
./node_modules/.bin/karma start karma.conf.js
******* 更新 *****
不确定你是如何处理你的 babel 预设的,也许你正在使用 babelrc 并且没有找到它(或者无论如何都没有在你的基本 webpack 配置中的某种方式)但是你可以尝试添加类似的东西,但符合您的要求:
babel: {
babelrc: false,
presets: [
['es2015' {modules: false}],
'stage-1'
]
},
到 build/webpack.test.conf 中的 webpack 配置...很难说,因为我不知道你的 test.conf
中有什么我在另一个包中遇到了类似的问题,我发现是覆盖代码造成的。
在 test/unit 下打开 index.js 并注释这两行:
const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/)
srcContext.keys().forEach(srcContext)
这应该可以解决问题。
我找到的解决方案是通过 Babel 加载 Foundation。
webpack.base.conf.js
{
test: /\.js$/,
loader: 'babel-loader',
include: [
resolve('src'),
resolve('test'),
resolve('node_modules/foundation-sites') // Added this line.
]
},
主要的原因实际上在Foundation docs:
Our JavaScript uses some features of ECMAScript 2015. If you use Foundation with a build system, you'll need to compile our code to ES5. We use Babel in our templates to do this. Babel has plugins for every build system imaginable, so integrating it into an existing setup is easy.
基金会文档继续推荐包括和设置 babel "presets": ["es2015"]
但是 Vue CLI 的设置已经略有不同。
Vue CLI 已经使用了 babel-preset-env
和 babel-preset-stage2
插件,我后来了解到这些插件负责 ES2015 > ES5 的转换。 Vue CLI 使用多个加载器设置 webpack,因此似乎有必要将 Foundation 添加到 babel-loader
配置中。
目前我正在导入 Foundation 并将其从 Vue 的 main.js
入口点添加到全局 window
。接下来我可能会看看我是否可以使用 Expose loader.