Skip to content

Commit e307e08

Browse files
committed
feat: test coverage reached 100%
1 parent e8f326e commit e307e08

File tree

4 files changed

+126
-1
lines changed

4 files changed

+126
-1
lines changed

src/UDPClusterManager.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,10 @@ export class UDPClusterManager extends ClusterManager {
368368
if (typeof socket.close === 'function') {
369369
socket.removeAllListeners();
370370
socket.close(() => {
371-
socket?.unref();
371+
// unref may be missing or not a function on mocked sockets
372+
if (socket && typeof (socket as any).unref === 'function') {
373+
(socket as any).unref();
374+
}
372375

373376
if (
374377
socketKey
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*!
2+
* ClusteredRedisQueue.addServerWithQueueInitializing default param branch
3+
*/
4+
import './mocks';
5+
import { expect } from 'chai';
6+
import { ClusteredRedisQueue } from '../src';
7+
8+
describe('ClusteredRedisQueue.addServerWithQueueInitializing() default param', () => {
9+
it('should use default initializeQueue=true when second param omitted', async () => {
10+
const cq: any = new ClusteredRedisQueue('CQ-Default', {
11+
logger: console,
12+
cluster: [{ host: '127.0.0.1', port: 6379 }],
13+
});
14+
// prevent any actual start/subscription side-effects
15+
(cq as any).state.started = false;
16+
(cq as any).state.subscription = null;
17+
18+
const server = { host: '192.168.0.1', port: 6380 };
19+
const initializedSpy = new Promise<void>((resolve) => {
20+
cq['clusterEmitter'].once('initialized', () => resolve());
21+
});
22+
23+
// Call without the second argument to hit default "true" branch
24+
(cq as any).addServerWithQueueInitializing(server);
25+
26+
await initializedSpy; // should emit initialized when default is true
27+
28+
// Ensure the server added and queue length updated
29+
expect((cq as any).servers.some((s: any) => s.host === server.host && s.port === server.port)).to.equal(true);
30+
expect((cq as any).queueLength).to.equal((cq as any).imqs.length);
31+
32+
await cq.destroy();
33+
});
34+
});
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*!
2+
* UDPClusterManager missing branches coverage
3+
*/
4+
import './mocks';
5+
import { expect } from 'chai';
6+
import * as sinon from 'sinon';
7+
import { UDPClusterManager } from '../src';
8+
9+
describe('UDPClusterManager - cover remaining branches', () => {
10+
it('serverAliveWait should handle existing.timeout falsy (|| 0) path and remove on timeout', async () => {
11+
// Arrange cluster stub
12+
const server: any = { host: 'h', port: 1, timer: undefined, timeout: undefined, timestamp: undefined };
13+
const cluster: any = {
14+
find: sinon.stub().callsFake((_s: any, _strict?: boolean) => server),
15+
remove: sinon.stub(),
16+
};
17+
18+
// Use fake timers to control setTimeout and Date
19+
const clock = sinon.useFakeTimers();
20+
try {
21+
// make timestamp truthy
22+
clock.tick(1);
23+
// Alive correction > 0 ensures timer is scheduled even if timeout is falsy
24+
(UDPClusterManager as any).serverAliveWait(cluster, server, 1);
25+
// Advance time to trigger setTimeout callback and make delta >= currentTimeout (1ms)
26+
clock.tick(2);
27+
28+
expect(cluster.remove.called).to.equal(true);
29+
} finally {
30+
clock.restore();
31+
}
32+
});
33+
34+
it('destroySocket should call socket.unref() when socket is present', async () => {
35+
// Prepare fake socket with unref
36+
const unref = sinon.spy();
37+
const removeAll = sinon.spy();
38+
const sock: any = {
39+
removeAllListeners: removeAll,
40+
close: (cb: (err?: any) => void) => cb(),
41+
unref,
42+
};
43+
const key = 'test-key';
44+
(UDPClusterManager as any).sockets[key] = sock;
45+
await (UDPClusterManager as any).destroySocket(key, sock);
46+
expect(unref.called).to.equal(true);
47+
expect((UDPClusterManager as any).sockets[key]).to.equal(undefined);
48+
});
49+
50+
it('destroySocket should work when socket.unref() is absent (optional chaining negative branch)', async () => {
51+
const removeAll = sinon.spy();
52+
const sock: any = {
53+
removeAllListeners: removeAll,
54+
close: (cb: (err?: any) => void) => cb(),
55+
// no unref method
56+
};
57+
const key = 'test-key-2';
58+
(UDPClusterManager as any).sockets[key] = sock;
59+
await (UDPClusterManager as any).destroySocket(key, sock);
60+
// should not throw, sockets map cleaned
61+
expect((UDPClusterManager as any).sockets[key]).to.equal(undefined);
62+
});
63+
});
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*!
2+
* UDPClusterManager serverAliveWait: cover currentTimeout left side (existing.timeout truthy)
3+
*/
4+
import './mocks';
5+
import { expect } from 'chai';
6+
import * as sinon from 'sinon';
7+
import { UDPClusterManager } from '../src';
8+
9+
describe('UDPClusterManager.serverAliveWait truthy timeout', () => {
10+
it('should use existing.timeout (truthy) in currentTimeout and remove on expiry', async () => {
11+
const server: any = { host: 'h', port: 1, timer: undefined, timeout: 2, timestamp: undefined };
12+
const cluster: any = {
13+
find: sinon.stub().callsFake((_s: any, _strict?: boolean) => server),
14+
remove: sinon.stub(),
15+
};
16+
const clock = sinon.useFakeTimers();
17+
try {
18+
(UDPClusterManager as any).serverAliveWait(cluster, server, 0);
19+
clock.tick(3);
20+
expect(cluster.remove.called).to.equal(true);
21+
} finally {
22+
clock.restore();
23+
}
24+
});
25+
});

0 commit comments

Comments
 (0)