Skip to content
Closed
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@

## [Unreleased]
### Added
- `retry_of` property support for test item start request to link retried test items to their predecessors in the hierarchy, improving performance tracking and metrics accuracy.

## [5.5.11] - 2026-05-22
### Added
- Google Analytics improvements.
Expand Down
80 changes: 80 additions & 0 deletions __tests__/report-portal-client.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,86 @@ describe('ReportPortal javascript client', () => {

expect(client.itemRetriesChainMap.get).toHaveBeenCalledWith('id1__name__');
});

it('should add retry_of property when retrying an item', async () => {
const client = new RPClient({
apiKey: 'startLaunchTest',
endpoint: 'https://rp.us/api/v1',
project: 'tst',
});
client.map = {
launchId: {
children: ['tempId1', 'tempId2'],
promiseStart: Promise.resolve(),
realId: 'launchRealId',
},
tempId1: {
children: [],
promiseStart: Promise.resolve(),
realId: 'item1RealId',
},
tempId2: {
children: [],
promiseStart: Promise.resolve(),
},
};
const itemKey = 'launchId__name__';
jest.spyOn(client, 'calculateItemRetriesChainMapKey').mockReturnValue(itemKey);
jest.spyOn(client, 'getUniqId').mockReturnValue('tempId2');
jest.spyOn(client.restClient, 'create').mockResolvedValue({ id: 'item2RealId' });

// First item - store it in the retry chain map
client.itemRetriesChainMap.set(itemKey, client.map.tempId1);

// Now retry with second item
const result = client.startTestItem({ name: 'test', type: 'TEST', retry: true }, 'launchId');
await result.promise;

// Verify the API was called with retry_of in the payload
expect(client.restClient.create).toHaveBeenCalledWith(
'item/',
expect.objectContaining({
retry_of: 'item1RealId',
}),
);
});

it('should not add retry_of if previous item not in chain map', async () => {
const client = new RPClient({
apiKey: 'startLaunchTest',
endpoint: 'https://rp.us/api/v1',
project: 'tst',
});
client.map = {
launchId: {
children: ['tempId1'],
promiseStart: Promise.resolve(),
realId: 'launchRealId',
},
tempId1: {
children: [],
promiseStart: Promise.resolve(),
},
};
const itemKey = 'launchId__name__';
jest.spyOn(client, 'calculateItemRetriesChainMapKey').mockReturnValue(itemKey);
jest.spyOn(client, 'getUniqId').mockReturnValue('tempId1');
jest.spyOn(client.restClient, 'create').mockResolvedValue({ id: 'item1RealId' });

// Manually clear the retry chain map
client.itemRetriesChainMap.clear();

const result = client.startTestItem({ name: 'test', type: 'TEST', retry: true }, 'launchId');
await result.promise;

// Verify the API was called WITHOUT retry_of
expect(client.restClient.create).toHaveBeenCalledWith(
'item/',
expect.not.objectContaining({
retry_of: expect.anything(),
}),
);
});
});

describe('finishTestItem', () => {
Expand Down
15 changes: 13 additions & 2 deletions lib/report-portal-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,12 @@ class RPClient {
testItemDataRQ.name,
testItemDataRQ.uniqueId,
);
const executionItemPromise = testItemDataRQ.retry && this.itemRetriesChainMap.get(itemKey);
let previousItemObj = null;
if (testItemDataRQ.retry) {
previousItemObj = this.itemRetriesChainMap.get(itemKey);
// previousItemObj may not have realId yet if promise hasn't resolved
}
const executionItemPromise = previousItemObj && previousItemObj.promiseStart;

const tempId = this.getUniqId();
this.map[tempId] = this.getNewItemObj((resolve, reject) => {
Expand All @@ -570,6 +575,12 @@ class RPClient {
url += `${realParentId}`;
}
testItemData.launchUuid = realLaunchId;

// Add retry_of if this is a retry and previous item exists
if (previousItemObj && previousItemObj.realId) {
testItemData.retry_of = previousItemObj.realId;
}

this.logDebug(`Start test item with tempId ${tempId}`, testItemData);
this.restClient.create(url, testItemData).then(
(response) => {
Expand All @@ -591,7 +602,7 @@ class RPClient {
});
this.map[parentMapId].children.push(tempId);
this.itemRetriesChainKeyMapByTempId.set(tempId, itemKey);
this.itemRetriesChainMap.set(itemKey, this.map[tempId].promiseStart);
this.itemRetriesChainMap.set(itemKey, this.map[tempId]);

return {
tempId,
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions test-output.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

> @reportportal/client-javascript@5.5.11 test
> jest

sh: 1: jest: not found
Loading