Skip to content

Commit 483e072

Browse files
committed
churn(test) WIP update various commands to work with 8
1 parent 93b95c9 commit 483e072

10 files changed

+325
-229
lines changed

packages/client/lib/commands/GEOPOS.spec.ts

Lines changed: 133 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,149 @@ describe('GEOPOS', () => {
3232

3333
testUtils.testAll('geoPos with member', async client => {
3434
const coordinates = {
35-
longitude: '-122.06429868936538696',
36-
latitude: '37.37749628831998194'
35+
longitude: '-122.06429868936539',
36+
latitude: '37.37749628831998'
3737
};
3838

3939
await client.geoAdd('key', {
4040
member: 'member',
4141
...coordinates
4242
});
4343

44-
assert.deepEqual(
45-
await client.geoPos('key', 'member'),
46-
[coordinates]
44+
const result = await client.geoPos('key', 'member');
45+
46+
/**
47+
* - Redis < 8: Returns coordinates with 14 decimal places (e.g., "-122.06429868936539")
48+
* - Redis 8+: Returns coordinates with 17 decimal places (e.g., "-122.06429868936538696")
49+
*
50+
*/
51+
const PRECISION = 13; // Number of decimal places to compare
52+
53+
assert.ok(result.length === 1, 'Expected one result');
54+
55+
assert.ok(
56+
compareWithPrecision(result[0].longitude, coordinates.longitude, PRECISION),
57+
`Longitude mismatch: ${result[0].longitude} vs ${coordinates.longitude}`
58+
);
59+
assert.ok(
60+
compareWithPrecision(result[0].latitude, coordinates.latitude, PRECISION),
61+
`Latitude mismatch: ${result[0].latitude} vs ${coordinates.latitude}`
4762
);
4863
}, {
4964
client: GLOBAL.SERVERS.OPEN,
5065
cluster: GLOBAL.CLUSTERS.OPEN
5166
});
5267
});
68+
69+
describe('compareWithPrecision', () => {
70+
it('should match exact same numbers', () => {
71+
assert.strictEqual(
72+
compareWithPrecision('123.456789', '123.456789', 6),
73+
true
74+
);
75+
});
76+
77+
it('should match when actual has more precision than needed', () => {
78+
assert.strictEqual(
79+
compareWithPrecision('123.456789123456', '123.456789', 6),
80+
true
81+
);
82+
});
83+
84+
it('should match when expected has more precision than needed', () => {
85+
assert.strictEqual(
86+
compareWithPrecision('123.456789', '123.456789123456', 6),
87+
true
88+
);
89+
});
90+
91+
it('should fail when decimals differ within precision', () => {
92+
assert.strictEqual(
93+
compareWithPrecision('123.456689', '123.456789', 6),
94+
false
95+
);
96+
});
97+
98+
it('should handle negative numbers', () => {
99+
assert.strictEqual(
100+
compareWithPrecision('-122.06429868936538', '-122.06429868936539', 13),
101+
true
102+
);
103+
});
104+
105+
it('should fail when integer parts differ', () => {
106+
assert.strictEqual(
107+
compareWithPrecision('124.456789', '123.456789', 6),
108+
false
109+
);
110+
});
111+
112+
it('should handle zero decimal places', () => {
113+
assert.strictEqual(
114+
compareWithPrecision('123.456789', '123.456789', 0),
115+
true
116+
);
117+
});
118+
119+
it('should handle numbers without decimal points', () => {
120+
assert.strictEqual(
121+
compareWithPrecision('123', '123', 6),
122+
true
123+
);
124+
});
125+
126+
it('should handle one number without decimal point', () => {
127+
assert.strictEqual(
128+
compareWithPrecision('123', '123.000', 3),
129+
false
130+
);
131+
});
132+
133+
it('should match Redis coordinates with different precision', () => {
134+
assert.strictEqual(
135+
compareWithPrecision(
136+
'-122.06429868936538696',
137+
'-122.06429868936539',
138+
13
139+
),
140+
true
141+
);
142+
});
143+
144+
it('should match Redis latitude with different precision', () => {
145+
assert.strictEqual(
146+
compareWithPrecision(
147+
'37.37749628831998194',
148+
'37.37749628831998',
149+
14
150+
),
151+
true
152+
);
153+
});
154+
});
155+
156+
// Helper function to compare with fixed decimal places
157+
const compareWithPrecision = (actual, expected, decimals) => {
158+
const actualDotIndex = actual.indexOf('.');
159+
const expectedDotIndex = expected.indexOf('.');
160+
161+
// If either number doesn't have a decimal point
162+
if (actualDotIndex === -1 || expectedDotIndex === -1) {
163+
// If both don't have decimal points, compare directly
164+
if (actualDotIndex === -1 && expectedDotIndex === -1) {
165+
return actual === expected;
166+
}
167+
// If only one has a decimal point, add .000... to the other
168+
const withoutDecimal = actualDotIndex === -1 ? actual : expected;
169+
const withDecimal = actualDotIndex === -1 ? expected : actual;
170+
return compareWithPrecision(withoutDecimal + '.0', withDecimal, decimals);
171+
}
172+
173+
const integerPart = actual.slice(0, actualDotIndex);
174+
const decimalPart = actual.slice(actualDotIndex + 1, actualDotIndex + 1 + decimals);
175+
176+
const expectedIntegerPart = expected.slice(0, expectedDotIndex);
177+
const expectedDecimalPart = expected.slice(expectedDotIndex + 1, expectedDotIndex + 1 + decimals);
178+
179+
return integerPart === expectedIntegerPart && decimalPart === expectedDecimalPart;
180+
};

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,14 @@ describe('INFO', () => {
2424
index_name: 'index',
2525
index_options: [],
2626
index_definition: Object.create(null, {
27-
default_score: {
27+
28+
indexes_all: {
29+
value: 'false',
30+
configurable: true,
31+
enumerable: true
32+
},
33+
34+
default_score: {
2835
value: '1',
2936
configurable: true,
3037
enumerable: true

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

Lines changed: 60 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,43 +6,67 @@ import { SCHEMA_FIELD_TYPE } from './CREATE';
66
import { parseArgs } from '@redis/client/lib/commands/generic-transformers';
77

88
describe('PROFILE AGGREGATE', () => {
9-
describe('transformArguments', () => {
10-
it('without options', () => {
11-
assert.deepEqual(
12-
parseArgs(PROFILE_AGGREGATE, 'index', 'query'),
13-
['FT.PROFILE', 'index', 'AGGREGATE', 'QUERY', 'query']
14-
);
15-
});
9+
describe('transformArguments', () => {
10+
it('without options', () => {
11+
assert.deepEqual(
12+
parseArgs(PROFILE_AGGREGATE, 'index', 'query'),
13+
['FT.PROFILE', 'index', 'AGGREGATE', 'QUERY', 'query']
14+
);
15+
});
1616

17-
it('with options', () => {
18-
assert.deepEqual(
19-
parseArgs(PROFILE_AGGREGATE, 'index', 'query', {
20-
LIMITED: true,
21-
VERBATIM: true,
22-
STEPS: [{
23-
type: FT_AGGREGATE_STEPS.SORTBY,
24-
BY: '@by'
25-
}]
26-
}),
27-
['FT.PROFILE', 'index', 'AGGREGATE', 'LIMITED', 'QUERY', 'query',
28-
'VERBATIM', 'SORTBY', '1', '@by']
29-
);
30-
});
17+
it('with options', () => {
18+
assert.deepEqual(
19+
parseArgs(PROFILE_AGGREGATE, 'index', 'query', {
20+
LIMITED: true,
21+
VERBATIM: true,
22+
STEPS: [{
23+
type: FT_AGGREGATE_STEPS.SORTBY,
24+
BY: '@by'
25+
}]
26+
}),
27+
['FT.PROFILE', 'index', 'AGGREGATE', 'LIMITED', 'QUERY', 'query',
28+
'VERBATIM', 'SORTBY', '1', '@by']
29+
);
3130
});
31+
});
32+
33+
testUtils.testWithClient('client.ft.search', async client => {
34+
await Promise.all([
35+
client.ft.create('index', {
36+
field: SCHEMA_FIELD_TYPE.NUMERIC
37+
}),
38+
client.hSet('1', 'field', '1'),
39+
client.hSet('2', 'field', '2')
40+
]);
41+
42+
43+
const normalizeObject = obj => JSON.parse(JSON.stringify(obj));
44+
const res = await client.ft.profileAggregate('index', '*');
45+
46+
assert.deepEqual(
47+
normalizeObject({
48+
results: {
49+
total: 1,
50+
results: [{}, {}]
51+
},
52+
profile: [
53+
'Shards',
54+
[[
55+
'Total profile time', '0',
56+
'Parsing time', '0',
57+
'Pipeline creation time', '0',
58+
'Warning', 'None',
59+
'Iterators profile',
60+
['Type', 'WILDCARD', 'Time', '0', 'Counter', 2],
61+
'Result processors profile',
62+
[['Type', 'Index', 'Time', '0', 'Counter', 2]]
63+
]],
64+
'Coordinator',
65+
[]
66+
]
67+
}),
68+
normalizeObject(res)
69+
);
3270

33-
testUtils.testWithClient('client.ft.search', async client => {
34-
await Promise.all([
35-
client.ft.create('index', {
36-
field: SCHEMA_FIELD_TYPE.NUMERIC
37-
}),
38-
client.hSet('1', 'field', '1'),
39-
client.hSet('2', 'field', '2')
40-
]);
41-
42-
const res = await client.ft.profileAggregate('index', '*');
43-
assert.deepEqual('None', res.profile.warning);
44-
assert.ok(typeof res.profile.iteratorsProfile.counter === 'number');
45-
assert.ok(typeof res.profile.parsingTime === 'string');
46-
assert.ok(res.results.total == 1);
47-
}, GLOBAL.SERVERS.OPEN);
71+
}, GLOBAL.SERVERS.OPEN);
4872
});
Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,38 @@
11
import { CommandParser } from '@redis/client/dist/lib/client/parser';
2-
import { Command, ReplyUnion } from "@redis/client/dist/lib/RESP/types";
3-
import AGGREGATE, { AggregateRawReply, FtAggregateOptions, parseAggregateOptions } from "./AGGREGATE";
4-
import { ProfileOptions, ProfileRawReply, ProfileReply, transformProfile } from "./PROFILE_SEARCH";
5-
2+
import { Command, ReplyUnion, Resp2Reply, UnwrapReply } from '@redis/client/dist/lib/RESP/types';
3+
import AGGREGATE, { AggregateRawReply, FtAggregateOptions, parseAggregateOptions } from './AGGREGATE';
4+
import { ProfileOptions, ProfileRawReply, ProfileReply, } from './PROFILE_SEARCH';
5+
export interface TransformReplyType {
6+
2: (reply: UnwrapReply<Resp2Reply<ProfileRawReply<AggregateRawReply>>>) => ProfileReply;
7+
3: () => ReplyUnion;
8+
}
69
export default {
710
NOT_KEYED_COMMAND: true,
8-
IS_READ_ONLY: true,
9-
parseCommand(
10-
parser: CommandParser,
11-
index: string,
12-
query: string,
13-
options?: ProfileOptions & FtAggregateOptions
14-
) {
15-
parser.push('FT.PROFILE', index, 'AGGREGATE');
16-
17-
if (options?.LIMITED) {
18-
parser.push('LIMITED');
19-
}
20-
21-
parser.push('QUERY', query);
11+
IS_READ_ONLY: true,
12+
parseCommand(
13+
parser: CommandParser,
14+
index: string,
15+
query: string,
16+
options?: ProfileOptions & FtAggregateOptions
17+
) {
18+
parser.push('FT.PROFILE', index, 'AGGREGATE');
2219

23-
parseAggregateOptions(parser, options)
24-
},
25-
transformReply: {
26-
2: (reply: ProfileAggeregateRawReply): ProfileReply => {
27-
return {
28-
results: AGGREGATE.transformReply[2](reply[0]),
29-
profile: transformProfile(reply[1])
30-
}
31-
},
32-
3: undefined as unknown as () => ReplyUnion
33-
},
34-
unstableResp3: true
35-
} as const satisfies Command;
20+
if (options?.LIMITED) {
21+
parser.push('LIMITED');
22+
}
3623

37-
type ProfileAggeregateRawReply = ProfileRawReply<AggregateRawReply>;
24+
parser.push('QUERY', query);
25+
26+
parseAggregateOptions(parser, options)
27+
},
28+
transformReply: {
29+
2: (reply: UnwrapReply<Resp2Reply<ProfileRawReply<AggregateRawReply>>>): ProfileReply => {
30+
return {
31+
results: AGGREGATE.transformReply[2](reply[0]),
32+
profile: reply[1]
33+
}
34+
},
35+
3: undefined as unknown as () => ReplyUnion
36+
} as TransformReplyType,
37+
unstableResp3: true
38+
} as const satisfies Command;

0 commit comments

Comments
 (0)