wifi-densepose/vendor/sublinear-time-solver/crates/psycho-symbolic-reasoner/tests/basic.test.js

421 lines
12 KiB
JavaScript

import { test, describe } from 'node:test';
import { strictEqual, ok, deepStrictEqual } from 'node:assert';
/**
* Basic Test Suite for Psycho-Symbolic Reasoner
*
* These tests verify core functionality during development.
* More comprehensive tests will be added as implementation progresses.
*/
describe('Psycho-Symbolic Reasoner Tests', () => {
test('package.json is valid', async () => {
const pkg = await import('../package.json', { assert: { type: 'json' } });
strictEqual(pkg.default.name, 'psycho-symbolic-reasoner');
strictEqual(pkg.default.version, '1.0.0');
ok(pkg.default.description);
ok(pkg.default.keywords.length > 0);
strictEqual(pkg.default.license, 'MIT');
});
test('example files exist and are executable', async () => {
const fs = await import('fs/promises');
const path = await import('path');
const examplesDir = path.resolve('./examples');
const files = await fs.readdir(examplesDir);
ok(files.includes('basic-usage.js'));
ok(files.includes('mcp-integration.js'));
ok(files.includes('knowledge-base.json'));
// Check if example files are readable
const basicUsage = await fs.readFile(path.join(examplesDir, 'basic-usage.js'), 'utf8');
ok(basicUsage.includes('PsychoSymbolicReasoner'));
});
test('knowledge base structure is valid', async () => {
const knowledgeBase = await import('../examples/knowledge-base.json', {
assert: { type: 'json' }
});
const kb = knowledgeBase.default;
ok(kb.metadata);
ok(Array.isArray(kb.nodes));
ok(Array.isArray(kb.edges));
ok(Array.isArray(kb.rules));
// Check that nodes have required fields
if (kb.nodes.length > 0) {
const firstNode = kb.nodes[0];
ok(firstNode.id);
ok(firstNode.type);
ok(firstNode.properties);
}
// Check that edges reference valid nodes
if (kb.edges.length > 0) {
const firstEdge = kb.edges[0];
ok(firstEdge.from);
ok(firstEdge.to);
ok(firstEdge.relationship);
}
});
test('TypeScript configuration is valid', async () => {
const fs = await import('fs/promises');
const tsconfigPath = './tsconfig.json';
const tsconfig = JSON.parse(await fs.readFile(tsconfigPath, 'utf8'));
ok(tsconfig.compilerOptions);
strictEqual(tsconfig.compilerOptions.target, 'ES2022');
strictEqual(tsconfig.compilerOptions.module, 'ESNext');
ok(Array.isArray(tsconfig.include));
ok(Array.isArray(tsconfig.exclude));
});
test('CI/CD configuration exists', async () => {
const fs = await import('fs/promises');
const path = await import('path');
const ciPath = path.join('.github', 'workflows', 'ci.yml');
const ciConfig = await fs.readFile(ciPath, 'utf8');
ok(ciConfig.includes('CI/CD Pipeline'));
ok(ciConfig.includes('test-rust'));
ok(ciConfig.includes('test-typescript'));
ok(ciConfig.includes('publish'));
});
test('documentation files exist', async () => {
const fs = await import('fs/promises');
const docs = [
'README.md',
'CHANGELOG.md',
'CONTRIBUTING.md',
'LICENSE',
'docs/API.md'
];
for (const doc of docs) {
try {
await fs.access(doc);
ok(true, `${doc} exists`);
} catch (error) {
ok(false, `${doc} is missing`);
}
}
});
test('Rust workspace configuration', async () => {
const fs = await import('fs/promises');
const cargoToml = await fs.readFile('./Cargo.toml', 'utf8');
ok(cargoToml.includes('[workspace]'));
ok(cargoToml.includes('graph_reasoner'));
ok(cargoToml.includes('extractors'));
ok(cargoToml.includes('planner'));
});
test('build scripts are properly configured', async () => {
const pkg = await import('../package.json', { assert: { type: 'json' } });
const scripts = pkg.default.scripts;
ok(scripts.build);
ok(scripts['build:wasm']);
ok(scripts['build:ts']);
ok(scripts.test);
ok(scripts.lint);
ok(scripts.clean);
// Check that build script includes WASM and TypeScript builds
ok(scripts.build.includes('build:wasm'));
ok(scripts.build.includes('build:ts'));
});
test('dependencies are properly specified', async () => {
const pkg = await import('../package.json', { assert: { type: 'json' } });
// Check required dependencies
const deps = pkg.default.dependencies;
ok(deps['@modelcontextprotocol/sdk']);
ok(deps['fastmcp']);
ok(deps['commander']);
ok(deps['express']);
// Check dev dependencies
const devDeps = pkg.default.devDependencies;
ok(devDeps['typescript']);
ok(devDeps['wasm-pack']);
ok(devDeps['@typescript-eslint/eslint-plugin']);
});
test('package exports are correctly defined', async () => {
const pkg = await import('../package.json', { assert: { type: 'json' } });
const exports = pkg.default.exports;
ok(exports['.']);
ok(exports['./mcp']);
ok(exports['./reasoner']);
ok(exports['./extractors']);
ok(exports['./planner']);
ok(exports['./wasm']);
// Check that each export has import and types
Object.values(exports).forEach(exportDef => {
ok(exportDef.import);
ok(exportDef.types);
});
});
test('CLI binaries are properly configured', async () => {
const pkg = await import('../package.json', { assert: { type: 'json' } });
const bin = pkg.default.bin;
ok(bin['psycho-symbolic-reasoner']);
ok(bin['psycho-reasoner']);
ok(bin['psr']);
// All should point to the same CLI entry point
const cliPath = './dist/cli/index.js';
strictEqual(bin['psycho-symbolic-reasoner'], cliPath);
});
});
describe('Simulated Core Functionality Tests', () => {
test('sentiment analysis simulation', async () => {
// Simulate sentiment analysis functionality
const mockSentimentAnalysis = (text) => {
const positiveWords = ['happy', 'excited', 'great', 'excellent', 'love'];
const negativeWords = ['sad', 'angry', 'terrible', 'hate', 'awful'];
let score = 0;
const words = text.toLowerCase().split(' ');
words.forEach(word => {
if (positiveWords.includes(word)) score += 0.2;
if (negativeWords.includes(word)) score -= 0.2;
});
return {
score: Math.max(-1, Math.min(1, score)),
confidence: 0.8,
primaryEmotion: score > 0 ? 'joy' : score < 0 ? 'sadness' : 'neutral'
};
};
const result1 = mockSentimentAnalysis("I'm happy and excited about this project");
ok(result1.score > 0);
strictEqual(result1.primaryEmotion, 'joy');
const result2 = mockSentimentAnalysis("This is terrible and awful");
ok(result2.score < 0);
strictEqual(result2.primaryEmotion, 'sadness');
});
test('preference extraction simulation', async () => {
// Simulate preference extraction
const mockPreferenceExtraction = (text) => {
const preferences = [];
if (text.includes('like') || text.includes('prefer')) {
preferences.push({
type: 'like',
subject: 'user',
object: 'extracted_preference',
strength: 0.8,
confidence: 0.7
});
}
if (text.includes('dislike') || text.includes('hate')) {
preferences.push({
type: 'dislike',
subject: 'user',
object: 'extracted_preference',
strength: 0.7,
confidence: 0.8
});
}
return {
preferences,
confidence: 0.75,
categories: ['general']
};
};
const result = mockPreferenceExtraction("I like quiet environments but dislike crowded spaces");
strictEqual(result.preferences.length, 2);
strictEqual(result.preferences[0].type, 'like');
strictEqual(result.preferences[1].type, 'dislike');
});
test('graph reasoning simulation', async () => {
// Simulate graph query functionality
const mockGraphReasoning = (query) => {
const mockResults = [
{ activity: 'meditation', confidence: 0.9 },
{ activity: 'deep_breathing', confidence: 0.8 },
{ activity: 'exercise', confidence: 0.7 }
];
return {
results: mockResults,
executionTime: 25,
totalResults: mockResults.length
};
};
const result = mockGraphReasoning("find stress relief activities");
ok(Array.isArray(result.results));
ok(result.results.length > 0);
ok(result.executionTime > 0);
// Check result structure
const firstResult = result.results[0];
ok(firstResult.activity);
ok(typeof firstResult.confidence === 'number');
});
test('planning simulation', async () => {
// Simulate goal-oriented planning
const mockPlanning = (goal, state, preferences) => {
const actions = [
{
name: 'Take a break',
description: 'Step away from work for 10 minutes',
duration: 10,
priority: 0.8
},
{
name: 'Practice breathing',
description: 'Do 4-7-8 breathing exercise',
duration: 5,
priority: 0.9
}
];
return {
plan: actions,
confidence: 0.85,
estimatedDuration: actions.reduce((sum, action) => sum + action.duration, 0),
explanation: 'Plan designed to address immediate stress relief'
};
};
const result = mockPlanning(
'reduce stress',
{ energy: 'low', stress: 'high' },
[{ type: 'like', object: 'quick_solutions' }]
);
ok(Array.isArray(result.plan));
ok(result.plan.length > 0);
ok(typeof result.confidence === 'number');
ok(result.explanation);
// Check action structure
const firstAction = result.plan[0];
ok(firstAction.name);
ok(firstAction.description);
ok(typeof firstAction.duration === 'number');
});
});
describe('Integration Tests', () => {
test('MCP tool integration simulation', async () => {
// Simulate MCP tool registration and execution
const mockMCPTools = [
{
name: 'extractSentiment',
description: 'Analyze sentiment from text',
execute: async (params) => ({
score: 0.5,
primaryEmotion: 'joy',
confidence: 0.8
})
},
{
name: 'createPlan',
description: 'Generate action plan',
execute: async (params) => ({
plan: [
{ name: 'Action 1', duration: 10 },
{ name: 'Action 2', duration: 15 }
],
confidence: 0.9
})
}
];
// Test tool registration
strictEqual(mockMCPTools.length, 2);
// Test tool execution
const sentimentTool = mockMCPTools.find(t => t.name === 'extractSentiment');
const sentimentResult = await sentimentTool.execute({ text: 'Happy text' });
ok(sentimentResult.score);
ok(sentimentResult.primaryEmotion);
const planTool = mockMCPTools.find(t => t.name === 'createPlan');
const planResult = await planTool.execute({ goal: 'test goal' });
ok(Array.isArray(planResult.plan));
ok(planResult.confidence);
});
test('end-to-end workflow simulation', async () => {
// Simulate complete workflow: input -> analysis -> planning -> output
const userInput = "I'm feeling stressed about upcoming deadlines";
// Step 1: Sentiment analysis
const sentiment = {
score: -0.6,
primaryEmotion: 'stress',
confidence: 0.9
};
// Step 2: Preference extraction
const preferences = {
preferences: [
{ type: 'like', object: 'quick_relief', strength: 0.8 }
]
};
// Step 3: Graph reasoning
const techniques = {
results: [
{ technique: 'deep_breathing', effectiveness: 0.9 },
{ technique: 'short_break', effectiveness: 0.7 }
]
};
// Step 4: Planning
const plan = {
plan: [
{ name: 'Deep breathing', duration: 5, priority: 0.9 },
{ name: 'Take a break', duration: 10, priority: 0.7 }
],
confidence: 0.85
};
// Verify workflow
ok(sentiment.score < 0); // Negative sentiment detected
strictEqual(sentiment.primaryEmotion, 'stress');
ok(preferences.preferences.length > 0);
ok(techniques.results.length > 0);
ok(plan.plan.length > 0);
ok(plan.confidence > 0.8);
});
});