Skip to main content
Glama

TriliumNext Notes' MCP Server

createNote.test.js13.8 kB
/** * Create Note Validation Tests * Tests the createNoteSchema validation functionality */ import { describe, it } from 'node:test'; import assert from 'node:assert'; // Import create note schema and validation functions from build directory import { createNoteSchema, attributeSchema, safeValidate } from '../../../../build/utils/validationUtils.js'; describe('Create Note Validation', () => { describe('Basic Create Note Validation', () => { it('should validate correct create note request', () => { const validRequest = { parentNoteId: 'root', title: 'Test Note', type: 'text', content: '<p>This is a test note</p>' }; const result = safeValidate(createNoteSchema, validRequest); assert.strictEqual(result.success, true); assert.ok(result.data); assert.strictEqual(result.data.title, 'Test Note'); assert.strictEqual(result.data.type, 'text'); assert.strictEqual(result.data.content, '<p>This is a test note</p>'); }); it('should validate create note with minimal content', () => { const validRequest = { parentNoteId: 'root', title: 'Empty Note', type: 'text', content: '' }; const result = safeValidate(createNoteSchema, validRequest); assert.strictEqual(result.success, true); assert.strictEqual(result.data.content, ''); }); it('should reject multiple content items (not supported)', () => { const invalidRequest = { parentNoteId: 'root', title: 'Multi-content Note', type: 'text', content: [ { type: 'text', content: '<p>First section</p>' }, { type: 'text', content: '<p>Second section</p>' } ] }; const result = safeValidate(createNoteSchema, invalidRequest); assert.strictEqual(result.success, false); assert.ok(result.error); }); }); describe('Note Type Validation', () => { it('should validate all supported note types', () => { const validTypes = [ 'text', 'code', 'render', 'search', 'relationMap', 'book', 'noteMap', 'mermaid', 'webView' ]; validTypes.forEach(type => { const request = { parentNoteId: 'root', title: 'Test Note', type: type, content: 'test' }; const result = safeValidate(createNoteSchema, request); assert.strictEqual(result.success, true, `Note type ${type} should be valid`); }); }); it('should reject invalid note types', () => { const invalidRequest = { parentNoteId: 'root', title: 'Test Note', type: 'invalid_type', content: '<p>This is a test note</p>' }; const result = safeValidate(createNoteSchema, invalidRequest); assert.strictEqual(result.success, false); assert.ok(result.error); assert.ok(result.error.includes('type')); }); it('should reject note types that are not in enum', () => { const unsupportedTypes = ['canvas', 'widget', 'custom']; unsupportedTypes.forEach(type => { const request = { parentNoteId: 'root', title: 'Test Note', type: type, content: 'test' }; const result = safeValidate(createNoteSchema, request); assert.strictEqual(result.success, false, `Note type ${type} should be invalid`); }); }); }); describe('Content Validation', () => { it('should validate text content items', () => { const validRequest = { parentNoteId: 'root', title: 'Text Content Note', type: 'text', content: 'Plain text content' }; const result = safeValidate(createNoteSchema, validRequest); assert.strictEqual(result.success, true); assert.strictEqual(typeof result.data.content, 'string'); }); it('should validate content as string type', () => { const validRequest = { parentNoteId: 'root', title: 'String Content Note', type: 'text', content: 'test' }; const result = safeValidate(createNoteSchema, validRequest); assert.strictEqual(result.success, true); assert.strictEqual(result.data.content, 'test'); }); it('should validate content with complex HTML', () => { const validRequest = { parentNoteId: 'root', title: 'Complex HTML Note', type: 'text', content: '<div><h1>Title</h1><p>Content with <strong>formatting</strong></p></div>' }; const result = safeValidate(createNoteSchema, validRequest); assert.strictEqual(result.success, true); }); }); describe('Parent Note ID Validation', () => { it('should validate with standard parent note IDs', () => { const validParents = ['root', 'abc123', 'parent_123', 'note-id-456']; validParents.forEach(parentId => { const request = { parentNoteId: parentId, title: 'Test Note', type: 'text', content: 'test' }; const result = safeValidate(createNoteSchema, request); assert.strictEqual(result.success, true, `Parent ID ${parentId} should be valid`); }); }); it('should reject empty parent note ID', () => { const invalidRequest = { parentNoteId: '', title: 'Test Note', type: 'text', content: 'test' }; const result = safeValidate(createNoteSchema, invalidRequest); assert.strictEqual(result.success, false); assert.ok(result.error); assert.ok(result.error.includes('Parent note ID cannot be empty')); }); it('should validate with UUID-style parent note ID', () => { const validRequest = { parentNoteId: '12345678-1234-1234-1234-123456789012', title: 'Test Note', type: 'text', content: 'test' }; const result = safeValidate(createNoteSchema, validRequest); assert.strictEqual(result.success, true); }); }); describe('Title Validation', () => { it('should validate with various titles', () => { const validTitles = [ 'Simple Title', 'Title with Numbers 123', 'Title-with-dashes', 'Title_with_underscores', 'Title with special chars: àáâãä', 'A', // Single character 'A'.repeat(100) // Long title ]; validTitles.forEach(title => { const request = { parentNoteId: 'root', title: title, type: 'text', content: 'test' }; const result = safeValidate(createNoteSchema, request); assert.strictEqual(result.success, true, `Title "${title}" should be valid`); }); }); it('should reject empty title', () => { const invalidRequest = { parentNoteId: 'root', title: '', type: 'text', content: 'test' }; const result = safeValidate(createNoteSchema, invalidRequest); assert.strictEqual(result.success, false); assert.ok(result.error); assert.ok(result.error.includes('Title cannot be empty')); }); it('should accept whitespace-only title (Zod min(1) allows strings with length > 0)', () => { const request = { parentNoteId: 'root', title: ' ', type: 'text', content: 'test' }; const result = safeValidate(createNoteSchema, request); assert.strictEqual(result.success, true); }); }); describe('Attributes Integration', () => { it('should validate create note with attributes', () => { const validRequest = { parentNoteId: 'root', title: 'Project Board', type: 'book', content: '', attributes: [ { type: 'relation', name: 'template', value: 'Board', position: 10 } ] }; const result = safeValidate(createNoteSchema, validRequest); assert.strictEqual(result.success, true); assert.ok(result.data); assert.strictEqual(result.data.attributes.length, 1); }); it('should validate create note with multiple attributes', () => { const validRequest = { parentNoteId: 'root', title: 'Complex Note', type: 'book', content: '', attributes: [ { type: 'relation', name: 'template', value: 'Board', position: 10 }, { type: 'label', name: 'project', value: 'api', position: 20 } ] }; const result = safeValidate(createNoteSchema, validRequest); assert.strictEqual(result.success, true); assert.strictEqual(result.data.attributes.length, 2); }); it('should validate create note with empty attributes array', () => { const validRequest = { parentNoteId: 'root', title: 'Note with Empty Attributes', type: 'text', content: 'test', attributes: [] }; const result = safeValidate(createNoteSchema, validRequest); assert.strictEqual(result.success, true); assert.strictEqual(result.data.attributes.length, 0); }); }); describe('Optional Parameters', () => { it('should validate create note with forceCreate parameter', () => { const validRequest = { parentNoteId: 'root', title: 'Test Note', type: 'text', content: '<p>Test content</p>', forceCreate: true }; const result = safeValidate(createNoteSchema, validRequest); assert.strictEqual(result.success, true); assert.ok(result.data); assert.strictEqual(result.data.forceCreate, true); }); it('should validate create note with forceCreate false', () => { const validRequest = { parentNoteId: 'root', title: 'Test Note', type: 'text', content: '<p>Test content</p>', forceCreate: false }; const result = safeValidate(createNoteSchema, validRequest); assert.strictEqual(result.success, true); assert.strictEqual(result.data.forceCreate, false); }); it('should validate create note with mime type', () => { const validRequest = { parentNoteId: 'root', title: 'MIME Note', type: 'text', content: 'test', mime: 'text/plain' }; const result = safeValidate(createNoteSchema, validRequest); assert.strictEqual(result.success, true); assert.strictEqual(result.data.mime, 'text/plain'); }); }); describe('Required Field Validation', () => { it('should reject missing required fields', () => { const invalidRequest = { parentNoteId: 'root', title: 'Test Note' // Missing type and content }; const result = safeValidate(createNoteSchema, invalidRequest); assert.strictEqual(result.success, false); assert.ok(result.error.includes('type') || result.error.includes('content')); }); it('should reject request missing parentNoteId', () => { const invalidRequest = { title: 'Test Note', type: 'text', content: 'test' }; const result = safeValidate(createNoteSchema, invalidRequest); assert.strictEqual(result.success, false); assert.ok(result.error); }); it('should reject request missing title', () => { const invalidRequest = { parentNoteId: 'root', type: 'text', content: 'test' }; const result = safeValidate(createNoteSchema, invalidRequest); assert.strictEqual(result.success, false); assert.ok(result.error); }); it('should reject request missing type', () => { const invalidRequest = { parentNoteId: 'root', title: 'Test Note', content: 'test' }; const result = safeValidate(createNoteSchema, invalidRequest); assert.strictEqual(result.success, false); assert.ok(result.error); }); it('should accept request without content (optional parameter)', () => { const validRequest = { parentNoteId: 'root', title: 'Test Note', type: 'text' }; const result = safeValidate(createNoteSchema, validRequest); assert.strictEqual(result.success, true); assert.ok(result.data); }); }); describe('Edge Cases', () => { it('should validate minimal valid request', () => { const minimalRequest = { parentNoteId: 'root', title: 'A', type: 'text', content: '' }; const result = safeValidate(createNoteSchema, minimalRequest); assert.strictEqual(result.success, true); }); it('should validate request with all optional fields', () => { const completeRequest = { parentNoteId: 'root', title: 'Complete Note', type: 'book', content: 'Full content', mime: 'text/html', attributes: [ { type: 'label', name: 'complete', position: 1 } ], forceCreate: true }; const result = safeValidate(createNoteSchema, completeRequest); assert.strictEqual(result.success, true); }); it('should validate note with special characters in title', () => { const specialCharRequest = { parentNoteId: 'root', title: 'Note with émojis 🎉 and spëciål chäracters', type: 'text', content: 'Special content' }; const result = safeValidate(createNoteSchema, specialCharRequest); assert.strictEqual(result.success, true); }); }); });

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/tan-yong-sheng/triliumnext-mcp'

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