Skip to content

Commit 46faace

Browse files
authored
Merge branch 'master' into patch-1
2 parents 8953b8f + f0ed142 commit 46faace

File tree

15 files changed

+3788
-3828
lines changed

15 files changed

+3788
-3828
lines changed

.circleci/config.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ version: 2
22
jobs:
33
build:
44
docker:
5-
- image: circleci/node:8.10
5+
- image: circleci/node:10.16.3
66

77
working_directory: ~/repo
88

@@ -12,16 +12,16 @@ jobs:
1212
# Download and cache dependencies
1313
- restore_cache:
1414
keys:
15-
- node-8-dependencies-{{ checksum "package.json" }}
15+
- node-10-dependencies-{{ checksum "package.json" }}
1616
# fallback to using the latest cache if no exact match is found
17-
- node-8-dependencies-
17+
- node-10-dependencies-
1818

1919
- run: yarn install
2020

2121
- save_cache:
2222
paths:
2323
- node_modules
24-
key: node-8-dependencies-{{ checksum "package.json" }}
24+
key: node-10-dependencies-{{ checksum "package.json" }}
2525

2626
# run tests!
2727
- run: npm run test

README.md

+65-8
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
# vue-jest
22

3-
Jest Vue transformer with source map support
3+
Jest transformer for Vue single file components
44

