Although the cucumber tests indicate success, protractor fails to interact with the elements on the webpage

Recently, I delved into the realm of Protractor+Cucumber+Typescript and devised a sample framework utilizing Page Object Design along with a small script to execute some click actions. URL:

My endeavor to click on the "Customer Login" button seems futile as it fails to interact with the element while Cucumber still displays the test as passed.

I attempted to leverage async/await for promise handling but unfortunately without success. Protractor Version: 5.4.2 TypeScript Version: 3.3.4000 Node Version: v10.15.3 NPM version: 6.4.1

Feature File:
Feature: Authentication at XYZ bank

@OutlineScenario
Scenario: Customer Access

Given I navigate to XYZ Bank's homepage
Then I initiate the Customer Login process
Then I specify the Customer Name
Then I proceed with the login action

Page Object:

    import { element, by } from "protractor";
    import { Select } from "../utilities/selectClass";
  export class loginPage {

        //elements

        customerLoginButton = element(by.cssContainingText('.btn btn-primary btn-lg', 'Customer Login'));
        loginButton = element(by.className('btn btn-default'));
        yourNameDropDown = element(by.model('custId'));
        bankManagerLoginButton = element(by.xpath("//button[contains(text(),'Bank Manager Login')]"));
        homeButton = element(by.className('btn home'));

        //function to trigger Customer Login
        customerLogin() {
            this.customerLoginButton.click();
        }

        //function to choose a Name from the Dropdown
        selectName() {
            const select: Select = new Select(this.yourNameDropDown);
            select.selectByVisibleText("Harry Potter");
        }

        //function to execute the Login action
        clickLogin() {
            this.loginButton.click();
        }

        //function to activate Bank Manager Login
        bankManagerLogin() {
            this.bankManagerLoginButton.click();
        }

        clickHome() {
            this.homeButton.click();
        }
    }

StepDefinition:

import {loginPage} from "../pages/loginPage";
import {addCustomer} from "../pages/addCustomer";
import { browser } from "protractor";
import { Then, Given } from "cucumber";
const chai = require("chai").use(require("chai-as-promised"));
const expect = chai.expect;
const login: loginPage = new loginPage();
const addcustomer: addCustomer = new addCustomer();

Given('I navigate to XYZ Bank\'s homepage', function() {
    expect(browser.getTitle()).to.eventually.equal("Protractor practice website - Banking App");
   });

Then(/^I initiate the Customer Login process$/, function() {
   login.customerLogin();
  });

  Then('I specify the Customer Name', function() {
   login.selectName();
 });

 Then('I proceed with the login action', function () {
   login.clickLogin();
 });

config.ts

import { browser, Config } from "protractor";
import { Reporter } from "../utilities/reporter";
const jsonReports = process.cwd() + "/reports/json";

export const config: Config = {
    seleniumAddress: "http://127.0.0.1:4444/wd/hub",

    SELENIUM_PROMISE_MANAGER: false,

    baseUrl: "http://www.way2automation.com/angularjs-protractor/banking/#/login",

    capabilities: {
        browserName: "chrome",
    },

    framework: "custom",
    frameworkPath: require.resolve("protractor-cucumber-framework"),

    specs: [
        "../../features/*.feature",
    ],

    onPrepare: () => {
        browser.ignoreSynchronization = true;
        browser.manage().window().maximize();
        Reporter.createDirectory(jsonReports);
    },

    cucumberOpts: {
        compiler: "ts:ts-node/register",
        format: "json:./reports/json/cucumber_report.json",
        require: ["../../typeScript/stepdefinitions/*.js", "../../typeScript/utilities/*.js"],
        strict: true,
        tags: "@CucumberScenario or @ProtractorScenario or @TypeScriptScenario or @OutlineScenario",
    },

    onComplete: () => {
        Reporter.createHTMLReport();
    },
}

Answer №1

If you are utilizing the Control Flow in webdriver (as opposed to async/await), it is necessary to ensure that you return the last line of each step, even when using expects that involve eventually. For instance, if login.customerLogin() returns a promise that remains unresolved, you must use return login.customerLogin() so Cucumber can handle its resolution.

On a related note, we have observed that transitioning to async/await instead of control flow has significantly alleviated the challenges associated with writing tests in protractor. It is remarkable how many times a simple omission of returning a single step or assertion resulted in false positives or obscure errors.

Answer №2

When working with Protractor, it's important to remember that its functions run asynchronously. This means you need to wait for the promises to be resolved before moving on. One way to do this is by using the then function. If you're looking for a guide on promises, check out this resource.

Another approach to handling promises in Protractor is through the use of async/await. This method is recommended as it makes your code more readable. Simply make all your step definition functions async and call Protractor functions with await, which will pause execution until the promise is resolved. Your 'customer login' function and step should look something like this:

async customerLogin() {
    await this.customerLoginButton.click();
}

