UNPKG

@ordojs/core

Version:

Core compiler and runtime for OrdoJS framework

192 lines (167 loc) 6.41 kB
/** * @fileoverview Tests for RPC generator and client-server separation */ import { describe, expect, it } from 'vitest'; import { OrdoJSCodeGenerator } from './code-generator-fixed.js'; import { RPCGenerator } from './rpc-generator.js'; describe('RPC Generator', () => { const rpcGenerator = new RPCGenerator({ endpoint: '/api/rpc', timeout: 5000, retries: 2, errorHandling: 'throw', authentication: true }); // Mock component AST with server functions const mockAST: any = { component: { name: 'TestComponent', serverBlock: { functions: [ { name: 'fetchData', parameters: [ { name: 'id', isOptional: false, dataType: { name: 'string', isArray: false, isOptional: false, genericTypes: [] } }, { name: 'filter', isOptional: true, dataType: { name: 'string', isArray: false, isOptional: true, genericTypes: [] } } ], returnType: { name: 'object', isArray: false, isOptional: false, genericTypes: [] }, isAsync: true, isPublic: true, middleware: ['authMiddleware'], permissions: ['read:data'] }, { name: 'privateFunction', parameters: [], returnType: { name: 'void', isArray: false, isOptional: false, genericTypes: [] }, isAsync: false, isPublic: false, middleware: [], permissions: [] } ] } } }; it('should generate RPC stubs for public server functions', () => { const stubs = rpcGenerator.generateRPCStubs(mockAST); // Should only generate stubs for public functions expect(stubs.length).toBe(1); expect(stubs[0].functionName).toBe('fetchData'); // Should include metadata expect(stubs[0].metadata.componentName).toBe('TestComponent'); expect(stubs[0].metadata.parameters.length).toBe(2); expect(stubs[0].metadata.isAsync).toBe(true); // Should generate correct endpoint expect(stubs[0].serverEndpoint).toBe('/api/rpc/TestComponent/fetchData'); // Client code should be a string containing the function implementation expect(typeof stubs[0].clientCode).toBe('string'); expect(stubs[0].clientCode).toContain('async function fetchData'); expect(stubs[0].clientCode).toContain('id, filter'); }); it('should generate client module with all RPC stubs', () => { const stubs = rpcGenerator.generateRPCStubs(mockAST); const clientModule = rpcGenerator.generateRPCClientModule(stubs, 'TestComponent'); // Should generate a class with the component name expect(clientModule).toContain('export class TestComponentRPCClient'); // Should include authentication helper when authentication is enabled expect(clientModule).toContain('function getAuthToken()'); // Should export a default instance expect(clientModule).toContain('export default new TestComponentRPCClient()'); }); it('should generate server routes module', () => { const stubs = rpcGenerator.generateRPCStubs(mockAST); const serverModule = rpcGenerator.generateServerRoutesModule(stubs, 'TestComponent'); // Should import the server component expect(serverModule).toContain("require('./testcomponent-server')"); // Should create route handlers for each RPC endpoint expect(serverModule).toContain("app.post('/api/rpc/TestComponent/fetchData'"); // Should include middleware checks expect(serverModule).toContain('await authMiddleware(req, res)'); // Should include permission checks expect(serverModule).toContain('const requiredPermissions = ["read:data"]'); }); }); describe('Code Generator with RPC Integration', () => { // Mock component AST with server functions const mockAST: any = { component: { name: 'TestComponent', serverBlock: { functions: [ { name: 'fetchData', parameters: [ { name: 'id', isOptional: false, dataType: { name: 'string', isArray: false, isOptional: false, genericTypes: [] } }, { name: 'filter', isOptional: true, dataType: { name: 'string', isArray: false, isOptional: true, genericTypes: [] } } ], returnType: { name: 'object', isArray: false, isOptional: false, genericTypes: [] }, isAsync: true, isPublic: true, middleware: ['authMiddleware'], permissions: ['read:data'] } ] }, clientBlock: { reactiveVariables: [], computedValues: [], eventHandlers: [], functions: [], lifecycle: [] }, markupBlock: { elements: [], textNodes: [], interpolations: [] }, props: [] }, dependencies: [], exports: [], sourceMap: { version: 3, sources: [], names: [], mappings: '', sourcesContent: [] } }; it('should integrate RPC generator in code generation', () => { // Create code generator with RPC options const codeGenerator = new OrdoJSCodeGenerator({ minify: false, sourceMaps: true, target: 'development', rpcOptions: { endpoint: '/api/rpc', timeout: 5000, retries: 2, errorHandling: 'throw' } }); // Generate client code const clientCode = codeGenerator.generateClientCode(mockAST); // Verify RPC stubs are generated in client code expect(clientCode).toContain('component.server = component.server || {}'); expect(clientCode).toContain('component.server.fetchData = async function'); expect(clientCode).toContain('/api/rpc/TestComponent/fetchData'); expect(clientCode).toContain('const response = await fetch'); expect(clientCode).toContain('return result'); }); it('should generate server code with RPC endpoints', () => { const codeGenerator = new OrdoJSCodeGenerator({ minify: false, sourceMaps: true, target: 'development', rpcOptions: { endpoint: '/api/rpc' } }); // Generate server code const serverCode = codeGenerator.generateServerCode(mockAST); // Verify server functions are exported expect(serverCode).toContain('public async function fetchData'); expect(serverCode).toContain('serverModule.fetchData = fetchData'); }); });