UNPKG

@ordojs/core

Version:

Core compiler and runtime for OrdoJS framework

195 lines (167 loc) 5.88 kB
/** * @fileoverview Tests for OrdoJS SSR Engine */ import { describe, expect, it, vi } from 'vitest'; import { OrdoJSCodeGenerator } from './code-generator-fixed.js'; import { OrdoJSSSR } from './ssr-engine.js'; // Mock the code generator vi.mock('./code-generator-fixed.js', () => { return { OrdoJSCodeGenerator: vi.fn().mockImplementation(() => { return { generateHTML: vi.fn().mockImplementation((ast, props) => { return `<div data-ordojs-component="${ast.component.name}" data-ordojs-hydrate="true"> <h1>Hello, ${props?.name || 'World'}</h1> <p>This is a test component</p> </div>`; }) }; }) }; }); describe('OrdoJSSSR', () => { // Create a mock component AST const mockAST: any = { component: { name: 'TestComponent', props: [ { name: 'name', isRequired: false, defaultValue: { expressionType: 'LITERAL', value: 'World' } } ], clientBlock: { reactiveVariables: [ { name: 'count', initialValue: { expressionType: 'LITERAL', value: 0 }, dataType: { name: 'number', isArray: false, isOptional: false, genericTypes: [] } } ] }, serverBlock: { functions: [ { name: 'getServerSideProps', parameters: [], body: [], returnType: { name: 'object', isArray: false, isOptional: false, genericTypes: [] }, isAsync: true, isPublic: true, middleware: [], permissions: [] } ] }, markupBlock: { elements: [], textNodes: [], interpolations: [] } }, dependencies: [], exports: [], sourceMap: { version: 3, sources: [], names: [], mappings: '', sourcesContent: [] } }; it('should register components', () => { const ssr = new OrdoJSSSR(); ssr.registerComponent(mockAST); // Use a private property accessor for testing const registry = (ssr as any).componentRegistry; expect(registry.has('TestComponent')).toBe(true); }); it('should render a component to HTML', async () => { const ssr = new OrdoJSSSR(); ssr.registerComponent(mockAST); const html = await ssr.renderComponent('TestComponent', { name: 'Tester' }); // Check that the HTML contains the component name expect(html).toContain('data-ordojs-component="TestComponent"'); // Check that props were passed correctly expect(html).toContain('Hello, Tester'); // Check that hydration data was included expect(html).toContain('<script type="application/json" id="ordojs-hydration-data">'); expect(html).toContain('"componentName": "TestComponent"'); }); it('should generate hydration data', () => { const ssr = new OrdoJSSSR(); const hydrationData = ssr.generateHydrationData(mockAST, { name: 'Tester' }); expect(hydrationData.componentName).toBe('TestComponent'); expect(hydrationData.props).toEqual({ name: 'Tester' }); expect(hydrationData.initialState).toEqual({ count: 0 }); expect(hydrationData.version).toBe('1.0'); }); it('should handle data fetching', async () => { const ssr = new OrdoJSSSR({ dataFetcher: async (component, props) => { return { serverData: 'fetched data' }; } }); ssr.registerComponent(mockAST); const data = await ssr.handleDataFetching('TestComponent', { name: 'Tester' }); expect(data.props).toEqual({ name: 'Tester', serverData: 'fetched data' }); }); it('should render a route', async () => { const ssr = new OrdoJSSSR({ routes: [ { path: '/users/:id', component: 'TestComponent', dataFetcher: async (params, query) => { return { userId: params.id, filter: query.filter }; } } ] }); ssr.registerComponent(mockAST); const html = await ssr.renderRoute('/users/123?filter=active'); // Check that route params were passed to the component expect(html).toContain('data-ordojs-component="TestComponent"'); // The mock code generator doesn't actually use these props, but we can verify // the route handling by checking that the function was called expect(OrdoJSCodeGenerator).toHaveBeenCalled(); }); it('should generate a complete HTML document', () => { const ssr = new OrdoJSSSR(); const content = '<div>Test content</div>'; const document = ssr.generateDocument(content, 'Test Page', ['/js/app.js'], ['/css/styles.css']); expect(document).toContain('<!DOCTYPE html>'); expect(document).toContain('<title>Test Page</title>'); expect(document).toContain('<div id="app"><div>Test content</div></div>'); expect(document).toContain('<script src="/js/app.js" defer></script>'); expect(document).toContain('<link rel="stylesheet" href="/css/styles.css">'); }); it('should throw an error when component is not found', async () => { const ssr = new OrdoJSSSR(); await expect(ssr.renderComponent('NonExistentComponent')).rejects.toThrow( 'Component "NonExistentComponent" not found in registry' ); }); it('should throw an error when no routes are configured', async () => { const ssr = new OrdoJSSSR(); await expect(ssr.renderRoute('/some-path')).rejects.toThrow( 'No routes configured for SSR' ); }); it('should throw an error when no matching route is found', async () => { const ssr = new OrdoJSSSR({ routes: [ { path: '/users/:id', component: 'TestComponent' } ] }); await expect(ssr.renderRoute('/products/123')).rejects.toThrow( 'No route found for path: /products/123' ); }); });