Skip to content

Commit 0d6f48c

Browse files
author
Artem
committed
#RI-3030, #RI-3032, #RI-3034, #RI-3036 Itests
1 parent c419cb3 commit 0d6f48c

File tree

10 files changed

+507
-21
lines changed

10 files changed

+507
-21
lines changed

redisinsight/api/src/modules/cli/utils/getUnsupportedCommands.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { getUnsupportedCommands } from './getUnsupportedCommands';
22

33
describe('cli unsupported commands', () => {
44
it('should return correct list', () => {
5-
const expectedResult = ['monitor', 'subscribe', 'psubscribe', 'sync', 'psync', 'script debug'];
5+
const expectedResult = ['monitor', 'subscribe', 'psubscribe', 'ssubscribe', 'sync', 'psync', 'script debug'];
66

77
expect(getUnsupportedCommands()).toEqual(expectedResult);
88
});

redisinsight/api/src/modules/profiler/models/log-file.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ export class LogFile {
124124
this.writeStream?.close();
125125
this.writeStream = null;
126126
const size = this.getFileSize();
127-
fs.unlink(this.filePath);
127+
fs.unlinkSync(this.filePath);
128128

129129
this.analyticsEvents.get(TelemetryEvents.ProfilerLogDeleted)(this.instanceId, size);
130130
} catch (e) {

redisinsight/api/src/modules/pub-sub/pub-sub.controller.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {
22
Body,
3-
Controller, Param, Post,
3+
Controller, Param, Post, UsePipes, ValidationPipe
44
} from '@nestjs/common';
55
import { ApiTags } from '@nestjs/swagger';
66
import { ApiRedisInstanceOperation } from 'src/decorators/api-redis-instance-operation.decorator';
@@ -11,6 +11,7 @@ import { PublishResponse } from 'src/modules/pub-sub/dto/publish.response';
1111

1212
@ApiTags('Pub/Sub')
1313
@Controller('pub-sub')
14+
@UsePipes(new ValidationPipe())
1415
export class PubSubController {
1516
constructor(private service: PubSubService) {}
1617

redisinsight/api/src/modules/pub-sub/pub-sub.gateway.ts

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,24 +31,14 @@ export class PubSubGateway implements OnGatewayConnection, OnGatewayDisconnect {
3131

3232
@SubscribeMessage(PubSubClientEvents.Subscribe)
3333
async subscribe(@Client() client: UserClient, @Body() dto: SubscribeDto): Promise<any> {
34-
try {
35-
await this.service.subscribe(client, dto);
36-
return { status: 'ok' };
37-
} catch (e) {
38-
this.logger.error('Unable to subscribe', e);
39-
throw e;
40-
}
34+
await this.service.subscribe(client, dto);
35+
return { status: 'ok' };
4136
}
4237

4338
@SubscribeMessage(PubSubClientEvents.Unsubscribe)
4439
async unsubscribe(@Client() client: UserClient, @Body() dto: SubscribeDto): Promise<any> {
45-
try {
46-
await this.service.unsubscribe(client, dto);
47-
return { status: 'ok' };
48-
} catch (e) {
49-
this.logger.error('Unable to unsubscribe', e);
50-
throw e;
51-
}
40+
await this.service.unsubscribe(client, dto);
41+
return { status: 'ok' };
5242
}
5343

5444
async handleConnection(client: Socket): Promise<void> {

redisinsight/api/src/modules/pub-sub/pub-sub.service.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,12 @@ export class PubSubService {
3333
)));
3434
} catch (e) {
3535
this.logger.error('Unable to create subscriptions', e);
36-
throw e;
36+
37+
if (e instanceof HttpException) {
38+
throw e;
39+
}
40+
41+
throw catchAclError(e);
3742
}
3843
}
3944

@@ -49,7 +54,13 @@ export class PubSubService {
4954
this.subscriptionProvider.createSubscription(userClient, subDto),
5055
)));
5156
} catch (e) {
52-
this.logger.error('Unable to create subscriptions', e);
57+
this.logger.error('Unable to unsubscribe', e);
58+
59+
if (e instanceof HttpException) {
60+
throw e;
61+
}
62+
63+
throw catchAclError(e);
5364
}
5465
}
5566

redisinsight/api/src/modules/workbench/utils/getUnsupportedCommands.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { getUnsupportedCommands } from './getUnsupportedCommands';
22

