Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"es6": true,
"jest": true
},
"ignorePatterns": ["__tests__/**/*"],
"rules": {
"valid-jsdoc": ["error", { "requireReturn": false }],
"consistent-return": 0,
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
### Added
- `skippedIsNotIssue` option to not mark skipped tests as 'To Investigate' in ReportPortal.
### Fixed
- Error for empty `restClientConfig` while using HTTP retries.

## [5.5.7] - 2025-12-09
### Changed
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ rpClient.checkConnect().then(() => {
| restClientConfig | Optional | Not set | Check the details in the [HTTP client config](#http-client-options). |
| launchUuidPrint | Optional | false | Whether to print the current launch UUID. |
| launchUuidPrintOutput | Optional | 'STDOUT' | Launch UUID printing output. Possible values: 'STDOUT', 'STDERR', 'FILE', 'ENVIRONMENT'. Works only if `launchUuidPrint` set to `true`. File format: `rp-launch-uuid-${launch_uuid}.tmp`. Env variable: `RP_LAUNCH_UUID`. |
| token | Deprecated | Not set | Use `apiKey` or `oauth` instead. |
| skippedIsNotIssue | Optional | False | ReportPortal provides feature to mark skipped tests as not 'To Investigate'. Option could be equal boolean values: `true` - skipped tests will not be marked as 'To Investigate' on application. `false` - skipped tests considered as issues and will be marked as 'To Investigate' on application. |

### HTTP client options

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5.5.7
5.5.8-SNAPSHOT
102 changes: 102 additions & 0 deletions __tests__/report-portal-client.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,108 @@ describe('ReportPortal javascript client', () => {
});
});

it('should automatically add NOT_ISSUE when status is SKIPPED and skippedIsNotIssue is true', function (done) {
const mockClient = new RPClient(
{
apiKey: 'test',
endpoint: 'https://reportportal-stub-url',
launch: 'test launch',
project: 'test project',
skippedIsNotIssue: true,
},
{ name: 'test', version: '1.0.0' },
);

const spyFinishTestItemPromiseStart = jest
.spyOn(mockClient, 'finishTestItemPromiseStart')
.mockImplementation(() => {});

mockClient.map = {
testItemId: {
children: [],
finishSend: false,
promiseFinish: Promise.resolve(),
resolveFinish: () => {},
},
};

const finishTestItemRQ = {
status: 'skipped',
};

mockClient.finishTestItem('testItemId', finishTestItemRQ);

setTimeout(() => {
try {
expect(spyFinishTestItemPromiseStart).toHaveBeenCalledWith(
expect.any(Object),
'testItemId',
expect.objectContaining({
status: 'skipped',
issue: { issueType: 'NOT_ISSUE' },
}),
);
done();
} catch (error) {
done(error);
}
}, 50);
});

it('should not add NOT_ISSUE when status is SKIPPED and skippedIsNotIssue is false', function (done) {
const mockClient = new RPClient(
{
apiKey: 'test',
endpoint: 'https://reportportal-stub-url',
launch: 'test launch',
project: 'test project',
skippedIsNotIssue: false,
},
{ name: 'test', version: '1.0.0' },
);

const spyFinishTestItemPromiseStart = jest
.spyOn(mockClient, 'finishTestItemPromiseStart')
.mockImplementation(() => {});

mockClient.map = {
testItemId: {
children: [],
finishSend: false,
promiseFinish: Promise.resolve(),
resolveFinish: () => {},
},
};

const finishTestItemRQ = {
status: 'skipped',
};

mockClient.finishTestItem('testItemId', finishTestItemRQ);

setTimeout(() => {
try {
expect(spyFinishTestItemPromiseStart).toHaveBeenCalledWith(
expect.any(Object),
'testItemId',
expect.objectContaining({
status: 'skipped',
}),
);
expect(spyFinishTestItemPromiseStart).not.toHaveBeenCalledWith(
expect.any(Object),
'testItemId',
expect.objectContaining({
issue: expect.anything(),
}),
);
done();
} catch (error) {
done(error);
}
}, 100);
});

describe('saveLog', () => {
it('should return object with tempId and promise', () => {
const client = new RPClient({ apiKey: 'any', endpoint: 'https://rp.api', project: 'prj' });
Expand Down
20 changes: 20 additions & 0 deletions __tests__/rest.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,26 @@ describe('RestClient', () => {
};
expect(retryConfig.retryCondition(timeoutError)).toBe(true);
});

it('handles undefined restClientConfig without crashing during retries', () => {
const client = new RestClient({
baseURL: options.baseURL,
headers: options.headers,
restClientConfig: undefined,
});

const retryConfig = client.getRetryConfig();
expect(retryConfig.retries).toBe(6);

const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
const onRetry = retryConfig.onRetry;

expect(() => {
onRetry(1, { code: 'ECONNABORTED' }, { method: 'GET', url: 'http://test.com' });
}).not.toThrow();

consoleSpy.mockRestore();
});
});

describe('buildPath', () => {
Expand Down
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ declare module '@reportportal/client-javascript' {
launchUuidPrintOutput?: string;
restClientConfig?: RestClientConfig;
token?: string;
skippedIsNotIssue?: boolean;
/**
* OAuth 2.0 configuration object. When provided, OAuth authentication will be used instead of API key.
*/
Expand Down
1 change: 1 addition & 0 deletions lib/commons/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
if (!calculatedApiKey) {
throw new ReportPortalRequiredOptionError('apiKey');
} else {
console.warn(`Option 'token' is deprecated. Use 'apiKey' instead.`);

Check warning on line 27 in lib/commons/config.js

View workflow job for this annotation

GitHub Actions / test (22)

Unexpected console statement

Check warning on line 27 in lib/commons/config.js

View workflow job for this annotation

GitHub Actions / test (18)

Unexpected console statement

Check warning on line 27 in lib/commons/config.js

View workflow job for this annotation

GitHub Actions / test (16)

Unexpected console statement

Check warning on line 27 in lib/commons/config.js

View workflow job for this annotation

GitHub Actions / test (14)

Unexpected console statement

Check warning on line 27 in lib/commons/config.js

View workflow job for this annotation

GitHub Actions / test (20)

Unexpected console statement
}
}

Expand Down Expand Up @@ -115,10 +115,11 @@
description: options.description,
launchUuidPrint: options.launchUuidPrint,
launchUuidPrintOutput,
skippedIsNotIssue: !!options.skippedIsNotIssue,
};
} catch (error) {
// don't throw the error up to not break the entire process
console.dir(error);

Check warning on line 122 in lib/commons/config.js

View workflow job for this annotation

GitHub Actions / test (22)

Unexpected console statement

Check warning on line 122 in lib/commons/config.js

View workflow job for this annotation

GitHub Actions / test (18)

Unexpected console statement

Check warning on line 122 in lib/commons/config.js

View workflow job for this annotation

GitHub Actions / test (16)

Unexpected console statement

Check warning on line 122 in lib/commons/config.js

View workflow job for this annotation

GitHub Actions / test (14)

Unexpected console statement

Check warning on line 122 in lib/commons/config.js

View workflow job for this annotation

GitHub Actions / test (20)

Unexpected console statement
}

return calculatedOptions;
Expand Down
15 changes: 15 additions & 0 deletions lib/report-portal-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,14 @@ class RPClient {
this.launchUuid = launchDataRQ.id;
} else {
const systemAttr = helpers.getSystemAttribute();
if (this.config.skippedIsNotIssue === true) {
const skippedIsNotIssueAttribute = {
key: 'skippedIssue',
value: 'false',
system: true,
};
systemAttr.push(skippedIsNotIssueAttribute);
}
const attributes = Array.isArray(launchDataRQ.attributes)
? launchDataRQ.attributes.concat(systemAttr)
: systemAttr;
Expand Down Expand Up @@ -612,6 +620,13 @@ class RPClient {
...finishTestItemRQ,
};

if (
finishTestItemData.status === RP_STATUSES.SKIPPED &&
this.config.skippedIsNotIssue === true
) {
finishTestItemData.issue = { issueType: 'NOT_ISSUE' };
}

itemObj.finishSend = true;
this.logDebug(`Finish all children for test item with tempId ${itemTempId}`);
Promise.allSettled(
Expand Down
2 changes: 1 addition & 1 deletion lib/rest.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ method: ${method}`,
getRetryConfig() {
const retryOption = this.restClientConfig?.retry;
const onRetry = (retryCount, error, requestConfig) => {
if (this.restClientConfig.debug) {
if (this.restClientConfig?.debug) {
console.log(`[retry #${retryCount}] ${requestConfig.method?.toUpperCase()} ${requestConfig.url} -> ${error.code || error.message}`);
}
};
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"scripts": {
"build": "npm run clean && tsc",
"clean": "rimraf ./build",
"lint": "eslint ./statistics/**/* ./lib/**/* ./__tests__/**/*",
"lint": "eslint ./statistics/**/* ./lib/**/*",
"format": "npm run lint -- --fix",
"test": "jest",
"test:coverage": "jest --coverage"
Expand Down
Loading