Skip to content

Commit

Permalink
Merge pull request #200 from reportportal/develop
Browse files Browse the repository at this point in the history
Release 5.3.3
  • Loading branch information
AmsterGet authored Aug 15, 2024
2 parents df1ab31 + ab333b0 commit 573a4d2
Show file tree
Hide file tree
Showing 15 changed files with 507 additions and 89 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/CI-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20
- name: Install of node dependencies
run: npm install
- name: Run lint
run: npm run lint
- name: Run tests and check coverage
run: npm run test:coverage
# - name: Run tests and check coverage
# run: npm run test:coverage
10 changes: 5 additions & 5 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20
- name: Install of node dependencies
run: npm install
- name: Run lint
run: npm run lint
- name: Run tests and check coverage
run: npm run test:coverage
# - name: Run tests and check coverage
# run: npm run test:coverage

publish-to-npm-and-gpr:
needs: build
Expand All @@ -43,7 +43,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20
registry-url: 'https://registry.npmjs.org'
- name: Install of node dependencies
run: npm install
Expand All @@ -57,7 +57,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20
registry-url: 'https://npm.pkg.github.com'
scope: '@reportportal'
- name: Publish to GPR
Expand Down
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
### Added
- `uploadVideo` option. Allows uploading Cypress videos for specs. Check the readme for details.

