New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

wdio-reportportal-reporter

Package Overview
Dependencies
Maintainers
1
Versions
57
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

wdio-reportportal-reporter - npm Package Compare versions

Comparing version 0.0.7 to 0.0.8

.github/ISSUE_TEMPLATE.md

104

build/reporter.js

@@ -7,4 +7,13 @@ 'use strict';

var _stringify = require('babel-runtime/core-js/json/stringify');
var _stringify2 = _interopRequireDefault(_stringify);
var _assign = require('babel-runtime/core-js/object/assign');
var _assign2 = _interopRequireDefault(_assign);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* eslint-disable object-curly-newline */
const { EventEmitter } = require('events');

@@ -14,3 +23,3 @@ const ReportPortalClient = require('reportportal-client');

const { testItemStatuses, events, entityType } = require('./constants');
const { promiseErrorHandler, logger } = require('./utils');
const { promiseErrorHandler, logger, isEmpty, limit, sendToReporter } = require('./utils');

@@ -26,4 +35,11 @@ const { PASSED, FAILED, SKIPPED } = testItemStatuses;

this.config = config;
this.client = new ReportPortalClient(options);
const { tempId, promise } = this.client.startLaunch({ mode: options.mode || 'DEFAULT' });
this.options = (0, _assign2.default)({
enableSeleniumCommandReporting: false,
seleniumCommandsLogLevel: 'debug',
enableScreenshotsReporting: false,
screenshotsLogLevel: 'info'
}, options);
this.client = new ReportPortalClient(options.rpConfig);
const { tempId, promise } = this.client.startLaunch({ mode: options.rpConfig.mode || 'DEFAULT' });
promiseErrorHandler(promise);

@@ -40,2 +56,6 @@ this.tempLaunchId = tempId;

this.on('start', this.start.bind(this));
this.on('runner:command', this.runnerCommand.bind(this));
this.on('runner:result', this.runnerResult.bind(this));
// Rp events

@@ -152,2 +172,60 @@ this.on(events.RP_LOG, this.sendLog.bind(this));

runnerCommand(command) {
if (!this.options.enableSeleniumCommandReporting || this.isMultiremote) {
return;
}
const parentId = this.getParentId(command.cid);
if (!parentId) {
return;
}
const method = `${command.method} ${command.uri.path}`;
if (!isEmpty(command.data)) {
const data = (0, _stringify2.default)(limit(command.data));
this.sendLog({ cid: command.cid, level: this.options.seleniumCommandsLogLevel, message: `${method}\n${data}` });
} else {
this.sendLog({ cid: command.cid, level: this.options.seleniumCommandsLogLevel, message: `${method}` });
}
}
start(event) {
this.isMultiremote = event.isMultiremote;
}
runnerResult(command) {
if (this.isMultiremote) {
return;
}
const parentId = this.getParentId(command.cid);
if (!parentId) {
return;
}
const isScreenshot = command.requestOptions.uri.path.match(/\/session\/[^/]*\/screenshot/) && command.body.value;
if (isScreenshot) {
if (this.options.enableScreenshotsReporting) {
const obj = {
cid: command.cid,
level: this.options.screenshotsLogLevel,
name: 'screenshot.png',
content: command.body.value
};
this.sendFile(obj);
}
}
if (this.options.enableSeleniumCommandReporting) {
if (command.body && !isEmpty(command.body.value)) {
const method = `${command.requestOptions.uri.path}`;
// eslint-disable-next-line no-param-reassign
delete command.body.sessionId;
const data = (0, _stringify2.default)(limit(command.body));
this.sendLog({ cid: command.cid, level: this.options.seleniumCommandsLogLevel, message: `${method}\n${data}` });
}
}
}
async sendLogToLastFailedItem({ cid, level, message }) {

@@ -234,4 +312,24 @@ if (!(await this.waitForFailedTest(cid, 2000, 10))) {

}
static sendLog(level, message) {
sendToReporter(events.RP_LOG, { level, message });
}
static sendFile(level, name, content, type = 'image/png') {
// eslint-disable-next-line object-curly-newline
sendToReporter(events.RP_FILE, { level, name, content, type });
}
static sendLogToLastFailedTest(level, message) {
sendToReporter(events.RP_FAILED_LOG, { level, message });
}
static sendFileToLastFailedTest(level, name, content, type = 'image/png') {
// eslint-disable-next-line object-curly-newline
sendToReporter(events.RP_FAILED_FILE, { level, name, content, type });
}
}
ReportPortalReporter.reporterName = 'reportportal';
module.exports = ReportPortalReporter;

