From e484d1ecc5e405259767c0fd84072226fee40b71 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 11 Oct 2022 16:27:38 +0200 Subject: Refactor test utilities to improve names --- tests/xxx_mdx_plugin_recma_jsx_rewrite.rs | 381 ++++++++++++++++++++++++++++++ 1 file changed, 381 insertions(+) create mode 100644 tests/xxx_mdx_plugin_recma_jsx_rewrite.rs (limited to 'tests/xxx_mdx_plugin_recma_jsx_rewrite.rs') diff --git a/tests/xxx_mdx_plugin_recma_jsx_rewrite.rs b/tests/xxx_mdx_plugin_recma_jsx_rewrite.rs new file mode 100644 index 0000000..497155f --- /dev/null +++ b/tests/xxx_mdx_plugin_recma_jsx_rewrite.rs @@ -0,0 +1,381 @@ +extern crate micromark; +extern crate swc_common; +extern crate swc_ecma_ast; +extern crate swc_ecma_codegen; +mod test_utils; +use micromark::{micromark_to_mdast, Constructs, Location, ParseOptions}; +use pretty_assertions::assert_eq; +use test_utils::{ + hast_util_to_swc::hast_util_to_swc, + mdast_util_to_hast::mdast_util_to_hast, + mdx_plugin_recma_document::{mdx_plugin_recma_document, Options as DocumentOptions}, + mdx_plugin_recma_jsx_rewrite::{mdx_plugin_recma_jsx_rewrite, Options as RewriteOptions}, + swc::{parse_esm, parse_expression, serialize}, +}; + +fn from_markdown(value: &str, options: &RewriteOptions) -> Result { + let location = Location::new(value.as_bytes()); + let mdast = micromark_to_mdast( + value, + &ParseOptions { + constructs: Constructs::mdx(), + mdx_esm_parse: Some(Box::new(parse_esm)), + mdx_expression_parse: Some(Box::new(parse_expression)), + ..ParseOptions::default() + }, + )?; + let hast = mdast_util_to_hast(&mdast); + let program = hast_util_to_swc(&hast, Some("example.mdx".into()), Some(&location))?; + let program = mdx_plugin_recma_document(program, &DocumentOptions::default(), Some(&location))?; + let program = mdx_plugin_recma_jsx_rewrite(program, options, Some(&location)); + let value = serialize(&program.module); + Ok(value) +} + +#[test] +fn mdx_plugin_recma_jsx_rewrite_test() -> Result<(), String> { + assert_eq!( + from_markdown("", &Default::default())?, + "function _createMdxContent(props) { + return <>; +} +function MDXContent(props = {}) { + const { wrapper: MDXLayout } = props.components || {}; + return MDXLayout ? <_createMdxContent {...props}/> : _createMdxContent(props); +} +export default MDXContent; +", + "should work on an empty file", + ); + + assert_eq!( + from_markdown("# hi", &Default::default())?, + "function _createMdxContent(props) { + const _components = Object.assign({ + h1: \"h1\" + }, props.components); + return <_components.h1 >{\"hi\"}; +} +function MDXContent(props = {}) { + const { wrapper: MDXLayout } = props.components || {}; + return MDXLayout ? <_createMdxContent {...props}/> : _createMdxContent(props); +} +export default MDXContent; +", + "should support passing in a layout (as `wrapper`) and components for literal tags", + ); + + assert_eq!( + from_markdown( + "export {MyLayout as default} from './a.js'\n\n# hi", + &Default::default() + )?, + "import { MyLayout as MDXLayout } from './a.js'; +function _createMdxContent(props) { + const _components = Object.assign({ + h1: \"h1\" + }, props.components); + return <_components.h1 >{\"hi\"}; +} +function MDXContent(props = {}) { + return <_createMdxContent {...props}/>; +} +export default MDXContent; +", + "should not support passing in a layout if one is defined locally", + ); + + assert_eq!( + from_markdown("# ", &Default::default())?, + "function _createMdxContent(props) { + const _components = Object.assign({ + h1: \"h1\" + }, props.components), { Hi } = _components; + if (!Hi) _missingMdxReference(\"Hi\", true); + return <_components.h1 >; +} +function MDXContent(props = {}) { + const { wrapper: MDXLayout } = props.components || {}; + return MDXLayout ? <_createMdxContent {...props}/> : _createMdxContent(props); +} +export default MDXContent; +function _missingMdxReference(id, component) { + throw new Error(\"Expected \" + (component ? \"component\" : \"object\") + \" `\" + id + \"` to be defined: you likely forgot to import, pass, or provide it.\"); +} +", + "should support passing in a component", + ); + + assert_eq!( + from_markdown(", , ", &Default::default())?, + "function _createMdxContent(props) { + const _components = Object.assign({ + p: \"p\" + }, props.components), { X , Y } = _components; + if (!X) _missingMdxReference(\"X\", true); + if (!X.y) _missingMdxReference(\"X.y\", true); + if (!Y) _missingMdxReference(\"Y\", false); + if (!Y.Z) _missingMdxReference(\"Y.Z\", true); + return <_components.p >{\", \"}{\", \"}; +} +function MDXContent(props = {}) { + const { wrapper: MDXLayout } = props.components || {}; + return MDXLayout ? <_createMdxContent {...props}/> : _createMdxContent(props); +} +export default MDXContent; +function _missingMdxReference(id, component) { + throw new Error(\"Expected \" + (component ? \"component\" : \"object\") + \" `\" + id + \"` to be defined: you likely forgot to import, pass, or provide it.\"); +} +", + "should support passing in component objects", + ); + + assert_eq!( + from_markdown("import {Hi} from './a.js'\n\n# ", &Default::default())?, + "import { Hi } from './a.js'; +function _createMdxContent(props) { + const _components = Object.assign({ + h1: \"h1\" + }, props.components); + return <_components.h1 >; +} +function MDXContent(props = {}) { + const { wrapper: MDXLayout } = props.components || {}; + return MDXLayout ? <_createMdxContent {...props}/> : _createMdxContent(props); +} +export default MDXContent; +", + "should not support passing in a component if one is defined locally", + ); + + assert_eq!( + from_markdown("# ", &Default::default())?, + "function _createMdxContent(props) { + const _components = Object.assign({ + h1: \"h1\", + \"a-b\": \"a-b\" + }, props.components), _component0 = _components[\"a-b\"]; + return <_components.h1 ><_component0 />; +} +function MDXContent(props = {}) { + const { wrapper: MDXLayout } = props.components || {}; + return MDXLayout ? <_createMdxContent {...props}/> : _createMdxContent(props); +} +export default MDXContent; +", + "should support passing in a component for a JSX identifier that is not a valid JS identifier", + ); + + assert_eq!( + from_markdown("# ", &RewriteOptions { + provider_import_source: Some("x".into()), + ..Default::default() + })?, + "import { useMDXComponents as _provideComponents } from \"x\"; +function _createMdxContent(props) { + const _components = Object.assign({ + h1: \"h1\" + }, _provideComponents(), props.components), { Hi } = _components; + if (!Hi) _missingMdxReference(\"Hi\", true); + return <_components.h1 >; +} +function MDXContent(props = {}) { + const { wrapper: MDXLayout } = Object.assign({}, _provideComponents(), props.components); + return MDXLayout ? <_createMdxContent {...props}/> : _createMdxContent(props); +} +export default MDXContent; +function _missingMdxReference(id, component) { + throw new Error(\"Expected \" + (component ? \"component\" : \"object\") + \" `\" + id + \"` to be defined: you likely forgot to import, pass, or provide it.\"); +} +", + "should support providing a layout, literal tags, and components", + ); + + assert_eq!( + from_markdown("", &RewriteOptions { + provider_import_source: Some("x".into()), + ..Default::default() + })?, + "import { useMDXComponents as _provideComponents } from \"x\"; +function _createMdxContent(props) { + return <>; +} +function MDXContent(props = {}) { + const { wrapper: MDXLayout } = Object.assign({}, _provideComponents(), props.components); + return MDXLayout ? <_createMdxContent {...props}/> : _createMdxContent(props); +} +export default MDXContent; +", + "should support a provider on an empty file", + ); + + assert_eq!( + from_markdown(", , ", &RewriteOptions { + provider_import_source: Some("x".into()), + ..Default::default() + })?, + "import { useMDXComponents as _provideComponents } from \"x\"; +function _createMdxContent(props) { + const _components = Object.assign({ + p: \"p\" + }, _provideComponents(), props.components), { X , Y } = _components; + if (!X) _missingMdxReference(\"X\", true); + if (!X.y) _missingMdxReference(\"X.y\", true); + if (!Y) _missingMdxReference(\"Y\", false); + if (!Y.Z) _missingMdxReference(\"Y.Z\", true); + return <_components.p >{\", \"}{\", \"}; +} +function MDXContent(props = {}) { + const { wrapper: MDXLayout } = Object.assign({}, _provideComponents(), props.components); + return MDXLayout ? <_createMdxContent {...props}/> : _createMdxContent(props); +} +export default MDXContent; +function _missingMdxReference(id, component) { + throw new Error(\"Expected \" + (component ? \"component\" : \"object\") + \" `\" + id + \"` to be defined: you likely forgot to import, pass, or provide it.\"); +} +", + "should support providing component objects", + ); + + assert_eq!( + from_markdown("export function A() { + return +} + + +", &Default::default())?, + "export function A() { + return ; +} +function _createMdxContent(props) { + return ; +} +function MDXContent(props = {}) { + const { wrapper: MDXLayout } = props.components || {}; + return MDXLayout ? <_createMdxContent {...props}/> : _createMdxContent(props); +} +export default MDXContent; +", + "should not support passing components in locally defined components", + ); + + assert_eq!( + from_markdown("export function A() { + return +} + + +", &RewriteOptions { + provider_import_source: Some("x".into()), + ..Default::default() +})?, + "import { useMDXComponents as _provideComponents } from \"x\"; +export function A() { + const { B } = _provideComponents(); + if (!B) _missingMdxReference(\"B\", true); + return ; +} +function _createMdxContent(props) { + return ; +} +function MDXContent(props = {}) { + const { wrapper: MDXLayout } = Object.assign({}, _provideComponents(), props.components); + return MDXLayout ? <_createMdxContent {...props}/> : _createMdxContent(props); +} +export default MDXContent; +function _missingMdxReference(id, component) { + throw new Error(\"Expected \" + (component ? \"component\" : \"object\") + \" `\" + id + \"` to be defined: you likely forgot to import, pass, or provide it.\"); +} +", + "should support providing components in locally defined components", + ); + + assert_eq!( + from_markdown("export function A() { + return +} + + +", &RewriteOptions { + provider_import_source: Some("x".into()), + ..Default::default() +})?, + "import { useMDXComponents as _provideComponents } from \"x\"; +export function A() { + const _components = Object.assign({ + \"b-c\": \"b-c\" + }, _provideComponents()), _component0 = _components[\"b-c\"]; + return <_component0 />; +} +function _createMdxContent(props) { + return ; +} +function MDXContent(props = {}) { + const { wrapper: MDXLayout } = Object.assign({}, _provideComponents(), props.components); + return MDXLayout ? <_createMdxContent {...props}/> : _createMdxContent(props); +} +export default MDXContent; +", + "should support providing components with JSX identifiers that are not JS identifiers in locally defined components", + ); + + assert_eq!( + from_markdown("export function A() { + return , , +} + + +", &RewriteOptions { + provider_import_source: Some("x".into()), + ..Default::default() +})?, + "import { useMDXComponents as _provideComponents } from \"x\"; +export function A() { + const { X , Y } = _provideComponents(); + if (!X) _missingMdxReference(\"X\", true); + if (!X.y) _missingMdxReference(\"X.y\", true); + if (!Y) _missingMdxReference(\"Y\", false); + if (!Y.Z) _missingMdxReference(\"Y.Z\", true); + return , , ; +} +function _createMdxContent(props) { + return ; +} +function MDXContent(props = {}) { + const { wrapper: MDXLayout } = Object.assign({}, _provideComponents(), props.components); + return MDXLayout ? <_createMdxContent {...props}/> : _createMdxContent(props); +} +export default MDXContent; +function _missingMdxReference(id, component) { + throw new Error(\"Expected \" + (component ? \"component\" : \"object\") + \" `\" + id + \"` to be defined: you likely forgot to import, pass, or provide it.\"); +} +", + "should support providing components with JSX identifiers that are not JS identifiers in locally defined components", + ); + + assert_eq!( + from_markdown("# ", &RewriteOptions { + development: true, + ..Default::default() + })?, + "function _createMdxContent(props) { + const _components = Object.assign({ + h1: \"h1\" + }, props.components), { Hi } = _components; + if (!Hi) _missingMdxReference(\"Hi\", true, \"1:3-1:9\"); + return <_components.h1 >; +} +function MDXContent(props = {}) { + const { wrapper: MDXLayout } = props.components || {}; + return MDXLayout ? <_createMdxContent {...props}/> : _createMdxContent(props); +} +export default MDXContent; +function _missingMdxReference(id, component, place) { + throw new Error(\"Expected \" + (component ? \"component\" : \"object\") + \" `\" + id + \"` to be defined: you likely forgot to import, pass, or provide it.\" + (place ? \"\\nIt’s referenced in your code at `\" + place + \"` in `example.mdx`\" : \"\")); +} +", + "should create missing reference helpers w/o positional info in `development` mode", + ); + + Ok(()) +} -- cgit