Then(/^I click Customer Login$/, async function() {
    await login.customerLogin();
}

If you opt for async/await, there's no need to use chai-as-promised because using await on an async function returns the value similarly to how chai's eventually works. This effectively waits for a promise to resolve. Therefore, replace your current 'I am on XYZ Bank home page' step with the following:

expect(await browser.getTitle()).to.equal("Title");

For further reading, here are some useful sources:

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

Discovering the Type Inference of Function Composition Method (Chaining) in TypeScript

I'm working on implementing a function that can add a chainable method for function composition. Here's what I have so far: Also see: TypeScript playground { const F = <T, U>(f: (a: T) => U) => { type F = { compose: <V ...

How can Jest be configured to test for the "permission denied" error?

In my Jest test, I am testing the behavior when trying to start a node http server with an invalid path for the socket file: describe('On any platform', (): void => { it('throws an error when trying to start with an invalid socket P ...

Tips for resolving TS7022 issue within Vue Composition API

I encountered an issue while attempting to import a component in my file that generated the following error message: TS7022: 'default' implicitly has type 'any' because it does not have a type annotation and is referenced directly or in ...

Angular form requests can utilize the Spring Security Jwt Token to allow all options methods

Despite checking numerous sources online, I am facing a persistent issue with my Angular application. The problem arises when using HttpClient along with an Angular interceptor to set headers for authentication in my Java Rest API using JWT tokens. The int ...

Tips on validating interconnected strings with the help of yup within a react native environment

In my scenario, I am dealing with two date strings called start_date and end_date. Initially, both of these start off as empty strings: export interface FilterSchema { start_date?: any; end_date?: any; } const initialValues: FilterSchema = { s ...

Unable to retrieve the third attribute of a Class using Angular2's toString method

Here is the code snippet I am working with: import { Component } from '@angular/core'; @Component({ selector: 'my-app', template: ` <h1>Hello {{name}}</h1> <p><strong>Email:</strong> {{email}}< ...

Is there a method in TypeScript to make an enum more dynamic by parameterizing it?

I've defined this enum in our codebase. enum EventDesc { EVENT1 = 'event 1', EVENT2 = 'event 2', EVENT3 = 'event 3' } The backend has EVENT1, EVENT2, EVENT3 as event types. On the UI, we display event 1, event 2, a ...

Incorporating Swift code into a NativeScript app

I'm attempting to integrate native Swift code into my NativeScript application. Despite following the guidelines provided in the documentation, specifically adding a Swift source file to App_Resources/iOS/src/ and using publicly exposed classes direct ...

Tips for declaring a particular type during the process of destructuring in Typescript

I have my own custom types defined as shown below: export type Extensions = | '.gif' | '.png' | '.jpeg' | '.jpg' | '.svg' | '.txt' | '.jpg' | '.csv' | '. ...

The Vuex MutationAction decorator cannot be assigned to a TypedPropertyDescriptor

I am a beginner in Typescript and apologize in advance if this is a rookie mistake. I am struggling to resolve this TS error: @Module({ namespaced: true, name: "Admin" }) class Admin extends VuexModule { public adminUserList: UserList = []; ...

Adjust website content depending on user's authentication status

My goal is to display a logout button when the user is logged in and a login button if they are not. I am using JSON tokens to determine if a user is logged in or not, by checking if the token is null. However, this approach does not seem to be working. Ca ...

Attempting to update Typescript on Linux Mint using npm

I am currently using typescript 2.1.4 and npm version 6.7.0. Realizing that 2.1.4 is quite outdated, I decided to try and update it. Here are the steps I took, which unfortunately did not work: $ sudo npm update -g typescript $ tsc --version Vesion 2.1. ...

Steps for incorporating a filter feature in an Angular Material table

.HTML: Can someone assist me with implementing a filter in this component? I tried using it with the expansion table, but unfortunately, the filter is not working as expected. <mat-dialog-content style="width: 63rem; overflow: initial;"&g ...

Exploring the power of utilizing multiple classes with conditions in Angular 2+

Can you help me figure out how to use a condition for selecting multiple classes with [ngClass] in Angular? <td> <span [ngClass]="{ 'badge badge-success': server.type === 'PRODUCTION', 'ba ...

Implement a nested filter in Angular 8 to enhance data manipulation

Is it possible to apply a filter inside another filter in this scenario? I have a table of orders with nested tables of services, and I want to only display the orders where the type of service is 'type1'. I tried using the following line of code ...

Embarking on your ABLY journey!

Incorporating https://github.com/ably/ably-js into my project allowed me to utilize typescript effectively. Presently, my code updates the currentBid information in the mongodb document alongside the respective auctionId. The goal is to link the auctionId ...

Conditions are in an angular type provider with AOT

I am facing an issue with my Angular project that is compiled using AOT. I am trying to dynamically register a ClassProvider based on certain configurations. The simplified code snippet I am currently using is below: const isMock = Math.random() > 0.5; ...

attempting to pass a boolean type through props resulting in a type error

Hey, check out this component I created: import * as Styled from './styles'; export type HeadingProps = { children: React.ReactNode | string; colorDark: boolean; }; export const Heading = ({ children, colorDark }: HeadingProps) => { re ...

The pipe operator in Angular is failing to function as intended

I encountered an error while using the replace operator in Angular. Can someone help me identify the issue? Check out this link for more information ...

What is the process for executing cucumber tests using a batch file?

I am looking to execute my Cucumber Features using a custom batch file, but I need guidance on how to achieve this. The batch file should provide the capability to run specific test cases based on Tags or feature files of my choice. ...