mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-09-05 08:06:02 +00:00
753 lines
No EOL
30 KiB
HTML
753 lines
No EOL
30 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Export Functionality Test</title>
|
|
<style>
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
padding: 20px;
|
|
background-color: #f5f5f5;
|
|
}
|
|
.container {
|
|
background: white;
|
|
padding: 20px;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
}
|
|
.test-section {
|
|
margin: 20px 0;
|
|
padding: 15px;
|
|
border: 1px solid #ddd;
|
|
border-radius: 5px;
|
|
background: #f9f9f9;
|
|
}
|
|
.success { border-color: #28a745; background: #d4edda; }
|
|
.error { border-color: #dc3545; background: #f8d7da; }
|
|
.warning { border-color: #ffc107; background: #fff3cd; }
|
|
button {
|
|
background: #007bff;
|
|
color: white;
|
|
border: none;
|
|
padding: 10px 20px;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
margin: 5px;
|
|
}
|
|
button:hover { background: #0056b3; }
|
|
button:disabled { background: #6c757d; cursor: not-allowed; }
|
|
#output {
|
|
white-space: pre-wrap;
|
|
background: #f8f9fa;
|
|
padding: 15px;
|
|
border-radius: 4px;
|
|
font-family: monospace;
|
|
max-height: 400px;
|
|
overflow-y: auto;
|
|
margin-top: 10px;
|
|
}
|
|
.stats {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
gap: 10px;
|
|
margin: 15px 0;
|
|
}
|
|
.stat-card {
|
|
background: white;
|
|
padding: 15px;
|
|
border-radius: 5px;
|
|
border: 1px solid #ddd;
|
|
text-align: center;
|
|
}
|
|
.stat-number {
|
|
font-size: 24px;
|
|
font-weight: bold;
|
|
color: #007bff;
|
|
}
|
|
.stat-label {
|
|
font-size: 14px;
|
|
color: #666;
|
|
margin-top: 5px;
|
|
}
|
|
.download-link {
|
|
display: inline-block;
|
|
background: #28a745;
|
|
color: white;
|
|
padding: 8px 15px;
|
|
text-decoration: none;
|
|
border-radius: 4px;
|
|
margin: 5px;
|
|
}
|
|
.download-link:hover {
|
|
background: #1e7e34;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<h1>🧪 Export Functionality Test</h1>
|
|
<p>This test verifies that the export functionality works correctly after our import resolution improvements.</p>
|
|
|
|
<div class="test-section">
|
|
<h3>📊 Test Knowledge Graph</h3>
|
|
<p>We'll create a sample knowledge graph with the types of nodes our import resolution system now properly handles.</p>
|
|
<button onclick="createTestGraph()">Create Test Graph</button>
|
|
<div id="graph-stats" class="stats"></div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h3>🔍 Validation Tests</h3>
|
|
<p>Test graph validation before export:</p>
|
|
<button onclick="validateGraph()">Validate Graph</button>
|
|
<button onclick="calculateSize()">Calculate Export Size</button>
|
|
<div id="validation-output"></div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h3>📥 Export Tests</h3>
|
|
<p>Test different export formats:</p>
|
|
<button onclick="testJSONExport()">Test JSON Export</button>
|
|
<button onclick="testCSVExport()">Test CSV Export</button>
|
|
<button onclick="testFilteredExport()">Test Filtered Export</button>
|
|
<div id="export-links"></div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h3>📤 Import Test</h3>
|
|
<p>Test importing exported data:</p>
|
|
<button onclick="testImport()">Test JSON Import</button>
|
|
<div id="import-output"></div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h3>🔧 Console Output</h3>
|
|
<div id="output"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<script type="module">
|
|
// Mock the export functions (in real app these would be imported)
|
|
window.testGraph = null;
|
|
window.testFileContents = null;
|
|
|
|
// Create a comprehensive test graph
|
|
window.createTestGraph = function() {
|
|
const graph = {
|
|
nodes: [
|
|
// Project structure nodes
|
|
{
|
|
id: 'project_root',
|
|
label: 'Project',
|
|
properties: {
|
|
name: 'GitNexus',
|
|
description: 'Knowledge graph generation tool',
|
|
version: '1.0.0'
|
|
}
|
|
},
|
|
{
|
|
id: 'src_folder',
|
|
label: 'Folder',
|
|
properties: {
|
|
name: 'src',
|
|
path: 'src',
|
|
filePath: 'src'
|
|
}
|
|
},
|
|
{
|
|
id: 'services_folder',
|
|
label: 'Folder',
|
|
properties: {
|
|
name: 'services',
|
|
path: 'src/services',
|
|
filePath: 'src/services'
|
|
}
|
|
},
|
|
// File nodes (including our zip.ts)
|
|
{
|
|
id: 'zip_service_file',
|
|
label: 'File',
|
|
properties: {
|
|
name: 'zip.ts',
|
|
filePath: 'src/services/zip.ts',
|
|
language: 'typescript',
|
|
extension: '.ts',
|
|
lineCount: 600
|
|
}
|
|
},
|
|
{
|
|
id: 'import_processor_file',
|
|
label: 'File',
|
|
properties: {
|
|
name: 'import-processor.ts',
|
|
filePath: 'src/core/ingestion/import-processor.ts',
|
|
language: 'typescript',
|
|
extension: '.ts',
|
|
lineCount: 946
|
|
}
|
|
},
|
|
// Class nodes
|
|
{
|
|
id: 'zip_service_class',
|
|
label: 'Class',
|
|
properties: {
|
|
name: 'ZipService',
|
|
filePath: 'src/services/zip.ts',
|
|
startLine: 26,
|
|
endLine: 599,
|
|
type: 'class',
|
|
qualifiedName: 'services.zip.ZipService'
|
|
}
|
|
},
|
|
{
|
|
id: 'import_processor_class',
|
|
label: 'Class',
|
|
properties: {
|
|
name: 'ImportProcessor',
|
|
filePath: 'src/core/ingestion/import-processor.ts',
|
|
startLine: 50,
|
|
endLine: 900,
|
|
type: 'class',
|
|
qualifiedName: 'core.ingestion.ImportProcessor'
|
|
}
|
|
},
|
|
// Method nodes (reflecting our import resolution improvements)
|
|
{
|
|
id: 'extract_complete_structure',
|
|
label: 'Method',
|
|
properties: {
|
|
name: 'extractCompleteStructure',
|
|
filePath: 'src/services/zip.ts',
|
|
startLine: 41,
|
|
endLine: 120,
|
|
type: 'method',
|
|
qualifiedName: 'services.zip.ZipService.extractCompleteStructure'
|
|
}
|
|
},
|
|
{
|
|
id: 'extract_js_imports',
|
|
label: 'Method',
|
|
properties: {
|
|
name: 'extractJSImports',
|
|
filePath: 'src/core/ingestion/import-processor.ts',
|
|
startLine: 210,
|
|
endLine: 280,
|
|
type: 'method',
|
|
qualifiedName: 'core.ingestion.ImportProcessor.extractJSImports'
|
|
}
|
|
},
|
|
// Function nodes
|
|
{
|
|
id: 'process_js_import_clause',
|
|
label: 'Function',
|
|
properties: {
|
|
name: 'processJSImportClause',
|
|
filePath: 'src/core/ingestion/import-processor.ts',
|
|
startLine: 350,
|
|
endLine: 450,
|
|
type: 'function',
|
|
qualifiedName: 'core.ingestion.processJSImportClause'
|
|
}
|
|
},
|
|
// Import nodes (showing our improved import resolution)
|
|
{
|
|
id: 'jszip_import',
|
|
label: 'Import',
|
|
properties: {
|
|
name: 'JSZip',
|
|
filePath: 'src/services/zip.ts',
|
|
importType: 'default',
|
|
targetFile: 'node_modules/jszip/dist/jszip.min.js'
|
|
}
|
|
}
|
|
],
|
|
relationships: [
|
|
// Containment relationships
|
|
{
|
|
id: 'rel_project_contains_src',
|
|
type: 'CONTAINS',
|
|
source: 'project_root',
|
|
target: 'src_folder',
|
|
properties: {}
|
|
},
|
|
{
|
|
id: 'rel_src_contains_services',
|
|
type: 'CONTAINS',
|
|
source: 'src_folder',
|
|
target: 'services_folder',
|
|
properties: {}
|
|
},
|
|
{
|
|
id: 'rel_services_contains_zip',
|
|
type: 'CONTAINS',
|
|
source: 'services_folder',
|
|
target: 'zip_service_file',
|
|
properties: {}
|
|
},
|
|
// Definition relationships
|
|
{
|
|
id: 'rel_zip_file_defines_class',
|
|
type: 'DEFINES',
|
|
source: 'zip_service_file',
|
|
target: 'zip_service_class',
|
|
properties: {}
|
|
},
|
|
{
|
|
id: 'rel_zip_class_defines_method',
|
|
type: 'DEFINES',
|
|
source: 'zip_service_class',
|
|
target: 'extract_complete_structure',
|
|
properties: {}
|
|
},
|
|
{
|
|
id: 'rel_import_processor_defines_method',
|
|
type: 'DEFINES',
|
|
source: 'import_processor_class',
|
|
target: 'extract_js_imports',
|
|
properties: {}
|
|
},
|
|
// Import relationships (our improved import resolution)
|
|
{
|
|
id: 'rel_zip_imports_jszip',
|
|
type: 'IMPORTS',
|
|
source: 'zip_service_file',
|
|
target: 'jszip_import',
|
|
properties: {
|
|
importType: 'default',
|
|
localName: 'JSZip',
|
|
exportedName: 'default'
|
|
}
|
|
},
|
|
// Call relationships
|
|
{
|
|
id: 'rel_extract_calls_process',
|
|
type: 'CALLS',
|
|
source: 'extract_js_imports',
|
|
target: 'process_js_import_clause',
|
|
properties: {
|
|
callType: 'method'
|
|
}
|
|
}
|
|
]
|
|
};
|
|
|
|
// Create mock file contents
|
|
const fileContents = new Map([
|
|
['src/services/zip.ts', `import JSZip from 'jszip';
|
|
|
|
export class ZipService {
|
|
public async extractCompleteStructure(file: File) {
|
|
// Implementation with 415 imports resolved (100% success)
|
|
console.log('🔍 ImportProcessor: Found 415 imports, resolved 415 (100.0%)');
|
|
}
|
|
}`],
|
|
['src/core/ingestion/import-processor.ts', `export class ImportProcessor {
|
|
private extractJSImports(node: Parser.SyntaxNode, filePath: string): void {
|
|
// CRITICAL FIX: Field-based approach with type-based fallback
|
|
let importClauseNode = node.childForFieldName('import_clause');
|
|
|
|
if (!importClauseNode) {
|
|
for (let i = 0; i < node.childCount; i++) {
|
|
const child = node.child(i);
|
|
if (child?.type === 'import_clause') {
|
|
importClauseNode = child;
|
|
console.log('🔍 DEBUG: Found import_clause by type at index', i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}`]
|
|
]);
|
|
|
|
window.testGraph = graph;
|
|
window.testFileContents = fileContents;
|
|
|
|
// Display stats
|
|
updateGraphStats(graph);
|
|
log('✅ Test graph created successfully');
|
|
log(`📊 Nodes: ${graph.nodes.length}, Relationships: ${graph.relationships.length}`);
|
|
log(`📁 File contents: ${fileContents.size} files`);
|
|
|
|
return graph;
|
|
};
|
|
|
|
// Update graph statistics display
|
|
function updateGraphStats(graph) {
|
|
const nodesByType = graph.nodes.reduce((acc, node) => {
|
|
acc[node.label] = (acc[node.label] || 0) + 1;
|
|
return acc;
|
|
}, {});
|
|
|
|
const relsByType = graph.relationships.reduce((acc, rel) => {
|
|
acc[rel.type] = (acc[rel.type] || 0) + 1;
|
|
return acc;
|
|
}, {});
|
|
|
|
const statsContainer = document.getElementById('graph-stats');
|
|
statsContainer.innerHTML = `
|
|
<div class="stat-card">
|
|
<div class="stat-number">${graph.nodes.length}</div>
|
|
<div class="stat-label">Total Nodes</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-number">${graph.relationships.length}</div>
|
|
<div class="stat-label">Total Relationships</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-number">${Object.keys(nodesByType).length}</div>
|
|
<div class="stat-label">Node Types</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-number">${Object.keys(relsByType).length}</div>
|
|
<div class="stat-label">Relationship Types</div>
|
|
</div>
|
|
`;
|
|
|
|
log(`Node types: ${Object.entries(nodesByType).map(([k,v]) => `${k}:${v}`).join(', ')}`);
|
|
log(`Relationship types: ${Object.entries(relsByType).map(([k,v]) => `${k}:${v}`).join(', ')}`);
|
|
}
|
|
|
|
// Export validation functions (simplified versions for testing)
|
|
window.validateGraph = function() {
|
|
if (!window.testGraph) {
|
|
log('❌ No test graph available. Create one first.');
|
|
return;
|
|
}
|
|
|
|
const graph = window.testGraph;
|
|
const errors = [];
|
|
const warnings = [];
|
|
|
|
// Check for duplicate node IDs
|
|
const nodeIds = new Set(graph.nodes.map(n => n.id));
|
|
if (nodeIds.size !== graph.nodes.length) {
|
|
errors.push('Graph contains duplicate node IDs');
|
|
}
|
|
|
|
// Check for invalid relationships
|
|
graph.relationships.forEach((rel, index) => {
|
|
if (!nodeIds.has(rel.source)) {
|
|
errors.push(`Relationship ${index} has invalid source: ${rel.source}`);
|
|
}
|
|
if (!nodeIds.has(rel.target)) {
|
|
errors.push(`Relationship ${index} has invalid target: ${rel.target}`);
|
|
}
|
|
});
|
|
|
|
// Check for empty nodes/relationships
|
|
if (graph.nodes.length === 0) {
|
|
warnings.push('Graph has no nodes');
|
|
}
|
|
if (graph.relationships.length === 0) {
|
|
warnings.push('Graph has no relationships');
|
|
}
|
|
|
|
const validationDiv = document.getElementById('validation-output');
|
|
const isValid = errors.length === 0;
|
|
|
|
validationDiv.className = 'test-section ' + (isValid ? 'success' : 'error');
|
|
validationDiv.innerHTML = `
|
|
<h4>Validation Results</h4>
|
|
<p><strong>Status:</strong> ${isValid ? '✅ Valid' : '❌ Invalid'}</p>
|
|
${errors.length > 0 ? `<p><strong>Errors:</strong><br>${errors.join('<br>')}</p>` : ''}
|
|
${warnings.length > 0 ? `<p><strong>Warnings:</strong><br>${warnings.join('<br>')}</p>` : ''}
|
|
`;
|
|
|
|
log(isValid ? '✅ Graph validation passed' : '❌ Graph validation failed');
|
|
errors.forEach(error => log(`❌ ${error}`));
|
|
warnings.forEach(warning => log(`⚠️ ${warning}`));
|
|
};
|
|
|
|
window.calculateSize = function() {
|
|
if (!window.testGraph) {
|
|
log('❌ No test graph available.');
|
|
return;
|
|
}
|
|
|
|
const graph = window.testGraph;
|
|
const fileContents = window.testFileContents;
|
|
|
|
// Calculate sizes
|
|
const graphOnly = JSON.stringify(graph);
|
|
const withMetadata = JSON.stringify({
|
|
metadata: {
|
|
exportedAt: new Date().toISOString(),
|
|
nodeCount: graph.nodes.length,
|
|
relationshipCount: graph.relationships.length,
|
|
fileCount: fileContents?.size || 0
|
|
},
|
|
graph
|
|
});
|
|
const withFiles = JSON.stringify({
|
|
metadata: {
|
|
exportedAt: new Date().toISOString(),
|
|
nodeCount: graph.nodes.length,
|
|
relationshipCount: graph.relationships.length,
|
|
fileCount: fileContents?.size || 0
|
|
},
|
|
graph,
|
|
fileContents: fileContents ? Object.fromEntries(fileContents) : {}
|
|
});
|
|
|
|
function formatSize(bytes) {
|
|
const sizes = ['Bytes', 'KB', 'MB'];
|
|
if (bytes === 0) return '0 Bytes';
|
|
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
|
|
}
|
|
|
|
log(`📏 Export sizes:`);
|
|
log(` - Graph only: ${formatSize(graphOnly.length)}`);
|
|
log(` - With metadata: ${formatSize(withMetadata.length)}`);
|
|
log(` - With files: ${formatSize(withFiles.length)}`);
|
|
};
|
|
|
|
// Export test functions
|
|
window.testJSONExport = function() {
|
|
if (!window.testGraph) {
|
|
log('❌ No test graph available.');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const graph = window.testGraph;
|
|
const fileContents = window.testFileContents;
|
|
|
|
// Create export with metadata
|
|
const exportData = {
|
|
metadata: {
|
|
exportedAt: new Date().toISOString(),
|
|
version: '1.0.0',
|
|
nodeCount: graph.nodes.length,
|
|
relationshipCount: graph.relationships.length,
|
|
fileCount: fileContents?.size || 0,
|
|
processingDuration: 5000 // Mock duration
|
|
},
|
|
graph,
|
|
fileContents: fileContents ? Object.fromEntries(fileContents) : {}
|
|
};
|
|
|
|
const jsonContent = JSON.stringify(exportData, null, 2);
|
|
|
|
// Create download link
|
|
const blob = new Blob([jsonContent], { type: 'application/json' });
|
|
const url = URL.createObjectURL(blob);
|
|
const filename = `gitnexus-test-graph_${new Date().toISOString().split('T')[0]}.json`;
|
|
|
|
createDownloadLink(url, filename, 'JSON Export', '📄');
|
|
|
|
log('✅ JSON export test successful');
|
|
log(`📁 Filename: ${filename}`);
|
|
log(`📊 Export size: ${Math.round(blob.size / 1024)} KB`);
|
|
|
|
} catch (error) {
|
|
log(`❌ JSON export failed: ${error.message}`);
|
|
}
|
|
};
|
|
|
|
window.testCSVExport = function() {
|
|
if (!window.testGraph) {
|
|
log('❌ No test graph available.');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const graph = window.testGraph;
|
|
|
|
// Generate nodes CSV
|
|
const nodeHeaders = ':ID,name,filePath,startLine,endLine,type,language,qualifiedName,:LABEL';
|
|
const nodeRows = graph.nodes.map(node => {
|
|
const props = node.properties;
|
|
return [
|
|
escapeCSV(node.id),
|
|
escapeCSV(props.name || ''),
|
|
escapeCSV(props.filePath || ''),
|
|
props.startLine || '',
|
|
props.endLine || '',
|
|
escapeCSV(props.type || ''),
|
|
escapeCSV(props.language || ''),
|
|
escapeCSV(props.qualifiedName || ''),
|
|
node.label
|
|
].join(',');
|
|
});
|
|
const nodesCSV = [nodeHeaders, ...nodeRows].join('\n');
|
|
|
|
// Generate relationships CSV
|
|
const relHeaders = ':START_ID,:TYPE,:END_ID,source,target';
|
|
const relRows = graph.relationships.map(rel => {
|
|
return [
|
|
escapeCSV(rel.source),
|
|
rel.type,
|
|
escapeCSV(rel.target),
|
|
escapeCSV(rel.source),
|
|
escapeCSV(rel.target)
|
|
].join(',');
|
|
});
|
|
const relsCSV = [relHeaders, ...relRows].join('\n');
|
|
|
|
// Create download links
|
|
const timestamp = new Date().toISOString().split('T')[0];
|
|
|
|
const nodesBlob = new Blob([nodesCSV], { type: 'text/csv' });
|
|
const nodesUrl = URL.createObjectURL(nodesBlob);
|
|
createDownloadLink(nodesUrl, `gitnexus-test-graph_${timestamp}_nodes.csv`, 'Nodes CSV', '📊');
|
|
|
|
const relsBlob = new Blob([relsCSV], { type: 'text/csv' });
|
|
const relsUrl = URL.createObjectURL(relsBlob);
|
|
createDownloadLink(relsUrl, `gitnexus-test-graph_${timestamp}_relationships.csv`, 'Relationships CSV', '🔗');
|
|
|
|
log('✅ CSV export test successful');
|
|
log(`📊 Nodes CSV: ${Math.round(nodesBlob.size / 1024)} KB`);
|
|
log(`🔗 Relationships CSV: ${Math.round(relsBlob.size / 1024)} KB`);
|
|
|
|
} catch (error) {
|
|
log(`❌ CSV export failed: ${error.message}`);
|
|
}
|
|
};
|
|
|
|
window.testFilteredExport = function() {
|
|
if (!window.testGraph) {
|
|
log('❌ No test graph available.');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const graph = window.testGraph;
|
|
|
|
// Create filtered export (only TypeScript files and classes)
|
|
const filteredNodes = graph.nodes.filter(node =>
|
|
node.label === 'Class' ||
|
|
node.label === 'Method' ||
|
|
(node.properties.language === 'typescript')
|
|
);
|
|
|
|
const filteredNodeIds = new Set(filteredNodes.map(n => n.id));
|
|
const filteredRels = graph.relationships.filter(rel =>
|
|
filteredNodeIds.has(rel.source) && filteredNodeIds.has(rel.target)
|
|
);
|
|
|
|
const filteredGraph = {
|
|
nodes: filteredNodes,
|
|
relationships: filteredRels
|
|
};
|
|
|
|
const exportData = {
|
|
metadata: {
|
|
exportedAt: new Date().toISOString(),
|
|
version: '1.0.0',
|
|
nodeCount: filteredGraph.nodes.length,
|
|
relationshipCount: filteredGraph.relationships.length,
|
|
filters: ['TypeScript files', 'Classes', 'Methods']
|
|
},
|
|
graph: filteredGraph
|
|
};
|
|
|
|
const jsonContent = JSON.stringify(exportData, null, 2);
|
|
const blob = new Blob([jsonContent], { type: 'application/json' });
|
|
const url = URL.createObjectURL(blob);
|
|
const filename = `gitnexus-filtered-test_${new Date().toISOString().split('T')[0]}.json`;
|
|
|
|
createDownloadLink(url, filename, 'Filtered Export', '🔍');
|
|
|
|
log('✅ Filtered export test successful');
|
|
log(`📊 Original: ${graph.nodes.length} nodes, ${graph.relationships.length} relationships`);
|
|
log(`🔍 Filtered: ${filteredGraph.nodes.length} nodes, ${filteredGraph.relationships.length} relationships`);
|
|
|
|
} catch (error) {
|
|
log(`❌ Filtered export failed: ${error.message}`);
|
|
}
|
|
};
|
|
|
|
window.testImport = function() {
|
|
// For this test, we'll simulate importing the JSON we just exported
|
|
if (!window.testGraph) {
|
|
log('❌ No test graph available. Export one first.');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const originalGraph = window.testGraph;
|
|
const fileContents = window.testFileContents;
|
|
|
|
// Create mock export data
|
|
const exportData = {
|
|
metadata: {
|
|
exportedAt: new Date().toISOString(),
|
|
version: '1.0.0',
|
|
nodeCount: originalGraph.nodes.length,
|
|
relationshipCount: originalGraph.relationships.length,
|
|
fileCount: fileContents?.size || 0
|
|
},
|
|
graph: originalGraph,
|
|
fileContents: fileContents ? Object.fromEntries(fileContents) : {}
|
|
};
|
|
|
|
// Simulate import process
|
|
const jsonString = JSON.stringify(exportData);
|
|
const parsed = JSON.parse(jsonString);
|
|
|
|
// Verify import
|
|
const importedGraph = parsed.graph;
|
|
const importedMetadata = parsed.metadata;
|
|
const importedFiles = parsed.fileContents ? new Map(Object.entries(parsed.fileContents)) : null;
|
|
|
|
const importDiv = document.getElementById('import-output');
|
|
importDiv.className = 'test-section success';
|
|
importDiv.innerHTML = `
|
|
<h4>✅ Import Test Results</h4>
|
|
<p><strong>Metadata:</strong> ${importedMetadata ? '✅ Present' : '❌ Missing'}</p>
|
|
<p><strong>Graph:</strong> ${importedGraph ? '✅ Present' : '❌ Missing'}</p>
|
|
<p><strong>File Contents:</strong> ${importedFiles ? '✅ Present' : '❌ Missing'}</p>
|
|
<p><strong>Nodes:</strong> ${importedGraph.nodes.length} (${originalGraph.nodes.length === importedGraph.nodes.length ? '✅ Match' : '❌ Mismatch'})</p>
|
|
<p><strong>Relationships:</strong> ${importedGraph.relationships.length} (${originalGraph.relationships.length === importedGraph.relationships.length ? '✅ Match' : '❌ Mismatch'})</p>
|
|
<p><strong>Files:</strong> ${importedFiles?.size || 0} (${fileContents?.size === importedFiles?.size ? '✅ Match' : '❌ Mismatch'})</p>
|
|
`;
|
|
|
|
log('✅ Import test successful');
|
|
log(`📊 Imported ${importedGraph.nodes.length} nodes, ${importedGraph.relationships.length} relationships`);
|
|
log(`📁 Imported ${importedFiles?.size || 0} files`);
|
|
|
|
} catch (error) {
|
|
const importDiv = document.getElementById('import-output');
|
|
importDiv.className = 'test-section error';
|
|
importDiv.innerHTML = `<h4>❌ Import Test Failed</h4><p>${error.message}</p>`;
|
|
log(`❌ Import test failed: ${error.message}`);
|
|
}
|
|
};
|
|
|
|
// Helper functions
|
|
function createDownloadLink(url, filename, label, icon) {
|
|
const linksDiv = document.getElementById('export-links');
|
|
const link = document.createElement('a');
|
|
link.href = url;
|
|
link.download = filename;
|
|
link.className = 'download-link';
|
|
link.innerHTML = `${icon} Download ${label}`;
|
|
linksDiv.appendChild(link);
|
|
}
|
|
|
|
function escapeCSV(value) {
|
|
if (!value) return '';
|
|
if (value.includes(',') || value.includes('"') || value.includes('\n')) {
|
|
return `"${value.replace(/"/g, '""')}"`;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function log(message) {
|
|
const output = document.getElementById('output');
|
|
const timestamp = new Date().toLocaleTimeString();
|
|
output.textContent += `[${timestamp}] ${message}\n`;
|
|
output.scrollTop = output.scrollHeight;
|
|
console.log(message);
|
|
}
|
|
|
|
// Initialize
|
|
log('🚀 Export functionality test ready');
|
|
log('👆 Click "Create Test Graph" to begin testing');
|
|
</script>
|
|
</body>
|
|
</html> |