@@ -1,5 +0,26 @@

"use strict";
'use strict';
/* eslint-disable no-console */
var _assign = require('babel-runtime/core-js/object/assign');
var _assign2 = _interopRequireDefault(_assign);
var _stringify = require('babel-runtime/core-js/json/stringify');
var _stringify2 = _interopRequireDefault(_stringify);
var _keys = require('babel-runtime/core-js/object/keys');
var _keys2 = _interopRequireDefault(_keys);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* eslint-disable no-console,no-param-reassign */
const stringify = require('json-stringify-safe');
const OBJLENGTH = 10;
const ARRLENGTH = 10;
const STRINGLIMIT = 1000;
const STRINGTRUNCATE = 200;
const notBase64 = /[^A-Z0-9+/=]/i;
const logger = {

@@ -23,2 +44,76 @@ info(msg) {

module.exports = { promiseErrorHandler, logger };
const isEmpty = object => !object || (0, _keys2.default)(object).length === 0;
const isBase64 = str => {
if (typeof str !== 'string') {
return false;
}
const len = str.length;
if (!len || len % 4 !== 0 || notBase64.test(str)) {
return false;
}
const firstPaddingChar = str.indexOf('=');
return firstPaddingChar === -1 || firstPaddingChar === len - 1 || firstPaddingChar === len - 2 && str[len - 1] === '=';
};
/**
* Limit the length of an arbitrary variable of any type, suitable for being logged or displayed
* @param {Any} val Any variable
* @return {Any} Limited var of same type
*/
const limit = val => {
if (!val) return val;
// Ensure we're working with a copy
let value = JSON.parse(stringify(val));
switch (Object.prototype.toString.call(value)) {
case '[object String]':
if (value.length > 100 && isBase64(value)) {
return `[base64] ${value.length} bytes`;
}
if (value.length > STRINGLIMIT) {
return `${value.substr(0, STRINGTRUNCATE)} ... (${value.length - STRINGTRUNCATE} more bytes)`;
}
return value;
case '[object Array]':
{
const { length } = value;
if (length > ARRLENGTH) {
value = value.slice(0, ARRLENGTH);
value.push(`(${length - ARRLENGTH} more items)`);
}
return value.map(limit);
}
case '[object Object]':
{
const keys = (0, _keys2.default)(value);
const removed = [];
for (let i = 0, l = keys.length; i < l; i += 1) {
if (i < OBJLENGTH) {
value[keys[i]] = limit(value[keys[i]]);
} else {
delete value[keys[i]];
removed.push(keys[i]);
}
}
if (removed.length) {
value._ = `${keys.length - OBJLENGTH} more keys: ${(0, _stringify2.default)(removed)}`;
}
return value;
}
default:
{
return value;
}
}
};
const sendToReporter = (event, msg = {}) => {
process.send((0, _assign2.default)({ event }, msg));
};
module.exports = { promiseErrorHandler, logger, isEmpty, limit, sendToReporter };

@@ -0,1 +1,2 @@

/* eslint-disable object-curly-newline */
const { EventEmitter } = require('events');

@@ -5,3 +6,3 @@ const ReportPortalClient = require('reportportal-client');

const { testItemStatuses, events, entityType } = require('./constants');
const { promiseErrorHandler, logger } = require('./utils');
const { promiseErrorHandler, logger, isEmpty, limit, sendToReporter } = require('./utils');

@@ -17,4 +18,11 @@ const { PASSED, FAILED, SKIPPED } = testItemStatuses;

this.config = config;
this.client = new ReportPortalClient(options);
const { tempId, promise } = this.client.startLaunch({ mode: options.mode || 'DEFAULT' });
this.options = Object.assign({
enableSeleniumCommandReporting: false,
seleniumCommandsLogLevel: 'debug',
enableScreenshotsReporting: false,
screenshotsLogLevel: 'info',
}, options);
this.client = new ReportPortalClient(options.rpConfig);
const { tempId, promise } = this.client.startLaunch({ mode: options.rpConfig.mode || 'DEFAULT' });
promiseErrorHandler(promise);

@@ -31,2 +39,6 @@ this.tempLaunchId = tempId;

this.on('start', ::this.start);
this.on('runner:command', ::this.runnerCommand);
this.on('runner:result', ::this.runnerResult);
// Rp events

@@ -151,2 +163,60 @@ this.on(events.RP_LOG, ::this.sendLog);

runnerCommand(command) {
if (!this.options.enableSeleniumCommandReporting || this.isMultiremote) {
return;
}
const parentId = this.getParentId(command.cid);
if (!parentId) {
return;
}
const method = `${command.method} ${command.uri.path}`;
if (!isEmpty(command.data)) {
const data = JSON.stringify(limit(command.data));
this.sendLog({ cid: command.cid, level: this.options.seleniumCommandsLogLevel, message: `${method}\n${data}` });
} else {
this.sendLog({ cid: command.cid, level: this.options.seleniumCommandsLogLevel, message: `${method}` });
}
}
start(event) {
this.isMultiremote = event.isMultiremote;
}
runnerResult(command) {
if (this.isMultiremote) {
return;
}
const parentId = this.getParentId(command.cid);
if (!parentId) {
return;
}
const isScreenshot = command.requestOptions.uri.path.match(/\/session\/[^/]*\/screenshot/) && command.body.value;
if (isScreenshot) {
if (this.options.enableScreenshotsReporting) {
const obj = {
cid: command.cid,
level: this.options.screenshotsLogLevel,
name: 'screenshot.png',
content: command.body.value,
};
this.sendFile(obj);
}
}
if (this.options.enableSeleniumCommandReporting) {
if (command.body && !isEmpty(command.body.value)) {
const method = `${command.requestOptions.uri.path}`;
// eslint-disable-next-line no-param-reassign
delete command.body.sessionId;
const data = JSON.stringify(limit(command.body));
this.sendLog({ cid: command.cid, level: this.options.seleniumCommandsLogLevel, message: `${method}\n${data}` });
}
}
}
async sendLogToLastFailedItem({ cid, level, message }) {

@@ -233,4 +303,24 @@ if (!(await this.waitForFailedTest(cid, 2000, 10))) {

}
static sendLog(level, message) {
sendToReporter(events.RP_LOG, { level, message });
}
static sendFile(level, name, content, type = 'image/png') {
// eslint-disable-next-line object-curly-newline
sendToReporter(events.RP_FILE, { level, name, content, type });
}
static sendLogToLastFailedTest(level, message) {
sendToReporter(events.RP_FAILED_LOG, { level, message });
}
static sendFileToLastFailedTest(level, name, content, type = 'image/png') {
// eslint-disable-next-line object-curly-newline
sendToReporter(events.RP_FAILED_FILE, { level, name, content, type });
}
}
ReportPortalReporter.reporterName = 'reportportal';
module.exports = ReportPortalReporter;

@@ -1,3 +0,10 @@

/* eslint-disable no-console */
/* eslint-disable no-console,no-param-reassign */
const stringify = require('json-stringify-safe');
const OBJLENGTH = 10;
const ARRLENGTH = 10;
const STRINGLIMIT = 1000;
const STRINGTRUNCATE = 200;
const notBase64 = /[^A-Z0-9+/=]/i;
const logger = {

@@ -21,2 +28,75 @@ info(msg) {

module.exports = { promiseErrorHandler, logger };
const isEmpty = object => !object || Object.keys(object).length === 0;
const isBase64 = (str) => {
if (typeof str !== 'string') {
return false;
}
const len = str.length;
if (!len || len % 4 !== 0 || notBase64.test(str)) {
return false;
}
const firstPaddingChar = str.indexOf('=');
return firstPaddingChar === -1 ||
firstPaddingChar === len - 1 ||
(firstPaddingChar === len - 2 && str[len - 1] === '=');
};
/**
* Limit the length of an arbitrary variable of any type, suitable for being logged or displayed
* @param {Any} val Any variable
* @return {Any} Limited var of same type
*/
const limit = (val) => {
if (!val) return val;
// Ensure we're working with a copy
let value = JSON.parse(stringify(val));
switch (Object.prototype.toString.call(value)) {
case '[object String]':
if (value.length > 100 && isBase64(value)) {
return `[base64] ${value.length} bytes`;
}
if (value.length > STRINGLIMIT) {
return `${value.substr(0, STRINGTRUNCATE)} ... (${value.length - STRINGTRUNCATE} more bytes)`;
}
return value;
case '[object Array]': {
const { length } = value;
if (length > ARRLENGTH) {
value = value.slice(0, ARRLENGTH);
value.push(`(${length - ARRLENGTH} more items)`);
}
return value.map(limit);
}
case '[object Object]': {
const keys = Object.keys(value);
const removed = [];
for (let i = 0, l = keys.length; i < l; i += 1) {
if (i < OBJLENGTH) {
value[keys[i]] = limit(value[keys[i]]);
} else {
delete value[keys[i]];
removed.push(keys[i]);
}
}
if (removed.length) {
value._ = `${keys.length - OBJLENGTH} more keys: ${JSON.stringify(removed)}`;
}
return value;
}
default: {
return value;
}
}
};
const sendToReporter = (event, msg = {}) => {
process.send({ event, ...msg });
};
module.exports = { promiseErrorHandler, logger, isEmpty, limit, sendToReporter };

7

package.json
{
"name": "wdio-reportportal-reporter",
"version": "0.0.7",
"version": "0.0.8",
"description": "A WebdriverIO plugin. Report results to Report Portal.",

@@ -31,3 +31,4 @@ "main": "build/reporter.js",

"wdio-plugin",
"wdio-reporter"
"wdio-reporter",
"reportportal"
],

@@ -42,2 +43,3 @@ "author": "Boris Osipov <osipov.boris@gmail.com>",

"babel-runtime": "^6.26.0",
"json-stringify-safe": "~5.0.1",
"reportportal-client": "https://github.com/reportportal/client-javascript.git#b09e49b"

@@ -67,2 +69,3 @@ },

"wdio-cucumber-framework": "^2.2.7",
"wdio-mocha-framework": "^0.6.3",
"wdio-phantomjs-service": "^0.2.2",

@@ -69,0 +72,0 @@ "webdriverio": "^4.12.0"

@@ -12,3 +12,3 @@ WDIO Report Portal Reporter

"devDependencies": {
"wdio-reportportal-reporter": "~0.0.6"
"wdio-reportportal-reporter": "~0.0.8"
}

@@ -30,7 +30,13 @@ }

reportportal: {
token: '00000000-0000-0000-0000-00000000000',
endpoint: 'https://reportportal-url/api/v1',
launch: 'launch_name',
project: 'project_name',
mode: 'DEFAULT'
rpConfig: {
token: '00000000-0000-0000-0000-00000000000',
endpoint: 'https://reportportal-url/api/v1',
launch: 'launch_name',
project: 'project_name',
mode: 'DEFAULT'
},
enableSeleniumCommandReporting: false,
enableScreenshotsReporting: false,
seleniumCommandsLogLevel: 'debug',
screenshotsLogLevel: 'info',
}

@@ -41,1 +47,48 @@ },

```
## Additional API
Api methods can be accessed using:
```js
const reporter = require('wdio-allure-reporter')
```
### Methods description
* `sendLog(level, message) ` – send log to current suite\test item.
* `level` (*String*) - log level. Values ['trace', 'debug', 'info', 'warn', 'error'].
* `message` (*String*)– log message content.
* `sendFile(level, name, content, [type])` – send file to current suite\test item.
* `level` (*String*) - log level. Values ['trace', 'debug', 'info', 'warn', 'error'].
* `name` (*String*)– file name.
* `content` (*String*) – attachment content
* `type` (*String*, optional) – attachment MIME-type, `image/png` by default
* `sendLogToLastFailedTest(level, message)` - send log to last failed test item.
* `level` (*String*) - log level. Values ['trace', 'debug', 'info', 'warn', 'error'].
* `message` (*String*)– log message content.
* `sendFileToLastFailedTest(level, name, content, [type])` – send file to last failed test item.
* `level` (*String*) - log level. Values ['trace', 'debug', 'info', 'warn', 'error'].
* `name` (*String*)– file name.
* `content` (*String*) – attachment content
* `type` (*String*, optional) – attachment MIME-type, `image/png` by default
Pay attention: `sendLog`\\`sendFile` sends log to **current test item**. It means if you send log without active test(e.g from hooks or on suite level) you will not be able to access them in Report Portal UI.
Methods `sendLogToLastFailedTest`\\`sendFileToLastFailedTest` are useful when you need to send screenshots or logs to the failed test item from wdio afterTest hook.
Mocha example:
```js
const reporter = require('wdio-allure-reporter');
exports.config = {
...
afterTest: async function afterTest(test) {
if (test.passed === false) {
const screenshot = await browser.saveScreenshot();
reporter.sendFileToLastFailedTest('error', 'failed.png', screenshot);
}
},
...
```
## License
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc