Skip to content

Commit cb3b77f

Browse files
Be/feature/broken itests (#5102)
* RI-7583: fix ITests
1 parent dc4d1f9 commit cb3b77f

28 files changed

+953
-457
lines changed

.github/workflows/tests-integration.yml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,13 @@ env:
5050
TEST_MEDIUM_DB_DUMP: ${{ secrets.TEST_MEDIUM_DB_DUMP }}
5151
TEST_BIG_DB_DUMP: ${{ secrets.TEST_BIG_DB_DUMP }}
5252
REPORT_NAME: 'report-it'
53+
# Disabled RTE for now. Need to prepare reasonable dataset to not take so much time for tests.
54+
# "oss-st-big": "OSS Standalone v6 and all modules and predefined amount of data inside (~3-4M)",
5355
ITESTS_NAMES: |
5456
{
5557
"oss-st-5": "OSS Standalone v5",
5658
"oss-st-5-pass": "OSS Standalone v5 with admin pass required",
5759
"oss-st-6": "OSS Standalone v6 and all modules",
58-
"oss-st-big": "OSS Standalone v6 and all modules and predefined amount of data inside (~3-4M)",
5960
"mods-preview": "OSS Standalone and all preview modules",
6061
"oss-st-6-tls": "OSS Standalone v6 with TLS enabled",
6162
"oss-st-6-tls-auth": "OSS Standalone v6 with TLS auth required",
@@ -153,6 +154,15 @@ jobs:
153154
cp ./redisinsight/api/test/test-runs/coverage/test-run-result.xml ./itest/results/${{ matrix.rte }}.result.xml
154155
cp ./redisinsight/api/test/test-runs/coverage/test-run-coverage.json ./itest/coverages/${{ matrix.rte }}.coverage.json
155156
157+
- name: Process test results
158+
if: always()
159+
run: |
160+
mkdir -p itest/coverages && mkdir -p itest/results
161+
162+
cp ./redisinsight/api/test/test-runs/coverage/test-run-result.json ./itest/results/${{ matrix.rte }}.result.json
163+
cp ./redisinsight/api/test/test-runs/coverage/test-run-result.xml ./itest/results/${{ matrix.rte }}.result.xml
164+
cp ./redisinsight/api/test/test-runs/coverage/test-run-coverage.json ./itest/coverages/${{ matrix.rte }}.coverage.json
165+
156166
- name: Upload coverage files as artifact
157167
if: always()
158168
uses: actions/upload-artifact@v4
@@ -230,7 +240,7 @@ jobs:
230240
reporter: java-junit
231241
list-tests: 'failed'
232242
list-suites: 'failed'
233-
fail-on-error: 'false'
243+
fail-on-error: 'true'
234244

235245
- name: Add link to report in the workflow summary
236246
if: always()

redisinsight/api/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js -d ./config/ormconfig.ts",
3535
"test:api": "cross-env NODE_ENV=test ts-mocha --paths --config ./test/api/.mocharc.yml",
3636
"test:api:cov": "nyc --reporter=html --reporter=text --reporter=text-summary yarn run test:api",
37-
"test:api:ci:cov": "cross-env NODE_ENV=test nyc --temp-dir coverage/.nyc_output --report-dir coverage --instrument -r text -r text-summary -r html yarn run test:api --reporter mocha-multi-reporters --reporter-options configFile=test/api/reporters.json; echo 'Exit code from tests:' $? > coverage/debug.log; echo 'NYC tests completed, checking .nyc_output...' >> coverage/debug.log; ls -la coverage/.nyc_output >> coverage/debug.log 2>&1; echo 'Running NYC merge...' >> coverage/debug.log; nyc merge coverage/.nyc_output coverage/test-run-coverage.json >> coverage/debug.log 2>&1; echo 'NYC merge exit code:' $? >> coverage/debug.log; echo 'NYC merge completed!' >> coverage/debug.log; ls -la coverage/test-run-coverage.json >> coverage/debug.log 2>&1",
37+
"test:api:ci:cov": "cross-env nyc -r text -r text-summary -r html yarn run test:api --reporter mocha-multi-reporters --reporter-options configFile=test/api/reporters.json && nyc merge .nyc_output ./coverage/test-run-coverage.json",
3838
"typeorm:migrate": "cross-env NODE_ENV=staging yarn typeorm migration:generate ./migration/migration",
3939
"typeorm:run": "yarn typeorm migration:run",
4040
"typeorm:run:stage": "cross-env NODE_ENV=staging yarn typeorm migration:run"

redisinsight/api/src/modules/cloud/common/exceptions/cloud-api.error.handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const wrapCloudApiError = (
2323
}
2424

2525
if (response) {
26-
const errorOptions = { cause: new Error(response?.data as string) };
26+
const errorOptions = { cause: response?.data };
2727
switch (response?.status) {
2828
case 401:
2929
return new CloudApiUnauthorizedException(errorMessage, errorOptions);

redisinsight/api/src/modules/cloud/common/exceptions/cloud-capi.error.handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const wrapCloudCapiError = (
1313

1414
if (error.response?.status === 401) {
1515
return new CloudCapiUnauthorizedException(message || error.message, {
16-
cause: new Error(error.response?.data as string),
16+
cause: error.response?.data,
1717
});
1818
}
1919

redisinsight/api/src/modules/database/providers/database.factory.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ describe('DatabaseFactory', () => {
9898
await service.createDatabaseModel(mockSessionMetadata, mockDatabase);
9999
fail();
100100
} catch (e) {
101-
expect(e.message).toEqual(RedisErrorCodes.SentinelParamsRequired);
101+
expect(e.message).toEqual(ERROR_MESSAGES.SENTINEL_MASTER_NAME_REQUIRED);
102102
}
103103
});
104104
it('should create cluster database model', async () => {

redisinsight/api/src/modules/database/providers/database.factory.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
ConnectionType,
55
HostingProvider,
66
} from 'src/modules/database/entities/database.entity';
7-
import { getHostingProvider } from 'src/utils';
7+
import { getHostingProvider, getRedisConnectionException } from 'src/utils';
88
import { Database } from 'src/modules/database/models/database';
99
import { ClientContext, SessionMetadata } from 'src/common/models';
1010
import ERROR_MESSAGES from 'src/constants/error-messages';
@@ -23,6 +23,7 @@ import {
2323
isSentinel,
2424
} from 'src/modules/redis/utils';
2525
import { RedisClient } from 'src/modules/redis/client';
26+
import { ReplyError } from 'src/models';
2627

2728
@Injectable()
2829
export class DatabaseFactory {
@@ -66,7 +67,10 @@ export class DatabaseFactory {
6667

6768
if (await isSentinel(client)) {
6869
if (!database.sentinelMaster) {
69-
throw new Error(RedisErrorCodes.SentinelParamsRequired);
70+
throw getRedisConnectionException(
71+
new ReplyError(RedisErrorCodes.SentinelParamsRequired),
72+
database,
73+
);
7074
}
7175
model = await this.createSentinelDatabaseModel(
7276
sessionMetadata,

redisinsight/api/src/utils/logsFormatter.spec.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,16 @@ import {
1414
sanitizeErrors,
1515
} from './logsFormatter';
1616

17+
const stringCause = 'string cause';
18+
const objectCause = { object: 'cause' };
1719
const simpleError = new Error('Original error');
1820
simpleError['some'] = 'field';
21+
const errorWithStringCause = new NotFoundException('Not found', {
22+
cause: stringCause,
23+
});
24+
const errorWithObjectCause = new NotFoundException('Not found', {
25+
cause: objectCause,
26+
});
1927
const errorWithCause = new NotFoundException('Not found', {
2028
cause: simpleError,
2129
});
@@ -26,6 +34,10 @@ const errorWithCauseDepth3 = new CloudOauthMisconfigurationException(
2634
'Misconfigured',
2735
{ cause: errorWithCauseDepth2 },
2836
);
37+
const errorWithObjectCauseDepth = new CloudOauthMisconfigurationException(
38+
'Misconfigured',
39+
{ cause: errorWithObjectCause },
40+
);
2941
const axiosError = new AxiosError(
3042
'Request failed with status code 404',
3143
'NOT_FOUND',
@@ -132,8 +144,18 @@ describe('logsFormatter', () => {
132144
expect(getOriginalErrorCause(errorWithCauseDepth3)).toEqual(simpleError);
133145
});
134146

135-
it('should return undefined if input is not an Error instance', () => {
136-
expect(getOriginalErrorCause({ cause: simpleError })).toEqual(undefined);
147+
it('should return simple error if it is last in the chain and only the one in cause', () => {
148+
expect(getOriginalErrorCause({ cause: simpleError })).toEqual(
149+
simpleError,
150+
);
151+
});
152+
153+
it('should return string as cause', () => {
154+
expect(getOriginalErrorCause(errorWithStringCause)).toEqual(stringCause);
155+
});
156+
157+
it('should return object as cause', () => {
158+
expect(getOriginalErrorCause(errorWithObjectCause)).toEqual(objectCause);
137159
});
138160

139161
it('should not fail if input is not specified', () => {
@@ -170,6 +192,16 @@ describe('logsFormatter', () => {
170192
});
171193
});
172194

195+
it('should return sanitized object with a single original cause for nested errors', () => {
196+
expect(
197+
sanitizeError(errorWithObjectCauseDepth, { omitSensitiveData: true }),
198+
).toEqual({
199+
type: 'CloudOauthMisconfigurationException',
200+
message: errorWithObjectCauseDepth.message,
201+
cause: objectCause,
202+
});
203+
});
204+
173205
it('should return sanitized object with a single original cause for nested errors (with stack)', () => {
174206
expect(sanitizeError(errorWithCauseDepth3)).toEqual({
175207
type: 'CloudOauthMisconfigurationException',

redisinsight/api/src/utils/logsFormatter.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,13 @@ type SanitizedError = {
1414
type: string;
1515
message: string;
1616
stack?: string;
17-
cause?: ReturnType<typeof sanitizeError>;
17+
cause?: unknown;
1818
};
1919

20-
export const getOriginalErrorCause = (cause: unknown): Error | undefined => {
21-
if (cause instanceof Error) {
22-
return getOriginalErrorCause((cause as any).cause) || cause;
20+
export const getOriginalErrorCause = (cause: unknown): unknown => {
21+
if (cause) {
22+
return getOriginalErrorCause(cause['cause']) || cause;
2323
}
24-
return undefined;
2524
};
2625

2726
export const sanitizeError = (
@@ -30,11 +29,17 @@ export const sanitizeError = (
3029
): SanitizedError | undefined => {
3130
if (!error) return undefined;
3231

32+
let cause = getOriginalErrorCause(error['cause']);
33+
34+
if (cause instanceof Error) {
35+
cause = sanitizeError(cause, opts);
36+
}
37+
3338
return {
3439
type: error.constructor?.name ?? 'UnknownError',
3540
message: String(error.message ?? 'Unknown error'),
3641
stack: opts.omitSensitiveData ? undefined : error.stack,
37-
cause: sanitizeError(getOriginalErrorCause((error as any).cause), opts),
42+
cause,
3843
};
3944
};
4045

@@ -86,7 +91,11 @@ export const prettyFileFormat = format.printf((info) => {
8691
});
8792

8893
const MAX_DEPTH = 10;
89-
export const logDataToPlain = (value: any, seen = new WeakSet(), depth = 0): any => {
94+
export const logDataToPlain = (
95+
value: any,
96+
seen = new WeakSet(),
97+
depth = 0,
98+
): any => {
9099
if (depth > MAX_DEPTH) return '[MaxDepthExceeded]';
91100

92101
if (value === null || typeof value !== 'object' || value instanceof Error) {

redisinsight/api/test/api/cloud/autodiscovery/POST-cloud-autodiscovery-databases.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,9 @@ describe('POST /cloud/autodiscovery/databases', () => {
174174
`/fixed/subscriptions/${mockImportCloudDatabaseDtoFixed.subscriptionId}/databases/${mockImportCloudDatabaseDtoFixed.databaseId}`,
175175
)
176176
.replyWithError({
177+
message: 'Unauthorized for this action',
177178
response: {
178179
status: 403,
179-
data: { message: 'Unauthorized for this action' },
180180
},
181181
});
182182
},
@@ -206,6 +206,7 @@ describe('POST /cloud/autodiscovery/databases', () => {
206206
`/subscriptions/${mockImportCloudDatabaseDto.subscriptionId}/databases/${mockImportCloudDatabaseDto.databaseId}`,
207207
)
208208
.replyWithError({
209+
message: ERROR_MESSAGES.UNAUTHORIZED,
209210
response: {
210211
status: 401,
211212
data: '',
@@ -238,9 +239,10 @@ describe('POST /cloud/autodiscovery/databases', () => {
238239
`/subscriptions/${mockImportCloudDatabaseDto.subscriptionId}/databases/${mockImportCloudDatabaseDto.databaseId}`,
239240
)
240241
.replyWithError({
242+
message: ERROR_MESSAGES.NOT_FOUND,
241243
response: {
242244
status: 404,
243-
data: 'Database was not found',
245+
data: ERROR_MESSAGES.NOT_FOUND,
244246
},
245247
});
246248
},

redisinsight/api/test/api/cloud/autodiscovery/POST-cloud-autodiscovery-get_databases.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,9 @@ describe('POST /cloud/autodiscovery/get-databases', () => {
154154
`/subscriptions/${mockGetCloudSubscriptionDatabasesDto.subscriptionId}/databases`,
155155
)
156156
.replyWithError({
157+
message: 'Unauthorized for this action',
157158
response: {
158159
status: 403,
159-
data: { message: 'Unauthorized for this action' },
160160
},
161161
});
162162
},
@@ -180,9 +180,9 @@ describe('POST /cloud/autodiscovery/get-databases', () => {
180180
`/subscriptions/${mockGetCloudSubscriptionDatabasesDto.subscriptionId}/databases`,
181181
)
182182
.replyWithError({
183+
message: ERROR_MESSAGES.UNAUTHORIZED,
183184
response: {
184185
status: 401,
185-
data: '',
186186
},
187187
});
188188
},
@@ -206,6 +206,7 @@ describe('POST /cloud/autodiscovery/get-databases', () => {
206206
`/subscriptions/${mockGetCloudSubscriptionDatabasesDto.subscriptionId}/databases`,
207207
)
208208
.replyWithError({
209+
message: ERROR_MESSAGES.NOT_FOUND,
209210
response: {
210211
status: 404,
211212
data: 'Subscription is not found',

0 commit comments

Comments
 (0)