## [5.3.2] - 2024-07-01
### Fixed
Expand All @@ -7,13 +9,15 @@
### Fixed
- [#192](https://github.com/reportportal/agent-js-cypress/issues/192). Reporter procreates an enormous amount of processes during execution. Thanks to [epam-avramenko](https://github.com/epam-avramenko).
### Changed
- `@reportportal/client-javascript` bumped to version `5.1.4`.
- `@reportportal/client-javascript` bumped to version `5.1.4`, new `launchUuidPrintOutput` types introduced: 'FILE', 'ENVIRONMENT'.

## [5.3.0] - 2024-05-07
### Added
- `cucumberStepStart` and `cucumberStepEnd` commands for reporting `cypress-cucumber-preprocessor` scenario steps as nested steps in RP.
### Security
- Updated versions of vulnerable packages (@reportportal/client-javascript, glob).
### Deprecated
- Node.js 12 usage. This minor version is the latest that supports Node.js 12.

## [5.2.0] - 2024-03-21
### Fixed
Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,11 @@ The full list of available options presented below.
| launchUuidPrint | Optional | false | Whether to print the current launch UUID. |
| launchUuidPrintOutput | Optional | 'STDOUT' | Launch UUID printing output. Possible values: 'STDOUT', 'STDERR'. Works only if `launchUuidPrint` set to `true`. |
| restClientConfig | Optional | Not set | `axios` like http client [config](https://github.com/axios/axios#request-config). May contain `agent` property for configure [http(s)](https://nodejs.org/api/https.html#https_https_request_url_options_callback) client, and other client options eg. `timeout`. For debugging and displaying logs you can set `debug: true`. |
| autoMerge | Optional | false | Enable automatic report test items of all runned spec into one launch. You should install plugin or setup additional settings in reporterOptions. See [Automatically merge launch](#automatically-merge-launches). |
| uploadVideo | Optional | false | Whether to upload the Cypress video. |
| uploadVideoOnPasses | Optional | false | Whether to upload the Cypress video for a non-failure specs. Works only if `uploadVideo` set to `true`. |
| waitForVideoTimeout | Optional | 10000 | Value in `ms`. Since Cypress video processing may take extra time after the spec is complete, there is a timeout to wait for the video file readiness. Works only if `uploadVideo` set to `true`. |
| waitForVideoInterval | Optional | 500 | Value in `ms`. Interval to check if the video file is ready. The interval is used until `waitForVideoTimeout` is reached. Works only if `uploadVideo` set to `true`. |
| autoMerge | Optional | false | Enable automatic report test items of all run spec into one launch. You should install plugin or setup additional settings in reporterOptions. See [Automatically merge launch](#automatically-merge-launches). |
| reportHooks | Optional | false | Determines report before and after hooks or not. |
| isLaunchMergeRequired | Optional | false | Allows to merge Cypress run's into one launch at the end of the run. Needs additional setup. See [Manual merge launches](#manual-merge-launches). |
| parallel | Optional | false | Indicates to the reporter that spec files will be executed in parallel on different machines. Parameter could be equal boolean values. See [Parallel execution](#parallel-execution). |
Expand All @@ -152,7 +156,6 @@ const updatedConfig = {
apiKey: process.env.RP_API_KEY,
},
};

```

**For security reasons, you can also set token as a part of Environment Variables, instead of sharing it in the config file:**
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5.3.2
5.3.3-SNAPSHOT
1 change: 1 addition & 0 deletions lib/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const hookTypesMap = {

const reporterEvents = {
INIT: 'rpInit',
FULL_CONFIG: 'rpFullConfig',
LOG: 'rpLog',
LAUNCH_LOG: 'rpLaunchLog',
ADD_ATTRIBUTES: 'rpAddAttrbiutes',
Expand Down
9 changes: 5 additions & 4 deletions lib/cypressReporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ const { IPC_EVENTS } = require('./ipcEvents');
const {
getConfig,
getLaunchStartObject,
getSuiteStartObject,
getSuiteEndObject,
getSuiteStartInfo,
getSuiteEndInfo,
getTestInfo,
getHookInfo,
getTotalSpecs,
Expand All @@ -63,6 +63,7 @@ class CypressReporter extends Mocha.reporters.Base {
this.worker.send({ event: reporterEvents.INIT, config });

const configListener = (cypressFullConfig) => {
this.worker.send({ event: reporterEvents.FULL_CONFIG, config: cypressFullConfig });
CypressReporter.cypressConfig = cypressFullConfig;
CypressReporter.calcTotalLaunches();
};
Expand Down Expand Up @@ -132,13 +133,13 @@ class CypressReporter extends Mocha.reporters.Base {
if (!suite.title) return;
this.worker.send({
event: EVENT_SUITE_BEGIN,
suite: getSuiteStartObject(suite, this.runner.suite.file),
suite: getSuiteStartInfo(suite, this.runner.suite.file),
});
});

this.runner.on(EVENT_SUITE_END, (suite) => {
if (!suite.title) return;
this.worker.send({ event: EVENT_SUITE_END, suite: getSuiteEndObject(suite) });
this.worker.send({ event: EVENT_SUITE_END, suite: getSuiteEndInfo(suite) });
});

this.runner.on(EVENT_TEST_BEGIN, (test) => {
Expand Down
2 changes: 1 addition & 1 deletion lib/mergeLaunches.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const mergeParallelLaunches = async (client, config) => {
// 4. If not, merge all found launches with the same CI_BUILD_ID attribute value
const launchIds = response.content.map((launch) => launch.id);
const request = client.getMergeLaunchesRequest(launchIds);
request.description = config.reporterOptions.description;
request.description = config.description;
request.extendSuitesDescription = false;
const mergeURL = 'launch/merge';
await client.restClient.create(mergeURL, request, { headers: client.headers });
Expand Down
144 changes: 117 additions & 27 deletions lib/reporter.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020 EPAM Systems
* Copyright 2024 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -24,6 +24,9 @@ const {
getHookStartObject,
getAgentInfo,
getCodeRef,
getVideoFile,
getSuiteStartObject,
getSuiteEndObject,
} = require('./utils');

const { createMergeLaunchLockFile, deleteMergeLaunchLockFile } = require('./mergeLaunchesUtils');
Expand All @@ -47,7 +50,9 @@ class Reporter {
this.client = new RPClient(config.reporterOptions, agentInfo);
this.testItemIds = new Map();
this.hooks = new Map();
this.config = config;
this.config = config.reporterOptions;
this.fullCypressConfig = config;
this.videoPromises = [];

this.currentTestFinishParams = getInitialTestFinishParams();

Expand All @@ -61,13 +66,17 @@ class Reporter {
this.cucumberSteps = new Map();
}

saveFullConfig(config) {
this.fullCypressConfig = config;
}

resetCurrentTestFinishParams() {
this.currentTestFinishParams = getInitialTestFinishParams();
}

runStart(launchObj) {
const { tempId, promise } = this.client.startLaunch(launchObj);
const { launch, isLaunchMergeRequired } = this.config.reporterOptions;
const { launch, isLaunchMergeRequired } = this.config;
if (isLaunchMergeRequired) {
createMergeLaunchLockFile(launch, tempId);
}
Expand All @@ -76,7 +85,7 @@ class Reporter {
}

runEnd() {
const basePromise = this.config.reporterOptions.launchId
const basePromise = this.config.launchId
? this.client.getPromiseFinishAllItems(this.tempLaunchId)
: this.client.finishLaunch(
this.tempLaunchId,
Expand All @@ -88,15 +97,15 @@ class Reporter {
),
).promise;

const finishLaunchPromise = basePromise
const finishLaunchPromise = Promise.allSettled([basePromise, ...this.videoPromises])
.then(() => {
const { launch, isLaunchMergeRequired } = this.config.reporterOptions;
const { launch, isLaunchMergeRequired } = this.config;
if (isLaunchMergeRequired) {
deleteMergeLaunchLockFile(launch, this.tempLaunchId);
}
})
.then(() => {
const { parallel, autoMerge } = this.config.reporterOptions;
const { parallel, autoMerge } = this.config;
if (!(parallel && autoMerge)) {
return Promise.resolve();
}
Expand All @@ -108,30 +117,103 @@ class Reporter {

suiteStart(suite) {
const parentId = suite.parentId && this.testItemIds.get(suite.parentId);
const { tempId, promise } = this.client.startTestItem(suite, this.tempLaunchId, parentId);
const startSuiteObj = getSuiteStartObject(suite);
const { tempId, promise } = this.client.startTestItem(
startSuiteObj,
this.tempLaunchId,
parentId,
);
promiseErrorHandler(promise, 'Fail to start suite');
this.testItemIds.set(suite.id, tempId);
this.suitesStackTempInfo.push({ tempId, startTime: suite.startTime });
this.suitesStackTempInfo.push({
tempId,
startTime: suite.startTime,
title: suite.title || '',
id: suite.id,
testFileName: suite.testFileName,
});
}

suiteEnd(suite) {
const suiteId = this.testItemIds.get(suite.id);
const { uploadVideo = false } = this.config;
const { video: isVideoRecordingEnabled = false } = this.fullCypressConfig;
const isRootSuite =
this.suitesStackTempInfo.length && suite.id === this.suitesStackTempInfo[0].id;

const suiteFinishObj = this.prepareSuiteToFinish(suite);

if (isVideoRecordingEnabled && uploadVideo && isRootSuite) {
const suiteInfo = this.suitesStackTempInfo[0];
this.finishSuiteWithVideo(suiteInfo, suiteFinishObj);
} else {
const suiteTempId = this.testItemIds.get(suite.id);
this.finishSuite(suiteFinishObj, suiteTempId);
}
this.suitesStackTempInfo.pop();
}

prepareSuiteToFinish(suite) {
const suiteTestCaseId = this.suiteTestCaseIds.get(suite.title);
const suiteStatus = this.suiteStatuses.get(suite.title);
const finishTestItemPromise = this.client.finishTestItem(
suiteId,
Object.assign(
{
endTime: new Date().valueOf(),
},
suiteTestCaseId && { testCaseId: suiteTestCaseId },
suiteStatus && { status: suiteStatus },
),
).promise;
promiseErrorHandler(finishTestItemPromise, 'Fail to finish suite');
this.suitesStackTempInfo.pop();
let suiteFinishObj = getSuiteEndObject(suite);

suiteFinishObj = {
...suiteFinishObj,
status: suiteStatus || suite.status,
...(suiteTestCaseId && { testCaseId: suiteTestCaseId }),
};

suiteTestCaseId && this.suiteTestCaseIds.delete(suite.title);
suiteStatus && this.suiteStatuses.delete(suite.title);

return suiteFinishObj;
}

finishSuite(suiteFinishObj, suiteTempId) {
const finishTestItemPromise = this.client.finishTestItem(suiteTempId, suiteFinishObj).promise;
promiseErrorHandler(finishTestItemPromise, 'Fail to finish suite');
}

finishSuiteWithVideo(suiteInfo, suiteFinishObj) {
const uploadVideoOnPasses = this.config.uploadVideoOnPasses || false;
const suiteFailed = suiteFinishObj.status === testItemStatuses.FAILED;

// do not upload video if root suite passes and uploadVideoOnPasses is false
if ((!suiteFailed && !uploadVideoOnPasses) || !suiteInfo.testFileName) {
this.finishSuite(suiteFinishObj, suiteInfo.tempId);
} else {
const sendVideoPromise = this.sendVideo(suiteInfo).finally(() => {
this.finishSuite(suiteFinishObj, suiteInfo.tempId);
});
this.videoPromises.push(sendVideoPromise);
}
}

async sendVideo(suiteInfo) {
const { waitForVideoTimeout, waitForVideoInterval, videosFolder } = this.config;
const { testFileName, tempId, title } = suiteInfo;
const file = await getVideoFile(
testFileName,
videosFolder,
waitForVideoTimeout,
waitForVideoInterval,
);
if (!file) {
return null;
}

const sendVideoPromise = this.client.sendLog(
tempId,
{
message: `Video: '${title}' (${testFileName}.mp4)`,
level: logLevels.INFO,
time: new Date().valueOf(),
},
file,
).promise;
promiseErrorHandler(sendVideoPromise, 'Fail to save video');

return sendVideoPromise;
}

testStart(test) {
Expand Down Expand Up @@ -177,7 +259,7 @@ class Reporter {
const testInfo = Object.assign({}, test, this.currentTestFinishParams);
const finishTestItemPromise = this.client.finishTestItem(
testId,
getTestEndObject(testInfo, this.config.reporterOptions.skippedIssue),
getTestEndObject(testInfo, this.config.skippedIssue),
).promise;
promiseErrorHandler(finishTestItemPromise, 'Fail to finish test');
this.resetCurrentTestFinishParams();
Expand Down Expand Up @@ -377,6 +459,10 @@ class Reporter {
setTestItemStatus({ status, suiteTitle }) {
if (suiteTitle) {
this.suiteStatuses.set(suiteTitle, status);
const rootSuite = this.suitesStackTempInfo.length && this.suitesStackTempInfo[0];
if (rootSuite && status === testItemStatuses.FAILED) {
this.suitesStackTempInfo[0].status = status;
}
} else {
Object.assign(this.currentTestFinishParams, status && { status });
}
Expand All @@ -386,15 +472,19 @@ class Reporter {
this.launchStatus = status;
}

sendScreenshot(screenshotInfo, logMessage) {
async sendScreenshot(screenshotInfo, logMessage) {
const tempItemId = this.currentTestTempInfo && this.currentTestTempInfo.tempId;
const fileName = screenshotInfo.path;

if (!fileName || !tempItemId) return;
if (!fileName || !tempItemId) {
return;
}

const level = fileName && fileName.includes('(failed)') ? logLevels.ERROR : logLevels.INFO;
const file = getScreenshotAttachment(fileName);
if (!file) return;
const file = await getScreenshotAttachment(fileName);
if (!file) {
return;
}

const message = logMessage || `screenshot ${file.name}`;

Expand Down
Loading

0 comments on commit 573a4d2

Please sign in to comment.