The JsonFormatter is throwing an error because it is trying to access the property 'on' of an undefined variable

I have encountered an error while attempting to generate an HTML report using cucumber-html-reporter

The error message is:

Unhandled rejection TypeError: Cannot read property 'on' of undefined
at new JsonFormatter (C:\path-to-project\node_modules\cucumber\src\formatter\json_formatter.js:21:5)
at Object.<anonymous> (C:\path-to-project\test\reporting\CucumberReportExtension.ts:43:27)

I have reviewed the release notes for potential related issues but I am unsure if they are the cause of this problem. Any guidance on how to resolve this issue would be greatly appreciated.

If you have any alternative solutions for generating reports with cucumber-protractor in TypeScript, I would be interested. (Considering the versions mentioned below)

Protractor version: 5.1.2

Cucumber version: 3.0.0

ScenarioHook.ts

import {defineSupportCode} from "cucumber";
import {CucumberReportExtension} from 
"../reporting/CucumberReportExtension";

defineSupportCode(({AfterAll}) => {

  AfterAll(async () => {
     new CucumberReportExtension().myJsonFormatter;
  });
});

CucumberReportExtension.ts

import * as fs from 'fs';
import { mkdirp } from 'mkdirp';
import * as report from 'cucumber-html-reporter';
let Cucumber = require('cucumber');

export class CucumberReportExtension {

 private jsonDir = process.cwd() + "/reports/json";
 private htmlDir = process.cwd() + "/reports/html";
 private jsonFile = this.jsonDir + "/cucumber_report.json";

 private cucumberReporterOptions = {
    theme: "bootstrap",
    jsonFile: this.jsonFile,
    output: this.htmlDir + "/cucumber_reporter.html",
    reportSuiteAsScenarios: true,
    metadata: {
        "App Version":"0.0.1",
        "Test Environment": "TestingMicroSheet",
        "Browser": "Chrome  59.0.945",
        "Platform": "Windows 10",
        "Parallel": "Scenarios",
        "Executed": "Local"
    }
 };

 private CreateReportFile(dirName, fileName, fileContent) {
    //Check if the directory exist
    if (!fs.existsSync(dirName))
        mkdirp.sync(dirName);
    try {
        fs.writeFileSync(fileName, fileContent);
    }
    catch (message) {
        console.log("Failed to create File/Directory :" + message);
    }
 }

 private GenerateCucumberReport(cucumberReportOption){
    report.generate(cucumberReportOption);
 }

 myJsonFormatter = new Cucumber.JsonFormatter({
    log: jLog => {
        this.CreateReportFile(this.jsonDir, this.jsonFile, jLog);
        this.GenerateCucumberReport(this.cucumberReporterOptions);
    }
 });
}
export let JsonFormatter = new CucumberReportExtension().myJsonFormatter;

config.ts

import { Config } from 'protractor';

export let config: Config = {

 seleniumAddress: 'http://localhost:4444/wd/hub',

 framework: 'custom',
 frameworkPath: require.resolve('protractor-cucumber-framework'),
 specs: ["../features/*.feature"],

 baseUrl: "http://localhost:4200/",

 cucumberOpts: {
    compiler: "ts:ts-node/register",
    strict: true,
    format: ['json:../reporting/results.json'],
    require: ['../steps/*.js', '../hooks/*.js'],
    tags: '@smoke'
 }
}

package.json

{
  "name": "protractor-cucumber-sample",
  "version": "0.0.0",
  "private": true,
  "scripts": {
  "start": "node ./bin/www"
   },
  "dependencies": {
  "@types/jasmine": "^2.5.53",
  "body-parser": "~1.17.1",
  "cookie-parser": "~1.4.3",
  "debug": "~2.6.3",
  "express": "~4.15.2",
  "jade": "~1.11.0",
  "morgan": "~1.8.1",
  "serve-favicon": "~2.4.2"
   },
 "devDependencies": {
 "@types/chai": "^4.0.3",
 "@types/cucumber": "^2.0.3",
 "@types/mkdirp": "^0.5.0",
 "chai": "^4.1.1",
 "chai-as-promised": "^7.1.1",
 "cucumber": "^3.0.0",
 "cucumber-html-reporter": "^2.0.3",
 "jasmine": "^2.7.0",
 "jasminewd2": "^2.1.0",
 "protractor-cucumber-framework": "^4.0.2",
 "ts-node": "^3.3.0",
 "typescript": "^2.4.2"
  }
 }

