Skip to content

Commit

Permalink
feat: support for babelConfig and tsConfig (#111)
Browse files Browse the repository at this point in the history
  • Loading branch information
justinhelmer authored and eddyerburgh committed Oct 6, 2018
1 parent 89cd5f3 commit 4ac913d
Show file tree
Hide file tree
Showing 5 changed files with 324 additions and 24 deletions.
138 changes: 133 additions & 5 deletions README.md
Expand Up @@ -2,6 +2,8 @@

Jest Vue transformer with source map support

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

```bash
Expand All @@ -10,7 +12,7 @@ npm install --save-dev vue-jest

## Setup

To define vue-jest as a transformer for your .vue files, you need to map .vue files to the vue-jest module.
To define `vue-jest` as a transformer for your `.vue` files, map them to the `vue-jest` module:

```json
{
Expand Down Expand Up @@ -57,28 +59,154 @@ vue-jest compiles the script and template of SFCs into a JavaScript file that Je
- **typescript** (`lang="ts"`, `lang="typescript"`)
- **coffeescript** (`lang="coffee"`, `lang="coffeescript"`)

To define a tsconfig file that vue-jest will use when transpiling typescript, you can specify it in the jest globals
### Global Jest options

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

> *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

#### babelConfig

Provide `babelConfig` in one of the following formats:

- `<Boolean>`
- `<Object>`
- `<String>`

##### Boolean

- `true` - Enable Babel processing. `vue-jest` will try to find Babel configuration using [find-babel-config](https://www.npmjs.com/package/find-babel-config).

> This is the default behavior if [babelConfig](#babelconfig) is not defined.

- `false` - Skip Babel processing entirely:

```json
{
"jest": {
"globals": {
"vue-jest": {
"babelConfig": false
}
}
}
}
```

##### Object

Provide inline [Babel options](https://babeljs.io/docs/en/options):

```json
{
"jest": {
"globals": {
"vue-jest": {
"tsConfigFile": "tsconfig.jest.json"
"babelConfig": {
"presets": [
[
"env",
{
"useBuiltIns": "entry",
"shippedProposals": true
}
]
],
"plugins": [
"syntax-dynamic-import"
],
"env": {
"test": {
"plugins": [
"dynamic-import-node"
]
}
}
}
}
}
}
}
```

To define a babelrc file that vue-jest will use when transpiling javascript, you can specify it in the jest globals
##### String

If a string is provided, it will be an assumed path to a babel configuration file (e.g. `.babelrc`, `.babelrc.js`).
- Config file should export a Babel configuration object.
- Should *not* point to a [project-wide configuration file (babel.config.js)](https://babeljs.io/docs/en/config-files#project-wide-configuration), which exports a function.

```json
{
"jest": {
"globals": {
"vue-jest": {
"babelConfig": "path/to/.babelrc.js"
}
}
}
}
```

To use the [Config Function API](https://babeljs.io/docs/en/config-files#config-function-api), use inline options instead. i.e.:

```json
{
"jest": {
"globals": {
"vue-jest": {
"babelConfig": {
"configFile": "path/to/babel.config.js"
}
}
}
}
}
```

#### tsConfig

Provide `tsConfig` in one of the following formats:

- `<Boolean>`
- `<Object>`
- `<String>`

##### Boolean

- `true` - Process TypeScript files using custom configuration. `vue-jest` will try to find TypeScript configuration using [tsconfig.loadSync](https://www.npmjs.com/package/tsconfig#api).

> This is the default behavior if [tsConfig](#tsConfig) is not defined.

- `false` - Process TypeScript files using the [default configuration provided by vue-jest](https://github.com/vuejs/vue-jest/blob/master/lib/load-typescript-config.js#L5-L27).

##### Object

Provide inline [TypeScript compiler options](https://www.typescriptlang.org/docs/handbook/compiler-options.html):

```json
{
"jest": {
"globals": {
"vue-jest": {
"tsConfig": {
"importHelpers": true
}
}
}
}
}
```

##### String

If a string is provided, it will be an assumed path to a TypeScript configuration file:

```json
{
"jest": {
"globals": {
"vue-jest": {
"babelRcFile": "jest.babelrc"
"tsConfig": "path/to/tsconfig.json"
}
}
}
Expand Down
45 changes: 36 additions & 9 deletions lib/load-babel-config.js
@@ -1,10 +1,22 @@
const findBabelConfig = require('find-babel-config')
const logger = require('./logger')
const cache = require('./cache')
const deprecate = require('./deprecate')
const path = require('path')
const { readFileSync, existsSync } = require('fs')

module.exports = function getBabelConfig (vueJestConfig, filePath) {
const find = () => {
const { file, config } = findBabelConfig.sync(filePath || process.cwd())

if (!file) {
logger.info('no .babelrc found, skipping babel compilation')
cache.set('babel-config', false)
return
}

return config
}
const cachedConfig = cache.get('babel-config')
if (cachedConfig) {
return cachedConfig
Expand All @@ -14,22 +26,37 @@ module.exports = function getBabelConfig (vueJestConfig, filePath) {
let babelConfig

if (vueJestConfig.babelRcFile) {
deprecate.replace('babelRcFile', 'babelConfig')
babelConfig = JSON.parse(readFileSync(vueJestConfig.babelRcFile))
} else if (existsSync('babel.config.js')) {
babelConfig = require(path.resolve('babel.config.js'))
} else {
const { file, config } = findBabelConfig.sync(filePath || process.cwd())

if (!file) {
logger.info('no .babelrc found, skipping babel compilation')
cache.set('babel-config', false)
return
} else if (vueJestConfig.hasOwnProperty('babelConfig')) {
switch (typeof vueJestConfig.babelConfig) {
case 'string':
// a path to a config file is being passed in; load it
babelConfig = require(vueJestConfig.babelConfig)
break
case 'boolean':
// if babelConfig is true, search for it. If false, will end up
// returning undefined which results in no babel processing
if (vueJestConfig.babelConfig === true) {
babelConfig = find()
}
break
case 'object':
default:
// support for inline babel options
babelConfig = vueJestConfig.babelConfig
break
}
} else {
babelConfig = find()
}

babelConfig = config
if (babelConfig) {
cache.set('babel-config', babelConfig)
}

cache.set('babel-config', babelConfig)
return babelConfig
}
}
40 changes: 33 additions & 7 deletions lib/load-typescript-config.js
@@ -1,5 +1,6 @@
const tsconfig = require('tsconfig')
const cache = require('./cache')
const deprecate = require('./deprecate')
const logger = require('./logger')

const defaultTypescriptConfig = {
Expand Down Expand Up @@ -27,22 +28,47 @@ const defaultTypescriptConfig = {
}

module.exports.loadTypescriptConfig = function loadTypescriptConfig (vueJestConfig) {
const find = () => {
const { path, config } = tsconfig.loadSync(process.cwd())

if (!path) {
logger.info('no tsconfig.json found, defaulting to default typescript options')
}

return path ? config : defaultTypescriptConfig
}
const cachedConfig = cache.get('typescript-config')
if (cachedConfig) {
return cachedConfig
} else {
let typescriptConfig

if (vueJestConfig.tsConfigFile) {
deprecate.replace('tsConfigFile', 'tsConfig')
typescriptConfig = tsconfig.readFileSync(vueJestConfig.tsConfigFile)
} else {
const { path, config } = tsconfig.loadSync(process.cwd())

if (!path) {
logger.info('no tsconfig.json found, defaulting to default typescript options')
} else if (vueJestConfig.hasOwnProperty('tsConfig')) {
switch (typeof vueJestConfig.tsConfig) {
case 'string':
// a path to a config file is being passed in; load it
typescriptConfig = require(vueJestConfig.tsConfig)
break
case 'boolean':
// if tsConfig is true, search for it
if (vueJestConfig.tsConfig === true) {
typescriptConfig = find()
} else {
// use default typescript options
typescriptConfig = defaultTypescriptConfig
}
break
case 'object':
default:
// support for inline typescript options
typescriptConfig = vueJestConfig.tsConfig
break
}

typescriptConfig = path ? config : defaultTypescriptConfig
} else {
typescriptConfig = find()
}

cache.set('typescript-config', typescriptConfig)
Expand Down
59 changes: 58 additions & 1 deletion test/load-babel-config.spec.js
@@ -1,3 +1,4 @@
import findBabelConfig from 'find-babel-config'
import loadBabelConfig from '../lib/load-babel-config'
import { resolve } from 'path'
import {
Expand All @@ -10,6 +11,7 @@ import {
} from 'fs'
import clearModule from 'clear-module'
import cache from '../lib/cache'
import deprecate from '../lib/deprecate'

describe('load-babel-config.js', () => {
beforeEach(() => {
Expand Down Expand Up @@ -38,7 +40,10 @@ describe('load-babel-config.js', () => {
expect(babelConfigCached).toBe(undefined)
})

it('reads babelrc from jest globals if exists', () => {
it('[DEPRECATED] reads babelrc from jest globals if exists', () => {
const replace = deprecate.replace
deprecate.replace = jest.fn()

const jestGlobalBabelPath = resolve(__dirname, '../jest.babelrc')
writeFileSync(jestGlobalBabelPath, JSON.stringify({
plugins: ['foo']
Expand All @@ -48,7 +53,9 @@ describe('load-babel-config.js', () => {
babelRcFile: 'jest.babelrc'
})
expect(babelConfig).toEqual(jestGlobalBabelConfig)
expect(deprecate.replace).toHaveBeenCalledWith('babelRcFile', 'babelConfig')
unlinkSync(jestGlobalBabelPath)
deprecate.replace = replace
})

it('reads default babel if there is .babelrc', () => {
Expand Down Expand Up @@ -103,4 +110,54 @@ describe('load-babel-config.js', () => {
expect(babelConfig).toEqual(config)
unlinkSync(babelConfigPath)
})

describe('babelConfig option', () => {
it('supports a path to a babel configuration file', () => {
const babelConfigPath = resolve(__dirname, '../some-babel-config.js')
const config = {
plugins: ['foo']
}
writeFileSync(babelConfigPath, `module.exports = ${JSON.stringify(config)}`)
const babelConfig = loadBabelConfig({
babelConfig: babelConfigPath
})
expect(babelConfig).toEqual(config)
})

it('supports a boolean indicating whether or not to search for babel config', () => {
const config = {
plugins: ['foo']
}
findBabelConfig.sync = jest.fn(() => ({ file: true, config }))
const noBabelConfig = loadBabelConfig({
babelConfig: false
})
expect(findBabelConfig.sync).not.toHaveBeenCalled()
expect(noBabelConfig).toBeUndefined()

const babelConfig = loadBabelConfig({
babelConfig: true
})
expect(findBabelConfig.sync).toHaveBeenCalled()
expect(babelConfig).toEqual(config)
findBabelConfig.sync.mockRestore()
})

it('supports an inline babel configuration object', () => {
const config = {
plugins: ['foo']
}
const babelConfig = loadBabelConfig({
babelConfig: config
})
expect(babelConfig).toEqual(config)
})

it('defaults to searching for babel config if option is not provided', () => {
findBabelConfig.sync = jest.fn(() => ({}))
loadBabelConfig({})
expect(findBabelConfig.sync).toHaveBeenCalled()
findBabelConfig.sync.mockRestore()
})
})
})

0 comments on commit 4ac913d

Please sign in to comment.