- Delete unused dataMerger, formatter, Device model, dead service exports, and the empty agents/ + .gitkeep placeholders. - Extract STORE_MODES and MDM device-type filters into a shared constants.js. - Anchor bot regexes (^help|^store|^analyze) so "analyze store 305" no longer fires both handlers; replace catch-all noise. - Hoist inline require() calls in integrations to top-of-file imports. - Harden WebSocket server: Authorization header support, single-agent enforcement, bounded pending requests, server-level error handler, coalesced cache refresh in Meraki client. - Wrap Meraki/MDM network calls with withRetry; add request timeouts. - Migrate all console.* calls onto utils/logger.js (LOG_LEVEL aware); drive Webex framework logLevel from env. - Refactor storeDetail.js: shared renderClientLine + buildMdmSection helpers cut duplication roughly in half. - Refresh README structure, document LOG_LEVEL, add npm run agent script, add jest testMatch + new tests (handlers, HealthReport, Store, ws). Verified: npm run lint clean, 7 suites / 31 tests passing. Co-authored-by: Cursor <cursoragent@cursor.com>
87 lines
2.9 KiB
JavaScript
87 lines
2.9 KiB
JavaScript
const {
|
|
findMatchingClient,
|
|
getClientStatus,
|
|
formatLastSeen,
|
|
buildMerakiClientLink,
|
|
} = require('../utils/merakiMatcher');
|
|
|
|
describe('merakiMatcher', () => {
|
|
const sampleClients = [
|
|
{ id: 'c1', description: 'Register 305', status: 'Online', lastSeen: '2025-01-01T10:00:00Z' },
|
|
{
|
|
id: 'c2',
|
|
description: 'Printer Front',
|
|
status: 'Offline',
|
|
lastSeen: Date.now() - 5 * 60 * 1000,
|
|
},
|
|
{ id: 'c3', description: '192.168.10.45 - Terminal', status: 'Online', lastSeen: null },
|
|
{ id: 'c4', description: 'SRV-042', status: 'Online' },
|
|
];
|
|
|
|
describe('findMatchingClient', () => {
|
|
it('matches by exact or substring on description', () => {
|
|
expect(findMatchingClient(sampleClients, { name: 'Register 305' })).toBe(sampleClients[0]);
|
|
expect(findMatchingClient(sampleClients, { name: 'printer' })).toBe(sampleClients[1]);
|
|
});
|
|
|
|
it('matches using multiple identifier fields', () => {
|
|
const match = findMatchingClient(sampleClients, {
|
|
deviceName: 'Terminal',
|
|
ip_address: '192.168.10.45',
|
|
});
|
|
expect(match).toBe(sampleClients[2]);
|
|
});
|
|
|
|
it('matches MDM style UserName / DeviceFriendlyName', () => {
|
|
const match = findMatchingClient(sampleClients, {
|
|
UserName: 'SRV-042',
|
|
DeviceFriendlyName: 'Server 042',
|
|
});
|
|
expect(match).toBe(sampleClients[3]);
|
|
});
|
|
|
|
it('returns null when no clients or no match', () => {
|
|
expect(findMatchingClient([], { name: 'foo' })).toBeNull();
|
|
expect(findMatchingClient(sampleClients, { name: 'nonexistent' })).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('getClientStatus', () => {
|
|
it('returns correct emojis and fallback', () => {
|
|
expect(getClientStatus({ status: 'Online' })).toBe('✅ Online');
|
|
expect(getClientStatus({ status: 'Offline' })).toBe('❌ Offline');
|
|
expect(getClientStatus(null)).toBe('❓ Unknown');
|
|
expect(getClientStatus(undefined)).toBe('❓ Unknown');
|
|
});
|
|
});
|
|
|
|
describe('formatLastSeen', () => {
|
|
it('handles missing value', () => {
|
|
expect(formatLastSeen(null)).toBe('N/A');
|
|
expect(formatLastSeen(undefined)).toBe('N/A');
|
|
});
|
|
|
|
it('formats recent times', () => {
|
|
const justNow = new Date();
|
|
expect(formatLastSeen(justNow)).toBe('Just now');
|
|
|
|
const tenMin = new Date(Date.now() - 10 * 60 * 1000);
|
|
expect(formatLastSeen(tenMin)).toMatch(/10 min ago/);
|
|
});
|
|
});
|
|
|
|
describe('buildMerakiClientLink', () => {
|
|
const network = { id: 'N_123', name: 'Store 305', url: 'https://example.com/n/ABC123' };
|
|
|
|
it('builds a client link when possible', () => {
|
|
const client = { id: 'c99' };
|
|
const link = buildMerakiClientLink(network, client);
|
|
expect(link).toContain('/manage/clients/c99/overview');
|
|
});
|
|
|
|
it('returns empty string on bad input', () => {
|
|
expect(buildMerakiClientLink(null, {})).toBe('');
|
|
expect(buildMerakiClientLink(network, null)).toBe('');
|
|
});
|
|
});
|
|
});
|