Please feel free to ask for additional information that may assist in resolving this issue. If this platform is not appropriate for addressing this matter, kindly provide details of the correct forum where I can seek assistance. Thank you in advance.

Answer №1

When it comes to the latest cucumber 3.0 version, you are required to provide the node event emitter for your custom formatters. To understand how node events operate, refer to this link - https://nodejs.org/api/events.html

Now, incorporate this into your CucumberReportExtension.ts

import * as fs from 'fs';
import { mkdirp } from 'mkdirp';
import * as report from 'cucumber-html-reporter';
let Cucumber = require('cucumber');
import { EventEmitter } from 'events';
const eventBroadcaster = new EventEmitter();

export class CucumberReportExtension {

private jsonDir = process.cwd() + "/reports/json";
private htmlDir = process.cwd() + "/reports/html";
private jsonFile = this.jsonDir + "/cucumber_report.json";

private cucumberReporterOptions = {
theme: "bootstrap",
jsonFile: this.jsonFile,
output: this.htmlDir + "/cucumber_reporter.html",
reportSuiteAsScenarios: true,
metadata: {
    "App Version":"0.0.1",
    "Test Environment": "TestingMicroSheet",
    "Browser": "Chrome  59.0.945",
    "Platform": "Windows 10",
    "Parallel": "Scenarios",
    "Executed": "Local"
  }
};

private CreateReportFile(dirName, fileName, fileContent) {
//Verify if the directory exists
if (!fs.existsSync(dirName))
    mkdirp.sync(dirName);
try {
    fs.writeFileSync(fileName, fileContent);
}
catch (message) {
    console.log("Failed to create File/Directory :" + message);
 }
}

private GenerateCucumberReport(cucumberReportOption){
report.generate(cucumberReportOption);
 }

 myJsonFormatter = new Cucumber.JsonFormatter({
       eventBroadcaster: eventBroadcaster,
       log: jLog => {
           this.CreateReportFile(this.jsonDir, this.jsonFile, jLog);
           this.GenerateCucumberReport(this.cucumberReporterOptions);
        }
 });
}
export let JsonFormatter = new CucumberReportExtension().myJsonFormatter;

Note: This code has not been tested yet, but it is expected to function correctly! I will provide updates once I have experimented with the new features of cucumber 3.0!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to update a deeply nested array of objects?

