Skip to main content
Glama
form-creation-integration.test.ts7.8 kB
import { FormCreationTool } from '../form-creation-tool'; import { TallyApiService } from '../../services/tally-api-service'; import { FormConfig, QuestionType } from '../../models/form-config'; import { TallyApiClientConfig } from '../../services/TallyApiClient'; import { NlpService } from '../../services/nlp-service'; // Mock the TallyApiClient to capture the actual payload being sent jest.mock('../../services/TallyApiClient'); jest.mock('../../services/nlp-service'); describe('FormCreationTool - BlockBuilder Integration', () => { let tool: FormCreationTool; let mockApiClientConfig: TallyApiClientConfig; let capturedPayload: any; let mockNlpService: jest.Mocked<NlpService>; beforeEach(() => { mockApiClientConfig = { accessToken: 'test-token', baseURL: 'https://api.tally.so' }; // Clear captured payload capturedPayload = null; // Mock the TallyApiClient constructor and requestWithValidation method const MockTallyApiClient = require('../../services/TallyApiClient').TallyApiClient; MockTallyApiClient.mockImplementation(() => ({ requestWithValidation: jest.fn().mockImplementation((method, endpoint, schema, payload) => { capturedPayload = payload; return Promise.resolve({ id: 'test-form-id', url: 'https://tally.so/forms/test-form-id/edit', title: 'Test Form', createdAt: '2023-01-01T00:00:00Z', updatedAt: '2023-01-01T00:00:00Z' }); }) })); tool = new FormCreationTool(mockApiClientConfig); mockNlpService = (tool as any).nlpService as jest.Mocked<NlpService>; }); describe('BlockBuilder payload generation', () => { it('should generate correct Tally API payload with FORM_TITLE and question blocks', async () => { // Arrange - Mock NLP service to return a detailed form config const detailedFormConfig: FormConfig = { title: 'Contact Form', description: 'Please fill out this contact form', questions: [ { id: 'name', type: QuestionType.TEXT, label: 'Full Name', required: true, placeholder: 'Enter your full name' }, { id: 'email', type: QuestionType.EMAIL, label: 'Email Address', required: true, placeholder: 'Enter your email' }, { id: 'department', type: QuestionType.DROPDOWN, label: 'Department', required: false, options: [ { id: 'sales', text: 'Sales' }, { id: 'support', text: 'Support' }, { id: 'engineering', text: 'Engineering' } ] } ], settings: { submissionBehavior: 'message' as any } }; mockNlpService.generateFormConfig.mockReturnValue(detailedFormConfig); // Act await tool.execute({ naturalLanguagePrompt: 'Create a contact form', formTitle: 'Contact Form' }); // Assert - verify the payload structure expect(capturedPayload).toBeDefined(); expect(capturedPayload.status).toBe('PUBLISHED'); expect(capturedPayload.name).toBe('Contact Form'); expect(capturedPayload.blocks).toBeDefined(); expect(Array.isArray(capturedPayload.blocks)).toBe(true); const blocks = capturedPayload.blocks; // Debug: log the actual blocks to understand the structure console.log('Generated blocks:', JSON.stringify(blocks, null, 2)); // Should have: 1 FORM_TITLE + question blocks (each question generates TITLE + input blocks) expect(blocks.length).toBeGreaterThanOrEqual(4); // At least title + some question blocks // First block should be FORM_TITLE const titleBlock = blocks[0]; expect(titleBlock.type).toBe('FORM_TITLE'); expect(titleBlock.groupType).toBe('TEXT'); expect(titleBlock.payload.html).toBe('Contact Form'); expect(titleBlock.uuid).toMatch(/[0-9a-f-]{36}/); expect(titleBlock.groupUuid).toMatch(/[0-9a-f-]{36}/); // Verify question blocks are present const questionBlocks = blocks.filter(block => ['TITLE', 'INPUT_TEXT', 'INPUT_EMAIL', 'DROPDOWN_OPTION'].includes(block.type) ); expect(questionBlocks.length).toBeGreaterThan(0); // Check that each question block has proper structure questionBlocks.forEach(block => { expect(block.uuid).toMatch(/[0-9a-f-]{36}/); expect(block.groupUuid).toMatch(/[0-9a-f-]{36}/); expect(block.type).toBeDefined(); expect(block.groupType).toBeDefined(); expect(block.payload).toBeDefined(); }); }); it('should handle forms with only title block', async () => { // Arrange - Mock NLP service to return a simple form config const simpleFormConfig: FormConfig = { title: 'Simple Form', questions: [], settings: { submissionBehavior: 'message' as any } }; mockNlpService.generateFormConfig.mockReturnValue(simpleFormConfig); // Act await tool.execute({ naturalLanguagePrompt: 'Create a simple form', formTitle: 'Simple Form' }); // Assert expect(capturedPayload).toBeDefined(); expect(capturedPayload.blocks).toBeDefined(); expect(capturedPayload.blocks.length).toBeGreaterThanOrEqual(1); const titleBlock = capturedPayload.blocks[0]; expect(titleBlock.type).toBe('FORM_TITLE'); expect(titleBlock.payload.html).toBe('Simple Form'); }); it('should generate correct blocks for different question types', async () => { // Mock NLP service to return a form with various question types const multiTypeFormConfig: FormConfig = { title: 'Survey Form', questions: [ { id: 'q1', type: QuestionType.TEXT, label: 'Text Question', required: true }, { id: 'q2', type: QuestionType.MULTIPLE_CHOICE, label: 'Multiple Choice', required: false, options: [ { id: 'a', text: 'Option A' }, { id: 'b', text: 'Option B' } ] } ], settings: { submissionBehavior: 'message' as any } }; mockNlpService.generateFormConfig.mockReturnValue(multiTypeFormConfig); // Act const result = await tool.execute({ naturalLanguagePrompt: 'Create a survey with multiple question types' }); // Assert expect(result).toBeDefined(); expect(result.formUrl).toBeDefined(); expect(capturedPayload).toBeDefined(); expect(capturedPayload.blocks).toBeDefined(); expect(capturedPayload.blocks.length).toBeGreaterThanOrEqual(1); }); }); describe('API endpoint integration', () => { it('should call the correct endpoint with POST method', async () => { // Mock NLP service mockNlpService.generateFormConfig.mockReturnValue({ title: 'Test Form', questions: [], settings: { submissionBehavior: 'message' as any } }); // Act await tool.execute({ naturalLanguagePrompt: 'Create a test form' }); // Assert - verify the TallyApiClient was called correctly const tallyApiService = (tool as any).tallyApiService as TallyApiService; const apiClient = (tallyApiService as any).apiClient; expect(apiClient.requestWithValidation).toHaveBeenCalledWith( 'POST', '/forms', expect.any(Object), // TallyFormSchema expect.any(Object) // payload ); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/learnwithcc/tally-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server