Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'
This commit is contained in:
99
vendor/ruvector/examples/edge-net/dashboard/src/tests/App.test.tsx
vendored
Normal file
99
vendor/ruvector/examples/edge-net/dashboard/src/tests/App.test.tsx
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import { HeroUIProvider } from '@heroui/react';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import App from '../App';
|
||||
import { useNetworkStore } from '../stores/networkStore';
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
retry: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const renderApp = () => {
|
||||
return render(
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<HeroUIProvider>
|
||||
<App />
|
||||
</HeroUIProvider>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
};
|
||||
|
||||
describe('App', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
// Reset network store to initial state
|
||||
useNetworkStore.setState({
|
||||
stats: {
|
||||
totalNodes: 0,
|
||||
activeNodes: 0,
|
||||
totalCompute: 0,
|
||||
creditsEarned: 0,
|
||||
tasksCompleted: 0,
|
||||
uptime: 0,
|
||||
latency: 0,
|
||||
bandwidth: 0,
|
||||
},
|
||||
isConnected: false,
|
||||
isLoading: true,
|
||||
error: null,
|
||||
startTime: Date.now(),
|
||||
});
|
||||
});
|
||||
|
||||
it('renders loading state initially', () => {
|
||||
renderApp();
|
||||
expect(screen.getByText(/Initializing Edge-Net/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders main dashboard after loading', async () => {
|
||||
renderApp();
|
||||
|
||||
await waitFor(
|
||||
() => {
|
||||
expect(screen.getByText(/Network Overview/i)).toBeInTheDocument();
|
||||
},
|
||||
{ timeout: 3000 }
|
||||
);
|
||||
});
|
||||
|
||||
it('renders header with Edge-Net branding', async () => {
|
||||
renderApp();
|
||||
|
||||
await waitFor(
|
||||
() => {
|
||||
expect(screen.getByText('Edge-Net')).toBeInTheDocument();
|
||||
},
|
||||
{ timeout: 3000 }
|
||||
);
|
||||
});
|
||||
|
||||
it('shows connection status after network connects', async () => {
|
||||
renderApp();
|
||||
|
||||
// Wait for loading to complete and dashboard to render
|
||||
await waitFor(
|
||||
() => {
|
||||
expect(screen.getByText(/Network Overview/i)).toBeInTheDocument();
|
||||
},
|
||||
{ timeout: 3000 }
|
||||
);
|
||||
|
||||
// Update real stats which sets isConnected: true
|
||||
useNetworkStore.getState().updateRealStats();
|
||||
|
||||
// Now check for connection status - could be "Connected" or node count
|
||||
await waitFor(
|
||||
() => {
|
||||
const state = useNetworkStore.getState();
|
||||
// Verify the store state is connected
|
||||
expect(state.isConnected).toBe(true);
|
||||
},
|
||||
{ timeout: 1000 }
|
||||
);
|
||||
});
|
||||
});
|
||||
92
vendor/ruvector/examples/edge-net/dashboard/src/tests/components.test.tsx
vendored
Normal file
92
vendor/ruvector/examples/edge-net/dashboard/src/tests/components.test.tsx
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { HeroUIProvider } from '@heroui/react';
|
||||
import { StatCard } from '../components/common/StatCard';
|
||||
import { GlowingBadge } from '../components/common/GlowingBadge';
|
||||
import { CrystalLoader } from '../components/common/CrystalLoader';
|
||||
|
||||
const wrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<HeroUIProvider>{children}</HeroUIProvider>
|
||||
);
|
||||
|
||||
describe('StatCard', () => {
|
||||
it('renders title and value', () => {
|
||||
render(<StatCard title="Test Stat" value={1234} />, { wrapper });
|
||||
|
||||
expect(screen.getByText('Test Stat')).toBeInTheDocument();
|
||||
expect(screen.getByText('1,234')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders string value correctly', () => {
|
||||
render(<StatCard title="String Stat" value="45.8 TFLOPS" />, { wrapper });
|
||||
|
||||
expect(screen.getByText('45.8 TFLOPS')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows positive change indicator', () => {
|
||||
render(<StatCard title="Test" value={100} change={5.5} />, { wrapper });
|
||||
|
||||
expect(screen.getByText(/5.5%/)).toBeInTheDocument();
|
||||
expect(screen.getByText(/↑/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows negative change indicator', () => {
|
||||
render(<StatCard title="Test" value={100} change={-3.2} />, { wrapper });
|
||||
|
||||
expect(screen.getByText(/3.2%/)).toBeInTheDocument();
|
||||
expect(screen.getByText(/↓/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('applies different color variants', () => {
|
||||
const { rerender } = render(
|
||||
<StatCard title="Test" value={100} color="crystal" />,
|
||||
{ wrapper }
|
||||
);
|
||||
|
||||
expect(screen.getByText('Test')).toBeInTheDocument();
|
||||
|
||||
rerender(
|
||||
<HeroUIProvider>
|
||||
<StatCard title="Test" value={100} color="temporal" />
|
||||
</HeroUIProvider>
|
||||
);
|
||||
|
||||
expect(screen.getByText('Test')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('GlowingBadge', () => {
|
||||
it('renders children content', () => {
|
||||
render(<GlowingBadge>Test Badge</GlowingBadge>, { wrapper });
|
||||
|
||||
expect(screen.getByText('Test Badge')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('applies different color variants', () => {
|
||||
render(<GlowingBadge color="success">Success</GlowingBadge>, { wrapper });
|
||||
|
||||
expect(screen.getByText('Success')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('CrystalLoader', () => {
|
||||
it('renders without text', () => {
|
||||
const { container } = render(<CrystalLoader />, { wrapper });
|
||||
|
||||
expect(container.firstChild).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders with text', () => {
|
||||
render(<CrystalLoader text="Loading..." />, { wrapper });
|
||||
|
||||
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('supports different sizes', () => {
|
||||
const { rerender, container } = render(<CrystalLoader size="sm" />, { wrapper });
|
||||
expect(container.firstChild).toBeInTheDocument();
|
||||
|
||||
rerender(<HeroUIProvider><CrystalLoader size="lg" /></HeroUIProvider>);
|
||||
expect(container.firstChild).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
118
vendor/ruvector/examples/edge-net/dashboard/src/tests/debug.test.ts
vendored
Normal file
118
vendor/ruvector/examples/edge-net/dashboard/src/tests/debug.test.ts
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||
import {
|
||||
initDebugConsole,
|
||||
subscribeToLogs,
|
||||
getLogs,
|
||||
clearLogs,
|
||||
debug,
|
||||
timing,
|
||||
} from '../utils/debug';
|
||||
|
||||
describe('Debug Console', () => {
|
||||
beforeEach(() => {
|
||||
clearLogs();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('initDebugConsole', () => {
|
||||
it('initializes without errors', () => {
|
||||
expect(() => initDebugConsole()).not.toThrow();
|
||||
});
|
||||
|
||||
it('overrides console methods', () => {
|
||||
initDebugConsole();
|
||||
|
||||
// Console.log should still work
|
||||
expect(() => console.log('test')).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('debug logging', () => {
|
||||
it('logs info messages', () => {
|
||||
debug.info('Test info message', { data: 'test' });
|
||||
|
||||
const logs = getLogs();
|
||||
expect(logs.some((l) => l.message === 'Test info message')).toBe(true);
|
||||
});
|
||||
|
||||
it('logs warning messages', () => {
|
||||
debug.warn('Test warning', { warning: true });
|
||||
|
||||
const logs = getLogs();
|
||||
expect(logs.some((l) => l.level === 'warn')).toBe(true);
|
||||
});
|
||||
|
||||
it('logs error messages', () => {
|
||||
debug.error('Test error');
|
||||
|
||||
const logs = getLogs();
|
||||
expect(logs.some((l) => l.level === 'error')).toBe(true);
|
||||
});
|
||||
|
||||
it('logs debug messages', () => {
|
||||
debug.debug('Debug message');
|
||||
|
||||
const logs = getLogs();
|
||||
expect(logs.some((l) => l.level === 'debug')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('subscribeToLogs', () => {
|
||||
it('notifies subscribers on new logs', () => {
|
||||
const listener = vi.fn();
|
||||
subscribeToLogs(listener);
|
||||
|
||||
debug.log('New log');
|
||||
|
||||
expect(listener).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('returns unsubscribe function', () => {
|
||||
const listener = vi.fn();
|
||||
const unsubscribe = subscribeToLogs(listener);
|
||||
|
||||
unsubscribe();
|
||||
listener.mockClear();
|
||||
|
||||
debug.log('After unsubscribe');
|
||||
|
||||
// Listener should not be called after unsubscribe
|
||||
});
|
||||
});
|
||||
|
||||
describe('clearLogs', () => {
|
||||
it('removes all logs', () => {
|
||||
debug.log('Log 1');
|
||||
debug.log('Log 2');
|
||||
|
||||
expect(getLogs().length).toBeGreaterThan(0);
|
||||
|
||||
clearLogs();
|
||||
|
||||
expect(getLogs().length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('timing', () => {
|
||||
it('starts and ends timing', () => {
|
||||
timing.start('test-operation');
|
||||
const duration = timing.end('test-operation');
|
||||
|
||||
expect(duration).toBeGreaterThanOrEqual(0);
|
||||
});
|
||||
|
||||
it('returns 0 for unknown labels', () => {
|
||||
const duration = timing.end('unknown-label');
|
||||
expect(duration).toBe(0);
|
||||
});
|
||||
|
||||
it('measures async operations', async () => {
|
||||
const result = await timing.measure('async-op', async () => {
|
||||
await new Promise((r) => setTimeout(r, 10));
|
||||
return 'done';
|
||||
});
|
||||
|
||||
expect(result).toBe('done');
|
||||
});
|
||||
});
|
||||
});
|
||||
71
vendor/ruvector/examples/edge-net/dashboard/src/tests/setup.ts
vendored
Normal file
71
vendor/ruvector/examples/edge-net/dashboard/src/tests/setup.ts
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
import '@testing-library/jest-dom';
|
||||
import { afterEach, vi } from 'vitest';
|
||||
import { cleanup } from '@testing-library/react';
|
||||
|
||||
// Cleanup after each test
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
});
|
||||
|
||||
// Mock window.matchMedia
|
||||
Object.defineProperty(window, 'matchMedia', {
|
||||
writable: true,
|
||||
value: vi.fn().mockImplementation((query) => ({
|
||||
matches: false,
|
||||
media: query,
|
||||
onchange: null,
|
||||
addListener: vi.fn(),
|
||||
removeListener: vi.fn(),
|
||||
addEventListener: vi.fn(),
|
||||
removeEventListener: vi.fn(),
|
||||
dispatchEvent: vi.fn(),
|
||||
})),
|
||||
});
|
||||
|
||||
// Mock ResizeObserver
|
||||
(globalThis as Record<string, unknown>).ResizeObserver = vi.fn().mockImplementation(() => ({
|
||||
observe: vi.fn(),
|
||||
unobserve: vi.fn(),
|
||||
disconnect: vi.fn(),
|
||||
}));
|
||||
|
||||
// Mock IntersectionObserver
|
||||
(globalThis as Record<string, unknown>).IntersectionObserver = vi.fn().mockImplementation(() => ({
|
||||
observe: vi.fn(),
|
||||
unobserve: vi.fn(),
|
||||
disconnect: vi.fn(),
|
||||
}));
|
||||
|
||||
// Mock canvas context
|
||||
HTMLCanvasElement.prototype.getContext = vi.fn().mockReturnValue({
|
||||
clearRect: vi.fn(),
|
||||
beginPath: vi.fn(),
|
||||
moveTo: vi.fn(),
|
||||
lineTo: vi.fn(),
|
||||
stroke: vi.fn(),
|
||||
arc: vi.fn(),
|
||||
fill: vi.fn(),
|
||||
fillRect: vi.fn(),
|
||||
createRadialGradient: vi.fn().mockReturnValue({
|
||||
addColorStop: vi.fn(),
|
||||
}),
|
||||
scale: vi.fn(),
|
||||
});
|
||||
|
||||
// Mock requestAnimationFrame
|
||||
(globalThis as Record<string, unknown>).requestAnimationFrame = vi.fn((callback: FrameRequestCallback) => {
|
||||
return setTimeout(() => callback(performance.now()), 16) as unknown as number;
|
||||
});
|
||||
|
||||
(globalThis as Record<string, unknown>).cancelAnimationFrame = vi.fn((id: number) => {
|
||||
clearTimeout(id);
|
||||
});
|
||||
|
||||
// Mock performance.now
|
||||
if (!globalThis.performance) {
|
||||
(globalThis as unknown as Record<string, unknown>).performance = {} as Performance;
|
||||
}
|
||||
Object.defineProperty(globalThis.performance, 'now', {
|
||||
value: vi.fn(() => Date.now()),
|
||||
writable: true,
|
||||
});
|
||||
196
vendor/ruvector/examples/edge-net/dashboard/src/tests/stores.test.ts
vendored
Normal file
196
vendor/ruvector/examples/edge-net/dashboard/src/tests/stores.test.ts
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import { useNetworkStore } from '../stores/networkStore';
|
||||
import { useWASMStore } from '../stores/wasmStore';
|
||||
import { useMCPStore } from '../stores/mcpStore';
|
||||
import { useCDNStore } from '../stores/cdnStore';
|
||||
|
||||
describe('Network Store', () => {
|
||||
beforeEach(() => {
|
||||
// Reset to initial state (real data starts at 0)
|
||||
useNetworkStore.setState({
|
||||
stats: {
|
||||
totalNodes: 0,
|
||||
activeNodes: 0,
|
||||
totalCompute: 0,
|
||||
creditsEarned: 0,
|
||||
tasksCompleted: 0,
|
||||
uptime: 0,
|
||||
latency: 0,
|
||||
bandwidth: 0,
|
||||
},
|
||||
isConnected: false,
|
||||
isLoading: true,
|
||||
error: null,
|
||||
startTime: Date.now(),
|
||||
});
|
||||
});
|
||||
|
||||
it('should start with empty network (real data)', () => {
|
||||
const { stats } = useNetworkStore.getState();
|
||||
expect(stats.totalNodes).toBe(0);
|
||||
expect(stats.activeNodes).toBe(0);
|
||||
});
|
||||
|
||||
it('should update stats', () => {
|
||||
const { setStats } = useNetworkStore.getState();
|
||||
setStats({ activeNodes: 5, totalNodes: 10 });
|
||||
|
||||
const { stats } = useNetworkStore.getState();
|
||||
expect(stats.activeNodes).toBe(5);
|
||||
expect(stats.totalNodes).toBe(10);
|
||||
});
|
||||
|
||||
it('should update real stats and track network', () => {
|
||||
// Run multiple ticks to ensure stats update
|
||||
for (let i = 0; i < 50; i++) {
|
||||
useNetworkStore.getState().updateRealStats();
|
||||
}
|
||||
|
||||
const { stats, isConnected } = useNetworkStore.getState();
|
||||
// Network should be connected after updates
|
||||
expect(isConnected).toBe(true);
|
||||
// Some metrics should have updated
|
||||
expect(typeof stats.totalCompute).toBe('number');
|
||||
expect(typeof stats.uptime).toBe('number');
|
||||
});
|
||||
|
||||
it('should track connection status', () => {
|
||||
const { setConnected } = useNetworkStore.getState();
|
||||
|
||||
setConnected(false);
|
||||
expect(useNetworkStore.getState().isConnected).toBe(false);
|
||||
expect(useNetworkStore.getState().isLoading).toBe(false);
|
||||
|
||||
setConnected(true);
|
||||
expect(useNetworkStore.getState().isConnected).toBe(true);
|
||||
});
|
||||
|
||||
it('should calculate uptime', () => {
|
||||
const { getUptime } = useNetworkStore.getState();
|
||||
const uptime = getUptime();
|
||||
expect(typeof uptime).toBe('number');
|
||||
expect(uptime).toBeGreaterThanOrEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('WASM Store', () => {
|
||||
it('should have default modules', () => {
|
||||
const { modules } = useWASMStore.getState();
|
||||
expect(modules.length).toBeGreaterThan(0);
|
||||
expect(modules[0].id).toBe('edge-net');
|
||||
expect(modules[0].version).toBe('0.1.1');
|
||||
});
|
||||
|
||||
it('should start with unloaded modules', () => {
|
||||
const { modules } = useWASMStore.getState();
|
||||
const edgeNet = modules.find(m => m.id === 'edge-net');
|
||||
expect(edgeNet?.loaded).toBe(false);
|
||||
expect(edgeNet?.status).toBe('unloaded');
|
||||
expect(edgeNet?.size).toBe(0); // Size unknown until loaded
|
||||
});
|
||||
|
||||
it('should update module status', () => {
|
||||
const { updateModule } = useWASMStore.getState();
|
||||
|
||||
updateModule('edge-net', { status: 'loading' });
|
||||
|
||||
const updatedModules = useWASMStore.getState().modules;
|
||||
const edgeNet = updatedModules.find((m) => m.id === 'edge-net');
|
||||
expect(edgeNet?.status).toBe('loading');
|
||||
});
|
||||
|
||||
it('should track benchmarks', () => {
|
||||
const { addBenchmark, benchmarks } = useWASMStore.getState();
|
||||
const initialCount = benchmarks.length;
|
||||
|
||||
addBenchmark({
|
||||
moduleId: 'edge-net',
|
||||
operation: 'vector_ops_256',
|
||||
iterations: 1000,
|
||||
avgTime: 0.05,
|
||||
minTime: 0.01,
|
||||
maxTime: 0.15,
|
||||
throughput: 20000,
|
||||
});
|
||||
|
||||
expect(useWASMStore.getState().benchmarks.length).toBe(initialCount + 1);
|
||||
});
|
||||
|
||||
it('should clear benchmarks', () => {
|
||||
const { addBenchmark, clearBenchmarks } = useWASMStore.getState();
|
||||
|
||||
addBenchmark({
|
||||
moduleId: 'edge-net',
|
||||
operation: 'test',
|
||||
iterations: 100,
|
||||
avgTime: 1,
|
||||
minTime: 0.5,
|
||||
maxTime: 2,
|
||||
throughput: 100,
|
||||
});
|
||||
|
||||
clearBenchmarks();
|
||||
expect(useWASMStore.getState().benchmarks.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('MCP Store', () => {
|
||||
it('should have default tools', () => {
|
||||
const { tools } = useMCPStore.getState();
|
||||
expect(tools.length).toBeGreaterThan(0);
|
||||
expect(tools.some((t) => t.category === 'swarm')).toBe(true);
|
||||
});
|
||||
|
||||
it('should update tool status', () => {
|
||||
const { updateTool } = useMCPStore.getState();
|
||||
|
||||
updateTool('swarm_init', { status: 'running' });
|
||||
|
||||
const updatedTools = useMCPStore.getState().tools;
|
||||
const tool = updatedTools.find((t) => t.id === 'swarm_init');
|
||||
expect(tool?.status).toBe('running');
|
||||
});
|
||||
|
||||
it('should add results', () => {
|
||||
const { addResult } = useMCPStore.getState();
|
||||
|
||||
addResult({
|
||||
toolId: 'swarm_init',
|
||||
success: true,
|
||||
data: { test: true },
|
||||
timestamp: new Date(),
|
||||
duration: 100,
|
||||
});
|
||||
|
||||
const { results } = useMCPStore.getState();
|
||||
expect(results.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('CDN Store', () => {
|
||||
it('should have default scripts', () => {
|
||||
const { scripts } = useCDNStore.getState();
|
||||
expect(scripts.length).toBeGreaterThan(0);
|
||||
expect(scripts.some((s) => s.category === 'wasm')).toBe(true);
|
||||
});
|
||||
|
||||
it('should toggle script enabled state', () => {
|
||||
const { toggleScript, scripts } = useCDNStore.getState();
|
||||
const initialEnabled = scripts[0].enabled;
|
||||
|
||||
toggleScript(scripts[0].id);
|
||||
|
||||
const updatedScripts = useCDNStore.getState().scripts;
|
||||
expect(updatedScripts[0].enabled).toBe(!initialEnabled);
|
||||
});
|
||||
|
||||
it('should track auto-load setting', () => {
|
||||
const { setAutoLoad } = useCDNStore.getState();
|
||||
|
||||
setAutoLoad(true);
|
||||
expect(useCDNStore.getState().autoLoad).toBe(true);
|
||||
|
||||
setAutoLoad(false);
|
||||
expect(useCDNStore.getState().autoLoad).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user