2019-12-03 22:08:49 +01:00
/* eslint-env jest */
2021-08-24 14:52:45 +02:00
import os from 'os'
import path from 'path'
2021-10-07 01:46:46 +02:00
import { Span } from 'next/dist/trace'
import loader from 'next/dist/build/babel/loader'
2019-12-05 18:04:00 +01:00
const dir = path . resolve ( os . tmpdir ( ) )
2019-12-03 22:08:49 +01:00
2021-08-24 14:52:45 +02:00
const babel = async ( code : string , queryOpts = { } as any ) = > {
2021-10-07 01:46:46 +02:00
const { isServer = false , resourcePath = ` index.js ` } = queryOpts
2021-05-07 19:21:54 +02:00
2019-12-03 22:08:49 +01:00
let isAsync = false
2021-08-24 14:52:45 +02:00
return new Promise < string > ( ( resolve , reject ) = > {
2019-12-03 22:08:49 +01:00
function callback ( err , content ) {
if ( err ) {
reject ( err )
} else {
2021-10-07 01:46:46 +02:00
resolve ( content . replace ( /\n/g , '' ) )
2019-12-03 22:08:49 +01:00
}
}
2021-11-02 16:13:15 +01:00
const options = {
// loader opts
cwd : dir ,
isServer ,
distDir : path.resolve ( dir , '.next' ) ,
pagesDir :
'pagesDir' in queryOpts
? queryOpts . pagesDir
: path . resolve ( dir , 'pages' ) ,
cache : false ,
hasReactRefresh : false ,
}
2019-12-03 22:08:49 +01:00
const res = loader . bind ( {
resourcePath ,
async ( ) {
isAsync = true
return callback
} ,
callback ,
2020-06-30 15:05:29 +02:00
emitWarning() { } ,
2021-11-02 16:13:15 +01:00
query : options ,
getOptions : function ( ) {
return options
2019-12-03 22:08:49 +01:00
} ,
2021-10-07 01:46:46 +02:00
currentTraceSpan : new Span ( { name : 'test' } ) ,
2019-12-03 22:08:49 +01:00
} ) ( code , null )
if ( ! isAsync ) {
resolve ( res )
}
} )
}
describe ( 'next-babel-loader' , ( ) = > {
describe ( 'replace constants' , ( ) = > {
it ( 'should replace typeof window expression nested' , async ( ) = > {
const code = await babel ( 'function a(){console.log(typeof window)}' )
expect ( code ) . toMatchInlineSnapshot (
2023-10-19 19:38:24 +02:00
` "function a() { console.log("object");}" `
2019-12-03 22:08:49 +01:00
)
} )
it ( 'should replace typeof window expression top level (client)' , async ( ) = > {
const code = await babel ( 'typeof window;' )
2023-10-19 19:38:24 +02:00
expect ( code ) . toMatchInlineSnapshot ( ` ""object";" ` )
2019-12-03 22:08:49 +01:00
} )
it ( 'should replace typeof window expression top level (server)' , async ( ) = > {
const code = await babel ( 'typeof window;' , { isServer : true } )
2023-10-19 19:38:24 +02:00
expect ( code ) . toMatchInlineSnapshot ( ` ""undefined";" ` )
2019-12-03 22:08:49 +01:00
} )
2020-05-18 19:16:07 +02:00
it ( 'should replace typeof window in === expression nested' , async ( ) = > {
2019-12-03 22:08:49 +01:00
const code = await babel (
` function a(){console.log(typeof window === 'undefined')} `
)
2021-10-07 01:46:46 +02:00
expect ( code ) . toMatchInlineSnapshot (
` "function a() { console.log(false);}" `
)
2019-12-03 22:08:49 +01:00
} )
it ( 'should replace typeof window expression top level' , async ( ) = > {
const code = await babel ( ` typeof window === 'undefined'; ` )
expect ( code ) . toMatchInlineSnapshot ( ` "false;" ` )
} )
2020-05-18 19:16:07 +02:00
it ( 'should replace typeof window in === expression top level' , async ( ) = > {
2019-12-03 22:08:49 +01:00
const code = await babel ( ` typeof window === 'object'; ` )
expect ( code ) . toMatchInlineSnapshot ( ` "true;" ` )
} )
2020-05-18 19:16:07 +02:00
it ( 'should replace typeof window in !== expression top level' , async ( ) = > {
2019-12-03 22:08:49 +01:00
const code = await babel ( ` typeof window !== 'undefined'; ` )
expect ( code ) . toMatchInlineSnapshot ( ` "true;" ` )
} )
2020-05-18 19:16:07 +02:00
it ( 'should replace typeof window expression !== object top level' , async ( ) = > {
2019-12-03 22:08:49 +01:00
const code = await babel ( ` typeof window !== 'object'; ` )
expect ( code ) . toMatchInlineSnapshot ( ` "false;" ` )
} )
2020-05-18 19:16:07 +02:00
it ( 'should replace typeof window expression top level serverside' , async ( ) = > {
2019-12-03 22:08:49 +01:00
const code = await babel ( ` typeof window !== 'undefined'; ` , {
isServer : true ,
} )
expect ( code ) . toMatchInlineSnapshot ( ` "false;" ` )
} )
2020-05-18 19:16:07 +02:00
it ( 'should replace typeof window expression !== object top level serverside' , async ( ) = > {
2019-12-03 22:08:49 +01:00
const code = await babel ( ` typeof window !== 'object'; ` , {
isServer : true ,
} )
expect ( code ) . toMatchInlineSnapshot ( ` "true;" ` )
} )
it ( 'should replace process.browser (1)' , async ( ) = > {
const code = await babel ( ` process.browser ` , {
isServer : false ,
} )
expect ( code ) . toMatchInlineSnapshot ( ` "true;" ` )
} )
it ( 'should replace process.browser (2)' , async ( ) = > {
const code = await babel ( ` process.browser ` , {
isServer : true ,
} )
expect ( code ) . toMatchInlineSnapshot ( ` "false;" ` )
} )
it ( 'should replace process.browser (3)' , async ( ) = > {
const code = await babel ( ` process.browser == false ` , {
isServer : true ,
} )
expect ( code ) . toMatchInlineSnapshot ( ` "true;" ` )
} )
it ( 'should replace process.browser (4)' , async ( ) = > {
const code = await babel ( ` if (process.browser === false) {} ` , {
isServer : true ,
} )
2021-10-07 01:46:46 +02:00
expect ( code ) . toMatchInlineSnapshot ( ` "if (true) {}" ` )
2019-12-03 22:08:49 +01:00
} )
it ( 'should replace process.browser (5)' , async ( ) = > {
const code = await babel ( ` if (process.browser) {} ` , {
isServer : true ,
} )
2021-10-07 01:46:46 +02:00
expect ( code ) . toMatchInlineSnapshot ( ` "if (false) {}" ` )
2019-12-03 22:08:49 +01:00
} )
it ( 'should replace NODE_ENV on client (prod)' , async ( ) = > {
const code = await babel ( ` process.env.NODE_ENV ` , {
isServer : false ,
} )
2023-10-19 19:38:24 +02:00
expect ( code ) . toMatchInlineSnapshot ( ` ""production";" ` )
2019-12-03 22:08:49 +01:00
} )
it ( 'should replace NODE_ENV on server' , async ( ) = > {
const code = await babel ( ` process.env.NODE_ENV ` , {
isServer : true ,
} )
2023-10-19 19:38:24 +02:00
expect ( code ) . toMatchInlineSnapshot ( ` ""production";" ` )
2019-12-03 22:08:49 +01:00
} )
2020-05-18 19:16:07 +02:00
it ( 'should replace NODE_ENV in === statement (prod)' , async ( ) = > {
2019-12-03 22:08:49 +01:00
const code = await babel ( ` if (process.env.NODE_ENV === 'production') {} ` )
2021-10-07 01:46:46 +02:00
expect ( code ) . toMatchInlineSnapshot ( ` "if (true) {}" ` )
2019-12-03 22:08:49 +01:00
} )
2020-05-18 19:16:07 +02:00
it ( 'should replace NODE_ENV in !== statement (prod)' , async ( ) = > {
2019-12-03 22:08:49 +01:00
const code = await babel ( ` if (process.env.NODE_ENV !== 'production') {} ` )
2021-10-07 01:46:46 +02:00
expect ( code ) . toMatchInlineSnapshot ( ` "if (false) {}" ` )
2019-12-03 22:08:49 +01:00
} )
2019-12-05 18:04:00 +01:00
2021-05-07 19:21:54 +02:00
it ( 'should handle no pagesDir' , async ( ) = > {
const code = await babel (
`
import dynamic from 'next/dynamic'
const Comp = dynamic ( ( ) = > import ( 'comp' ) )
export default function Page ( props ) {
return < Comp / >
}
` ,
{
pagesDir : undefined ,
}
)
expect (
2021-10-07 01:46:46 +02:00
code . replace ( /modules: \[".*?"/ , 'modules:["/path/to/page"' )
2021-05-07 19:21:54 +02:00
) . toMatchInlineSnapshot (
2023-10-19 19:38:24 +02:00
` "var _jsxFileName = "index.js";import React from "react";var __jsx = React.createElement;import dynamic from 'next/dynamic';const Comp = dynamic(() => import('comp'), { loadableGenerated: { webpack: () => [require.resolveWeak('comp')] }});export default function Page(props) { return __jsx(Comp, { __self: this, __source: { fileName: _jsxFileName, lineNumber: 7, columnNumber: 18 } });}" `
2021-05-07 19:21:54 +02:00
)
} )
2019-12-05 18:04:00 +01:00
it ( 'should not drop unused exports by default' , async ( ) = > {
const code = await babel (
// effectful
` import"core-js"; ` +
// basic
` import{foo,bar}from"a";import baz from"b"; ` +
// complex
2019-12-06 17:46:00 +01:00
` import * as React from "react"; ` +
2019-12-05 18:04:00 +01:00
` import baz2,{yeet}from"c"; ` +
` import baz3,{cats}from"d"; ` +
` import{c,d}from"e"; ` +
` import{e as ee,f as ff}from"f"; `
)
expect ( code ) . toMatchInlineSnapshot (
2023-10-19 19:38:24 +02:00
` "import "core-js";import { foo, bar } from "a";import baz from "b";import * as React from "react";import baz2, { yeet } from "c";import baz3, { cats } from "d";import { c, d } from "e";import { e as ee, f as ff } from "f";" `
2019-12-05 18:04:00 +01:00
)
} )
const pageFile = path . resolve ( dir , 'pages' , 'index.js' )
it ( 'should not drop unused exports by default in a page' , async ( ) = > {
const code = await babel (
// effectful
` import"core-js"; ` +
// basic
` import{foo,bar}from"a";import baz from"b"; ` +
// complex
2019-12-06 17:46:00 +01:00
` import*as React from"react"; ` +
2019-12-05 18:04:00 +01:00
` import baz2,{yeet}from"c"; ` +
` import baz3,{cats}from"d"; ` +
` import{c,d}from"e"; ` +
` import{e as ee,f as ff}from"f"; ` ,
{ resourcePath : pageFile }
)
expect ( code ) . toMatchInlineSnapshot (
2023-10-19 19:38:24 +02:00
` "import "core-js";import { foo, bar } from "a";import baz from "b";import * as React from "react";import baz2, { yeet } from "c";import baz3, { cats } from "d";import { c, d } from "e";import { e as ee, f as ff } from "f";" `
2019-12-05 18:04:00 +01:00
)
} )
it ( 'should drop unused exports in a modern-apis page' , async ( ) = > {
const code = await babel (
// effectful
` import"core-js"; ` +
// basic
` import{foo,bar}from"a";import baz from"b"; ` +
// complex
2019-12-06 17:46:00 +01:00
` import*as React from"react"; ` +
2019-12-05 18:04:00 +01:00
` import baz2,{yeet}from"c"; ` +
` import baz3,{cats}from"d"; ` +
` import{c,d}from"e"; ` +
` import{e as ee,f as ff}from"f"; ` +
` ` +
2020-02-27 18:57:39 +01:00
` export function getStaticProps() {foo;bar;baz;cats;baz2;ff; return { props: {} } } ` ,
2019-12-05 18:04:00 +01:00
{ resourcePath : pageFile }
)
2019-12-07 04:57:14 +01:00
expect ( code ) . toMatchInlineSnapshot (
2023-10-19 19:38:24 +02:00
` "import "core-js";import * as React from "react";import { yeet } from "c";import baz3 from "d";import { c, d } from "e";import { e as ee } from "f";" `
2019-12-07 04:57:14 +01:00
)
2019-12-05 18:04:00 +01:00
} )
it ( 'should keep used exports in a modern-apis page (server)' , async ( ) = > {
const code = await babel (
// effectful
` import"core-js"; ` +
// basic
` import{foo,bar}from"a";import baz from"b";import ooo from"ooo"; ` +
// complex
2019-12-06 17:46:00 +01:00
` import*as React from"react"; ` +
2019-12-05 18:04:00 +01:00
` import baz2,{yeet}from"c"; ` +
` import baz3,{cats}from"d"; ` +
` import{c,d}from"e"; ` +
` import{e as ee,f as ff}from"f"; ` +
` ` +
2020-02-27 18:57:39 +01:00
` export function getStaticProps() {foo();baz2();ff();ooo(); return { props: {} }} ` +
2019-12-05 18:04:00 +01:00
` export default function () { return bar(); } ` ,
{ resourcePath : pageFile , isServer : true }
)
expect ( code ) . toMatchInlineSnapshot (
2023-10-19 19:38:24 +02:00
` "import "core-js";import { foo, bar } from "a";import baz from "b";import ooo from "ooo";import * as React from "react";import baz2, { yeet } from "c";import baz3, { cats } from "d";import { c, d } from "e";import { e as ee, f as ff } from "f";export function getStaticProps() { foo(); baz2(); ff(); ooo(); return { props: {} };}export default function () { return bar();}" `
2019-12-05 18:04:00 +01:00
)
} )
it ( 'should keep used exports in a modern-apis page (client)' , async ( ) = > {
const code = await babel (
// effectful
` import"core-js"; ` +
// basic
` import{foo,bar}from"a";import baz from"b";import ooo from"ooo"; ` +
// complex
2019-12-06 17:46:00 +01:00
` import*as React from"react"; ` +
2019-12-05 18:04:00 +01:00
` import baz2,{yeet}from"c"; ` +
` import baz3,{cats}from"d"; ` +
` import{c,d}from"e"; ` +
` import{e as ee,f as ff}from"f"; ` +
` ` +
2020-02-27 18:57:39 +01:00
` export function getStaticProps() {foo();baz2();ff();ooo();cats; return { props: {} }} ` +
2019-12-05 18:04:00 +01:00
` export default function () { return cats + bar(); } ` ,
{ resourcePath : pageFile , isServer : false }
)
expect ( code ) . toMatchInlineSnapshot (
2023-10-19 19:38:24 +02:00
` "import "core-js";import { bar } from "a";import baz from "b";import * as React from "react";import { yeet } from "c";import baz3, { cats } from "d";import { c, d } from "e";import { e as ee } from "f";export var __N_SSG = true;export default function () { return cats + bar();}" `
2019-12-05 18:04:00 +01:00
)
} )
2019-12-06 17:46:00 +01:00
it ( 'should keep used exports and react in a modern-apis page with JSX (client)' , async ( ) = > {
const code = await babel (
// effectful
` import"core-js"; ` +
// basic
` import{foo,bar}from"a";import baz from"b";import ooo from"ooo"; ` +
// complex
` import*as React from"react"; ` +
` import baz2,{yeet}from"c"; ` +
` import baz3,{cats}from"d"; ` +
` import{c,d}from"e"; ` +
` import{e as ee,f as ff}from"f"; ` +
` ` +
2020-02-27 18:57:39 +01:00
` export function getStaticProps() {foo();baz2();ff();ooo(); return { props: {} }} ` +
2019-12-06 17:46:00 +01:00
` export default function () { return <div>{cats + bar()}</div> } ` ,
{ resourcePath : pageFile , isServer : false }
)
2021-10-07 01:46:46 +02:00
expect ( code ) . toContain (
` var __jsx = React.createElement;import "core-js";import { bar } from "a";import baz from "b";import * as React from "react";import { yeet } from "c";import baz3, { cats } from "d";import { c, d } from "e";import { e as ee } from "f";export var __N_SSG = true;export default function () { return __jsx("div", { __self: this, __source: { fileName: _jsxFileName, lineNumber: 1, columnNumber: 326 } }, cats + bar());} `
2020-05-15 22:51:29 +02:00
)
} )
2019-12-03 22:08:49 +01:00
} )
} )