babel-plugin-root-require
Version:
Transforms require module paths that have a prefix referring to the project root. Also works on `require.resolve`.
210 lines (186 loc) • 5.49 kB
JavaScript
const test = require('tape')
const {transform} = require('babel-core')
const plugin = require('../')
const plugins = [plugin]
const rimraf = require('rimraf')
const exec = require('child_process').exec
const reloadRequire = require('require-reload')(require)
const fixtures = __dirname + '/fixtures'
const fixture = name => fixtures + '/' + name
const tmpDir = '/tmp/test-root-require'
const resetState = () => rimraf.sync(tmpDir)
const compile = (src, cwd, cb) => {
return exec(`${require.resolve('babel-cli/bin/babel')} ${src} -d ${tmpDir} --plugins ${__dirname}/../index`, {cwd}, (err, body) => {
console.log(body)
cb(err, body)
})
}
require('./does-not-transform')
test('transforms prefixed module path to relative path to module', t => {
t.plan(1)
const result = transform('require("~/a/b/c");', {
filename: 'a/b/d',
plugins
})
t.equal(result.code, 'require("./c");')
})
test('opts.longPath replaces prefix with relative path to project root', t => {
t.plan(1)
const result = transform('require("~/a/b/c");', {
filename: 'a/b/d',
plugins: [[plugin, {long: true}]]
})
t.equal(result.code, 'require("../../a/b/c");')
})
test('transforms prefix from file in root directory', t => {
t.plan(1)
compile('./', fixture('a'), err => {
if (err) { return t.fail(err) }
const result = reloadRequire(tmpDir + '/req-a')
resetState()
t.equal(result, 'a')
})
})
test('transforms prefix nested', t => {
t.plan(1)
compile('./', fixture('b'), err => {
if (err) { return t.fail(err) }
const result = reloadRequire(tmpDir + '/nest/nest/b')
resetState()
t.equal(result, 'b')
})
})
test('transforms prefix for expression starting with prefix', t => {
t.plan(1)
compile('./', fixture('c'), err => {
if (err) { return t.fail(err) }
const result = reloadRequire(tmpDir)
resetState()
t.equal(result, 'c')
})
})
test('transforms prefix for argument with string and variable', t => {
t.plan(1)
compile('./', fixture('d'), err => {
if (err) { return t.fail(err) }
const result = reloadRequire(tmpDir)
resetState()
t.equal(result, 'd')
})
})
test('transforms prefix when followed by a string not ending in a slash, followed by stuff', t => {
t.plan(1)
compile('./', fixture('e'), err => {
if (err) { return t.fail(err) }
const result = reloadRequire(tmpDir)
resetState()
t.equal(result, 'e')
})
})
test('transforms prefix with template string interpolation', t => {
t.plan(1)
compile('./', fixture('f'), err => {
if (err) { return t.fail(err) }
const result = reloadRequire(tmpDir)
resetState()
t.equal(result, 'f')
})
})
test('works with relative projectRoot opt and relative filename', t => {
t.plan(1)
const result = transform('require("~/foo");', {
filename: 'src/file.js',
plugins: [[plugin, {projectRoot: './src'}]]
})
t.equal(result.code, 'require("./foo");')
})
test('works with relative projectRoot opt and absolute filename', t => {
t.plan(1)
const result = transform('require("~/foo");', {
filename: process.cwd() + '/src/file.js',
plugins: [[plugin, {projectRoot: './src'}]]
})
t.equal(result.code, 'require("./foo");')
})
test('works with absolute projectRoot opt and relative filename', t => {
t.plan(1)
const result = transform('require("~/foo");', {
filename: 'src/file.js',
plugins: [[plugin, {projectRoot: process.cwd() + '/src'}]]
})
t.equal(result.code, 'require("./foo");')
})
test('works with absolute projectRoot opt and absolute filename', t => {
t.plan(1)
const result = transform('require("~/foo");', {
filename: process.cwd() + '/src/file.js',
plugins: [[plugin, {projectRoot: process.cwd() + '/src'}]]
})
t.equal(result.code, 'require("./foo");')
})
test('uses `prefix` option', t => {
t.plan(1)
const result = transform('require("^/foo");', {
filename: 'file.js',
plugins: [[plugin, {prefix: '^'}]]
})
t.equal(result.code, 'require("./foo");')
})
test('`prefix` option can be several character long', t => {
t.plan(1)
const result = transform('require("hey-o/foo");', {
filename: 'file.js',
plugins: [[plugin, {prefix: 'hey-o'}]]
})
t.equal(result.code, 'require("./foo");')
})
test('throws error when `prefix` option is an object', t => {
t.plan(1)
try {
const result = transform('require(`~/${ myVar }`);', {
filename: 'a/file.js',
plugins: [[plugin, {prefix: {}}]]
})
t.fail('did not throw')
} catch (err) {
t.pass(err)
}
})
test('very nested', t => {
t.plan(1)
const result = transform('require("~/q/w/e/r/t/y");', {
filename: 'a/b/c/d/e/file.js',
plugins
})
t.equal(result.code, 'require("../../../../../q/w/e/r/t/y");')
})
test('transforms require.resolve', t => {
t.plan(1)
const result = transform('require.resolve("~/foo");', {
filename: 'file.js',
plugins
})
t.equal(result.code, 'require.resolve("./foo");')
})
test('transform require that is in a function scope', t => {
t.plan(1)
const code = `const foo = () => {
function bar() {
return require("~/a");
}
return bar;
};`
const result = transform(code, {
filename: 'b',
plugins
})
t.equal(result.code, code.replace('~', '.'))
})
test('preserves trailing slash', t => {
t.plan(1)
const result = transform('require("~/foo/" + bar);', {
filename: 'a',
plugins
})
t.equal(result.code, 'require("./foo/" + bar);')
})