151 lines
4.5 KiB
TypeScript
151 lines
4.5 KiB
TypeScript
// use package path instead relative because we want
|
|
// to test it in from /dist folder in integration tests
|
|
import linguiMacroPlugin, {
|
|
LinguiPluginOpts,
|
|
} from "@lingui-solid/babel-plugin-lingui-macro"
|
|
import { transformFileSync, transformSync, TransformOptions } from "@babel/core"
|
|
import prettier from "prettier"
|
|
import path from "path"
|
|
import fs from "fs"
|
|
|
|
export type TestCase = TestCaseInline | TestCaseFixture
|
|
|
|
type TestCaseInline = {
|
|
/**
|
|
* Input code for testing
|
|
*/
|
|
code: string
|
|
/**
|
|
* If not set, snapshot testing will be used
|
|
*/
|
|
expected?: string
|
|
} & TestCaseCommon
|
|
|
|
type TestCaseFixture = {
|
|
filename: string
|
|
} & TestCaseCommon
|
|
|
|
type TestCaseCommon = {
|
|
name?: string
|
|
production?: boolean
|
|
useTypescriptPreset?: boolean
|
|
macroOpts?: LinguiPluginOpts
|
|
only?: boolean
|
|
skip?: boolean
|
|
}
|
|
|
|
export type MacroTesterOptions = {
|
|
cases: TestCase[]
|
|
}
|
|
|
|
export function macroTester(opts: MacroTesterOptions) {
|
|
process.env.LINGUI_CONFIG = path.join(__dirname, "lingui.config.js")
|
|
|
|
const clean = (value: string) =>
|
|
prettier.format(value, { parser: "babel-ts" }).replace(/\n+/, "\n")
|
|
|
|
opts.cases.forEach((testCase, index) => {
|
|
const { name, production, only, skip, useTypescriptPreset, macroOpts } =
|
|
testCase
|
|
|
|
let group = test
|
|
if (only) group = test.only
|
|
if (skip) group = test.skip
|
|
const groupName = name != null ? name : `#${index + 1}`
|
|
|
|
group(groupName, () => {
|
|
const originalEnv = process.env.NODE_ENV
|
|
|
|
if (production) {
|
|
process.env.NODE_ENV = "production"
|
|
}
|
|
|
|
try {
|
|
if ("filename" in testCase) {
|
|
const inputPath = path.relative(
|
|
process.cwd(),
|
|
path.join(__dirname, "fixtures", testCase.filename)
|
|
)
|
|
const expectedPath = inputPath.replace(/\.js$/, ".expected.js")
|
|
const expected = fs
|
|
.readFileSync(expectedPath, "utf8")
|
|
.replace(/\r/g, "")
|
|
.trim()
|
|
|
|
const actualPlugin = transformFileSync(inputPath, {
|
|
...getDefaultBabelOptions("plugin", macroOpts, useTypescriptPreset),
|
|
cwd: path.dirname(inputPath),
|
|
})
|
|
.code.replace(/\r/g, "")
|
|
.trim()
|
|
|
|
const actualMacro = transformFileSync(inputPath, {
|
|
...getDefaultBabelOptions("plugin", macroOpts, useTypescriptPreset),
|
|
cwd: path.dirname(inputPath),
|
|
})
|
|
.code.replace(/\r/g, "")
|
|
.trim()
|
|
|
|
// output from plugin transformation should be the same to macro transformation
|
|
expect(actualPlugin).toBe(actualMacro)
|
|
|
|
expect(clean(actualPlugin)).toEqual(clean(expected))
|
|
} else {
|
|
const actualPlugin = transformSync(
|
|
testCase.code,
|
|
getDefaultBabelOptions("plugin", macroOpts, useTypescriptPreset)
|
|
).code.trim()
|
|
|
|
const actualMacro = transformSync(
|
|
testCase.code,
|
|
getDefaultBabelOptions("macro", macroOpts, useTypescriptPreset)
|
|
).code.trim()
|
|
|
|
// output from plugin transformation should be the same to macro transformation
|
|
expect(actualPlugin).toBe(actualMacro)
|
|
|
|
if (testCase.expected) {
|
|
expect(clean(actualPlugin)).toEqual(clean(testCase.expected))
|
|
} else {
|
|
expect(
|
|
clean(testCase.code) + "\n↓ ↓ ↓ ↓ ↓ ↓\n\n" + clean(actualPlugin)
|
|
).toMatchSnapshot()
|
|
}
|
|
}
|
|
} finally {
|
|
process.env.LINGUI_CONFIG = ""
|
|
process.env.NODE_ENV = originalEnv
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
export const getDefaultBabelOptions = (
|
|
transformType: "plugin" | "macro" = "plugin",
|
|
macroOpts: LinguiPluginOpts = {},
|
|
isTs: boolean = false
|
|
): TransformOptions => {
|
|
return {
|
|
filename: "<filename>" + (isTs ? ".tsx" : "jsx"),
|
|
configFile: false,
|
|
babelrc: false,
|
|
presets: [...(isTs ? ["@babel/preset-typescript"] : [])],
|
|
plugins: [
|
|
"@babel/plugin-syntax-jsx",
|
|
transformType === "plugin"
|
|
? [linguiMacroPlugin, macroOpts]
|
|
: [
|
|
"macros",
|
|
{
|
|
lingui: macroOpts,
|
|
// macro plugin uses package `resolve` to find a path of macro file
|
|
// this will not follow jest pathMapping and will resolve path from ./build
|
|
// instead of ./src which makes testing & developing hard.
|
|
// here we override resolve and provide correct path for testing
|
|
resolvePath: (source: string) => require.resolve(source),
|
|
},
|
|
],
|
|
],
|
|
}
|
|
}
|