import { describe, it, expect, vi, beforeEach } from 'vitest'; import { ExampleGenerator } from '@/services/example-generator'; import type { NodeExamples } from '@/services/example-generator'; // Mock the database vi.mock('better-sqlite3'); describe('ExampleGenerator', () => { beforeEach(() => { vi.clearAllMocks(); }); describe('getExamples', () => { it('should return curated examples for HTTP Request node', () => { const examples = ExampleGenerator.getExamples('nodes-base.httpRequest'); expect(examples).toHaveProperty('minimal'); expect(examples).toHaveProperty('common'); expect(examples).toHaveProperty('advanced'); // Check minimal example expect(examples.minimal).toEqual({ url: 'https://api.example.com/data' }); // Check common example has required fields expect(examples.common).toMatchObject({ method: 'POST', url: 'https://api.example.com/users', sendBody: true, contentType: 'json' }); // Check advanced example has error handling expect(examples.advanced).toMatchObject({ method: 'POST', onError: 'continueRegularOutput', retryOnFail: true, maxTries: 3 }); }); it('should return curated examples for Webhook node', () => { const examples = ExampleGenerator.getExamples('nodes-base.webhook'); expect(examples.minimal).toMatchObject({ path: 'my-webhook', httpMethod: 'POST' }); expect(examples.common).toMatchObject({ responseMode: 'lastNode', responseData: 'allEntries', responseCode: 200 }); }); it('should return curated examples for Code node', () => { const examples = ExampleGenerator.getExamples('nodes-base.code'); expect(examples.minimal).toMatchObject({ language: 'javaScript', jsCode: 'return [{json: {result: "success"}}];' }); expect(examples.common?.jsCode).toContain('items.map'); expect(examples.common?.jsCode).toContain('DateTime.now()'); expect(examples.advanced?.jsCode).toContain('try'); expect(examples.advanced?.jsCode).toContain('catch'); }); it('should generate basic examples for unconfigured nodes', () => { const essentials = { required: [ { name: 'url', type: 'string' }, { name: 'method', type: 'options', options: [{ value: 'GET' }, { value: 'POST' }] } ], common: [ { name: 'timeout', type: 'number' } ] }; const examples = ExampleGenerator.getExamples('nodes-base.unknownNode', essentials); expect(examples.minimal).toEqual({ url: 'https://api.example.com', method: 'GET' }); expect(examples.common).toBeUndefined(); expect(examples.advanced).toBeUndefined(); }); it('should use common property if no required fields exist', () => { const essentials = { required: [], common: [ { name: 'name', type: 'string' } ] }; const examples = ExampleGenerator.getExamples('nodes-base.unknownNode', essentials); expect(examples.minimal).toEqual({ name: 'John Doe' }); }); it('should return empty minimal object if no essentials provided', () => { const examples = ExampleGenerator.getExamples('nodes-base.unknownNode'); expect(examples.minimal).toEqual({}); }); }); describe('special example nodes', () => { it('should provide webhook processing example', () => { const examples = ExampleGenerator.getExamples('nodes-base.code.webhookProcessing'); expect(examples.minimal?.jsCode).toContain('const webhookData = items[0].json.body'); expect(examples.minimal?.jsCode).toContain('// ❌ WRONG'); expect(examples.minimal?.jsCode).toContain('// ✅ CORRECT'); }); it('should provide data transformation examples', () => { const examples = ExampleGenerator.getExamples('nodes-base.code.dataTransform'); expect(examples.minimal?.jsCode).toContain('CSV-like data to JSON'); expect(examples.minimal?.jsCode).toContain('split'); }); it('should provide aggregation example', () => { const examples = ExampleGenerator.getExamples('nodes-base.code.aggregation'); expect(examples.minimal?.jsCode).toContain('items.reduce'); expect(examples.minimal?.jsCode).toContain('totalAmount'); }); it('should provide JMESPath filtering example', () => { const examples = ExampleGenerator.getExamples('nodes-base.code.jmespathFiltering'); expect(examples.minimal?.jsCode).toContain('$jmespath'); expect(examples.minimal?.jsCode).toContain('`100`'); // Backticks for numeric literals expect(examples.minimal?.jsCode).toContain('✅ CORRECT'); }); it('should provide Python example', () => { const examples = ExampleGenerator.getExamples('nodes-base.code.pythonExample'); expect(examples.minimal?.pythonCode).toContain('_input.all()'); expect(examples.minimal?.pythonCode).toContain('to_py()'); expect(examples.minimal?.pythonCode).toContain('import json'); }); it('should provide AI tool example', () => { const examples = ExampleGenerator.getExamples('nodes-base.code.aiTool'); expect(examples.minimal?.mode).toBe('runOnceForEachItem'); expect(examples.minimal?.jsCode).toContain('calculate discount'); expect(examples.minimal?.jsCode).toContain('$json.quantity'); }); it('should provide crypto usage example', () => { const examples = ExampleGenerator.getExamples('nodes-base.code.crypto'); expect(examples.minimal?.jsCode).toContain("require('crypto')"); expect(examples.minimal?.jsCode).toContain('randomBytes'); expect(examples.minimal?.jsCode).toContain('createHash'); }); it('should provide static data example', () => { const examples = ExampleGenerator.getExamples('nodes-base.code.staticData'); expect(examples.minimal?.jsCode).toContain('$getWorkflowStaticData'); expect(examples.minimal?.jsCode).toContain('processCount'); }); }); describe('database node examples', () => { it('should provide PostgreSQL examples', () => { const examples = ExampleGenerator.getExamples('nodes-base.postgres'); expect(examples.minimal).toMatchObject({ operation: 'executeQuery', query: 'SELECT * FROM users LIMIT 10' }); expect(examples.advanced?.query).toContain('ON CONFLICT'); expect(examples.advanced?.retryOnFail).toBe(true); }); it('should provide MongoDB examples', () => { const examples = ExampleGenerator.getExamples('nodes-base.mongoDb'); expect(examples.minimal).toMatchObject({ operation: 'find', collection: 'users' }); expect(examples.common).toMatchObject({ operation: 'findOneAndUpdate', options: { upsert: true, returnNewDocument: true } }); }); it('should provide MySQL examples', () => { const examples = ExampleGenerator.getExamples('nodes-base.mySql'); expect(examples.minimal?.query).toContain('SELECT * FROM products'); expect(examples.common?.operation).toBe('insert'); }); }); describe('communication node examples', () => { it('should provide Slack examples', () => { const examples = ExampleGenerator.getExamples('nodes-base.slack'); expect(examples.minimal).toMatchObject({ resource: 'message', operation: 'post', channel: '#general', text: 'Hello from n8n!' }); expect(examples.common?.attachments).toBeDefined(); expect(examples.common?.retryOnFail).toBe(true); }); it('should provide Email examples', () => { const examples = ExampleGenerator.getExamples('nodes-base.emailSend'); expect(examples.minimal).toMatchObject({ fromEmail: 'sender@example.com', toEmail: 'recipient@example.com', subject: 'Test Email' }); expect(examples.common?.html).toContain('