glam/frontend/tests/unit/sparql-export.test.ts
kempersc 2761857b0d Add scripts for converting OWL/Turtle ontology to Mermaid and PlantUML diagrams
- 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.
2025-11-22 23:01:13 +01:00

235 lines
7 KiB
TypeScript

/**
* Tests for SPARQL Results Export
*/
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import {
exportToCsv,
exportToJson,
exportToJsonLd,
exportAndDownload,
} from '../../src/lib/sparql/export';
import type { SelectResults } from '../../src/lib/sparql/client';
describe('SPARQL Export', () => {
const mockResults: SelectResults = {
head: { vars: ['subject', 'predicate', 'object'] },
results: {
bindings: [
{
subject: { type: 'uri', value: 'http://example.org/s1' },
predicate: { type: 'uri', value: 'http://example.org/p1' },
object: { type: 'literal', value: 'Object 1' },
},
{
subject: { type: 'uri', value: 'http://example.org/s2' },
predicate: { type: 'uri', value: 'http://example.org/p2' },
object: { type: 'literal', value: 'Object 2', 'xml:lang': 'en' },
},
{
subject: { type: 'bnode', value: '_:b1' },
predicate: { type: 'uri', value: 'http://example.org/p3' },
object: {
type: 'literal',
value: '42',
datatype: 'http://www.w3.org/2001/XMLSchema#integer',
},
},
],
},
};
describe('exportToCsv', () => {
it('should export results to CSV format', () => {
const csv = exportToCsv(mockResults);
expect(csv).toContain('subject,predicate,object');
expect(csv).toContain('http://example.org/s1');
expect(csv).toContain('Object 1');
});
it('should escape CSV values with commas', () => {
const results: SelectResults = {
head: { vars: ['text'] },
results: {
bindings: [{ text: { type: 'literal', value: 'value, with, commas' } }],
},
};
const csv = exportToCsv(results);
expect(csv).toContain('"value, with, commas"');
});
it('should escape CSV values with quotes', () => {
const results: SelectResults = {
head: { vars: ['text'] },
results: {
bindings: [{ text: { type: 'literal', value: 'value "with" quotes' } }],
},
};
const csv = exportToCsv(results);
expect(csv).toContain('"value ""with"" quotes"');
});
it('should handle empty results', () => {
const results: SelectResults = {
head: { vars: ['a', 'b'] },
results: { bindings: [] },
};
const csv = exportToCsv(results);
expect(csv).toBe('');
});
it('should include language tags in CSV', () => {
const csv = exportToCsv(mockResults);
expect(csv).toContain('Object 2@en');
});
it('should include datatypes in CSV', () => {
const csv = exportToCsv(mockResults);
expect(csv).toContain('42^^http://www.w3.org/2001/XMLSchema#integer');
});
it('should handle missing values', () => {
const results: SelectResults = {
head: { vars: ['a', 'b', 'c'] },
results: {
bindings: [
{ a: { type: 'literal', value: 'A' } },
// b and c are missing
],
},
};
const csv = exportToCsv(results);
expect(csv).toContain('A,,');
});
});
describe('exportToJson', () => {
it('should export results to JSON format', () => {
const json = exportToJson(mockResults);
const parsed = JSON.parse(json);
expect(parsed).toHaveProperty('head');
expect(parsed).toHaveProperty('results');
expect(parsed.head.vars).toEqual(['subject', 'predicate', 'object']);
expect(parsed.results.bindings).toHaveLength(3);
});
it('should format JSON with indentation', () => {
const json = exportToJson(mockResults);
expect(json).toContain('\n ');
});
});
describe('exportToJsonLd', () => {
it('should export results to JSON-LD format', () => {
const jsonld = exportToJsonLd(mockResults);
const parsed = JSON.parse(jsonld);
expect(parsed).toHaveProperty('@context');
expect(parsed).toHaveProperty('@graph');
expect(parsed['@graph']).toHaveLength(3);
});
it('should convert URIs to @id', () => {
const jsonld = exportToJsonLd(mockResults);
const parsed = JSON.parse(jsonld);
const firstResult = parsed['@graph'][0];
expect(firstResult.subject).toHaveProperty('@id');
expect(firstResult.subject['@id']).toBe('http://example.org/s1');
});
it('should convert literals to @value', () => {
const jsonld = exportToJsonLd(mockResults);
const parsed = JSON.parse(jsonld);
const firstResult = parsed['@graph'][0];
expect(firstResult.object).toHaveProperty('@value');
expect(firstResult.object['@value']).toBe('Object 1');
});
it('should include language tags', () => {
const jsonld = exportToJsonLd(mockResults);
const parsed = JSON.parse(jsonld);
const secondResult = parsed['@graph'][1];
expect(secondResult.object).toHaveProperty('@language');
expect(secondResult.object['@language']).toBe('en');
});
it('should include datatypes', () => {
const jsonld = exportToJsonLd(mockResults);
const parsed = JSON.parse(jsonld);
const thirdResult = parsed['@graph'][2];
expect(thirdResult.object).toHaveProperty('@type');
expect(thirdResult.object['@type']).toBe(
'http://www.w3.org/2001/XMLSchema#integer'
);
});
it('should assign blank node IDs to results', () => {
const jsonld = exportToJsonLd(mockResults);
const parsed = JSON.parse(jsonld);
expect(parsed['@graph'][0]['@id']).toMatch(/_:result\d+/);
expect(parsed['@graph'][0]['@type']).toBe('SparqlResult');
});
});
describe('exportAndDownload', () => {
let createElementSpy: any;
let linkElement: any;
beforeEach(() => {
linkElement = {
href: '',
download: '',
click: vi.fn(),
};
createElementSpy = vi.spyOn(document, 'createElement').mockReturnValue(linkElement);
global.URL.createObjectURL = vi.fn(() => 'blob:mock-url');
global.URL.revokeObjectURL = vi.fn();
global.Blob = vi.fn() as any;
});
afterEach(() => {
vi.restoreAllMocks();
});
it('should download CSV file', () => {
exportAndDownload(mockResults, 'csv', 'test-results');
expect(linkElement.download).toBe('test-results.csv');
expect(linkElement.click).toHaveBeenCalled();
expect(global.URL.revokeObjectURL).toHaveBeenCalledWith('blob:mock-url');
});
it('should download JSON file', () => {
exportAndDownload(mockResults, 'json', 'test-results');
expect(linkElement.download).toBe('test-results.json');
expect(linkElement.click).toHaveBeenCalled();
});
it('should download JSON-LD file', () => {
exportAndDownload(mockResults, 'jsonld', 'test-results');
expect(linkElement.download).toBe('test-results.jsonld');
expect(linkElement.click).toHaveBeenCalled();
});
it('should use default filename if not provided', () => {
exportAndDownload(mockResults, 'csv');
expect(linkElement.download).toBe('sparql-results.csv');
});
});
});