/* eslint-disable max-len */ import { compile } from '../' import generate from '@babel/generator' import { parse } from '@babel/parser' /** * Parses js-code to ast and compile again to js. Used to bring in a view that * is obtained when compiling ast. */ const recompile = (jsCode: string): string => generate(parse(jsCode, { plugins: ['jsx'], sourceType: 'module' }).program).code describe('elements', () => { test('should convert simple div', () => { expect(compile('
', false)).toBe('
;') }) test('should close self-closing elements', () => { expect(compile('', false)).toBe(';') expect(compile('', false)).toBe(';') expect(compile('
', false)).toBe('
;') }) test('should wrap multiple elements to fragment', () => { expect(compile('
', false)).toBe('
;') expect(compile('Some text
', false)).toBe('Some text
;') expect(compile('
', false)).toBe( '
;' ) }) }) describe('element values', () => { test('should create literal value', () => { expect(compile('
Value
', false)).toBe('
Value
;') }) test('should create value with expression', () => { expect(compile('
Lorem {{ipsum}} dolor sit amet
')).toBe( recompile('props =>
Lorem {props.ipsum} dolor sit amet
') ) }) test('should escape curly braces in handlebars template', () => { expect(compile('
Lorem {ipsum} dolor sit {amet
')).toBe( recompile(`props =>
Lorem {"{"}ipsum{"}"} dolor sit {"{"}amet
`) ) }) }) describe('component support', () => { test('should return component', () => { expect(compile('
')).toBe('props =>
;') }) test("shouldn't return component", () => { expect(compile('
', false)).toBe('
;') }) test('should add "props" prefix to variables in component', () => { expect(compile('
{{variable}}
')).toBe(recompile('props =>
{props.variable}
')) }) test('shouldn\'t add "props" prefix to variables if it\'s not component', () => { expect(compile('
{{variable}}
', false)).toBe('
{variable}
;') }) test('should export component by default', () => { expect(compile('
{{variable}}
', { isModule: true, isComponent: true })).toBe( recompile('export default props =>
{props.variable}
') ) }) }) describe('element attributes', () => { test('should convert simple text attribute', () => { expect(compile('
', false)).toBe('
;') }) test('should remove unsupported attribute', () => { expect(compile('
', false)).toBe('
;') }) test('should convert specific attribute name', () => { expect(compile('
', false)).toBe('
;') expect(compile('
', false)).toBe('
;') expect(compile('
', false)).toBe('
;') expect(compile('', false)).toBe( ';' ) }) test('should convert attribute with statement', () => { expect(compile('
', false)).toBe('
;') expect(compile('
', false)).toBe('
;') expect(compile('
')).toBe(recompile('props =>
;')) }) xtest('should throw error when used reserved JavaScript words', () => { // TODO }) test('should convert attribute with concatenation statement', () => { expect(compile('
', false)).toBe('
;') expect(compile('
', false)).toBe('
;') expect(compile('
')).toBe(recompile('props =>
;')) expect(compile('
')).toBe(recompile('props =>
;')) expect(compile('
')).toBe( recompile('props =>
;') ) expect(compile('Link', false)).toBe( 'Link;' ) }) test('should convert the "styles" string to stylesObject', () => { expect(compile('
', false)).toBe( recompile('
') ) }) test('should convert the "styles" string with variables to stylesObject', () => { // Block of styles expect( compile( '
', false ) ).toBe( recompile( `
` ) ) // Trailing semicolon expect(compile('
', false)).toBe( recompile(`
`) ) // Expression in key expect(compile('
', false)).toBe( recompile(`
`) ) }) }) describe('comments', () => { test('should convert comment in JSX code', () => { expect(compile('
{{~! comment ~}}
', false)).toBe(recompile('
{/* comment */}
;')) expect(compile('
{{~!-- long-comment --~}}
', false)).toBe(recompile('
{/* long-comment */}
;')) expect(compile('
{{! comment ~}}
', false)).toBe(recompile('
{/* comment */}
;')) expect(compile('
{{!-- long-comment --~}}
', false)).toBe(recompile('
{/* long-comment */}
;')) expect(compile('
{{~! comment }}
', false)).toBe(recompile('
{/* comment */}
;')) expect(compile('
{{~!-- long-comment --}}
', false)).toBe(recompile('
{/* long-comment */}
;')) expect(compile('
', false)).toBe(recompile('
{/* html comment */}
;')) }) test("shouldn't convert top-level comment", () => { // Not supported currently // expect(compile('{{!-- comment --}}')).toBe(recompile('/* comment */')) expect(() => compile('{{!-- comment --}}')).toThrowError() }) }) describe('block statements', () => { describe('condition statement', () => { test('should convert condition if-then ', () => { expect(compile('
{{#if variable}}
{{/if}}
')).toBe( recompile('props =>
{Boolean(props.variable) &&
}
;') ) }) test('should convert condition if-then-else ', () => { expect(compile('
{{#if variable}}
{{else}}{{/if}}
')).toBe( recompile('props =>
{Boolean(props.variable) ?
: }
;') ) }) test('should convert condition unless-then ', () => { expect(compile('
{{#unless variable}}
{{/unless}}
')).toBe( recompile('props =>
{!Boolean(props.variable) &&
}
;') ) }) test('should convert condition unless-then-else ', () => { expect(compile('
{{#unless variable}}
{{else}}{{/unless}}
')).toBe( recompile('props =>
{!Boolean(props.variable) ?
: }
;') ) }) test('should wrap multiple block children into fragment', () => { expect(compile('
{{#if variable}}
{{/if}}
')).toBe( recompile('props =>
{Boolean(props.variable) &&
}
;') ) }) test('should convert condition statement in root', () => { expect(compile('{{#if variable}}
{{else}}{{/if}}')).toBe( recompile('props => Boolean(props.variable) ?
: ;') ) }) }) describe('each statement', () => { test('each block statement', () => { expect(compile('
{{#each list}}
{{/each}}
')).toBe( 'props =>
{props.list.map((item, i) =>
)}
;' ) }) test('nested each block statements', () => { expect(compile('
{{#each list}}{{#each list.nested}}
{{/each}}{{/each}}
')).toBe( 'props =>
{props.list.map((item, i) => {item.list.nested.map((item, i) =>
)})}
;' ) }) test('siblings each block statements with path expression - no component', () => { expect( compile( '
{{#each list}}
{{name}}
{{/each}}{{#each list}}
{{name}}
{{/each}}
', false ) ).toBe( '
{list.map((item, i) =>
{item.name}
)}{list.map((item, i) =>
{item.name}
)}
;' ) }) test('should wrap multiple block children into fragment with keys', () => { expect(compile('
{{#each list}}
Text{{/each}}
')).toBe( 'props =>
{props.list.map((item, i) =>
Text)}
;' ) }) }) }) describe('include react import', () => { test('with isModule true', () => { expect(compile('
', { isComponent: true, isModule: true, includeImport: true })).toBe( 'import React from "react";\nexport default (props =>
);' ) }) test('with isModule false', () => { expect(compile('
', { isComponent: true, isModule: false, includeImport: true })).toBe( 'props =>
;' ) }) test('with isComponent false', () => { expect(compile('
', { isComponent: false, isModule: true, includeImport: true })).toBe( 'import React from "react";\nexport default
;' ) }) })