Skip to content

unit tests in single file (fixes #223) #241

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions karma.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module.exports = function (config) {
config.set({
preprocessors: {
'**/*.vue': ['webpack', 'sourcemap']
},
webpack: {
devtool: 'inline-source-map',
module: {
loaders: [
{ test: /\.vue$/, loader: './index.js' }
]
}
},
frameworks: ['mocha', 'chai'],
files: ['test/*.vue'],
plugins: [
require('karma-webpack'),
require('karma-mocha'),
require('karma-chai'),
require('karma-chrome-launcher'),
require('karma-phantomjs-launcher'),
require('karma-sourcemap-loader')
]
})
}
78 changes: 56 additions & 22 deletions lib/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ module.exports = function (content) {
var parts = parse(content, fileName, this.sourceMap)
var hasLocalStyles = false
var output = 'var __vue_script__, __vue_template__\n'
var testOutput = ''

// check if there are any template syntax errors
var templateWarnings = parts.template.length && parts.template[0].warnings
Expand All @@ -163,29 +164,60 @@ module.exports = function (content) {
output += getRequire('style', style, i, style.scoped)
})

// add require for script
var script
if (parts.script.length) {
script = parts.script[0]
output +=
'__vue_script__ = ' + (
script.src
? getRequireForImport('script', script, 0)
: getRequire('script', script, 0)
)
// check and warn named exports
if (!this.minimize) {
// add requires for scripts
var hasScript = false
parts.script.forEach(function (script, i) {
if (script.test === undefined) {
if (hasScript) {
throw new Error(
'[vue-loader] Only one <script> tag is ' +
'allowed inside a Vue component.'
)
}
hasScript = true
output +=
'if (__vue_script__ &&\n' +
' __vue_script__.__esModule &&\n' +
' Object.keys(__vue_script__).length > 1) {\n' +
' console.warn(' + JSON.stringify(
'[vue-loader] ' + path.relative(process.cwd(), filePath) +
': named exports in *.vue files are ignored.'
) + ')' +
'}\n'
'__vue_script__ = ' + (
script.src
? getRequireForImport('script', script, i)
: getRequire('script', script, i)
)
// check and warn named exports
if (!this.minimize) {
output +=
'if (__vue_script__ &&\n' +
' __vue_script__.__esModule &&\n' +
' Object.keys(__vue_script__).length > 1) {\n' +
' console.warn(' + JSON.stringify(
'[vue-loader] ' + path.relative(process.cwd(), filePath) +
': named exports in *.vue files are ignored.'
) + ')' +
'}\n'
}
} else if (!this.minimize && process.env.NODE_ENV !== 'production') {
var requireStr = script.src
? getRequireForImport('script', script, i)
: getRequire('script', script, i)
switch (script.test) {
case 'karma':
testOutput +=
'if (window._karma__ !== "null") {\n' +
' var Vue = require("vue")\n' +
' var vueComp = Vue.extend(module.exports)\n' +
' vueComp = new vueComp()\n' +
' document.body.appendChild(vueComp.$mount().$el)\n' +
' window.vueTestComp = vueComp\n' +
' ' + requireStr.replace('require("!!', 'require("!!imports-loader?this=>window.vueTestComp!') +
' delete window.vueTestComp\n' +
'}\n'
break
default:
testOutput +=
'window.vueTestComp = module.exports\n' +
requireStr.replace('require("!!', 'require("!!imports-loader?this=>window.vueTestComp!') +
'window.vueTestComp = null\n'
}
}
}
})

// add require for template
var template
Expand Down Expand Up @@ -241,7 +273,9 @@ module.exports = function (content) {
' return mod\n' +
'}'
}

if (testOutput) {
output += '\n' + testOutput
}
// done
return output
}
Expand Down
47 changes: 10 additions & 37 deletions lib/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ module.exports = function (content, filename, needMap) {
var type = node.tagName
var lang = getAttribute(node, 'lang')
var src = getAttribute(node, 'src')
var test = getAttribute(node, 'test')
var scoped = getAttribute(node, 'scoped') != null
var warnings = null
var map = null
Expand All @@ -48,12 +49,9 @@ module.exports = function (content, filename, needMap) {
}

// node count check
if (
(type === 'script' || type === 'template') &&
output[type].length > 0
) {
if (type === 'template' && output[type].length > 0) {
throw new Error(
'[vue-loader] Only one <script> or <template> tag is ' +
'[vue-loader] Only one <template> tag is ' +
'allowed inside a Vue component.'
)
}
Expand All @@ -74,7 +72,8 @@ module.exports = function (content, filename, needMap) {
} else if (type === 'script') {
output.script.push({
src: src,
lang: lang
lang: lang,
test: test
})
}
return
Expand All @@ -96,20 +95,8 @@ module.exports = function (content, filename, needMap) {
// extract part
var start = node.childNodes[0].__location.startOffset
var end = node.childNodes[node.childNodes.length - 1].__location.endOffset
var result
var lineOffset
if (type === 'script') {
lineOffset = 0
// preserve other parts as commenets so that linters
// and babel can output correct line numbers in warnings
result =
commentScript(content.slice(0, start), lang) +
deindent(content.slice(start, end)) +
commentScript(content.slice(end), lang)
} else {
lineOffset = content.slice(0, start).split(splitRE).length - 1
result = deindent(content.slice(start, end))
}
var lineOffset = content.slice(0, start).split(splitRE).length - 1
var result = Array(lineOffset + 1).join('\n') + deindent(content.slice(start, end))

if (needMap) {
// generate source map
Expand All @@ -128,7 +115,7 @@ module.exports = function (content, filename, needMap) {
map.addMapping({
source: filenameWithHash,
original: {
line: index + 1 + lineOffset,
line: index + 1,
column: 0
},
generated: {
Expand All @@ -146,34 +133,20 @@ module.exports = function (content, filename, needMap) {
result += '\n/* generated by vue-loader */\n'
}
}

output[type].push({
lang: lang,
scoped: scoped,
content: result,
map: map && map.toJSON(),
warnings: warnings
warnings: warnings,
test: test
})
})

cache.set(cacheKey, output)
return output
}

function commentScript (content, lang) {
var symbol = getCommentSymbol(lang)
var lines = content.split(splitRE)
return lines.map(function (line, index) {
// preserve EOL
if (index === lines.length - 1 && emptyRE.test(line)) {
return ''
} else {
return symbol + (emptyRE.test(line) ? '' : ' ' + line)
}
})
.join('\n')
}

function getCommentSymbol (lang) {
return commentSymbols[lang] || '//'
}
Expand Down
74 changes: 43 additions & 31 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,37 +24,30 @@
"homepage": "https://github.com/vuejs/vue-loader",
"scripts": {
"lint": "eslint lib",
"test": "eslint lib && mocha test/test.js --slow 5000 --timeout 10000",
"watch:mocha": "mocha --watch",
"watch:karma": "karma start --browsers Chrome --auto-watch",
"test:mocha": "mocha",
"test:karma": "karma start --browsers PhantomJS --single-run",
"test": "npm run lint && npm run test:mocha && npm run test:karma",
"docs": "cd docs && gitbook serve",
"deploy-docs": "bash ./docs/deploy.sh"
},
"dependencies": {
"autoprefixer": "^6.0.3",
"consolidate": "^0.14.0",
"de-indent": "^1.0.0",
"autoprefixer": "^6.3.6",
"consolidate": "^0.14.1",
"de-indent": "^1.0.2",
"hash-sum": "^1.0.2",
"loader-utils": "^0.2.10",
"lru-cache": "^2.7.0",
"object-assign": "^4.0.0",
"parse5": "^2.1.0",
"postcss": "^5.0.10",
"postcss-selector-parser": "^1.1.2",
"source-map": "^0.5.3",
"vue-template-validator": "^1.0.0"
},
"peerDependencies": {
"babel-loader": "^6.2.4",
"babel-core": "^6.8.0",
"babel-plugin-transform-runtime": "^6.8.0",
"babel-runtime": "^6.0.0",
"babel-preset-es2015": "^6.6.0",
"css-loader": "*",
"vue-html-loader": "^1.0.0",
"vue-style-loader": "^1.0.0",
"vue-hot-reload-api": "^1.2.0"
"loader-utils": "^0.2.15",
"lru-cache": "^4.0.1",
"object-assign": "^4.1.0",
"parse5": "^2.1.5",
"postcss": "^5.0.21",
"postcss-selector-parser": "^2.0.0",
"source-map": "^0.5.6",
"vue-template-validator": "^1.1.5"
},
"devDependencies": {
"babel-core": "^6.8.0",
"babel-core": "^6.9.0",
"babel-loader": "^6.2.4",
"babel-plugin-transform-runtime": "^6.8.0",
"babel-preset-es2015": "^6.6.0",
Expand All @@ -65,21 +58,40 @@
"css-loader": "^0.23.1",
"eslint": "^2.9.0",
"eslint-config-vue": "^1.0.0",
"babel-plugin-transform-runtime": "^6.9.0",
"babel-preset-es2015": "^6.9.0",
"babel-runtime": "^6.9.0",
"chai": "^3.5.0",
"coffee-loader": "^0.7.2",
"coffee-script": "^1.10.0",
"css-loader": "^0.23.1",
"eslint": "^2.10.2",
"eslint-config-vue": "^1.0.2",
"expose-loader": "^0.7.1",
"extract-text-webpack-plugin": "^1.0.1",
"file-loader": "^0.8.5",
"imports-loader": "^0.6.5",
"inject-loader": "^2.0.1",
"jade": "^1.11.0",
"jsdom": "^8.5.0",
"jsdom": "^9.2.0",
"karma": "^0.13.22",
"karma-chai": "^0.1.0",
"karma-chrome-launcher": "^1.0.1",
"karma-mocha": "^1.0.1",
"karma-phantomjs-launcher": "^1.0.0",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^1.7.0",
"mkdirp": "^0.5.1",
"mocha": "^2.2.5",
"mocha": "^2.5.2",
"node-libs-browser": "^1.0.0",
"rimraf": "^2.4.0",
"phantomjs-prebuilt": "^2.1.7",
"rimraf": "^2.5.2",
"stylus": "^0.54.5",
"stylus-loader": "^2.0.0",
"vue-hot-reload-api": "^1.2.0",
"vue-html-loader": "^1.0.0",
"stylus-loader": "^2.1.0",
"vue": "^1.0.24",
"vue-hot-reload-api": "^1.3.2",
"vue-html-loader": "^1.2.2",
"vue-style-loader": "^1.0.0",
"webpack": "^1.12.2"
"webpack": "^1.13.1"
}
}
14 changes: 14 additions & 0 deletions test/autoprefix.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<style>
body {
transform: scale(1);
}
</style>
<script test>
var styles = window.document.querySelectorAll('style')
var style = styles[styles.length-1].textContent
describe("vue-loader", function () {
it('autoprefix', function () {
expect(style).to.contain('body {\n -webkit-transform: scale(1);\n transform: scale(1);\n}')
})
})
</script>
31 changes: 31 additions & 0 deletions test/basic.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<script>
module.exports = {
data () {
return {
msg: 'Hello from Component A!'
}
}
}
</script>
<template>
<h2 class="red">{{msg}}</h2>
</template>

<style>
comp-a h2 {
color: #f00;
}
</style>

<script test>
var module = window.vueTestComp
var styles = window.document.querySelectorAll('style')
var style = styles[styles.length-1].textContent
describe("vue-loader", function () {
it('basic', function () {
expect(module.template).to.contain('<h2 class="red">{{msg}}</h2>')
expect(module.data().msg).to.contain('Hello from Component A!')
expect(style).to.contain('comp-a h2 {\n color: #f00;\n}')
})
})
</script>
5 changes: 0 additions & 5 deletions test/fixtures/autoprefix.vue

This file was deleted.

Loading