5-
> **NOTE:** This is documentation for `vue-jest@3.x`. [View the vue-jest@2.x documentation](https://github.com/vuejs/vue-jest/tree/e694fc7ce11ae1ac1c778ed7c4402515c5f0d5aa)
5+
> **NOTE:** This is documentation for `vue-jest@4.x`. [View the vue-jest@3.x documentation](https://github.com/vuejs/vue-jest/tree/v3)
66
77
## Usage
88

99
```bash
1010
npm install --save-dev vue-jest
11+
yarn add vue-jest --dev
1112
```
1213

1314
### Usage with Babel 7
@@ -16,18 +17,20 @@ If you use [jest](https://github.com/facebook/jest) > 24.0.0 and [babel-jest](ht
1617

1718
```bash
1819
npm install --save-dev babel-core@bridge
20+
yarn add babel-core@bridge --dev
1921
```
2022

2123
## Setup
2224

23-
To define `vue-jest` as a transformer for your `.vue` files, map them to the `vue-jest` module:
25+
To use `vue-jest` as a transformer for your `.vue` files, map them to the `vue-jest` module:
2426

2527
```json
2628
{
2729
"jest": {
2830
"transform": {
2931
"^.+\\.vue$": "vue-jest"
3032
}
33+
}
3134
}
3235
```
3336

@@ -45,18 +48,15 @@ A full config will look like this.
4548
}
4649
```
4750

48-
If you're on a version of Jest older than 22.4.0, you need to set `mapCoverage` to `true` in order to use source maps.
49-
50-
## Example Projects
51+
## Examples
5152

5253
Example repositories testing Vue components with jest and vue-jest:
5354

54-
- [Avoriaz with Jest](https://github.com/eddyerburgh/avoriaz-jest-example)
5555
- [Vue Test Utils with Jest](https://github.com/eddyerburgh/vue-test-utils-jest-example)
5656

5757
## Supported langs
5858

59-
vue-jest compiles the script and template of SFCs into a JavaScript file that Jest can run. **Currently, SCSS, SASS and Stylus are the only style languages that are compiled**.
59+
vue-jest compiles `<script />`, `<template />`, and `<style />` blocks with supported `lang` attributes into JavaScript that Jest can run.
6060

6161
### Supported script languages
6262

@@ -67,8 +67,65 @@ vue-jest compiles the script and template of SFCs into a JavaScript file that Je
6767

6868
You can change the behavior of `vue-jest` by using `jest.globals`.
6969

70+
#### Supporting custom blocks
71+
72+
A great feature of the Vue SFC compiler is that it can support custom blocks. You might want to use those blocks in your tests. To render out custom blocks for testing purposes, you'll need to write a transformer. Once you have your transformer, you'll add an entry to vue-jest's transform map. This is how [vue-i18n's](https://github.com/kazupon/vue-i18n) `<i18n>` custom blocks are supported in unit tests.
73+
74+
A `package.json` Example
75+
76+
```json
77+
{
78+
"jest": {
79+
"moduleFileExtensions": ["js", "json", "vue"],
80+
"transform": {
81+
"^.+\\.js$": "babel-jest",
82+
"^.+\\.vue$": "vue-jest"
83+
},
84+
"globals": {
85+
"vue-jest": {
86+
"transform": {
87+
"your-custom-block": "./custom-block-processor.js"
88+
}
89+
}
90+
}
91+
}
92+
}
93+
```
94+
7095
> _Tip:_ Need programmatic configuration? Use the [--config](https://jestjs.io/docs/en/cli.html#config-path) option in Jest CLI, and export a `.js` file
7196
97+
A `jest.config.js` Example - If you're using a dedicated configuration file like you can reference and require your processor in the config file instead of using a file reference.
98+
99+
```js
100+
module.exports = {
101+
globals: {
102+
'vue-jest': {
103+
transform: {
104+
'your-custom-block': require('./custom-block-processor')
105+
}
106+
}
107+
}
108+
}
109+
```
110+
111+
#### Writing a processor
112+
113+
Processors must return an object with a "process" method, like so...
114+
115+
```js
116+
module.exports = {
117+
/**
118+
* Process the content inside of a custom block and prepare it for execution in a testing environment
119+
* @param {SFCCustomBlock[]} blocks All of the blocks matching your type, returned from `@vue/component-compiler-utils`
120+
* @param {string} vueOptionsNamespace The internal namespace for a component's Vue Options in vue-jest
121+
* @param {string} filename The SFC file being processed
122+
* @param {Object} config The full Jest config
123+
* @returns {string} The code to be output after processing all of the blocks matched by this type
124+
*/
125+
process(blocks, vueOptionsNamepsace, filename, config) {}
126+
}
127+
```
128+
72129
#### babelConfig
73130

74131
Provide `babelConfig` in one of the following formats:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<script>
2+
export default {
3+
name: 'FunctionalSFCRender',
4+
functional: true,
5+
render(createElement, { $style }) {
6+
return createElement('div', {
7+
class: [$style.ModuleClass]
8+
})
9+
}
10+
}
11+
</script>
12+
13+
<style lang="scss" module>
14+
.ModuleClass {
15+
width: auto;
16+
}
17+
</style>

e2e/__projects__/basic/test.js

+7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import jestVue from 'vue-jest'
66
import RenderFunction from './components/RenderFunction.vue'
77
import Jade from './components/Jade.vue'
88
import FunctionalSFC from './components/FunctionalSFC.vue'
9+
import FunctionalSFCRender from './components/FunctionalSFCRender.vue'
910
import Basic from './components/Basic.vue'
1011
import BasicSrc from './components/BasicSrc.vue'
1112
import { randomExport } from './components/NamedExport.vue'
@@ -92,6 +93,12 @@ test('processes functional components', () => {
9293
expect(clickSpy).toHaveBeenCalledWith(1)
9394
})
9495

96+
test('processes functional components using render function', () => {
97+
const wrapper = mount(FunctionalSFCRender)
98+
const CSS_CLASSES = ['ModuleClass']
99+
expect(wrapper.classes().toString()).toBe(CSS_CLASSES.toString())
100+
})
101+
95102
test('processes SFC with functional template from parent', () => {
96103
const wrapper = mount(FunctionalSFCParent)
97104
expect(wrapper.text().trim()).toBe('foo')

e2e/__projects__/custom-transformers/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
"@babel/preset-env": "^7.2.3",
1717
"@vue/test-utils": "^1.0.0-beta.28",
1818
"jest": "^24.0.0",
19-
"node-sass": "^4.11.0",
2019
"postcss": "^7.0.13",
2120
"postcss-color-function": "^4.0.1",
21+
"sass": "^1.23.7",
2222
"vue-jest": "file:../../../"
2323
},
2424
"jest": {

e2e/__projects__/style/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
"@babel/preset-env": "^7.2.3",
1717
"@vue/test-utils": "^1.0.0-beta.28",
1818
"jest": "^24.0.0",
19-
"node-sass": "^4.11.0",
2019
"postcss": "^7.0.13",
20+
"sass": "^1.23.7",
2121
"vue-jest": "file:../../../"
2222
},
2323
"jest": {

lib/constants.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
vueOptionsNamespace: '__options__',
3+
defaultVueJestConfig: {
4+
transform: {}
5+
}
6+
}

lib/generate-code.js

+15-8
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
const namespace = require('./constants').vueOptionsNamespace
2+
13
const splitRE = /\r?\n/g
24

35
module.exports = function generateCode(
46
scriptResult,
57
templateResult,
68
stylesResult,
9+
customBlocksResult,
710
isFunctional
811
) {
912
let output = ''
@@ -21,7 +24,7 @@ module.exports = function generateCode(
2124
}
2225

2326
output +=
24-
`var __options__ = typeof exports.default === 'function' ` +
27+
`var ${namespace} = typeof exports.default === 'function' ` +
2528
`? exports.default.options ` +
2629
`: exports.default\n`
2730

@@ -37,11 +40,11 @@ module.exports = function generateCode(
3740

3841
output +=
3942
`__options__.render = render\n` +
40-
`__options__.staticRenderFns = staticRenderFns\n`
43+
`${namespace}.staticRenderFns = staticRenderFns\n`
4144

4245
if (isFunctional) {
43-
output += '__options__.functional = true\n'
44-
output += '__options__._compiled = true\n'
46+
output += `${namespace}.functional = true\n`
47+
output += `${namespace}._compiled = true\n`
4548
}
4649
}
4750

@@ -59,22 +62,26 @@ module.exports = function generateCode(
5962
if (isFunctional) {
6063
output +=
6164
`;(function() {\n` +
62-
` var originalRender = __options__.render\n` +
65+
` var originalRender = ${namespace}.render\n` +
6366
` var styleFn = function () { ${styleStr} }\n` +
64-
` __options__.render = function renderWithStyleInjection (h, context) {\n` +
67+
` ${namespace}.render = function renderWithStyleInjection (h, context) {\n` +
6568
` styleFn.call(context)\n` +
6669
` return originalRender(h, context)\n` +
6770
` }\n` +
6871
`})()\n`
6972
} else {
7073
output +=
7174
`;(function() {\n` +
72-
` var beforeCreate = __options__.beforeCreate\n` +
75+
` var beforeCreate = ${namespace}.beforeCreate\n` +
7376
` var styleFn = function () { ${styleStr} }\n` +
74-
` __options__.beforeCreate = beforeCreate ? [].concat(beforeCreate, styleFn) : [styleFn]\n` +
77+
` ${namespace}.beforeCreate = beforeCreate ? [].concat(beforeCreate, styleFn) : [styleFn]\n` +
7578
`})()\n`
7679
}
7780
}
81+
82+
if (customBlocksResult) {
83+
output += `;\n ${customBlocksResult}`
84+
}
7885
return {
7986
code: output,
8087
renderFnStartLine,

lib/process-custom-blocks.js

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
const { getVueJestConfig, getCustomTransformer } = require('./utils')
2+
const vueOptionsNamespace = require('./constants').vueOptionsNamespace
3+
4+
function applyTransformer(
5+
transformer,
6+
blocks,
7+
vueOptionsNamespace,
8+
filename,
9+
config
10+
) {
11+
return transformer.process({ blocks, vueOptionsNamespace, filename, config })
12+
}
13+
14+
function groupByType(acc, block) {
15+
acc[block.type] = acc[block.type] || []
16+
acc[block.type].push(block)
17+
return acc
18+
}
19+
20+
module.exports = function(allBlocks, filename, config) {
21+
const blocksByType = allBlocks.reduce(groupByType, {})
22+
const code = []
23+
for (const [type, blocks] of Object.entries(blocksByType)) {
24+
const transformer = getCustomTransformer(
25+
getVueJestConfig(config).transform,
26+
type
27+
)
28+
if (transformer) {
29+
const codeStr = applyTransformer(
30+
transformer,
31+
blocks,
32+
vueOptionsNamespace,
33+
filename,
34+
config
35+
)
36+
code.push(codeStr)
37+
}
38+
}
39+
40+
return code.length ? code.join('\n') : ''
41+
}

lib/process.js

+15-5
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ const splitRE = /\r?\n/g
22

33
const VueTemplateCompiler = require('vue-template-compiler')
44
const generateSourceMap = require('./generate-source-map')
5-
const typescriptTransformer = require('./typescript-transformer')
6-
const coffeescriptTransformer = require('./coffee-transformer')
5+
const typescriptTransformer = require('./transformers/typescript')
6+
const coffeescriptTransformer = require('./transformers/coffee')
77
const _processStyle = require('./process-style')
8+
const processCustomBlocks = require('./process-custom-blocks')
89
const getVueJestConfig = require('./utils').getVueJestConfig
910
const logResultErrors = require('./utils').logResultErrors
1011
const stripInlineSourceMap = require('./utils').stripInlineSourceMap
@@ -99,11 +100,19 @@ module.exports = function(src, filename, config) {
99100
const templateResult = processTemplate(descriptor.template, filename, config)
100101
const scriptResult = processScript(descriptor.script, filename, config)
101102
const stylesResult = processStyle(descriptor.styles, filename, config)
103+
const customBlocksResult = processCustomBlocks(
104+
descriptor.customBlocks,
105+
filename,
106+
config
107+
)
102108

103109
const isFunctional =
104-
descriptor.template &&
105-
descriptor.template.attrs &&
106-
descriptor.template.attrs.functional
110+
(descriptor.template &&
111+
descriptor.template.attrs &&
112+
descriptor.template.attrs.functional) ||
113+
(descriptor.script &&
114+
descriptor.script.content &&
115+
/functional:\s*true/.test(descriptor.script.content))
107116

108117
const templateStart = descriptor.template && descriptor.template.start
109118
const templateLine = src.slice(0, templateStart).split(splitRE).length
@@ -112,6 +121,7 @@ module.exports = function(src, filename, config) {
112121
scriptResult,
113122
templateResult,
114123
stylesResult,
124+
customBlocksResult,
115125
isFunctional
116126
)
117127

lib/coffee-transformer.js renamed to lib/transformers/coffee.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
const ensureRequire = require('./ensure-require.js')
2-
const throwError = require('./utils').throwError
3-
const getBabelOptions = require('./utils').getBabelOptions
1+
const ensureRequire = require('../ensure-require.js')
2+
const throwError = require('../utils').throwError
3+
const getBabelOptions = require('../utils').getBabelOptions
44

55
module.exports = {
66
process(src, filename, config) {

0 commit comments

Comments
 (0)