@ordojs/core
Version:
Core compiler and runtime for OrdoJS framework
117 lines (101 loc) • 3.49 kB
text/typescript
/**
* @fileoverview Final parser validation tests
*/
import { describe, expect, it } from 'vitest';
import { OrdoJSLexer } from './lexer.js';
import { OrdoJSParser } from './parser.js';
describe('OrdoJSParser - Final Validation', () => {
const parseComponent = (source: string) => {
const lexer = new OrdoJSLexer(source, 'test.ordo');
const tokens = lexer.tokenize();
const parser = new OrdoJSParser(tokens, {}, 'test.ordo');
return parser.parse();
};
it('should parse minimal component', () => {
const source = `
component TestComponent {
markup {
<div>Hello World</div>
}
}
`;
const ast = parseComponent(source);
expect(ast.component.name).toBe('TestComponent');
expect(ast.component.markupBlock.elements).toHaveLength(1);
expect(ast.component.markupBlock.elements[0].tagName).toBe('div');
});
it('should parse component with client block', () => {
const source = `
component TestComponent {
client {
let count = 0;
const name = "test";
}
markup {
<div>{count}</div>
}
}
`;
const ast = parseComponent(source);
expect(ast.component.clientBlock).toBeDefined();
expect(ast.component.clientBlock!.reactiveVariables).toHaveLength(2);
expect(ast.component.clientBlock!.reactiveVariables[0].name).toBe('count');
expect(ast.component.clientBlock!.reactiveVariables[1].name).toBe('name');
});
it('should parse component with server block', () => {
const source = `
component TestComponent {
server {
public getData(): string {
return "data";
}
}
markup {
<div>Test</div>
}
}
`;
const ast = parseComponent(source);
expect(ast.component.serverBlock).toBeDefined();
expect(ast.component.serverBlock!.functions).toHaveLength(1);
expect(ast.component.serverBlock!.functions[0].name).toBe('getData');
expect(ast.component.serverBlock!.functions[0].isPublic).toBe(true);
});
it('should parse HTML with attributes', () => {
const source = `
component TestComponent {
markup {
<div class="container" id="main">
<input type="text" placeholder="Enter text" />
<button disabled>Click me</button>
</div>
}
}
`;
const ast = parseComponent(source);
const mainDiv = ast.component.markupBlock.elements[0];
expect(mainDiv.attributes).toHaveLength(2);
expect(mainDiv.attributes[0].name).toBe('class');
expect(mainDiv.attributes[0].value).toBe('container');
expect(mainDiv.attributes[1].name).toBe('id');
expect(mainDiv.attributes[1].value).toBe('main');
expect(mainDiv.children).toHaveLength(2);
});
it('should parse component with props', () => {
const source = `
component TestComponent(title: string, count: number = 0) {
markup {
<div>{title}: {count}</div>
}
}
`;
const ast = parseComponent(source);
expect(ast.component.props).toHaveLength(2);
expect(ast.component.props[0].name).toBe('title');
expect(ast.component.props[0].dataType.name).toBe('string');
expect(ast.component.props[0].isRequired).toBe(true);
expect(ast.component.props[1].name).toBe('count');
expect(ast.component.props[1].dataType.name).toBe('number');
expect(ast.component.props[1].isRequired).toBe(false);
});
});