Testing Locally

Test your Trik before publishing to ensure it works correctly.

Build First

If using TypeScript, compile to JavaScript:

npm run build # or tsc

Ensure your entry.module path points to the compiled output:

{ "entry": { "module": "./dist/graph.js", "export": "default", "runtime": "node" } }

Manual Testing

Using the Gateway

Create a test script:

// test.ts import { TrikGateway } from '@trikhub/gateway'; async function test() { const gateway = new TrikGateway(); // Load your local trik await gateway.loadTrik('./'); // Test search action console.log('Testing search...'); const searchResult = await gateway.execute( 'yourname/my-trik', 'search', { topic: 'AI' } ); console.log('Search result:', JSON.stringify(searchResult, null, 2)); // Test with session if (searchResult.success && searchResult.sessionId) { console.log('\nTesting details with session...'); const detailsResult = await gateway.execute( 'yourname/my-trik', 'details', { reference: 'the first one' }, { sessionId: searchResult.sessionId } ); console.log('Details result:', JSON.stringify(detailsResult, null, 2)); } } test().catch(console.error);

Run it:

npx tsx test.ts

Using the Playground

The playgrounds provide an interactive environment:

  1. Navigate to the JS playground:
cd examples/js/local-playground npm install
  1. Add your trik to .trikhub/config.json:
{ "triks": ["yourname/my-trik"] }
  1. Run interactive mode:
npm run dev

Test your trik in conversation:

You: Search for articles about machine learning Assistant: I found 3 articles about AI. You: Show me the first one Assistant: [Article content displayed]

Unit Tests

Write unit tests for your graph logic:

// graph.test.ts import { describe, it, expect } from 'vitest'; import graph from './graph'; describe('article-search', () => { describe('search action', () => { it('returns success template with results', async () => { const result = await graph.invoke({ action: 'search', input: { topic: 'AI' } }); expect(result.responseMode).toBe('template'); expect(result.agentData.template).toBe('success'); expect(result.agentData.count).toBeGreaterThan(0); }); it('returns empty template for no results', async () => { const result = await graph.invoke({ action: 'search', input: { topic: 'nonexistent-topic-xyz' } }); expect(result.responseMode).toBe('template'); expect(result.agentData.template).toBe('empty'); }); }); describe('details action', () => { it('returns article via passthrough', async () => { const result = await graph.invoke({ action: 'details', input: { articleId: 'art-001' } }); expect(result.responseMode).toBe('passthrough'); expect(result.userContent.contentType).toBe('article'); expect(result.userContent.content).toContain('Healthcare'); }); it('returns not_found for invalid ID', async () => { const result = await graph.invoke({ action: 'details', input: { articleId: 'invalid-id' } }); expect(result.responseMode).toBe('template'); expect(result.agentData.template).toBe('not_found'); }); }); });

Run tests:

npm test # or npx vitest

Session Handling Tests

describe('session handling', () => { it('resolves ordinal references', async () => { const result = await graph.invoke({ action: 'details', input: { reference: 'the second one' }, session: { sessionId: 'test-session', history: [{ action: 'search', input: { topic: 'AI' }, agentData: { template: 'success', articleIds: ['art-001', 'art-002', 'art-003'] } }] } }); expect(result.responseMode).toBe('passthrough'); expect(result.userContent.metadata.articleId).toBe('art-002'); }); });

Integration Tests

Test with actual LangChain integration:

// integration.test.ts import { describe, it, expect } from 'vitest'; import { TrikGateway } from '@trikhub/gateway'; import { createLangChainTools } from '@trikhub/gateway/langchain'; describe('LangChain integration', () => { it('creates tools from trik', async () => { const gateway = new TrikGateway(); await gateway.loadTrik('./'); const tools = createLangChainTools(gateway, {}); expect(tools.length).toBeGreaterThan(0); expect(tools.some(t => t.name.includes('search'))).toBe(true); }); it('executes tool and returns result', async () => { const gateway = new TrikGateway(); await gateway.loadTrik('./'); const tools = createLangChainTools(gateway, {}); const searchTool = tools.find(t => t.name.includes('search')); const result = await searchTool?.invoke({ topic: 'AI' }); const parsed = JSON.parse(result); expect(parsed.success).toBe(true); }); });

Schema Validation

Test that outputs match your declared schemas:

import Ajv from 'ajv'; import manifest from './manifest.json'; const ajv = new Ajv(); describe('schema validation', () => { it('search output matches agentDataSchema', async () => { const result = await graph.invoke({ action: 'search', input: { topic: 'AI' } }); const validate = ajv.compile(manifest.actions.search.agentDataSchema); const valid = validate(result.agentData); expect(valid).toBe(true); if (!valid) console.log(validate.errors); }); });

Testing Checklist

Before publishing, verify:

  • All actions return valid responses
  • Template mode returns correct template values
  • Passthrough mode returns required contentType and content
  • Error cases return appropriate error templates
  • Session handling works for multi-turn conversations
  • Outputs match declared schemas
  • No sensitive data leaks into agentData

Debugging Tips

Enable Debug Logging

const { tools } = await loadLangChainTriks({ debug: true // Logs all tool calls and responses });

Check Gateway Output

const result = await gateway.execute('my-trik', 'search', { topic: 'AI' }); console.log('Full result:', JSON.stringify(result, null, 2));

Inspect Session History

// In your graph.ts export default { async invoke({ action, input, session }) { console.log('Session ID:', session?.sessionId); console.log('History entries:', session?.history?.length); console.log('History:', JSON.stringify(session?.history, null, 2)); // ... } }

Next: Publish your trik to the registry.