import { describe, it, expect } from 'vitest'; import { getAllTemplates, getTemplatesByCategory, getTemplateById, applyTemplateVariables, getCategories, getCategoryDisplayName, type QueryTemplate, } from '../../src/lib/sparql/templates'; describe('SPARQL Templates', () => { describe('getAllTemplates', () => { it('should return all query templates', () => { const templates = getAllTemplates(); expect(templates).toBeDefined(); expect(templates.length).toBeGreaterThan(0); expect(templates.length).toBeGreaterThanOrEqual(15); // We created 16 templates }); it('should return templates with required fields', () => { const templates = getAllTemplates(); for (const template of templates) { expect(template.id).toBeDefined(); expect(template.name).toBeDefined(); expect(template.description).toBeDefined(); expect(template.category).toBeDefined(); expect(template.query).toBeDefined(); expect(Array.isArray(template.variables)).toBe(true); } }); }); describe('getTemplatesByCategory', () => { it('should return templates filtered by category', () => { const basicTemplates = getTemplatesByCategory('basic'); expect(basicTemplates.length).toBeGreaterThan(0); expect(basicTemplates.every(t => t.category === 'basic')).toBe(true); }); it('should return empty array for non-existent category templates', () => { const aggregationTemplates = getTemplatesByCategory('aggregation'); expect(aggregationTemplates.length).toBeGreaterThan(0); }); it('should handle all categories', () => { const categories: QueryTemplate['category'][] = [ 'basic', 'advanced', 'aggregation', 'geographic', 'relationships', ]; for (const category of categories) { const templates = getTemplatesByCategory(category); expect(Array.isArray(templates)).toBe(true); } }); }); describe('getTemplateById', () => { it('should return template by ID', () => { const template = getTemplateById('find-all-museums'); expect(template).toBeDefined(); expect(template?.id).toBe('find-all-museums'); expect(template?.name).toBe('Find All Museums'); }); it('should return undefined for non-existent ID', () => { const template = getTemplateById('non-existent-id'); expect(template).toBeUndefined(); }); }); describe('applyTemplateVariables', () => { it('should replace single variable', () => { const query = 'SELECT ?inst WHERE { ?inst schema:addressLocality "%CITY%" }'; const result = applyTemplateVariables(query, { CITY: 'Amsterdam' }); expect(result).toContain('Amsterdam'); expect(result).not.toContain('%CITY%'); }); it('should replace multiple variables', () => { const query = 'SELECT ?inst WHERE { ?inst schema:name "%NAME%" . ?inst schema:addressLocality "%CITY%" }'; const result = applyTemplateVariables(query, { NAME: 'Rijksmuseum', CITY: 'Amsterdam', }); expect(result).toContain('Rijksmuseum'); expect(result).toContain('Amsterdam'); expect(result).not.toContain('%NAME%'); expect(result).not.toContain('%CITY%'); }); it('should handle variables without % delimiters', () => { const query = 'SELECT ?inst WHERE { ?inst schema:addressLocality "%CITY%" }'; const result = applyTemplateVariables(query, { CITY: 'Copenhagen' }); expect(result).toContain('Copenhagen'); }); it('should replace all occurrences of variable', () => { const query = 'SELECT ?inst WHERE { ?inst schema:name "%NAME%" . FILTER(CONTAINS(?name, "%NAME%")) }'; const result = applyTemplateVariables(query, { NAME: 'Museum' }); const occurrences = (result.match(/Museum/g) || []).length; expect(occurrences).toBe(2); }); it('should leave query unchanged if no variables provided', () => { const query = 'SELECT ?inst WHERE { ?inst a schema:Museum }'; const result = applyTemplateVariables(query, {}); expect(result).toBe(query); }); }); describe('getCategories', () => { it('should return all category names', () => { const categories = getCategories(); expect(categories).toEqual([ 'basic', 'advanced', 'aggregation', 'geographic', 'relationships', ]); }); }); describe('getCategoryDisplayName', () => { it('should return display names for categories', () => { expect(getCategoryDisplayName('basic')).toBe('Basic Queries'); expect(getCategoryDisplayName('advanced')).toBe('Advanced Queries'); expect(getCategoryDisplayName('aggregation')).toBe('Aggregation & Statistics'); expect(getCategoryDisplayName('geographic')).toBe('Geographic Queries'); expect(getCategoryDisplayName('relationships')).toBe('Relationships & Hierarchies'); }); }); describe('Template query validation', () => { it('should have valid SPARQL syntax in all templates', () => { const templates = getAllTemplates(); for (const template of templates) { // Basic checks for SPARQL structure const query = template.query; // Should have query type expect(query).toMatch(/\b(SELECT|CONSTRUCT|ASK|DESCRIBE)\b/i); // Should have balanced braces const openBraces = (query.match(/\{/g) || []).length; const closeBraces = (query.match(/\}/g) || []).length; expect(openBraces).toBe(closeBraces); // Should have PREFIX declarations before query type if (query.includes('PREFIX')) { const prefixIndex = query.indexOf('PREFIX'); const selectIndex = query.search(/\b(SELECT|CONSTRUCT|ASK|DESCRIBE)\b/i); expect(prefixIndex).toBeLessThan(selectIndex); } } }); it('should declare variables correctly in templates', () => { const templatesWithVars = getAllTemplates().filter(t => t.variables.length > 0); for (const template of templatesWithVars) { for (const variable of template.variables) { // Variable should be present in query expect(template.query).toContain(variable); } } }); }); });