Skip to content

Commit e8f326e

Browse files
committed
feat: add more tests to improve coverage
1 parent 9433e68 commit e8f326e

File tree

4 files changed

+184
-0
lines changed

4 files changed

+184
-0
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*!
2+
* Additional RedisQueue tests: connect() option fallbacks branches
3+
*/
4+
import './mocks';
5+
import { expect } from 'chai';
6+
import { RedisQueue, IMQMode } from '../src';
7+
8+
function makeLogger() {
9+
return {
10+
log: (..._args: any[]) => undefined,
11+
info: (..._args: any[]) => undefined,
12+
warn: (..._args: any[]) => undefined,
13+
error: (..._args: any[]) => undefined,
14+
} as any;
15+
}
16+
17+
describe('RedisQueue.connect() option fallbacks', function() {
18+
this.timeout(10000);
19+
20+
it('should use fallback values when falsy options are provided', async () => {
21+
const logger = makeLogger();
22+
// Intentionally provide falsy values to trigger `||` fallbacks in connect()
23+
const rq: any = new RedisQueue('ConnFallbacks', {
24+
logger,
25+
port: 0 as unknown as number, // falsy to trigger 6379 fallback
26+
host: '' as unknown as string, // falsy to trigger 'localhost' fallback
27+
prefix: '' as unknown as string, // falsy to trigger '' fallback in connectionName
28+
cleanup: false,
29+
}, IMQMode.BOTH);
30+
31+
await rq.start();
32+
33+
// Basic sanity: writer/reader/watcher are created
34+
expect(Boolean(rq.writer)).to.equal(true);
35+
expect(Boolean(rq.reader)).to.equal(true);
36+
expect(Boolean(rq.watcher)).to.equal(true);
37+
38+
await rq.destroy();
39+
});
40+
});
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*!
2+
* Additional RedisQueue tests: processCleanup connectedKeys filter branches
3+
*/
4+
import './mocks';
5+
import { expect } from 'chai';
6+
import * as sinon from 'sinon';
7+
import { RedisQueue, uuid } from '../src';
8+
9+
describe('RedisQueue.processCleanup connectedKeys RX/filter combinations', function() {
10+
this.timeout(5000);
11+
12+
it('should handle RX_CLIENT_TEST true but filter false case (exclude unmatched prefix)', async () => {
13+
const name = `PCleanRX_${uuid()}`;
14+
const rq: any = new RedisQueue(name, {
15+
logger: console,
16+
cleanup: true,
17+
prefix: 'imqA',
18+
cleanupFilter: '*',
19+
});
20+
21+
await rq.start();
22+
23+
const writer: any = rq.writer;
24+
25+
// Stub client('LIST') to include a writer channel with a different prefix,
26+
// so RX_CLIENT_TEST.test(name) is true but filter.test(name) is false.
27+
const clientStub = sinon.stub(writer, 'client');
28+
clientStub.callsFake(async (cmd: string) => {
29+
if (cmd === 'LIST') {
30+
return [
31+
'id=1 name=imqZ:Other:writer:pid:1:host:x', // RX true, filter false
32+
'id=2 name=imqA:Other:subscription:pid:1:host:x', // RX false, filter true
33+
].join('\n');
34+
}
35+
return true as any;
36+
});
37+
38+
// Return no keys on SCAN to avoid deletions and just walk the branch
39+
const scanStub = sinon.stub(writer, 'scan');
40+
scanStub.resolves(['0', []] as any);
41+
42+
const delSpy = sinon.spy(writer, 'del');
43+
44+
await rq.processCleanup();
45+
46+
expect(delSpy.called).to.equal(false);
47+
48+
clientStub.restore();
49+
scanStub.restore();
50+
delSpy.restore();
51+
await rq.destroy();
52+
});
53+
});
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*!
2+
* Additional RedisQueue tests for processCleanup branches: multi-scan and no-deletion path
3+
*/
4+
import './mocks';
5+
import { expect } from 'chai';
6+
import * as sinon from 'sinon';
7+
import { RedisQueue, uuid } from '../src';
8+
9+
describe('RedisQueue.processCleanup multi-scan/no-delete branches', function() {
10+
this.timeout(5000);
11+
12+
it('should handle multi-page SCAN (cursor != "0" first) and avoid deletion when keys belong to connected clients', async () => {
13+
const name = `PClean_${uuid()}`;
14+
const rq: any = new RedisQueue(name, {
15+
logger: console,
16+
cleanup: true,
17+
prefix: 'imq',
18+
cleanupFilter: '*',
19+
});
20+
21+
await rq.start();
22+
23+
const writer: any = rq.writer;
24+
25+
// Stub scan to first return non-zero cursor with undefined keys (to exercise `|| []`),
26+
// then return zero cursor with keys that include connectedKey (so no removal happens).
27+
const scanStub = sinon.stub(writer, 'scan');
28+
scanStub.onCall(0).resolves(['1', undefined] as any);
29+
scanStub.onCall(1).resolves(['0', [`imq:${name}:reader:pid:123`]] as any);
30+
31+
const delSpy = sinon.spy(writer, 'del');
32+
33+
await rq.processCleanup();
34+
35+
// del should not be called because keysToRemove.length === 0
36+
expect(delSpy.called).to.equal(false);
37+
38+
scanStub.restore();
39+
delSpy.restore();
40+
await rq.destroy();
41+
});
42+
});
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*!
2+
* Additional RedisQueue tests for processCleanup branches: clients.match null and cleanupFilter falsy
3+
*/
4+
import './mocks';
5+
import { expect } from 'chai';
6+
import * as sinon from 'sinon';
7+
import { RedisQueue, uuid } from '../src';
8+
9+
describe('RedisQueue.processCleanup null-match and falsy cleanupFilter', function() {
10+
this.timeout(5000);
11+
12+
it('should handle clients.match returning null and cleanupFilter as falsy (\'\')', async () => {
13+
const name = `PCleanNull_${uuid()}`;
14+
const rq: any = new RedisQueue(name, {
15+
logger: console,
16+
cleanup: true,
17+
prefix: 'imq',
18+
cleanupFilter: '', // falsy to exercise "|| '*'" in both RegExp and SCAN MATCH
19+
});
20+
21+
await rq.start();
22+
23+
const writer: any = rq.writer;
24+
25+
// Force clients.match(...) to return null by stubbing client('LIST') to return a string without 'name='
26+
const clientStub = sinon.stub(writer, 'client');
27+
clientStub.callsFake(async (cmd: string) => {
28+
if (cmd === 'LIST') {
29+
return 'id=1 flags=x'; // no 'name='
30+
}
31+
return true as any;
32+
});
33+
34+
// Ensure SCAN returns no keys, to avoid deletions and just cover the branch paths
35+
const scanStub = sinon.stub(writer, 'scan');
36+
scanStub.resolves(['0', []] as any);
37+
38+
const delSpy = sinon.spy(writer, 'del');
39+
40+
await rq.processCleanup();
41+
42+
expect(delSpy.called).to.equal(false);
43+
44+
clientStub.restore();
45+
scanStub.restore();
46+
delSpy.restore();
47+
await rq.destroy();
48+
});
49+
});

0 commit comments

Comments
 (0)