33
describe('workbench unsupported commands', () => {
44
it('should return correct list', () => {
5-
const expectedResult = ['monitor', 'subscribe', 'psubscribe', 'sync', 'psync', 'script debug', 'select'];
5+
const expectedResult = ['monitor', 'subscribe', 'psubscribe', 'ssubscribe', 'sync', 'psync', 'script debug', 'select'];
66

77
expect(getUnsupportedCommands()).toEqual(expectedResult);
88
});

redisinsight/api/test/api/info/GET-info-cli-unsupported-commands.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ describe('GET /info/cli-unsupported-commands', () => {
2727
name: 'Should return array with unsupported commands for CLI tool',
2828
statusCode: 200,
2929
responseSchema,
30-
responseBody: ['monitor', 'subscribe', 'psubscribe', 'sync', 'psync', 'script debug'],
30+
responseBody: ['monitor', 'subscribe', 'psubscribe', 'ssubscribe', 'sync', 'psync', 'script debug'],
3131
},
3232
].map(mainCheckFn);
3333
});
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
import {
2+
describe,
3+
it,
4+
before,
5+
deps,
6+
Joi,
7+
requirements,
8+
generateInvalidDataTestCases,
9+
validateInvalidDataTestCase,
10+
validateApiCall
11+
} from '../deps';
12+
import { Socket } from 'socket.io-client';
13+
const { server, request, constants, rte, getSocket } = deps;
14+
15+
// endpoint to test
16+
const endpoint = (instanceId = constants.TEST_INSTANCE_ID) =>
17+
request(server).post(`/instance/${instanceId}/pub-sub/messages`);
18+
19+
const dataSchema = Joi.object({
20+
channel: Joi.string().required(),
21+
message: Joi.string().required(),
22+
}).messages({
23+
'any.required': '{#label} should not be empty',
24+
}).strict();
25+
26+
const validInputData = {
27+
channel: constants.TEST_PUB_SUB_CHANNEL_1,
28+
message: constants.TEST_PUB_SUB_MESSAGE_1,
29+
};
30+
31+
const responseSchema = Joi.object().keys({
32+
affected: Joi.number().integer().required().min(0),
33+
}).required().strict();
34+
35+
const mainCheckFn = async (testCase) => {
36+
it(testCase.name, async () => {
37+
// additional checks before test run
38+
if (testCase.before) {
39+
await testCase.before();
40+
}
41+
42+
await validateApiCall({
43+
endpoint,
44+
...testCase,
45+
});
46+
47+
// additional checks after test pass
48+
if (testCase.after) {
49+
await testCase.after();
50+
}
51+
});
52+
};
53+
54+
const getClient = async (instanceId): Promise<Socket> => {
55+
return getSocket('pub-sub', {
56+
query: { instanceId },
57+
});
58+
};
59+
60+
const pSubscription = {
61+
channel: '*',
62+
type: 'p',
63+
};
64+
65+
let client;
66+
67+
describe('POST /instance/:instanceId/pub-sub/messages', () => {
68+
describe('Validation', () => {
69+
generateInvalidDataTestCases(dataSchema, validInputData).map(
70+
validateInvalidDataTestCase(endpoint, dataSchema),
71+
);
72+
});
73+
74+
describe('Common', () => {
75+
beforeEach(async () => {
76+
client = await getClient(constants.TEST_INSTANCE_ID);
77+
await new Promise((res) => {
78+
client.emit('subscribe', { subscriptions: [pSubscription] }, res);
79+
});
80+
});
81+
82+
afterEach(async () => {
83+
client.close();
84+
});
85+
86+
[
87+
{
88+
name: 'Should send message',
89+
data: {
90+
...validInputData,
91+
},
92+
responseSchema,
93+
statusCode: 201,
94+
responseBody: {
95+
affected: 1,
96+
},
97+
},
98+
{
99+
name: 'Should return NotFound error if instance id does not exists',
100+
endpoint: () => endpoint(constants.TEST_NOT_EXISTED_INSTANCE_ID),
101+
data: {
102+
...validInputData,
103+
},
104+
statusCode: 404,
105+
responseBody: {
106+
statusCode: 404,
107+
error: 'Not Found',
108+
message: 'Invalid database instance id.',
109+
},
110+
},
111+
].map(mainCheckFn);
112+
});
113+
114+
describe('ACL', () => {
115+
requirements('rte.acl');
116+
117+
before(async () => await rte.data.generateKeys(true));
118+
before(async () => rte.data.setAclUserRules('~* +@all'));
119+
120+
[
121+
{
122+
name: 'Should publish method',
123+
endpoint: () => endpoint(constants.TEST_INSTANCE_ACL_ID),
124+
statusCode: 201,
125+
data: {
126+
...validInputData,
127+
},
128+
},
129+
{
130+
name: 'Should throw error if no permissions for "publish" command',
131+
endpoint: () => endpoint(constants.TEST_INSTANCE_ACL_ID),
132+
data: {
133+
...validInputData,
134+
},
135+
statusCode: 403,
136+
responseBody: {
137+
statusCode: 403,
138+
error: 'Forbidden',
139+
},
140+
before: () => rte.data.setAclUserRules('~* +@all -publish')
141+
},
142+
].map(mainCheckFn);
143+
});
144+
});

0 commit comments

Comments
 (0)