- Implemented `owl_to_mermaid.py` to convert OWL/Turtle files into Mermaid class diagrams. - Implemented `owl_to_plantuml.py` to convert OWL/Turtle files into PlantUML class diagrams. - Added two new PlantUML files for custodian multi-aspect diagrams.
186 lines
6.3 KiB
TypeScript
186 lines
6.3 KiB
TypeScript
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);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
});
|