Skip to content

feat: update to support babelConfig and tsConfig #111

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

Merged
merged 1 commit into from
Oct 6, 2018
Merged
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
138 changes: 133 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Jest Vue transformer with source map support

> **NOTE:** This is documentation for `[email protected]`. [View the [email protected] 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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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()
})
})
})
Loading