mirror of
https://github.com/ptarmiganlabs/butler-sos.git
synced 2025-12-19 09:47:53 -05:00
Improve InfluxDB test coverage
This commit is contained in:
60
src/lib/influxdb/__tests__/error-metrics.test.js
Normal file
60
src/lib/influxdb/__tests__/error-metrics.test.js
Normal file
@@ -0,0 +1,60 @@
|
||||
import { jest, describe, test, expect } from '@jest/globals';
|
||||
import { postErrorMetricsToInfluxdb } from '../error-metrics.js';
|
||||
|
||||
describe('error-metrics', () => {
|
||||
describe('postErrorMetricsToInfluxdb', () => {
|
||||
test('should resolve successfully with valid error stats', async () => {
|
||||
const errorStats = {
|
||||
HEALTH_API: {
|
||||
total: 5,
|
||||
servers: {
|
||||
sense1: 3,
|
||||
sense2: 2,
|
||||
},
|
||||
},
|
||||
INFLUXDB_V3_WRITE: {
|
||||
total: 2,
|
||||
servers: {
|
||||
_no_server_context: 2,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
await expect(postErrorMetricsToInfluxdb(errorStats)).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
test('should resolve successfully with empty error stats', async () => {
|
||||
const errorStats = {};
|
||||
|
||||
await expect(postErrorMetricsToInfluxdb(errorStats)).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
test('should resolve successfully with null input', async () => {
|
||||
await expect(postErrorMetricsToInfluxdb(null)).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
test('should resolve successfully with undefined input', async () => {
|
||||
await expect(postErrorMetricsToInfluxdb(undefined)).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
test('should resolve successfully with complex error stats', async () => {
|
||||
const errorStats = {
|
||||
API_TYPE_1: {
|
||||
total: 100,
|
||||
servers: {
|
||||
server1: 25,
|
||||
server2: 25,
|
||||
server3: 25,
|
||||
server4: 25,
|
||||
},
|
||||
},
|
||||
API_TYPE_2: {
|
||||
total: 0,
|
||||
servers: {},
|
||||
},
|
||||
};
|
||||
|
||||
await expect(postErrorMetricsToInfluxdb(errorStats)).resolves.toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -47,6 +47,81 @@ jest.unstable_mockModule('../v1/queue-metrics.js', () => ({
|
||||
storeLogEventQueueMetricsV1: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../v1/health-metrics.js', () => ({
|
||||
storeHealthMetricsV1: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../v2/health-metrics.js', () => ({
|
||||
storeHealthMetricsV2: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../v3/health-metrics.js', () => ({
|
||||
postHealthMetricsToInfluxdbV3: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../v1/sessions.js', () => ({
|
||||
storeSessionsV1: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../v2/sessions.js', () => ({
|
||||
storeSessionsV2: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../v3/sessions.js', () => ({
|
||||
postProxySessionsToInfluxdbV3: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../v1/butler-memory.js', () => ({
|
||||
storeButlerMemoryV1: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../v2/butler-memory.js', () => ({
|
||||
storeButlerMemoryV2: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../v3/butler-memory.js', () => ({
|
||||
postButlerSOSMemoryUsageToInfluxdbV3: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../v1/user-events.js', () => ({
|
||||
storeUserEventV1: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../v2/user-events.js', () => ({
|
||||
storeUserEventV2: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../v3/user-events.js', () => ({
|
||||
postUserEventToInfluxdbV3: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../v1/log-events.js', () => ({
|
||||
storeLogEventV1: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../v2/log-events.js', () => ({
|
||||
storeLogEventV2: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../v3/log-events.js', () => ({
|
||||
postLogEventToInfluxdbV3: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../v1/event-counts.js', () => ({
|
||||
storeEventCountV1: jest.fn(),
|
||||
storeRejectedEventCountV1: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../v2/event-counts.js', () => ({
|
||||
storeEventCountV2: jest.fn(),
|
||||
storeRejectedEventCountV2: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../v3/event-counts.js', () => ({
|
||||
storeEventCountInfluxDBV3: jest.fn(),
|
||||
storeRejectedEventCountInfluxDBV3: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('InfluxDB Factory', () => {
|
||||
let factory;
|
||||
let globals;
|
||||
@@ -54,6 +129,12 @@ describe('InfluxDB Factory', () => {
|
||||
let v3Impl;
|
||||
let v2Impl;
|
||||
let v1Impl;
|
||||
let v3Health, v2Health, v1Health;
|
||||
let v3Sessions, v2Sessions, v1Sessions;
|
||||
let v3Memory, v2Memory, v1Memory;
|
||||
let v3User, v2User, v1User;
|
||||
let v3Log, v2Log, v1Log;
|
||||
let v3EventCounts, v2EventCounts, v1EventCounts;
|
||||
|
||||
beforeEach(async () => {
|
||||
jest.clearAllMocks();
|
||||
@@ -63,6 +144,31 @@ describe('InfluxDB Factory', () => {
|
||||
v3Impl = await import('../v3/queue-metrics.js');
|
||||
v2Impl = await import('../v2/queue-metrics.js');
|
||||
v1Impl = await import('../v1/queue-metrics.js');
|
||||
|
||||
v3Health = await import('../v3/health-metrics.js');
|
||||
v2Health = await import('../v2/health-metrics.js');
|
||||
v1Health = await import('../v1/health-metrics.js');
|
||||
|
||||
v3Sessions = await import('../v3/sessions.js');
|
||||
v2Sessions = await import('../v2/sessions.js');
|
||||
v1Sessions = await import('../v1/sessions.js');
|
||||
|
||||
v3Memory = await import('../v3/butler-memory.js');
|
||||
v2Memory = await import('../v2/butler-memory.js');
|
||||
v1Memory = await import('../v1/butler-memory.js');
|
||||
|
||||
v3User = await import('../v3/user-events.js');
|
||||
v2User = await import('../v2/user-events.js');
|
||||
v1User = await import('../v1/user-events.js');
|
||||
|
||||
v3Log = await import('../v3/log-events.js');
|
||||
v2Log = await import('../v2/log-events.js');
|
||||
v1Log = await import('../v1/log-events.js');
|
||||
|
||||
v3EventCounts = await import('../v3/event-counts.js');
|
||||
v2EventCounts = await import('../v2/event-counts.js');
|
||||
v1EventCounts = await import('../v1/event-counts.js');
|
||||
|
||||
factory = await import('../factory.js');
|
||||
|
||||
// Setup default mocks
|
||||
@@ -72,6 +178,33 @@ describe('InfluxDB Factory', () => {
|
||||
v2Impl.storeLogEventQueueMetricsV2.mockResolvedValue();
|
||||
v1Impl.storeUserEventQueueMetricsV1.mockResolvedValue();
|
||||
v1Impl.storeLogEventQueueMetricsV1.mockResolvedValue();
|
||||
|
||||
v3Health.postHealthMetricsToInfluxdbV3.mockResolvedValue();
|
||||
v2Health.storeHealthMetricsV2.mockResolvedValue();
|
||||
v1Health.storeHealthMetricsV1.mockResolvedValue();
|
||||
|
||||
v3Sessions.postProxySessionsToInfluxdbV3.mockResolvedValue();
|
||||
v2Sessions.storeSessionsV2.mockResolvedValue();
|
||||
v1Sessions.storeSessionsV1.mockResolvedValue();
|
||||
|
||||
v3Memory.postButlerSOSMemoryUsageToInfluxdbV3.mockResolvedValue();
|
||||
v2Memory.storeButlerMemoryV2.mockResolvedValue();
|
||||
v1Memory.storeButlerMemoryV1.mockResolvedValue();
|
||||
|
||||
v3User.postUserEventToInfluxdbV3.mockResolvedValue();
|
||||
v2User.storeUserEventV2.mockResolvedValue();
|
||||
v1User.storeUserEventV1.mockResolvedValue();
|
||||
|
||||
v3Log.postLogEventToInfluxdbV3.mockResolvedValue();
|
||||
v2Log.storeLogEventV2.mockResolvedValue();
|
||||
v1Log.storeLogEventV1.mockResolvedValue();
|
||||
|
||||
v3EventCounts.storeEventCountInfluxDBV3.mockResolvedValue();
|
||||
v3EventCounts.storeRejectedEventCountInfluxDBV3.mockResolvedValue();
|
||||
v2EventCounts.storeEventCountV2.mockResolvedValue();
|
||||
v2EventCounts.storeRejectedEventCountV2.mockResolvedValue();
|
||||
v1EventCounts.storeEventCountV1.mockResolvedValue();
|
||||
v1EventCounts.storeRejectedEventCountV1.mockResolvedValue();
|
||||
});
|
||||
|
||||
describe('postUserEventQueueMetricsToInfluxdb', () => {
|
||||
@@ -157,4 +290,279 @@ describe('InfluxDB Factory', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('postHealthMetricsToInfluxdb', () => {
|
||||
const serverName = 'test-server';
|
||||
const host = 'test-host';
|
||||
const body = { version: '1.0' };
|
||||
const serverTags = [{ name: 'env', value: 'prod' }];
|
||||
|
||||
test('should route to v3 implementation when version is 3', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(3);
|
||||
|
||||
await factory.postHealthMetricsToInfluxdb(serverName, host, body, serverTags);
|
||||
|
||||
expect(v3Health.postHealthMetricsToInfluxdbV3).toHaveBeenCalledWith(
|
||||
serverName,
|
||||
host,
|
||||
body,
|
||||
serverTags
|
||||
);
|
||||
expect(v2Health.storeHealthMetricsV2).not.toHaveBeenCalled();
|
||||
expect(v1Health.storeHealthMetricsV1).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should route to v2 implementation when version is 2', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(2);
|
||||
|
||||
await factory.postHealthMetricsToInfluxdb(serverName, host, body, serverTags);
|
||||
|
||||
expect(v2Health.storeHealthMetricsV2).toHaveBeenCalledWith(
|
||||
serverName,
|
||||
host,
|
||||
body,
|
||||
serverTags
|
||||
);
|
||||
expect(v3Health.postHealthMetricsToInfluxdbV3).not.toHaveBeenCalled();
|
||||
expect(v1Health.storeHealthMetricsV1).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should route to v1 implementation when version is 1', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(1);
|
||||
|
||||
await factory.postHealthMetricsToInfluxdb(serverName, host, body, serverTags);
|
||||
|
||||
expect(v1Health.storeHealthMetricsV1).toHaveBeenCalledWith(serverTags, body);
|
||||
expect(v3Health.postHealthMetricsToInfluxdbV3).not.toHaveBeenCalled();
|
||||
expect(v2Health.storeHealthMetricsV2).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should throw error for unsupported version', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(4);
|
||||
|
||||
await expect(
|
||||
factory.postHealthMetricsToInfluxdb(serverName, host, body, serverTags)
|
||||
).rejects.toThrow('InfluxDB v4 not supported');
|
||||
});
|
||||
});
|
||||
|
||||
describe('postProxySessionsToInfluxdb', () => {
|
||||
const userSessions = { serverName: 'test', host: 'test-host' };
|
||||
|
||||
test('should route to v3 implementation when version is 3', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(3);
|
||||
|
||||
await factory.postProxySessionsToInfluxdb(userSessions);
|
||||
|
||||
expect(v3Sessions.postProxySessionsToInfluxdbV3).toHaveBeenCalledWith(userSessions);
|
||||
expect(v2Sessions.storeSessionsV2).not.toHaveBeenCalled();
|
||||
expect(v1Sessions.storeSessionsV1).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should route to v2 implementation when version is 2', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(2);
|
||||
|
||||
await factory.postProxySessionsToInfluxdb(userSessions);
|
||||
|
||||
expect(v2Sessions.storeSessionsV2).toHaveBeenCalledWith(userSessions);
|
||||
expect(v3Sessions.postProxySessionsToInfluxdbV3).not.toHaveBeenCalled();
|
||||
expect(v1Sessions.storeSessionsV1).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should route to v1 implementation when version is 1', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(1);
|
||||
|
||||
await factory.postProxySessionsToInfluxdb(userSessions);
|
||||
|
||||
expect(v1Sessions.storeSessionsV1).toHaveBeenCalledWith(userSessions);
|
||||
expect(v3Sessions.postProxySessionsToInfluxdbV3).not.toHaveBeenCalled();
|
||||
expect(v2Sessions.storeSessionsV2).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should throw error for unsupported version', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(10);
|
||||
|
||||
await expect(factory.postProxySessionsToInfluxdb(userSessions)).rejects.toThrow(
|
||||
'InfluxDB v10 not supported'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('postButlerSOSMemoryUsageToInfluxdb', () => {
|
||||
const memory = { heap_used: 100, heap_total: 200 };
|
||||
|
||||
test('should route to v3 implementation when version is 3', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(3);
|
||||
|
||||
await factory.postButlerSOSMemoryUsageToInfluxdb(memory);
|
||||
|
||||
expect(v3Memory.postButlerSOSMemoryUsageToInfluxdbV3).toHaveBeenCalledWith(memory);
|
||||
expect(v2Memory.storeButlerMemoryV2).not.toHaveBeenCalled();
|
||||
expect(v1Memory.storeButlerMemoryV1).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should route to v2 implementation when version is 2', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(2);
|
||||
|
||||
await factory.postButlerSOSMemoryUsageToInfluxdb(memory);
|
||||
|
||||
expect(v2Memory.storeButlerMemoryV2).toHaveBeenCalledWith(memory);
|
||||
});
|
||||
|
||||
test('should route to v1 implementation when version is 1', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(1);
|
||||
|
||||
await factory.postButlerSOSMemoryUsageToInfluxdb(memory);
|
||||
|
||||
expect(v1Memory.storeButlerMemoryV1).toHaveBeenCalledWith(memory);
|
||||
});
|
||||
|
||||
test('should throw error for unsupported version', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(7);
|
||||
|
||||
await expect(factory.postButlerSOSMemoryUsageToInfluxdb(memory)).rejects.toThrow(
|
||||
'InfluxDB v7 not supported'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('postUserEventToInfluxdb', () => {
|
||||
const msg = { host: 'test-host', command: 'OpenApp' };
|
||||
|
||||
test('should route to v3 implementation when version is 3', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(3);
|
||||
|
||||
await factory.postUserEventToInfluxdb(msg);
|
||||
|
||||
expect(v3User.postUserEventToInfluxdbV3).toHaveBeenCalledWith(msg);
|
||||
});
|
||||
|
||||
test('should route to v2 implementation when version is 2', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(2);
|
||||
|
||||
await factory.postUserEventToInfluxdb(msg);
|
||||
|
||||
expect(v2User.storeUserEventV2).toHaveBeenCalledWith(msg);
|
||||
});
|
||||
|
||||
test('should route to v1 implementation when version is 1', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(1);
|
||||
|
||||
await factory.postUserEventToInfluxdb(msg);
|
||||
|
||||
expect(v1User.storeUserEventV1).toHaveBeenCalledWith(msg);
|
||||
});
|
||||
|
||||
test('should throw error for unsupported version', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(0);
|
||||
|
||||
await expect(factory.postUserEventToInfluxdb(msg)).rejects.toThrow(
|
||||
'InfluxDB v0 not supported'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('postLogEventToInfluxdb', () => {
|
||||
const msg = { host: 'test-host', source: 'qseow-engine' };
|
||||
|
||||
test('should route to v3 implementation when version is 3', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(3);
|
||||
|
||||
await factory.postLogEventToInfluxdb(msg);
|
||||
|
||||
expect(v3Log.postLogEventToInfluxdbV3).toHaveBeenCalledWith(msg);
|
||||
});
|
||||
|
||||
test('should route to v2 implementation when version is 2', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(2);
|
||||
|
||||
await factory.postLogEventToInfluxdb(msg);
|
||||
|
||||
expect(v2Log.storeLogEventV2).toHaveBeenCalledWith(msg);
|
||||
});
|
||||
|
||||
test('should route to v1 implementation when version is 1', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(1);
|
||||
|
||||
await factory.postLogEventToInfluxdb(msg);
|
||||
|
||||
expect(v1Log.storeLogEventV1).toHaveBeenCalledWith(msg);
|
||||
});
|
||||
|
||||
test('should throw error for unsupported version', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(-1);
|
||||
|
||||
await expect(factory.postLogEventToInfluxdb(msg)).rejects.toThrow(
|
||||
'InfluxDB v-1 not supported'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('storeEventCountInfluxDB', () => {
|
||||
test('should route to v3 implementation when version is 3', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(3);
|
||||
|
||||
await factory.storeEventCountInfluxDB();
|
||||
|
||||
expect(v3EventCounts.storeEventCountInfluxDBV3).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should route to v2 implementation when version is 2', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(2);
|
||||
|
||||
await factory.storeEventCountInfluxDB();
|
||||
|
||||
expect(v2EventCounts.storeEventCountV2).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should route to v1 implementation when version is 1', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(1);
|
||||
|
||||
await factory.storeEventCountInfluxDB();
|
||||
|
||||
expect(v1EventCounts.storeEventCountV1).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should throw error for unsupported version', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(100);
|
||||
|
||||
await expect(factory.storeEventCountInfluxDB()).rejects.toThrow(
|
||||
'InfluxDB v100 not supported'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('storeRejectedEventCountInfluxDB', () => {
|
||||
test('should route to v3 implementation when version is 3', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(3);
|
||||
|
||||
await factory.storeRejectedEventCountInfluxDB();
|
||||
|
||||
expect(v3EventCounts.storeRejectedEventCountInfluxDBV3).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should route to v2 implementation when version is 2', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(2);
|
||||
|
||||
await factory.storeRejectedEventCountInfluxDB();
|
||||
|
||||
expect(v2EventCounts.storeRejectedEventCountV2).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should route to v1 implementation when version is 1', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(1);
|
||||
|
||||
await factory.storeRejectedEventCountInfluxDB();
|
||||
|
||||
expect(v1EventCounts.storeRejectedEventCountV1).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should throw error for unsupported version', async () => {
|
||||
utils.getInfluxDbVersion.mockReturnValue(99);
|
||||
|
||||
await expect(factory.storeRejectedEventCountInfluxDB()).rejects.toThrow(
|
||||
'InfluxDB v99 not supported'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
301
src/lib/influxdb/__tests__/index.test.js
Normal file
301
src/lib/influxdb/__tests__/index.test.js
Normal file
@@ -0,0 +1,301 @@
|
||||
import { jest, describe, test, expect, beforeEach, afterEach } from '@jest/globals';
|
||||
|
||||
// Mock globals
|
||||
const mockGlobals = {
|
||||
logger: {
|
||||
info: jest.fn(),
|
||||
verbose: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
},
|
||||
config: {
|
||||
get: jest.fn(),
|
||||
has: jest.fn(),
|
||||
},
|
||||
};
|
||||
|
||||
jest.unstable_mockModule('../../../globals.js', () => ({
|
||||
default: mockGlobals,
|
||||
}));
|
||||
|
||||
// Mock factory
|
||||
const mockFactory = {
|
||||
postHealthMetricsToInfluxdb: jest.fn(),
|
||||
postProxySessionsToInfluxdb: jest.fn(),
|
||||
postButlerSOSMemoryUsageToInfluxdb: jest.fn(),
|
||||
postUserEventToInfluxdb: jest.fn(),
|
||||
postLogEventToInfluxdb: jest.fn(),
|
||||
storeEventCountInfluxDB: jest.fn(),
|
||||
storeRejectedEventCountInfluxDB: jest.fn(),
|
||||
postUserEventQueueMetricsToInfluxdb: jest.fn(),
|
||||
postLogEventQueueMetricsToInfluxdb: jest.fn(),
|
||||
};
|
||||
|
||||
jest.unstable_mockModule('../factory.js', () => mockFactory);
|
||||
|
||||
// Mock shared utils
|
||||
jest.unstable_mockModule('../shared/utils.js', () => ({
|
||||
getFormattedTime: jest.fn((time) => `formatted-${time}`),
|
||||
}));
|
||||
|
||||
describe('InfluxDB Index (Facade)', () => {
|
||||
let indexModule;
|
||||
let globals;
|
||||
|
||||
beforeEach(async () => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
globals = (await import('../../../globals.js')).default;
|
||||
indexModule = await import('../index.js');
|
||||
|
||||
// Setup default mock implementations
|
||||
mockFactory.postHealthMetricsToInfluxdb.mockResolvedValue();
|
||||
mockFactory.postProxySessionsToInfluxdb.mockResolvedValue();
|
||||
mockFactory.postButlerSOSMemoryUsageToInfluxdb.mockResolvedValue();
|
||||
mockFactory.postUserEventToInfluxdb.mockResolvedValue();
|
||||
mockFactory.postLogEventToInfluxdb.mockResolvedValue();
|
||||
mockFactory.storeEventCountInfluxDB.mockResolvedValue();
|
||||
mockFactory.storeRejectedEventCountInfluxDB.mockResolvedValue();
|
||||
mockFactory.postUserEventQueueMetricsToInfluxdb.mockResolvedValue();
|
||||
mockFactory.postLogEventQueueMetricsToInfluxdb.mockResolvedValue();
|
||||
|
||||
globals.config.get.mockReturnValue(true);
|
||||
});
|
||||
|
||||
describe('getFormattedTime', () => {
|
||||
test('should be exported and callable', () => {
|
||||
expect(indexModule.getFormattedTime).toBeDefined();
|
||||
expect(typeof indexModule.getFormattedTime).toBe('function');
|
||||
});
|
||||
|
||||
test('should format time correctly', () => {
|
||||
const result = indexModule.getFormattedTime('20240101T120000');
|
||||
expect(result).toBe('formatted-20240101T120000');
|
||||
});
|
||||
});
|
||||
|
||||
describe('postHealthMetricsToInfluxdb', () => {
|
||||
test('should delegate to factory', async () => {
|
||||
const serverName = 'server1';
|
||||
const host = 'host1';
|
||||
const body = { version: '1.0' };
|
||||
const serverTags = [{ name: 'env', value: 'prod' }];
|
||||
|
||||
await indexModule.postHealthMetricsToInfluxdb(serverName, host, body, serverTags);
|
||||
|
||||
expect(mockFactory.postHealthMetricsToInfluxdb).toHaveBeenCalledWith(
|
||||
serverName,
|
||||
host,
|
||||
body,
|
||||
serverTags
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('postProxySessionsToInfluxdb', () => {
|
||||
test('should delegate to factory', async () => {
|
||||
const userSessions = { serverName: 'test', host: 'test-host' };
|
||||
|
||||
await indexModule.postProxySessionsToInfluxdb(userSessions);
|
||||
|
||||
expect(mockFactory.postProxySessionsToInfluxdb).toHaveBeenCalledWith(userSessions);
|
||||
});
|
||||
});
|
||||
|
||||
describe('postButlerSOSMemoryUsageToInfluxdb', () => {
|
||||
test('should delegate to factory', async () => {
|
||||
const memory = { heap_used: 100, heap_total: 200 };
|
||||
|
||||
await indexModule.postButlerSOSMemoryUsageToInfluxdb(memory);
|
||||
|
||||
expect(mockFactory.postButlerSOSMemoryUsageToInfluxdb).toHaveBeenCalledWith(memory);
|
||||
});
|
||||
});
|
||||
|
||||
describe('postUserEventToInfluxdb', () => {
|
||||
test('should delegate to factory', async () => {
|
||||
const msg = { host: 'test-host', command: 'OpenApp' };
|
||||
|
||||
await indexModule.postUserEventToInfluxdb(msg);
|
||||
|
||||
expect(mockFactory.postUserEventToInfluxdb).toHaveBeenCalledWith(msg);
|
||||
});
|
||||
});
|
||||
|
||||
describe('postLogEventToInfluxdb', () => {
|
||||
test('should delegate to factory', async () => {
|
||||
const msg = { host: 'test-host', source: 'qseow-engine' };
|
||||
|
||||
await indexModule.postLogEventToInfluxdb(msg);
|
||||
|
||||
expect(mockFactory.postLogEventToInfluxdb).toHaveBeenCalledWith(msg);
|
||||
});
|
||||
});
|
||||
|
||||
describe('storeEventCountInfluxDB', () => {
|
||||
test('should delegate to factory', async () => {
|
||||
await indexModule.storeEventCountInfluxDB('midnight', 'hour');
|
||||
|
||||
expect(mockFactory.storeEventCountInfluxDB).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should ignore deprecated parameters', async () => {
|
||||
await indexModule.storeEventCountInfluxDB('deprecated1', 'deprecated2');
|
||||
|
||||
expect(mockFactory.storeEventCountInfluxDB).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('storeRejectedEventCountInfluxDB', () => {
|
||||
test('should delegate to factory', async () => {
|
||||
await indexModule.storeRejectedEventCountInfluxDB('midnight', 'hour');
|
||||
|
||||
expect(mockFactory.storeRejectedEventCountInfluxDB).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should ignore deprecated parameters', async () => {
|
||||
await indexModule.storeRejectedEventCountInfluxDB({ data: 'old' }, { data: 'old2' });
|
||||
|
||||
expect(mockFactory.storeRejectedEventCountInfluxDB).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('postUserEventQueueMetricsToInfluxdb', () => {
|
||||
test('should delegate to factory', async () => {
|
||||
await indexModule.postUserEventQueueMetricsToInfluxdb({ some: 'data' });
|
||||
|
||||
expect(mockFactory.postUserEventQueueMetricsToInfluxdb).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should ignore deprecated parameter', async () => {
|
||||
await indexModule.postUserEventQueueMetricsToInfluxdb({ old: 'metrics' });
|
||||
|
||||
expect(mockFactory.postUserEventQueueMetricsToInfluxdb).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('postLogEventQueueMetricsToInfluxdb', () => {
|
||||
test('should delegate to factory', async () => {
|
||||
await indexModule.postLogEventQueueMetricsToInfluxdb({ some: 'data' });
|
||||
|
||||
expect(mockFactory.postLogEventQueueMetricsToInfluxdb).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should ignore deprecated parameter', async () => {
|
||||
await indexModule.postLogEventQueueMetricsToInfluxdb({ old: 'metrics' });
|
||||
|
||||
expect(mockFactory.postLogEventQueueMetricsToInfluxdb).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('setupUdpQueueMetricsStorage', () => {
|
||||
let intervalSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
intervalSpy = jest.spyOn(global, 'setInterval');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
intervalSpy.mockRestore();
|
||||
});
|
||||
|
||||
test('should return empty interval IDs when InfluxDB is disabled', () => {
|
||||
globals.config.get.mockImplementation((path) => {
|
||||
if (path.includes('influxdbConfig.enable')) return false;
|
||||
return undefined;
|
||||
});
|
||||
|
||||
const result = indexModule.setupUdpQueueMetricsStorage();
|
||||
|
||||
expect(result).toEqual({
|
||||
userEvents: null,
|
||||
logEvents: null,
|
||||
});
|
||||
expect(globals.logger.info).toHaveBeenCalledWith(
|
||||
expect.stringContaining('InfluxDB is disabled')
|
||||
);
|
||||
});
|
||||
|
||||
test('should setup user event queue metrics when enabled', () => {
|
||||
globals.config.get.mockImplementation((path) => {
|
||||
if (path.includes('influxdbConfig.enable')) return true;
|
||||
if (path.includes('userEvents.udpServerConfig.queueMetrics.influxdb.enable'))
|
||||
return true;
|
||||
if (
|
||||
path.includes('userEvents.udpServerConfig.queueMetrics.influxdb.writeFrequency')
|
||||
)
|
||||
return 60000;
|
||||
if (path.includes('logEvents.udpServerConfig.queueMetrics.influxdb.enable'))
|
||||
return false;
|
||||
return undefined;
|
||||
});
|
||||
|
||||
const result = indexModule.setupUdpQueueMetricsStorage();
|
||||
|
||||
expect(result.userEvents).not.toBeNull();
|
||||
expect(intervalSpy).toHaveBeenCalledWith(expect.any(Function), 60000);
|
||||
expect(globals.logger.info).toHaveBeenCalledWith(
|
||||
expect.stringContaining('user event queue metrics')
|
||||
);
|
||||
});
|
||||
|
||||
test('should setup log event queue metrics when enabled', () => {
|
||||
globals.config.get.mockImplementation((path) => {
|
||||
if (path.includes('influxdbConfig.enable')) return true;
|
||||
if (path.includes('userEvents.udpServerConfig.queueMetrics.influxdb.enable'))
|
||||
return false;
|
||||
if (path.includes('logEvents.udpServerConfig.queueMetrics.influxdb.enable'))
|
||||
return true;
|
||||
if (path.includes('logEvents.udpServerConfig.queueMetrics.influxdb.writeFrequency'))
|
||||
return 30000;
|
||||
return undefined;
|
||||
});
|
||||
|
||||
const result = indexModule.setupUdpQueueMetricsStorage();
|
||||
|
||||
expect(result.logEvents).not.toBeNull();
|
||||
expect(intervalSpy).toHaveBeenCalledWith(expect.any(Function), 30000);
|
||||
});
|
||||
|
||||
test('should setup both metrics when both enabled', () => {
|
||||
globals.config.get.mockImplementation((path) => {
|
||||
if (path.includes('influxdbConfig.enable')) return true;
|
||||
if (path.includes('userEvents.udpServerConfig.queueMetrics.influxdb.enable'))
|
||||
return true;
|
||||
if (
|
||||
path.includes('userEvents.udpServerConfig.queueMetrics.influxdb.writeFrequency')
|
||||
)
|
||||
return 45000;
|
||||
if (path.includes('logEvents.udpServerConfig.queueMetrics.influxdb.enable'))
|
||||
return true;
|
||||
if (path.includes('logEvents.udpServerConfig.queueMetrics.influxdb.writeFrequency'))
|
||||
return 55000;
|
||||
return undefined;
|
||||
});
|
||||
|
||||
const result = indexModule.setupUdpQueueMetricsStorage();
|
||||
|
||||
expect(result.userEvents).not.toBeNull();
|
||||
expect(result.logEvents).not.toBeNull();
|
||||
expect(intervalSpy).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
test('should log when metrics are disabled', () => {
|
||||
globals.config.get.mockImplementation((path) => {
|
||||
if (path.includes('influxdbConfig.enable')) return true;
|
||||
if (path.includes('queueMetrics.influxdb.enable')) return false;
|
||||
return undefined;
|
||||
});
|
||||
|
||||
indexModule.setupUdpQueueMetricsStorage();
|
||||
|
||||
expect(globals.logger.info).toHaveBeenCalledWith(
|
||||
expect.stringContaining('User event queue metrics storage to InfluxDB is disabled')
|
||||
);
|
||||
expect(globals.logger.info).toHaveBeenCalledWith(
|
||||
expect.stringContaining('Log event queue metrics storage to InfluxDB is disabled')
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
358
src/lib/influxdb/__tests__/shared-utils.test.js
Normal file
358
src/lib/influxdb/__tests__/shared-utils.test.js
Normal file
@@ -0,0 +1,358 @@
|
||||
import { jest, describe, test, expect, beforeEach } from '@jest/globals';
|
||||
|
||||
// Mock globals
|
||||
const mockGlobals = {
|
||||
logger: {
|
||||
info: jest.fn(),
|
||||
verbose: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
},
|
||||
config: {
|
||||
get: jest.fn(),
|
||||
has: jest.fn(),
|
||||
},
|
||||
influx: null,
|
||||
appNames: [],
|
||||
};
|
||||
|
||||
jest.unstable_mockModule('../../../globals.js', () => ({
|
||||
default: mockGlobals,
|
||||
}));
|
||||
|
||||
describe('Shared Utils - getFormattedTime', () => {
|
||||
let utils;
|
||||
let globals;
|
||||
|
||||
beforeEach(async () => {
|
||||
jest.clearAllMocks();
|
||||
globals = (await import('../../../globals.js')).default;
|
||||
utils = await import('../shared/utils.js');
|
||||
});
|
||||
|
||||
test('should return empty string for null input', () => {
|
||||
const result = utils.getFormattedTime(null);
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
test('should return empty string for undefined input', () => {
|
||||
const result = utils.getFormattedTime(undefined);
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
test('should return empty string for empty string input', () => {
|
||||
const result = utils.getFormattedTime('');
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
test('should return empty string for non-string input', () => {
|
||||
const result = utils.getFormattedTime(12345);
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
test('should return empty string for string shorter than minimum length', () => {
|
||||
const result = utils.getFormattedTime('20240101T12');
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
test('should return empty string for invalid date components', () => {
|
||||
const result = utils.getFormattedTime('abcdXXXXTxxxxxx');
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
test('should handle invalid date gracefully', () => {
|
||||
// JavaScript Date constructor is lenient and converts Month 13 to January of next year
|
||||
// So this doesn't actually fail - it's a valid date to JS
|
||||
const result = utils.getFormattedTime('20241301T250000');
|
||||
|
||||
// The function doesn't validate date ranges, so this will return a formatted time
|
||||
expect(typeof result).toBe('string');
|
||||
});
|
||||
|
||||
test('should format valid timestamp correctly', () => {
|
||||
// Mock Date.now to return a known value
|
||||
const mockNow = new Date('2024-01-01T13:00:00').getTime();
|
||||
jest.spyOn(Date, 'now').mockReturnValue(mockNow);
|
||||
|
||||
const result = utils.getFormattedTime('20240101T120000');
|
||||
|
||||
// Should show approximately 1 hour difference
|
||||
expect(result).toMatch(/\d+ days, \d+h \d+m \d+s/);
|
||||
|
||||
Date.now.mockRestore();
|
||||
});
|
||||
|
||||
test('should handle timestamps with exact minimum length', () => {
|
||||
const mockNow = new Date('2024-01-01T13:00:00').getTime();
|
||||
jest.spyOn(Date, 'now').mockReturnValue(mockNow);
|
||||
|
||||
const result = utils.getFormattedTime('20240101T120000');
|
||||
|
||||
expect(result).not.toBe('');
|
||||
expect(result).toMatch(/\d+ days/);
|
||||
|
||||
Date.now.mockRestore();
|
||||
});
|
||||
|
||||
test('should handle future timestamps', () => {
|
||||
const mockNow = new Date('2024-01-01T12:00:00').getTime();
|
||||
jest.spyOn(Date, 'now').mockReturnValue(mockNow);
|
||||
|
||||
// Server started in the future (edge case)
|
||||
const result = utils.getFormattedTime('20250101T120000');
|
||||
|
||||
// Result might be negative or weird, but shouldn't crash
|
||||
expect(typeof result).toBe('string');
|
||||
|
||||
Date.now.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Shared Utils - processAppDocuments', () => {
|
||||
let utils;
|
||||
let globals;
|
||||
|
||||
beforeEach(async () => {
|
||||
jest.clearAllMocks();
|
||||
globals = (await import('../../../globals.js')).default;
|
||||
utils = await import('../shared/utils.js');
|
||||
|
||||
globals.appNames = [
|
||||
{ id: 'app-123', name: 'Sales Dashboard' },
|
||||
{ id: 'app-456', name: 'HR Analytics' },
|
||||
{ id: 'app-789', name: 'Finance Report' },
|
||||
];
|
||||
});
|
||||
|
||||
test('should process empty array', async () => {
|
||||
const result = await utils.processAppDocuments([], 'TEST', 'active');
|
||||
|
||||
expect(result).toEqual({
|
||||
appNames: [],
|
||||
sessionAppNames: [],
|
||||
});
|
||||
});
|
||||
|
||||
test('should identify session apps correctly', async () => {
|
||||
const docIDs = ['SessionApp_12345', 'SessionApp_67890'];
|
||||
|
||||
const result = await utils.processAppDocuments(docIDs, 'TEST', 'active');
|
||||
|
||||
expect(result.sessionAppNames).toEqual(['SessionApp_12345', 'SessionApp_67890']);
|
||||
expect(result.appNames).toEqual([]);
|
||||
expect(globals.logger.debug).toHaveBeenCalledWith(
|
||||
expect.stringContaining('Session app is active')
|
||||
);
|
||||
});
|
||||
|
||||
test('should resolve app IDs to names', async () => {
|
||||
const docIDs = ['app-123', 'app-456'];
|
||||
|
||||
const result = await utils.processAppDocuments(docIDs, 'TEST', 'loaded');
|
||||
|
||||
expect(result.appNames).toEqual(['HR Analytics', 'Sales Dashboard']);
|
||||
expect(result.sessionAppNames).toEqual([]);
|
||||
expect(globals.logger.debug).toHaveBeenCalledWith(
|
||||
expect.stringContaining('App is loaded: Sales Dashboard')
|
||||
);
|
||||
});
|
||||
|
||||
test('should use doc ID when app name not found', async () => {
|
||||
const docIDs = ['app-unknown', 'app-123'];
|
||||
|
||||
const result = await utils.processAppDocuments(docIDs, 'TEST', 'in memory');
|
||||
|
||||
expect(result.appNames).toEqual(['Sales Dashboard', 'app-unknown']);
|
||||
expect(result.sessionAppNames).toEqual([]);
|
||||
});
|
||||
|
||||
test('should mix session apps and regular apps', async () => {
|
||||
const docIDs = ['app-123', 'SessionApp_abc', 'app-456', 'SessionApp_def', 'app-unknown'];
|
||||
|
||||
const result = await utils.processAppDocuments(docIDs, 'TEST', 'active');
|
||||
|
||||
expect(result.appNames).toEqual(['HR Analytics', 'Sales Dashboard', 'app-unknown']);
|
||||
expect(result.sessionAppNames).toEqual(['SessionApp_abc', 'SessionApp_def']);
|
||||
});
|
||||
|
||||
test('should sort both arrays alphabetically', async () => {
|
||||
const docIDs = ['app-789', 'app-123', 'app-456', 'SessionApp_z', 'SessionApp_a'];
|
||||
|
||||
const result = await utils.processAppDocuments(docIDs, 'TEST', 'active');
|
||||
|
||||
expect(result.appNames).toEqual(['Finance Report', 'HR Analytics', 'Sales Dashboard']);
|
||||
expect(result.sessionAppNames).toEqual(['SessionApp_a', 'SessionApp_z']);
|
||||
});
|
||||
|
||||
test('should handle session app prefix at start only', async () => {
|
||||
const docIDs = ['SessionApp_test', 'NotSessionApp_test', 'app-123'];
|
||||
|
||||
const result = await utils.processAppDocuments(docIDs, 'TEST', 'active');
|
||||
|
||||
expect(result.sessionAppNames).toEqual(['SessionApp_test']);
|
||||
expect(result.appNames).toEqual(['NotSessionApp_test', 'Sales Dashboard']);
|
||||
});
|
||||
|
||||
test('should handle single document', async () => {
|
||||
const docIDs = ['app-456'];
|
||||
|
||||
const result = await utils.processAppDocuments(docIDs, 'TEST', 'active');
|
||||
|
||||
expect(result.appNames).toEqual(['HR Analytics']);
|
||||
expect(result.sessionAppNames).toEqual([]);
|
||||
});
|
||||
|
||||
test('should handle many documents efficiently', async () => {
|
||||
const docIDs = Array.from({ length: 100 }, (_, i) =>
|
||||
i % 2 === 0 ? `SessionApp_${i}` : `app-${i}`
|
||||
);
|
||||
|
||||
const result = await utils.processAppDocuments(docIDs, 'TEST', 'active');
|
||||
|
||||
expect(result.sessionAppNames.length).toBe(50);
|
||||
expect(result.appNames.length).toBe(50);
|
||||
// Arrays are sorted alphabetically
|
||||
expect(result.sessionAppNames).toEqual(expect.arrayContaining(['SessionApp_0']));
|
||||
expect(result.appNames).toEqual(expect.arrayContaining(['app-1']));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Shared Utils - applyTagsToPoint3', () => {
|
||||
let utils;
|
||||
let mockPoint;
|
||||
|
||||
beforeEach(async () => {
|
||||
jest.clearAllMocks();
|
||||
utils = await import('../shared/utils.js');
|
||||
|
||||
mockPoint = {
|
||||
setTag: jest.fn().mockReturnThis(),
|
||||
};
|
||||
});
|
||||
|
||||
test('should return point unchanged for null tags', () => {
|
||||
const result = utils.applyTagsToPoint3(mockPoint, null);
|
||||
|
||||
expect(result).toBe(mockPoint);
|
||||
expect(mockPoint.setTag).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should return point unchanged for undefined tags', () => {
|
||||
const result = utils.applyTagsToPoint3(mockPoint, undefined);
|
||||
|
||||
expect(result).toBe(mockPoint);
|
||||
expect(mockPoint.setTag).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should return point unchanged for non-object tags', () => {
|
||||
const result = utils.applyTagsToPoint3(mockPoint, 'not-an-object');
|
||||
|
||||
expect(result).toBe(mockPoint);
|
||||
expect(mockPoint.setTag).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should apply single tag', () => {
|
||||
const tags = { env: 'production' };
|
||||
|
||||
const result = utils.applyTagsToPoint3(mockPoint, tags);
|
||||
|
||||
expect(result).toBe(mockPoint);
|
||||
expect(mockPoint.setTag).toHaveBeenCalledWith('env', 'production');
|
||||
expect(mockPoint.setTag).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('should apply multiple tags', () => {
|
||||
const tags = {
|
||||
env: 'production',
|
||||
region: 'us-east-1',
|
||||
service: 'qlik-sense',
|
||||
};
|
||||
|
||||
utils.applyTagsToPoint3(mockPoint, tags);
|
||||
|
||||
expect(mockPoint.setTag).toHaveBeenCalledTimes(3);
|
||||
expect(mockPoint.setTag).toHaveBeenCalledWith('env', 'production');
|
||||
expect(mockPoint.setTag).toHaveBeenCalledWith('region', 'us-east-1');
|
||||
expect(mockPoint.setTag).toHaveBeenCalledWith('service', 'qlik-sense');
|
||||
});
|
||||
|
||||
test('should convert non-string values to strings', () => {
|
||||
const tags = {
|
||||
count: 42,
|
||||
enabled: true,
|
||||
version: 3.14,
|
||||
};
|
||||
|
||||
utils.applyTagsToPoint3(mockPoint, tags);
|
||||
|
||||
expect(mockPoint.setTag).toHaveBeenCalledWith('count', '42');
|
||||
expect(mockPoint.setTag).toHaveBeenCalledWith('enabled', 'true');
|
||||
expect(mockPoint.setTag).toHaveBeenCalledWith('version', '3.14');
|
||||
});
|
||||
|
||||
test('should skip null values', () => {
|
||||
const tags = {
|
||||
env: 'production',
|
||||
region: null,
|
||||
service: 'qlik-sense',
|
||||
};
|
||||
|
||||
utils.applyTagsToPoint3(mockPoint, tags);
|
||||
|
||||
expect(mockPoint.setTag).toHaveBeenCalledTimes(2);
|
||||
expect(mockPoint.setTag).toHaveBeenCalledWith('env', 'production');
|
||||
expect(mockPoint.setTag).toHaveBeenCalledWith('service', 'qlik-sense');
|
||||
expect(mockPoint.setTag).not.toHaveBeenCalledWith('region', expect.anything());
|
||||
});
|
||||
|
||||
test('should skip undefined values', () => {
|
||||
const tags = {
|
||||
env: 'production',
|
||||
region: undefined,
|
||||
service: 'qlik-sense',
|
||||
};
|
||||
|
||||
utils.applyTagsToPoint3(mockPoint, tags);
|
||||
|
||||
expect(mockPoint.setTag).toHaveBeenCalledTimes(2);
|
||||
expect(mockPoint.setTag).toHaveBeenCalledWith('env', 'production');
|
||||
expect(mockPoint.setTag).toHaveBeenCalledWith('service', 'qlik-sense');
|
||||
});
|
||||
|
||||
test('should handle empty object', () => {
|
||||
const tags = {};
|
||||
|
||||
const result = utils.applyTagsToPoint3(mockPoint, tags);
|
||||
|
||||
expect(result).toBe(mockPoint);
|
||||
expect(mockPoint.setTag).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should handle tags with special characters', () => {
|
||||
const tags = {
|
||||
'tag-with-dash': 'value',
|
||||
tag_with_underscore: 'value2',
|
||||
'tag.with.dot': 'value3',
|
||||
};
|
||||
|
||||
utils.applyTagsToPoint3(mockPoint, tags);
|
||||
|
||||
expect(mockPoint.setTag).toHaveBeenCalledTimes(3);
|
||||
expect(mockPoint.setTag).toHaveBeenCalledWith('tag-with-dash', 'value');
|
||||
expect(mockPoint.setTag).toHaveBeenCalledWith('tag_with_underscore', 'value2');
|
||||
expect(mockPoint.setTag).toHaveBeenCalledWith('tag.with.dot', 'value3');
|
||||
});
|
||||
|
||||
test('should handle empty string values', () => {
|
||||
const tags = {
|
||||
env: '',
|
||||
region: 'us-east-1',
|
||||
};
|
||||
|
||||
utils.applyTagsToPoint3(mockPoint, tags);
|
||||
|
||||
expect(mockPoint.setTag).toHaveBeenCalledWith('env', '');
|
||||
expect(mockPoint.setTag).toHaveBeenCalledWith('region', 'us-east-1');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user