Setting up CucumberJs, Protractor, and TypeScript for Ionic2/Angular2 Projects

Having limited knowledge in TypeScript and Angular2, I've been attempting to run cucumber's features using steps written in TypeScript. However, when executing the steps.ts files, I encounter the following error message:

[launcher] Running 1 instances of WebDriver
[launcher] Error: TypeError: step.Given is not a function
    at Object.module.exports (/Users/roalcantara/Documents/Tango/tango/test/features/step_definitions/signIn.steps.ts:13:8)
    ...

It appears that the cucumber definitions were not properly compiled.

Here are my relevant configurations:

My directory structure looks like this:

/test/
|-/features/
|-xpto.feature
|--/step_definitions
|---xpto.step.ts

/package.json

{
  "name": "Tango",
  "version": "0.0.1",
  ...

/typings.json

{
  "dependencies": {},
  ...

/protractor.conf.js:

// @AngularClass
require('ts-node/register');
var helpers = require('./helpers');
...

One example of a step_definition file is:

/test/features/step_definitions/signUp.steps.ts

import cucumber = require('cucumber')
import {SignUpPage} from '../pages/signUp.page';
import {SignInPage} from '../pages/signIn.page';
...

Is there anything crucial that I might have overlooked?

Answer №1

The key to success was correcting the export declaration like so:

import {StepDefinition} from 'cucumber';
import {LoginPage} from '../pages/login.page';
import {HomePage} from '../pages/home.page';

let chai = require('chai').use(require('chai-as-promised'));
let expect = chai.expect;

export = function() {

  let loginPage = new LoginPage();
  let homePage = new HomePage();

  this.When(/^I navigate to login page$/, (callback:StepDefinition) => {
    loginPage.goToLoginPage();
    callback();
  });

  this.When(/^I enter 'username' as '([^"]*)'$/, (username:string, callback:StepDefinition) => {
    loginPage.enterUsername(username);
    callback();
  });

  this.When(/^I enter 'password' as '([^"]*)'$/, (password:string, callback:StepDefinition) => {
    loginPage.enterPassword(password);
    callback();
  });

  this.When(/^I click on 'Login' button$/, (callback:StepDefinition) => {
    loginPage.clickLoginButton();
    callback();
  });

  this.Then(/^I should see 'welcome message' '(.*)'$/, (message:string, callback:StepDefinition) => {
    let isDisplayed = (message === 'visible');
    expect(homePage.verifyWelcomeMessage()).to.become(isDisplayed).and.notify(callback);
  });
};

Following that adjustment, the cucumber tests executed smoothly.

Answer №2

To enhance your protractor.conf.js, consider removing the compiler option from cucumberOpts.

  cucumberOpts: {
    format: 'pretty',
    require: [
      'test/features/step_definitions/**/*.steps.ts'
    ],
    //compiler: 'ts:ts-node/register' can be removed
  },

Next, ensure your signUp.steps.ts aligns with this structure:

let chai = require('chai').use(require('chai-as-promised'));
let expect = chai.expect;

import {SignUpPage} from '../pages/signUp.page';
import {SignInPage} from '../pages/signIn.page';

import Callback = cucumber.CallbackStepDefinition;

//Start by creating a class
class SignupSteps{

  private index:SignInPage = new SignInPage();
  private page:SignUpPage = new SignUpPage();

  this.Given(/^I am not authenticated$/, (callback:Callback) => {
    index.openApp();
    callback();
  });

  this.When(/^I go to register$/, (callback:Callback) => {
    index.signUp();
    callback();
  });

  //Include steps for filling in form fields, submitting, and validating

}

//Expose the class by exporting it
export = SignupSteps;

For cleaner step definitions, you may explore https://github.com/timjroberts/cucumber-js-tsflow.

Discover a complete implementation at https://github.com/samvloeberghs/protractor-gherkin-cucumberjs-angular2.

Cheers

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 significance of utilizing an empty value `[]` for a typed array interface instead of using an empty `{}` for a typed object interface?

Why can I initialize friends below as an empty array [], but not do the same for session with an empty object {}? Is there a way to use the empty object without needing to make all keys optional in the interface? const initialState: { friends: Array< ...

Exploring the power of Typescript functions within a traditional VueJS project

TL;DR: How can I import and use a typescript module into my plain js Vue-Components? I have a Vue 2 (not yet 3) project. In this specific project, I have made the decision to refactor some of the code logic into ES modules for improved testability and reu ...

Concealing specific menu options for individual users within Angular 2

I have developed an angular application that features a login form with authentication using service and guard mechanisms. Within the authentication.service.ts file, I have created an interface called user with fields for username and password. Two users, ...

Why aren't the child elements in my React / Framer Motion animation staggered as expected?

In my finance application, I am creating a balance overview feature. To display the content, I pass props into a single <BalanceEntry> component and then map all entries onto the page. With Framer Motion, my goal is to animate each rendered <Bala ...

When using the router to send state, it returns as undefined

My scenario involves a component that utilizes the router to navigate to another component using a boolean variable in the URL: this.router.navigate(['/consume/course/' + this.id, {state: { isFirst }} ], { replaceUrl: true }); In the destination ...

Adding attributes dynamically to input elements in a React render function

I currently have an input tag inside my render function which looks like this: <input id="time" type="time"> I am now looking to dynamically add the value attribute to it. Is there a way to achieve this in React? Thank you for your help in advance ...

Issues with toggling the menu on Angular 14 using Bootstrap 4.6

I am struggling with implementing a menu on the header section of my Angular 14 homepage. The menu I added is not opening as expected. Even after trying various working menu samples from the internet, I couldn't get it to work in my project. Here are ...

Evaluating an AngularJS application using Selenium

Exploring the functionalities of an AngularJS application Discover more about Angular JS App Encountered an error while clicking on the UI Kit link on the website - Error at demoaj.Ajapp.main(Ajapp.java:16) Caused by: org.openqa.selenium.NoSuchEleme ...

Checking the types for object literals returned from Array.map functions

Check out this demonstration I made in the TypeScript playground: interface Test{ a: string b: string } const object: Test = { a: 'b', b: 'c', } function testIt(): Test[] { const data = [{b: '2', c: &apo ...

The type 'Document<any>' cannot be assigned to type 'Pick<Pick<_LeanDocument<TicketDoc>>'

My terminal is throwing an error that seems as clear as mud: TSError: ⨯ Unable to compile TypeScript: [orders-depl-9fbcb84ff-ngt2z orders] src/models/ticket.ts(47,5): error TS2322: Type 'Document' is not assignable to type 'Pick<Pick& ...

What is the method for creating pipes that filter multiple columns?

My pipe is designed to work exclusively for the "name" column and not for the author anymore. transform(items: Book[], filter: Book): any { if (!items || !filter) { return items; } // Filter items array; keep items that match and retu ...

Retrieve items from the <ng-content></ng-content> within the corresponding component in the TypeScript file

I'm facing an issue where I can't retrieve elements from ng-content within the same component. Here is my setup: Component HTML <div> <ng-content #action></ng-content> <app-comp2></app-comp2> </div> Component ...

What could be causing the conditional div to malfunction in Angular?

There are three conditional div elements on a page, each meant to be displayed based on specific conditions. <div *ngIf="isAvailable=='true'"> <form> <div class="form-group"> <label for ...

Activation of Angular SwUpdate deprecation

Within my Angular project, I am currently utilizing the following code snippet: this.swUpdate.available.subscribe(() => { ... }); While this code functions correctly, it does generate a warning regarding the deprecation of activated. How can I addre ...

Access the child component within an @ChildComponent directive in Angular

Is it possible to retrieve child components of another component? For instance, consider the following QueryList: @ContentChildren(SysColumn) syscolumns: QueryList<SysColumn>; This QueryList will contain all instances of the SysColumns class, which ...

How to deactivate Kendo Dropdownlist in Angular 2

Currently, I am attempting to disable a kendo-dropdownlist (named ddlChargeType). The goal is to prevent the user from manually selecting a value, while still allowing for programmatic selection (such as when a valid option is chosen in another dropdown, ...

Here is a guide on showcasing information obtained from ASP.NET API in Angular version 13

My goal is to fetch motorcycle data from a web API and showcase it in my Angular project. ASP.NET Framework Web API 4.7 Angular CLI: 13.3.7 Angular: 13.3.11 On the Web API end: Controller: [EnableCors(origins: "*", headers: "*", ...

Using Moneris with Google Pay in Angular

I'm currently working on implementing Google Pay with Moneris Gateway using the Google-Pay-button-Angular library. However, I'm unsure of how to connect Moneris with it. I followed a tutorial provided in this link but I'm unsure where to inp ...

Is it possible to enforce strict typing for a property within an object that is declared as type 'any'?

In my code, I am dealing with a parent object of type 'any' that remains constant and cannot be changed. Within this context, I need to define a property for the parent object, but no matter what I try, it always ends up being loosely typed as &a ...

Is it possible for me to create an interface that is derived from a specific type?

Is there a way to define an interface in TypeScript where the keys are based on a specific type? For example: type FruitTypes = "banana" | "apple" | "orange"; interface FruitInterface { [key: string]: any; // should use FruitTypes as keys instead of str ...