test: Fix telemetry tests (#3804)

* 🧪 Set telemetry env vars

* 🔥 Remove logging

* 🎨 Format with Prettier
This commit is contained in:
Iván Ovejero 2022-08-01 22:37:59 +02:00 committed by GitHub
parent 3de062202d
commit 231cfaa24d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,381 +1,385 @@
import { Telemetry } from '../../src/telemetry'; import { Telemetry } from '../../src/telemetry';
import config from '../../config';
jest.spyOn(Telemetry.prototype as any, 'createTelemetryClient').mockImplementation(() => { jest.spyOn(Telemetry.prototype as any, 'createTelemetryClient').mockImplementation(() => {
return { return {
flush: () => {}, flush: () => {},
identify: () => {}, identify: () => {},
track: () => {}, track: () => {},
}; };
}); });
describe('Telemetry', () => { describe('Telemetry', () => {
let startPulseSpy: jest.SpyInstance; let startPulseSpy: jest.SpyInstance;
const spyTrack = jest.spyOn(Telemetry.prototype, 'track'); const spyTrack = jest.spyOn(Telemetry.prototype, 'track');
let telemetry: Telemetry; let telemetry: Telemetry;
const n8nVersion = '0.0.0'; const n8nVersion = '0.0.0';
const instanceId = 'Telemetry unit test'; const instanceId = 'Telemetry unit test';
const testDateTime = new Date('2022-01-01 00:00:00'); const testDateTime = new Date('2022-01-01 00:00:00');
beforeAll(() => { beforeAll(() => {
startPulseSpy = jest.spyOn(Telemetry.prototype as any, 'startPulse').mockImplementation(() => {}); startPulseSpy = jest
jest.useFakeTimers(); .spyOn(Telemetry.prototype as any, 'startPulse')
jest.setSystemTime(testDateTime); .mockImplementation(() => {});
}); jest.useFakeTimers();
jest.setSystemTime(testDateTime);
config.set('diagnostics.enabled', true);
config.set('deployment.type', 'n8n-testing');
});
afterAll(() => { afterAll(() => {
jest.clearAllTimers(); jest.clearAllTimers();
jest.useRealTimers(); jest.useRealTimers();
startPulseSpy.mockRestore(); startPulseSpy.mockRestore();
telemetry.trackN8nStop(); telemetry.trackN8nStop();
}); });
beforeEach(() => { beforeEach(() => {
spyTrack.mockClear(); spyTrack.mockClear();
telemetry = new Telemetry(instanceId, n8nVersion); telemetry = new Telemetry(instanceId, n8nVersion);
}); });
afterEach(() => { afterEach(() => {
telemetry.trackN8nStop(); telemetry.trackN8nStop();
}); });
describe('trackN8nStop', () => { describe('trackN8nStop', () => {
test('should call track method', () => { test('should call track method', () => {
telemetry.trackN8nStop(); telemetry.trackN8nStop();
expect(spyTrack).toHaveBeenCalledTimes(1); expect(spyTrack).toHaveBeenCalledTimes(1);
}); });
}); });
describe('trackWorkflowExecution', () => { describe('trackWorkflowExecution', () => {
beforeEach(() => { beforeEach(() => {
jest.setSystemTime(testDateTime); jest.setSystemTime(testDateTime);
}); });
test('should count executions correctly', async () => { test('should count executions correctly', async () => {
const payload = { const payload = {
workflow_id: '1', workflow_id: '1',
is_manual: true, is_manual: true,
success: true, success: true,
error_node_type: 'custom-nodes-base.node-type' error_node_type: 'custom-nodes-base.node-type',
}; };
payload.is_manual = true; payload.is_manual = true;
payload.success = true; payload.success = true;
const execTime1 = fakeJestSystemTime('2022-01-01 12:00:00'); const execTime1 = fakeJestSystemTime('2022-01-01 12:00:00');
await telemetry.trackWorkflowExecution(payload); await telemetry.trackWorkflowExecution(payload);
fakeJestSystemTime('2022-01-01 12:30:00'); fakeJestSystemTime('2022-01-01 12:30:00');
await telemetry.trackWorkflowExecution(payload); await telemetry.trackWorkflowExecution(payload);
payload.is_manual = false; payload.is_manual = false;
payload.success = true; payload.success = true;
const execTime2 = fakeJestSystemTime('2022-01-01 13:00:00'); const execTime2 = fakeJestSystemTime('2022-01-01 13:00:00');
await telemetry.trackWorkflowExecution(payload); await telemetry.trackWorkflowExecution(payload);
fakeJestSystemTime('2022-01-01 12:30:00'); fakeJestSystemTime('2022-01-01 12:30:00');
await telemetry.trackWorkflowExecution(payload); await telemetry.trackWorkflowExecution(payload);
payload.is_manual = true; payload.is_manual = true;
payload.success = false; payload.success = false;
const execTime3 = fakeJestSystemTime('2022-01-01 14:00:00'); const execTime3 = fakeJestSystemTime('2022-01-01 14:00:00');
await telemetry.trackWorkflowExecution(payload); await telemetry.trackWorkflowExecution(payload);
fakeJestSystemTime('2022-01-01 12:30:00'); fakeJestSystemTime('2022-01-01 12:30:00');
await telemetry.trackWorkflowExecution(payload); await telemetry.trackWorkflowExecution(payload);
payload.is_manual = false; payload.is_manual = false;
payload.success = false; payload.success = false;
const execTime4 = fakeJestSystemTime('2022-01-01 15:00:00'); const execTime4 = fakeJestSystemTime('2022-01-01 15:00:00');
await telemetry.trackWorkflowExecution(payload); await telemetry.trackWorkflowExecution(payload);
fakeJestSystemTime('2022-01-01 12:30:00'); fakeJestSystemTime('2022-01-01 12:30:00');
await telemetry.trackWorkflowExecution(payload); await telemetry.trackWorkflowExecution(payload);
expect(spyTrack).toHaveBeenCalledTimes(0); expect(spyTrack).toHaveBeenCalledTimes(0);
const execBuffer = telemetry.getCountsBuffer(); const execBuffer = telemetry.getCountsBuffer();
expect(execBuffer['1'].manual_success?.count).toBe(2); expect(execBuffer['1'].manual_success?.count).toBe(2);
expect(execBuffer['1'].manual_success?.first).toEqual(execTime1); expect(execBuffer['1'].manual_success?.first).toEqual(execTime1);
expect(execBuffer['1'].prod_success?.count).toBe(2); expect(execBuffer['1'].prod_success?.count).toBe(2);
expect(execBuffer['1'].prod_success?.first).toEqual(execTime2); expect(execBuffer['1'].prod_success?.first).toEqual(execTime2);
expect(execBuffer['1'].manual_error?.count).toBe(2); expect(execBuffer['1'].manual_error?.count).toBe(2);
expect(execBuffer['1'].manual_error?.first).toEqual(execTime3); expect(execBuffer['1'].manual_error?.first).toEqual(execTime3);
expect(execBuffer['1'].prod_error?.count).toBe(2); expect(execBuffer['1'].prod_error?.count).toBe(2);
expect(execBuffer['1'].prod_error?.first).toEqual(execTime4); expect(execBuffer['1'].prod_error?.first).toEqual(execTime4);
}); });
test('should fire "Workflow execution errored" event for failed executions', async () => { test('should fire "Workflow execution errored" event for failed executions', async () => {
const payload = { const payload = {
workflow_id: '1', workflow_id: '1',
is_manual: true, is_manual: true,
success: false, success: false,
error_node_type: 'custom-nodes-base.node-type' error_node_type: 'custom-nodes-base.node-type',
}; };
const execTime1 = fakeJestSystemTime('2022-01-01 12:00:00'); const execTime1 = fakeJestSystemTime('2022-01-01 12:00:00');
await telemetry.trackWorkflowExecution(payload); await telemetry.trackWorkflowExecution(payload);
fakeJestSystemTime('2022-01-01 12:30:00'); fakeJestSystemTime('2022-01-01 12:30:00');
await telemetry.trackWorkflowExecution(payload); await telemetry.trackWorkflowExecution(payload);
let execBuffer = telemetry.getCountsBuffer(); let execBuffer = telemetry.getCountsBuffer();
// should not fire event for custom nodes // should not fire event for custom nodes
expect(spyTrack).toHaveBeenCalledTimes(0); expect(spyTrack).toHaveBeenCalledTimes(0);
expect(execBuffer['1'].manual_error?.count).toBe(2); expect(execBuffer['1'].manual_error?.count).toBe(2);
expect(execBuffer['1'].manual_error?.first).toEqual(execTime1); expect(execBuffer['1'].manual_error?.first).toEqual(execTime1);
payload.error_node_type = 'n8n-nodes-base.node-type'; payload.error_node_type = 'n8n-nodes-base.node-type';
fakeJestSystemTime('2022-01-01 13:00:00'); fakeJestSystemTime('2022-01-01 13:00:00');
await telemetry.trackWorkflowExecution(payload); await telemetry.trackWorkflowExecution(payload);
fakeJestSystemTime('2022-01-01 12:30:00'); fakeJestSystemTime('2022-01-01 12:30:00');
await telemetry.trackWorkflowExecution(payload); await telemetry.trackWorkflowExecution(payload);
execBuffer = telemetry.getCountsBuffer(); execBuffer = telemetry.getCountsBuffer();
// should fire event for custom nodes // should fire event for custom nodes
expect(spyTrack).toHaveBeenCalledTimes(2); expect(spyTrack).toHaveBeenCalledTimes(2);
expect(spyTrack).toHaveBeenCalledWith('Workflow execution errored', payload); expect(spyTrack).toHaveBeenCalledWith('Workflow execution errored', payload);
expect(execBuffer['1'].manual_error?.count).toBe(4); expect(execBuffer['1'].manual_error?.count).toBe(4);
expect(execBuffer['1'].manual_error?.first).toEqual(execTime1); expect(execBuffer['1'].manual_error?.first).toEqual(execTime1);
}); });
test('should track production executions count correctly', async () => { test('should track production executions count correctly', async () => {
const payload = { const payload = {
workflow_id: '1', workflow_id: '1',
is_manual: false, is_manual: false,
success: true, success: true,
error_node_type: 'node_type' error_node_type: 'node_type',
}; };
// successful execution // successful execution
const execTime1 = fakeJestSystemTime('2022-01-01 12:00:00'); const execTime1 = fakeJestSystemTime('2022-01-01 12:00:00');
await telemetry.trackWorkflowExecution(payload); await telemetry.trackWorkflowExecution(payload);
expect(spyTrack).toHaveBeenCalledTimes(0); expect(spyTrack).toHaveBeenCalledTimes(0);
let execBuffer = telemetry.getCountsBuffer(); let execBuffer = telemetry.getCountsBuffer();
expect(execBuffer['1'].manual_error).toBeUndefined(); expect(execBuffer['1'].manual_error).toBeUndefined();
expect(execBuffer['1'].manual_success).toBeUndefined(); expect(execBuffer['1'].manual_success).toBeUndefined();
expect(execBuffer['1'].prod_error).toBeUndefined(); expect(execBuffer['1'].prod_error).toBeUndefined();
expect(execBuffer['1'].prod_success?.count).toBe(1); expect(execBuffer['1'].prod_success?.count).toBe(1);
expect(execBuffer['1'].prod_success?.first).toEqual(execTime1); expect(execBuffer['1'].prod_success?.first).toEqual(execTime1);
// successful execution n8n node // successful execution n8n node
payload.error_node_type = 'n8n-nodes-base.merge'; payload.error_node_type = 'n8n-nodes-base.merge';
payload.workflow_id = '2'; payload.workflow_id = '2';
await telemetry.trackWorkflowExecution(payload); await telemetry.trackWorkflowExecution(payload);
expect(spyTrack).toHaveBeenCalledTimes(0); expect(spyTrack).toHaveBeenCalledTimes(0);
execBuffer = telemetry.getCountsBuffer(); execBuffer = telemetry.getCountsBuffer();
expect(execBuffer['1'].manual_error).toBeUndefined(); expect(execBuffer['1'].manual_error).toBeUndefined();
expect(execBuffer['1'].manual_success).toBeUndefined(); expect(execBuffer['1'].manual_success).toBeUndefined();
expect(execBuffer['1'].prod_error).toBeUndefined(); expect(execBuffer['1'].prod_error).toBeUndefined();
expect(execBuffer['1'].prod_success?.count).toBe(1); expect(execBuffer['1'].prod_success?.count).toBe(1);
expect(execBuffer['2'].prod_success?.count).toBe(1); expect(execBuffer['2'].prod_success?.count).toBe(1);
expect(execBuffer['1'].prod_success?.first).toEqual(execTime1); expect(execBuffer['1'].prod_success?.first).toEqual(execTime1);
expect(execBuffer['2'].prod_success?.first).toEqual(execTime1); expect(execBuffer['2'].prod_success?.first).toEqual(execTime1);
// additional successful execution // additional successful execution
payload.error_node_type = 'n8n-nodes-base.merge'; payload.error_node_type = 'n8n-nodes-base.merge';
payload.workflow_id = '2'; payload.workflow_id = '2';
await telemetry.trackWorkflowExecution(payload); await telemetry.trackWorkflowExecution(payload);
payload.error_node_type = 'n8n-nodes-base.merge'; payload.error_node_type = 'n8n-nodes-base.merge';
payload.workflow_id = '1'; payload.workflow_id = '1';
await telemetry.trackWorkflowExecution(payload); await telemetry.trackWorkflowExecution(payload);
expect(spyTrack).toHaveBeenCalledTimes(0); expect(spyTrack).toHaveBeenCalledTimes(0);
execBuffer = telemetry.getCountsBuffer(); execBuffer = telemetry.getCountsBuffer();
expect(execBuffer['1'].manual_error).toBeUndefined(); expect(execBuffer['1'].manual_error).toBeUndefined();
expect(execBuffer['1'].manual_success).toBeUndefined(); expect(execBuffer['1'].manual_success).toBeUndefined();
expect(execBuffer['1'].prod_error).toBeUndefined(); expect(execBuffer['1'].prod_error).toBeUndefined();
expect(execBuffer['2'].manual_error).toBeUndefined(); expect(execBuffer['2'].manual_error).toBeUndefined();
expect(execBuffer['2'].manual_success).toBeUndefined(); expect(execBuffer['2'].manual_success).toBeUndefined();
expect(execBuffer['2'].prod_error).toBeUndefined(); expect(execBuffer['2'].prod_error).toBeUndefined();
expect(execBuffer['1'].prod_success?.count).toBe(2); expect(execBuffer['1'].prod_success?.count).toBe(2);
expect(execBuffer['2'].prod_success?.count).toBe(2); expect(execBuffer['2'].prod_success?.count).toBe(2);
expect(execBuffer['1'].prod_success?.first).toEqual(execTime1); expect(execBuffer['1'].prod_success?.first).toEqual(execTime1);
expect(execBuffer['2'].prod_success?.first).toEqual(execTime1); expect(execBuffer['2'].prod_success?.first).toEqual(execTime1);
// failed execution // failed execution
const execTime2 = fakeJestSystemTime('2022-01-01 12:00:00'); const execTime2 = fakeJestSystemTime('2022-01-01 12:00:00');
payload.error_node_type = 'custom-package.custom-node'; payload.error_node_type = 'custom-package.custom-node';
payload.success = false; payload.success = false;
await telemetry.trackWorkflowExecution(payload); await telemetry.trackWorkflowExecution(payload);
expect(spyTrack).toHaveBeenCalledTimes(0); expect(spyTrack).toHaveBeenCalledTimes(0);
execBuffer = telemetry.getCountsBuffer(); execBuffer = telemetry.getCountsBuffer();
expect(execBuffer['1'].manual_error).toBeUndefined(); expect(execBuffer['1'].manual_error).toBeUndefined();
expect(execBuffer['1'].manual_success).toBeUndefined(); expect(execBuffer['1'].manual_success).toBeUndefined();
expect(execBuffer['2'].manual_error).toBeUndefined(); expect(execBuffer['2'].manual_error).toBeUndefined();
expect(execBuffer['2'].manual_success).toBeUndefined(); expect(execBuffer['2'].manual_success).toBeUndefined();
expect(execBuffer['2'].prod_error).toBeUndefined(); expect(execBuffer['2'].prod_error).toBeUndefined();
expect(execBuffer['1'].prod_error?.count).toBe(1); expect(execBuffer['1'].prod_error?.count).toBe(1);
expect(execBuffer['1'].prod_success?.count).toBe(2); expect(execBuffer['1'].prod_success?.count).toBe(2);
expect(execBuffer['2'].prod_success?.count).toBe(2); expect(execBuffer['2'].prod_success?.count).toBe(2);
expect(execBuffer['1'].prod_error?.first).toEqual(execTime2); expect(execBuffer['1'].prod_error?.first).toEqual(execTime2);
expect(execBuffer['1'].prod_success?.first).toEqual(execTime1); expect(execBuffer['1'].prod_success?.first).toEqual(execTime1);
expect(execBuffer['2'].prod_success?.first).toEqual(execTime1); expect(execBuffer['2'].prod_success?.first).toEqual(execTime1);
// failed execution n8n node // failed execution n8n node
payload.success = false; payload.success = false;
payload.error_node_type = 'n8n-nodes-base.merge'; payload.error_node_type = 'n8n-nodes-base.merge';
await telemetry.trackWorkflowExecution(payload); await telemetry.trackWorkflowExecution(payload);
expect(spyTrack).toHaveBeenCalledTimes(1); expect(spyTrack).toHaveBeenCalledTimes(1);
execBuffer = telemetry.getCountsBuffer(); execBuffer = telemetry.getCountsBuffer();
expect(execBuffer['1'].manual_error).toBeUndefined(); expect(execBuffer['1'].manual_error).toBeUndefined();
expect(execBuffer['1'].manual_success).toBeUndefined(); expect(execBuffer['1'].manual_success).toBeUndefined();
expect(execBuffer['2'].manual_error).toBeUndefined(); expect(execBuffer['2'].manual_error).toBeUndefined();
expect(execBuffer['2'].manual_success).toBeUndefined(); expect(execBuffer['2'].manual_success).toBeUndefined();
expect(execBuffer['2'].prod_error).toBeUndefined(); expect(execBuffer['2'].prod_error).toBeUndefined();
expect(execBuffer['1'].prod_success?.count).toBe(2); expect(execBuffer['1'].prod_success?.count).toBe(2);
expect(execBuffer['1'].prod_error?.count).toBe(2); expect(execBuffer['1'].prod_error?.count).toBe(2);
expect(execBuffer['2'].prod_success?.count).toBe(2); expect(execBuffer['2'].prod_success?.count).toBe(2);
expect(execBuffer['1'].prod_error?.first).toEqual(execTime2); expect(execBuffer['1'].prod_error?.first).toEqual(execTime2);
expect(execBuffer['1'].prod_success?.first).toEqual(execTime1); expect(execBuffer['1'].prod_success?.first).toEqual(execTime1);
expect(execBuffer['2'].prod_success?.first).toEqual(execTime1); expect(execBuffer['2'].prod_success?.first).toEqual(execTime1);
}); });
}); });
describe('pulse', () => { describe('pulse', () => {
let pulseSpy: jest.SpyInstance; let pulseSpy: jest.SpyInstance;
beforeAll(() => { beforeAll(() => {
startPulseSpy.mockRestore(); startPulseSpy.mockRestore();
}); });
beforeEach(() => { beforeEach(() => {
fakeJestSystemTime(testDateTime); fakeJestSystemTime(testDateTime);
pulseSpy = jest.spyOn(Telemetry.prototype as any, 'pulse'); pulseSpy = jest.spyOn(Telemetry.prototype as any, 'pulse');
}); });
afterEach(() => { afterEach(() => {
pulseSpy.mockClear(); pulseSpy.mockClear();
}) });
test('should trigger pulse in intervals', () => { test('should trigger pulse in intervals', () => {
expect(pulseSpy).toBeCalledTimes(0); expect(pulseSpy).toBeCalledTimes(0);
jest.advanceTimersToNextTimer(); jest.advanceTimersToNextTimer();
expect(pulseSpy).toBeCalledTimes(1); expect(pulseSpy).toBeCalledTimes(1);
expect(spyTrack).toHaveBeenCalledTimes(1); expect(spyTrack).toHaveBeenCalledTimes(1);
expect(spyTrack).toHaveBeenCalledWith('pulse'); expect(spyTrack).toHaveBeenCalledWith('pulse');
jest.advanceTimersToNextTimer(); jest.advanceTimersToNextTimer();
expect(pulseSpy).toBeCalledTimes(2); expect(pulseSpy).toBeCalledTimes(2);
expect(spyTrack).toHaveBeenCalledTimes(2); expect(spyTrack).toHaveBeenCalledTimes(2);
expect(spyTrack).toHaveBeenCalledWith('pulse'); expect(spyTrack).toHaveBeenCalledWith('pulse');
}); });
test('should track workflow counts correctly', async () => { test('should track workflow counts correctly', async () => {
expect(pulseSpy).toBeCalledTimes(0); expect(pulseSpy).toBeCalledTimes(0);
let execBuffer = telemetry.getCountsBuffer(); let execBuffer = telemetry.getCountsBuffer();
// expect clear counters on start // expect clear counters on start
expect(Object.keys(execBuffer).length).toBe(0); expect(Object.keys(execBuffer).length).toBe(0);
const payload = { const payload = {
workflow_id: '1',
is_manual: true,
success: true,
error_node_type: 'custom-nodes-base.node-type'
};
await telemetry.trackWorkflowExecution(payload);
await telemetry.trackWorkflowExecution(payload);
payload.is_manual = false;
payload.success = true;
await telemetry.trackWorkflowExecution(payload);
await telemetry.trackWorkflowExecution(payload);
payload.is_manual = true;
payload.success = false;
await telemetry.trackWorkflowExecution(payload);
await telemetry.trackWorkflowExecution(payload);
payload.is_manual = false;
payload.success = false;
await telemetry.trackWorkflowExecution(payload);
await telemetry.trackWorkflowExecution(payload);
payload.workflow_id = '2';
await telemetry.trackWorkflowExecution(payload);
await telemetry.trackWorkflowExecution(payload);
expect(spyTrack).toHaveBeenCalledTimes(0);
expect(pulseSpy).toBeCalledTimes(0);
jest.advanceTimersToNextTimer();
execBuffer = telemetry.getCountsBuffer();
expect(pulseSpy).toBeCalledTimes(1);
expect(spyTrack).toHaveBeenCalledTimes(3);
console.log(spyTrack.getMockImplementation());
expect(spyTrack).toHaveBeenNthCalledWith(1, 'Workflow execution count', {
event_version: '2',
workflow_id: '1', workflow_id: '1',
manual_error: { is_manual: true,
count: 2, success: true,
first: testDateTime, error_node_type: 'custom-nodes-base.node-type',
}, };
manual_success: {
count: 2, await telemetry.trackWorkflowExecution(payload);
first: testDateTime, await telemetry.trackWorkflowExecution(payload);
},
prod_error: { payload.is_manual = false;
count: 2, payload.success = true;
first: testDateTime, await telemetry.trackWorkflowExecution(payload);
}, await telemetry.trackWorkflowExecution(payload);
prod_success: {
count: 2, payload.is_manual = true;
first: testDateTime, payload.success = false;
} await telemetry.trackWorkflowExecution(payload);
}); await telemetry.trackWorkflowExecution(payload);
expect(spyTrack).toHaveBeenNthCalledWith(2, 'Workflow execution count', {
event_version: '2', payload.is_manual = false;
payload.success = false;
await telemetry.trackWorkflowExecution(payload);
await telemetry.trackWorkflowExecution(payload);
payload.workflow_id = '2';
await telemetry.trackWorkflowExecution(payload);
await telemetry.trackWorkflowExecution(payload);
expect(spyTrack).toHaveBeenCalledTimes(0);
expect(pulseSpy).toBeCalledTimes(0);
jest.advanceTimersToNextTimer();
execBuffer = telemetry.getCountsBuffer();
expect(pulseSpy).toBeCalledTimes(1);
expect(spyTrack).toHaveBeenCalledTimes(3);
expect(spyTrack).toHaveBeenNthCalledWith(1, 'Workflow execution count', {
event_version: '2',
workflow_id: '1',
manual_error: {
count: 2,
first: testDateTime,
},
manual_success: {
count: 2,
first: testDateTime,
},
prod_error: {
count: 2,
first: testDateTime,
},
prod_success: {
count: 2,
first: testDateTime,
},
});
expect(spyTrack).toHaveBeenNthCalledWith(2, 'Workflow execution count', {
event_version: '2',
workflow_id: '2', workflow_id: '2',
prod_error: { prod_error: {
count: 2, count: 2,
first: testDateTime, first: testDateTime,
} },
}); });
expect(spyTrack).toHaveBeenNthCalledWith(3, 'pulse'); expect(spyTrack).toHaveBeenNthCalledWith(3, 'pulse');
expect(Object.keys(execBuffer).length).toBe(0); expect(Object.keys(execBuffer).length).toBe(0);
jest.advanceTimersToNextTimer(); jest.advanceTimersToNextTimer();
execBuffer = telemetry.getCountsBuffer(); execBuffer = telemetry.getCountsBuffer();
expect(Object.keys(execBuffer).length).toBe(0); expect(Object.keys(execBuffer).length).toBe(0);
expect(pulseSpy).toBeCalledTimes(2); expect(pulseSpy).toBeCalledTimes(2);
expect(spyTrack).toHaveBeenCalledTimes(4); expect(spyTrack).toHaveBeenCalledTimes(4);
expect(spyTrack).toHaveBeenNthCalledWith(4, 'pulse'); expect(spyTrack).toHaveBeenNthCalledWith(4, 'pulse');
}); });
}); });
}); });
const fakeJestSystemTime = (dateTime: string | Date): Date => { const fakeJestSystemTime = (dateTime: string | Date): Date => {
const dt = new Date(dateTime); const dt = new Date(dateTime);
jest.setSystemTime(dt); jest.setSystemTime(dt);
return dt; return dt;
} };