/
next-babel.test.js
160 lines (137 loc) · 5.15 KB
/
next-babel.test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/* eslint-env jest */
import { transform } from '@babel/core'
const trim = s =>
s
.join('\n')
.trim()
.replace(/^\s+/gm, '')
// avoid generating __source annotations in JSX during testing:
const NODE_ENV = process.env.NODE_ENV
process.env.NODE_ENV = 'production'
const preset = require('next/dist/build/babel/preset')
process.env.NODE_ENV = NODE_ENV
const babel = (code, esm = false, presetOptions = {}) =>
transform(code, {
filename: 'noop.js',
presets: [[preset, presetOptions]],
babelrc: false,
configFile: false,
sourceType: 'module',
compact: true,
caller: {
name: 'tests',
supportsStaticESM: esm,
},
}).code
describe('next/babel', () => {
describe('jsx-pragma', () => {
it('should transform JSX to use a local identifier in modern mode', () => {
const output = babel(`const a = () => <a href="/">home</a>;`, true)
// it should add a React import:
expect(output).toMatch(`import React from"react"`)
// it should hoist JSX factory to a module level variable:
expect(output).toMatch(`var __jsx=React.createElement`)
// it should use that factory for all JSX:
expect(output).toMatch(`__jsx("a",{href:"/"`)
expect(
babel(`const a = ()=><a href="/">home</a>`, true)
).toMatchInlineSnapshot(
`"import React from\\"react\\";var __jsx=React.createElement;var a=function a(){return __jsx(\\"a\\",{href:\\"/\\"},\\"home\\");};"`
)
})
it('should transform JSX to use a local identifier in CommonJS mode', () => {
const output = babel(trim`
const a = () => <React.Fragment><a href="/">home</a></React.Fragment>;
`)
// Grab generated names from the compiled output.
// It looks something like this:
// var _react = _interopRequireDefault(require("react"));
// var __jsx = _react["default"].createElement;
// react: _react
// reactNamespace: _react["default"]
const [, react, reactNamespace] = output.match(
/(([a-z0-9_]+)(\[[^\]]*?\]|\.[a-z0-9_]+)*?)\.Fragment/i
)
expect(output).toMatch(`var ${reactNamespace}=`)
expect(output).toMatch(`require("react")`)
expect(output).toMatch(`var __jsx=${react}.createElement`)
// Fragment should use the same React namespace import:
expect(output).toMatch(`__jsx(${react}.Fragment`)
expect(output).toMatch(`__jsx("a",{href:"/"`)
expect(babel(`const a = ()=><a href="/">home</a>`)).toMatchInlineSnapshot(
`"\\"use strict\\";var _interopRequireDefault=require(\\"@babel/runtime/helpers/interopRequireDefault\\");var _react=_interopRequireDefault(require(\\"react\\"));var __jsx=_react[\\"default\\"].createElement;var a=function a(){return __jsx(\\"a\\",{href:\\"/\\"},\\"home\\");};"`
)
})
it('should support Fragment syntax', () => {
const output = babel(`const a = () => <>hello</>;`, true)
expect(output).toMatch(`React.Fragment`)
expect(babel(`const a = () => <>hello</>;`, true)).toMatchInlineSnapshot(
`"import React from\\"react\\";var __jsx=React.createElement;var a=function a(){return __jsx(React.Fragment,null,\\"hello\\");};"`
)
})
it('should support commonjs', () => {
const output = babel(
trim`
const React = require('react');
module.exports = () => <div>test2</div>;
`,
true
)
expect(output).toMatchInlineSnapshot(
`"var React=require('react');var __jsx=React.createElement;module.exports=function(){return __jsx(\\"div\\",null,\\"test2\\");};"`
)
})
})
describe('optimize-hook-destructuring', () => {
it('should transform Array-destructured hook return values use object destructuring', () => {
const output = babel(
trim`
import { useState } from 'react';
const [count, setCount] = useState(0);
`,
true
)
expect(output).toMatch(trim`
var _useState=useState(0),count=_useState[0],setCount=_useState[1];
`)
expect(output).toMatchInlineSnapshot(
`"import{useState}from'react';var _useState=useState(0),count=_useState[0],setCount=_useState[1];"`
)
})
it('should be able to ignore some Array-destructured hook return values', () => {
const output = babel(
trim`
import { useState } from 'react';
const [, setCount] = useState(0);
`,
true
)
expect(output).toMatch(trim`
var _useState=useState(0),setCount=_useState[1];
`)
expect(output).toMatchInlineSnapshot(
`"import{useState}from'react';var _useState=useState(0),setCount=_useState[1];"`
)
})
})
describe('experimental-modern-preset', () => {
it('should allow passing a custom Babel preset', () => {
const code = trim`
const [, b, c] = [...[1,2,3]];
({a}) => a;
`
const output = babel(code, true, {
'preset-env': {
targets: {
esmodules: true,
},
},
// our modern preset is no preset at all
'experimental-modern-preset': () => ({}),
})
expect(output).toMatch(trim`
const[,b,c]=[...[1,2,3]];({a})=>a;
`)
})
})
})