UNPKG

@ordojs/core

Version:

Core compiler and runtime for OrdoJS framework

275 lines (259 loc) 8.1 kB
/** * @fileoverview Tests for OrdoJS Code Generator */ import { describe, expect, it } from 'vitest'; import { ComponentAST, ComponentNode, HTMLElementNode, MarkupBlockNode, TextNode, } from '../types/index.js'; import { OrdoJSCodeGenerator } from './code-generator.js'; // Helper to create a simple source range function createRange(startLine: number, startCol: number, endLine: number, endCol: number) { return { start: { line: startLine, column: startCol, offset: 0 }, end: { line: endLine, column: endCol, offset: 0 } }; } describe('OrdoJSCodeGenerator', () => { it('should generate client code for a simple component', () => { // Create a simple AST manually const ast: ComponentAST = { component: { type: 'Component', name: 'SimpleComponent', props: [], markupBlock: { type: 'MarkupBlock', elements: [ { type: 'HTMLElement', tagName: 'div', attributes: [ { type: 'Attribute', name: 'class', value: 'container', isDirective: false, range: createRange(1, 1, 1, 20) } ], children: [ { type: 'Text', content: 'Hello, World!', range: createRange(1, 21, 1, 34) } as TextNode ], isSelfClosing: false, isVoidElement: false, range: createRange(1, 1, 1, 40) } as HTMLElementNode ], textNodes: [], interpolations: [], range: createRange(1, 1, 1, 40) } as MarkupBlockNode, range: createRange(1, 1, 1, 50) } as ComponentNode, dependencies: [], exports: [], sourceMap: { version: 3, sources: [], names: [], mappings: '', sourcesContent: [] } }; const generator = new OrdoJSCodeGenerator(); const code = generator.generateClientCode(ast); // Verify the generated code contains expected elements expect(code).toContain('function SimpleComponent(props = {})'); expect(code).toContain('document.createElement("div")'); expect(code).toContain('setAttribute("class", "container")'); expect(code).toContain('document.createTextNode("Hello, World!")'); }); it('should generate HTML for a simple component', () => { // Create a simple AST manually const ast: ComponentAST = { component: { type: 'Component', name: 'SimpleComponent', props: [], markupBlock: { type: 'MarkupBlock', elements: [ { type: 'HTMLElement', tagName: 'div', attributes: [ { type: 'Attribute', name: 'class', value: 'container', isDirective: false, range: createRange(1, 1, 1, 20) } ], children: [ { type: 'Text', content: 'Hello, World!', range: createRange(1, 21, 1, 34) } as TextNode ], isSelfClosing: false, isVoidElement: false, range: createRange(1, 1, 1, 40) } as HTMLElementNode ], textNodes: [], interpolations: [], range: createRange(1, 1, 1, 40) } as MarkupBlockNode, range: createRange(1, 1, 1, 50) } as ComponentNode, dependencies: [], exports: [], sourceMap: { version: 3, sources: [], names: [], mappings: '', sourcesContent: [] } }; const generator = new OrdoJSCodeGenerator(); const html = generator.generateHTML(ast); // Verify the generated HTML contains expected elements expect(html).toContain('<div class="container" data-ordojs-hydrate="true">Hello, World!</div>'); expect(html).toContain('data-ordojs-component="SimpleComponent"'); expect(html).toContain('data-ordojs-version="1.0"'); }); it('should generate HTML with component props', () => { // Create a component AST with props const ast: ComponentAST = { component: { type: 'Component', name: 'PropsComponent', props: [ { type: 'PropDefinition', name: 'title', dataType: { name: 'string', isArray: false, isOptional: false, genericTypes: [] }, isRequired: true, range: createRange(1, 1, 1, 20) }, { type: 'PropDefinition', name: 'count', dataType: { name: 'number', isArray: false, isOptional: false, genericTypes: [] }, defaultValue: { type: 'Expression', expressionType: 'LITERAL', value: 0, range: createRange(1, 30, 1, 31) }, isRequired: false, range: createRange(1, 21, 1, 40) } ], markupBlock: { type: 'MarkupBlock', elements: [ { type: 'HTMLElement', tagName: 'div', attributes: [], children: [ { type: 'Text', content: 'Component with props', range: createRange(1, 21, 1, 40) } as TextNode ], isSelfClosing: false, isVoidElement: false, range: createRange(1, 1, 1, 50) } as HTMLElementNode ], textNodes: [], interpolations: [], range: createRange(1, 1, 1, 60) } as MarkupBlockNode, range: createRange(1, 1, 1, 70) } as ComponentNode, dependencies: [], exports: [], sourceMap: { version: 3, sources: [], names: [], mappings: '', sourcesContent: [] } }; // Generate HTML with initial props const generator = new OrdoJSCodeGenerator(); const html = generator.generateHTML(ast, { title: 'Hello', count: 42 }); // Verify the generated HTML contains props data expect(html).toContain('data-props='); // Just check that the HTML contains the expected values expect(html).toContain('title'); expect(html).toContain('Hello'); expect(html).toContain('count'); expect(html).toContain('42'); }); it('should generate complete code bundle', () => { // Create a simple AST manually const ast: ComponentAST = { component: { type: 'Component', name: 'SimpleComponent', props: [], markupBlock: { type: 'MarkupBlock', elements: [ { type: 'HTMLElement', tagName: 'div', attributes: [], children: [ { type: 'Text', content: 'Hello, World!', range: createRange(1, 21, 1, 34) } as TextNode ], isSelfClosing: false, isVoidElement: false, range: createRange(1, 1, 1, 40) } as HTMLElementNode ], textNodes: [], interpolations: [], range: createRange(1, 1, 1, 40) } as MarkupBlockNode, range: createRange(1, 1, 1, 50) } as ComponentNode, dependencies: [], exports: [], sourceMap: { version: 3, sources: [], names: [], mappings: '', sourcesContent: [] } }; const generator = new OrdoJSCodeGenerator(); const bundle = generator.generate(ast); // Verify the bundle contains both client code and HTML expect(bundle.client).toBeDefined(); expect(bundle.html).toBeDefined(); expect(bundle.sourceMap).toBeDefined(); }); });