I have an array of objects with nested data that includes product, task, instrument details, and assets. I am attempting to locate a specific instrument by supplier ID and modify its asset values based on a given number. const data = [ { // Data for ...

The functionality of the KendoReact Grid for filtering and sorting is not functioning correctly when data is grouped

Once I group the data, the filter and sort functions in the KendoReact Grid stop working. Interestingly, if I bypass the grouping step and show the data without grouping, the filter and sort functions function perfectly fine. My main objective is to figu ...

The 'HTMLDivElement' type does not include the property 'prepend' in Typescript

When working with a typescript method, the following code snippet is used: some_existing_div.prepend(some_new_div) This may result in an error message: [ts] Property 'prepend' does not exist on type 'HTMLDivElement'. However, despi ...

Tips on enlarging the header size in ion-action-sheet within the VueJS framework of Ionic

Recently I started using Vue along with the ionic framework. This is a snippet of code from my application: <ion-action-sheet :is-open="isActionSheetOpen" header="Choose Payment" mode="ios" :buttons="buttons&qu ...

Can callback argument types be contingent on certain conditions? For example, could argument 0 be null if argument 1 is a string?

I am attempting to implement conditional type logic for the parameter types of a callback function. In this scenario, the first argument represents the value while the second argument could be an error message. type CallbackWithoutError = (value: string, ...

Customizing the initial page layout in Elm

I am new to Elm and I need help with a particular issue. Can someone provide guidance or direct me to a useful resource for solving this problem? The challenge I’m facing involves editing the start page of a website by removing specific elements, as list ...

Obtain the thread number of the current wdio instance

My automated UI tests run in parallel using the wdio maxInstances, generating a unique mobile number at the start of each test. 07 - All numbers start with this number. Next is a 9-digit number based on time & date - `new Date().getTime().toString(). ...

Is there a way to retrieve a compilation of custom directives that have been implemented on the Vue 3 component?

Is there a way to retrieve the list of custom directives applied to a component? When using the getCurrentInstance method, the directives property is null for the current component. I was expecting to see 'highlight' listed. How can I access the ...

The specified dependency, * core-js/fn/symbol, could not be located

I am in the process of developing a Vue.js application with Vuex and have encountered some errors during the build. I attempted to resolve the issue by installing npm install --save core-js/fn/symbol, but unfortunately, it did not work as expected. https:/ ...

Conceal or remove disabled years in Angular Material datepicker

I previously disabled years prior to 2018, but now I would like to hide or delete them. The year selection range currently starts from 1998, but it should begin at 2018 instead. Is there a way to display only 3-4 years instead of the current 24-year rang ...

What steps can be taken to avoid an abundance of JS event handlers in React?

Issue A problem arises when an application needs to determine the inner size of the window. The recommended React pattern involves registering an event listener using a one-time effect hook. Despite appearing to add the event listener only once, multiple ...

Launching a Node.js command-line interface to NPM, developed using TypeScript

I'm struggling with deploying my Node CLI tool to NPM. During development and testing, everything works fine. I can even use `npm link` on the repo without any issues. After successfully publishing and downloading the package, the application crashes ...

When trying to update a form field, the result may be an

Below is the code for my component: this.participantForm = this.fb.group({ occupation: [null], consent : new FormGroup({ consentBy: new FormControl(''), consentDate: new FormControl(new Date()) }) }) This is th ...

Attempting to perform an API invocation on a distant endpoint utilizing NestJS

var unirest = require("unirest"); var req = unirest("GET", "https://edamam-edamam-nutrition-analysis.p.rapidapi.com/api/nutrition-data"); req.query({ "ingr": "1 large apple" }); req.headers({ &qu ...

The color scheme in Visual Studio 2019 for Angular and Typescript code is quite unappealing

Currently following a Udemy course on Angular (Using Angular, Angular Material, Angularfire (+ Firebase with Firestore), and NgRx to create a functional Angular App). Instead of using VS Code, I decided to use Visual Studio 2019 to become more accustomed ...

Encountered a TypeScript error: Attempted to access property 'REPOSITORY' of an undefined variable

As I delve into TypeScript, a realm unfamiliar yet not entirely foreign due to my background in OO Design, confusion descends upon me like a veil. Within the confines of file application.ts, a code structure unfolds: class APPLICATION { constructor( ...

Is it possible to dynamically change an ngModel value directly from the component?

I'm currently immersed in an Angular project and my initial file setup was like this: dog.ts: export interface Dog { name: string; age: number; breed: string; } dog.component.ts: import { Dog } from '../dog'; @Component({ //setup ...

What changes can be implemented to convert this function to an asynchronous one?

Is it possible to convert the following function into an asynchronous function? getHandledSheet(): void { this.timesheetService.getAllTimesheets().subscribe({next: (response: TimeSheet[]) => {this.timesheetsHandled = response.filter(sheet => ...

The art of transforming properties into boolean values (in-depth)

I need to convert all types to either boolean or object type CastDeep<T, K = boolean> = { [P in keyof T]: K extends K[] ? K[] : T[P] extends ReadonlyArray<K> ? ReadonlyArray<CastDeep<K>> : CastDeep<T[P]> ...

The or operator in Typescript does not function properly when used as a generic argument

My current configuration is as follows: const foo = async <T>(a): Promise<T> => { return await a // call server here } type A = { bar: 'bar' } | { baz: 'baz' } foo<A>({ bar: 'bar' }) .then(response =& ...