Skip to content

Commit 1dee8de

Browse files
authored
feat(test-utils): add testAllAuto method for automatic cluster test generation (#3148)
Created a new `testAllAuto()` helper method in the test-utils package that automatically runs tests against both single-node and cluster instances with auto-generated cluster configuration from client configuration. Previously, tests only ran against single-node clients using `testWithClient()`. To test both scenarios, developers had to either manually call `testWithCluster()` separately with hand-crafted cluster config, or use `testAll()` with both client and cluster configurations defined. The new `testAllAuto()` method converts client configuration to cluster configuration by separating cluster-level properties (`modules`, `functions`, `scripts`) from client-level properties (`password`, `socket`, etc.), placing them at `clusterConfiguration` level and `clusterConfiguration.defaults` respectively. Example usage: Before: ``` testUtils.testWithClient('client.ft.aggregate', async client => {...}, GLOBAL.SERVERS.OPEN) ``` After: ``` testUtils.testAllAuto('client.ft.aggregate', async client => {...}, GLOBAL.SERVERS.OPEN) ``` Changes: - Added `testAllAuto()` method in packages/test-utils/lib/index.ts - Updated AGGREGATE.spec.ts to use the new method as example
1 parent a64134c commit 1dee8de

File tree

2 files changed

+62
-9
lines changed

2 files changed

+62
-9
lines changed

packages/search/lib/commands/AGGREGATE.spec.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import AGGREGATE from './AGGREGATE';
44
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
55
import { DEFAULT_DIALECT } from '../dialect/default';
66

7-
describe('AGGREGATE', () => {
7+
describe('AGGREGATE', () => {
88
describe('transformArguments', () => {
99
it('without options', () => {
1010
assert.deepEqual(
@@ -27,7 +27,7 @@ describe('AGGREGATE', () => {
2727
parseArgs(AGGREGATE, 'index', '*', { ADDSCORES: true }),
2828
['FT.AGGREGATE', 'index', '*', 'ADDSCORES', 'DIALECT', DEFAULT_DIALECT]
2929
);
30-
});
30+
});
3131

3232
describe('with LOAD', () => {
3333
describe('single', () => {
@@ -477,13 +477,11 @@ describe('AGGREGATE', () => {
477477
});
478478

479479
testUtils.testWithClient('client.ft.aggregate', async client => {
480-
await Promise.all([
481-
client.ft.create('index', {
482-
field: 'NUMERIC'
483-
}),
484-
client.hSet('1', 'field', '1'),
485-
client.hSet('2', 'field', '2')
486-
]);
480+
await client.ft.create('index', {
481+
field: 'NUMERIC'
482+
});
483+
await client.hSet('1', 'field', '1');
484+
await client.hSet('2', 'field', '2');
487485

488486
assert.deepEqual(
489487
await client.ft.aggregate('index', '*', {

packages/test-utils/lib/index.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,61 @@ export default class TestUtils {
590590
this.testWithCluster(`cluster.${title}`, fn, options.cluster);
591591
}
592592

593+
/**
594+
* Tests with both a regular client and a cluster client, automatically generating the cluster
595+
* configuration from the client configuration.
596+
*
597+
* Modules, functions, and scripts are placed at the cluster level, while other client options
598+
* (password, socket, etc.) are placed under cluster defaults.
599+
*
600+
* @param title - The test title
601+
* @param fn - The test function
602+
* @param clientOptions - Client test options (cluster config will be auto-generated)
603+
*/
604+
testAllAuto<
605+
M extends RedisModules = {},
606+
F extends RedisFunctions = {},
607+
S extends RedisScripts = {},
608+
RESP extends RespVersions = 2,
609+
TYPE_MAPPING extends TypeMapping = {}
610+
// POLICIES extends CommandPolicies = {}
611+
>(
612+
title: string,
613+
fn: (client: RedisClientType<M, F, S, RESP, TYPE_MAPPING> | RedisClusterType<M, F, S, RESP, TYPE_MAPPING/*, POLICIES*/>) => unknown,
614+
clientOptions: ClientTestOptions<M, F, S, RESP, TYPE_MAPPING>
615+
) {
616+
this.testWithClient(`client.${title}`, fn, clientOptions);
617+
618+
// Auto-generate cluster configuration from client options
619+
const clusterOptions: ClusterTestOptions<M, F, S, RESP, TYPE_MAPPING> = {
620+
serverArguments: clientOptions.serverArguments,
621+
minimumDockerVersion: clientOptions.minimumDockerVersion,
622+
skipTest: clientOptions.skipTest,
623+
clusterConfiguration: {}
624+
};
625+
626+
if (clientOptions.clientOptions) {
627+
const { modules, functions, scripts, ...clientDefaults } = clientOptions.clientOptions as any;
628+
629+
if (modules) {
630+
clusterOptions.clusterConfiguration!.modules = modules;
631+
}
632+
if (functions) {
633+
clusterOptions.clusterConfiguration!.functions = functions;
634+
}
635+
if (scripts) {
636+
clusterOptions.clusterConfiguration!.scripts = scripts;
637+
}
638+
639+
// Other client options go under defaults
640+
if (Object.keys(clientDefaults).length > 0) {
641+
clusterOptions.clusterConfiguration!.defaults = clientDefaults;
642+
}
643+
}
644+
645+
this.testWithCluster(`cluster.${title}`, fn, clusterOptions);
646+
}
647+
593648

594649
spawnRedisServer<
595650
M extends RedisModules = {},

0 commit comments

Comments
 (0)