LeDDGroup/typescript-transform-jsx

View on GitHub
src/index.test.ts

Summary

Maintainability
A
0 mins
Test Coverage
import * as ts from "typescript";
import transformer from "./index";
import safeEval from "safe-eval";

const compilerOptions: ts.CompilerOptions = {
  target: ts.ScriptTarget.ESNext,
  module: ts.ModuleKind.CommonJS,
  jsx: ts.JsxEmit.Preserve,
};

function compile(source: string) {
  const { outputText } = ts.transpileModule(source, {
    compilerOptions,
    transformers: { after: [transformer] },
  });
  return outputText;
}

function runFunction(source: string) {
  const compiled = compile(source);
  const wrapped = `(function () {${compiled}})()`;
  return safeEval(wrapped);
}

function run(source: string) {
  return safeEval(compile(source));
}

function checkf(source: string, expected: string) {
  const actual = runFunction(source);
  expect(actual).toBe(expected);
}

function check(source: string, expected: string) {
  const actual = run(source);
  expect(actual).toBe(expected);
}

test("simple", () => {
  check(
    '<div className="container" moreProps="hello">Hello World</div>;',
    '<div className="container" moreProps="hello">Hello World</div>'
  );
});

test("interpolation", () => {
  check('<div class={3}>{"hello"}</div>', '<div class="3">hello</div>');
});

test("fragments", () => {
  check("<><h1>hello</h1><h2>world</h2></>", "<h1>hello</h1><h2>world</h2>");
});

test("More Complex", () => {
  checkf(
    `
const Control = ({label, children}: any) => <div><label>{label}</label>{children}</div>
return <Control label='hello'>world</Control>;
`,
    "<div><label>hello</label>world</div>"
  );
});

test("spread", () => {
  checkf(
    `
const Control = ({label, children}: any) => <div><label>{label}</label>{children}</div>
return <Control {...{ label: "hello", children: "world" }} />;
`,
    "<div><label>hello</label>world</div>"
  );
});

test("spread2", () => {
  checkf(
    `
const Control = ({children, label, ...props}: any) => <label>{label}<a {...props}/></label>
return <Control label='hello' placeholder='world' type='string' />;
`,
    '<label>hello<a placeholder="world" type="string"/></label>'
  );
});

test("spread3", () => {
  checkf(
    `
const Input = ({ children, ...props }: any) => (
  <div class="uk-width-small-1-2 uk-margin-bottom"><input class="uk-width-1-1 uk-text-contrast form_input" {...props} /></div>
);
return <Input type="text" placeholder="First Name*" name="First Name" required/>
`,
    '<div class="uk-width-small-1-2 uk-margin-bottom"><input class="uk-width-1-1 uk-text-contrast form_input" type="text" placeholder="First Name*" name="First Name" required="true"/></div>'
  );
});

// https://reactjs.org/docs/jsx-in-depth.html#string-literals-1
test("whitespace between tags", () => {
  check(
    `
<h2>
    hello
    my
    <span>world</span>
</h2>
`,
    "<h2>hello my<span>world</span></h2>"
  );
});

test("whitespace between text", () => {
  check(
    `
<h2>
hello
my
w
<span>orld</span>
</h2>
`,
    "<h2>hello my w<span>orld</span></h2>"
  );
});