/** * Tests for useRdfParser Hook */ import { describe, it, expect, beforeEach } from 'vitest'; import { renderHook, waitFor } from '@testing-library/react'; import { useRdfParser } from '@/hooks/useRdfParser'; describe('useRdfParser', () => { it('should initialize with default state', () => { const { result } = renderHook(() => useRdfParser()); expect(result.current.isLoading).toBe(false); expect(result.current.error).toBe(null); expect(result.current.graphData).toBe(null); expect(typeof result.current.parse).toBe('function'); }); it('should parse N-Triples format', async () => { const { result } = renderHook(() => useRdfParser()); const ntriples = ` . . `.trim(); let parsePromise: Promise; await waitFor(() => { parsePromise = result.current.parse(ntriples, 'application/n-triples'); }); await waitFor(() => { expect(result.current.isLoading).toBe(false); }); expect(result.current.error).toBe(null); expect(result.current.graphData).not.toBe(null); expect(result.current.graphData?.nodes.length).toBeGreaterThan(0); expect(result.current.graphData?.links.length).toBeGreaterThan(0); }); it('should parse Turtle format', async () => { const { result } = renderHook(() => useRdfParser()); const turtle = ` @prefix ex: . ex:subject ex:predicate ex:object . ex:subject a ex:Type . `.trim(); await waitFor(() => { result.current.parse(turtle, 'text/turtle'); }); await waitFor(() => { expect(result.current.isLoading).toBe(false); }); expect(result.current.error).toBe(null); expect(result.current.graphData).not.toBe(null); expect(result.current.graphData?.nodes.length).toBeGreaterThan(0); }); it('should handle parsing errors', async () => { const { result } = renderHook(() => useRdfParser()); // N-Triples parser doesn't throw for invalid data - it just returns empty nodes/links // This test verifies it doesn't crash on bad input const invalid = 'This is not valid RDF'; await result.current.parse(invalid, 'application/n-triples'); await waitFor(() => { expect(result.current.isLoading).toBe(false); }); // Empty or minimal data is expected for invalid input expect(result.current.graphData).not.toBe(null); }); it('should handle unsupported format', async () => { const { result } = renderHook(() => useRdfParser()); await waitFor(async () => { try { await result.current.parse('test', 'application/rdf+xml' as any); } catch (err) { expect(err).toBeInstanceOf(Error); } }); }); it('should update loading state during parsing', async () => { const { result } = renderHook(() => useRdfParser()); const ntriples = ' .'; // Parsing is fast, so we just verify it completes expect(result.current.isLoading).toBe(false); await result.current.parse(ntriples, 'application/n-triples'); // Should finish loading await waitFor(() => { expect(result.current.isLoading).toBe(false); expect(result.current.graphData).not.toBe(null); }); }); it('should clear previous error on new parse', async () => { const { result } = renderHook(() => useRdfParser()); // Parse unsupported format to trigger error try { await result.current.parse('test', 'application/rdf+xml' as any); } catch (err) { // Expected - unsupported format throws } await waitFor(() => { expect(result.current.error).not.toBe(null); }); // Second parse with valid data should clear error const valid = ' .'; await result.current.parse(valid, 'application/n-triples'); await waitFor(() => { expect(result.current.error).toBe(null); expect(result.current.graphData).not.toBe(null); }); }); it('should preserve parsed data after parsing', async () => { const { result } = renderHook(() => useRdfParser()); const ntriples = ` . . `.trim(); await result.current.parse(ntriples, 'application/n-triples'); await waitFor(() => { expect(result.current.graphData).not.toBe(null); }); const data = result.current.graphData; // Data should persist across re-renders expect(data?.nodes.length).toBeGreaterThan(0); expect(data?.links.length).toBeGreaterThan(0); }); });