Navigating Protractor's Configuration File: Setting Up Error Messages

After working extensively with protractor, I've encountered an issue where a thrown error for timeout is displayed if an element is not found within 60 seconds. This default error message doesn't provide much insight into the actual problem. I'm seeking advice on how to customize error messages for scenarios when a specific element is not found.

Here's a snippet of my code:

Test case class:

const userData = require("../globalContent.json");
const Page = require("../objects/ikeaProductPage.obj");


describe("Product page", function () {

    ikeaPage = new Page();

    for (let [link, amount] of Object.entries(userData[browser.baseUrl])) {
        // The Ikea page is accessible by the specified URL
        it(`Is defined by the URL: ${link}`,
            async function() {
                await Page.navigateDesktop(`${link}`);
            });

        // page has a quantity label and it can be filled out with user data
        it("Has a label quantity that can receive user data",
            async function() {
                await Page.fillFormWithUserData(`${amount}`);
            });

        // Details page allows the user to add to cart
        it("Enables resolution of added to cart",
            async function() {
                await Page.hasAddToShoppingCart();
            });

        // Details page allows the user to proceed to the next stage when page has been resolved
        it("Allows the user to proceed to the next stage of add to cart",
            async function() {
                await Page.hasAddedToBag();
                await browser.sleep(1000);
            });
    }
});

Object class:

const utils = require("../utils/utils");
const Specs = require("../specs/ProductPage.specs");

module.exports = class Page {

    constructor() {
        const _fields = {
            amountInput: Specs.productAmount
        };

        const _formButtons = {
            addToCart: ikeaSpecs.addToCart
        };

        const _productFrame = {
            cartIcon: ikeaSpecs.cartIcon,
            addedToCartIcon: Specs.addedToCart,
        };

        this.getFields = function() {
            return _fields;
        };
        this.getFormButtons = function() {
            return _formButtons;
        };
        this.getFrame = function() {
            return _productFrame;
        };
    }

    getForm() {

        return {
            fields: this.getFields(),
            buttons: this.getFormButtons(),
        };
    }

    getPageFrame() {
        return {
            buttons: {
                iconFrames: this.getFrame()
            }
        };
    }


    //Navigate for Desktop
    async navigateDesktop(URL) {
        await browser.waitForAngularEnabled(false);
        await browser.manage().window().maximize();
        await browser.get(URL);
    }

    //Fill qty from globalContent.json
    async fillFormWithUserData(amountQuantity) {
        const formFields = this.getForm().fields.amountInput;
        await formFields.clear();
        await utils.sendKeys(formFields, amountQuantity);
    }

    //Check if we can add to shopping cart
    async hasAddToShoppingCart() {
        const formButton = this.getForm().buttons.addToCart;
        await utils.elementToBeClickable(formButton);
        await utils.click(formButton);
    }

    //Check if the product has been added
    async hasAddedToBag() {
        const frameCartIcon = this.getPageFrame().buttons.iconFrames.cartIcon;
        const frameAddedToCart = this.getPageFrame().buttons.iconFrames.addedToCartIcon;
        await utils.presenceOf(frameCartIcon);
        await utils.elementToBeClickable(frameAddedToCart);
    }

};

utils:

const utils = function () {
    var EC = protractor.ExpectedConditions;

    this.presenceOf = function (params) {
        return browser.wait(EC.presenceOf(params));
    };

    this.elementToBeClickable = function (params) {
        return browser.wait(EC.elementToBeClickable(params));
    };

    this.sendKeys = function (params, userData) {
        return params.sendKeys(userData);
    };

    this.click = function (params) {
        return browser.executeScript("arguments[0].click();", params.getWebElement());
    };

    this.switch = function (params) {
        return browser.switchTo().frame(params.getWebElement());
    };

    this.switchDefault = function () {
        return browser.switchTo().defaultContent();
    };
};

module.exports = new utils();

I'm interested in learning how I can handle errors more effectively instead of just relying on timeouts?

Answer №1

When utilizing the browser.wait function internally, it is important to explore and leverage its various parameters, as recommended by the documentation. The function accepts three parameters, each serving a distinct purpose:

browser.wait(
  () => true, // define your waiting condition
  timeout, // specify a timeout value (default is set to jasmineNodeOpts.defaultTimeoutInterval)
  optionalMessage // provide an optional message for better context
)

Revised Version

If all three parameters are utilized together, the implementation would resemble the following example:

this.presenceOf = function (element, customMessage) {
  return browser.wait(
    EC.presenceOf(element),
    jasmine.DEFAULT_TIMEOUT_INTERVAL,
    `Element ${element.locator().toString()} is not found. Message: ${customMessage}`
  )
};

Subsequently, calling the function would appear as shown below:

await utils.presenceOf(cartButton, 8000, "expecting cart button");

In the event of failure, an error stack similar to the following would be generated:

      - Failed: Element By(css selector, "specific css path") is not present. Message: expecting cart button
      Wait timed out after 500ms
      Wait timed out after 500ms
          at /Users/johndoe/project-folder/node_modules/selenium-webdriver/lib/promise.js:2201:17
          at ManagedPromise.invokeCallback_ (/Users/johndoe/project-folder/node_modules/selenium-webdriver/lib/promise.js:1376:14)
          at TaskQueue.execute_ (/Users/johndoe/project-folder/node_modules/selenium-webdriver/lib/promise.js:3084:14)
          at TaskQueue.executeNext_ (/Users/johndoe/project-folder/node_modules/selenium-webdriver/lib/promise.js:3067:27)
          at asyncRun (/Users/johndoe/project-folder/node_modules/selenium-webdriver/lib/promise.js:2927:27)
          at /Users/johndoe/project-folder/node_modules/selenium-webdriver/lib/promise.js:668:7
          at processTicksAndRejections (internal/process/next_tick.js:81:5)
      From: Task: Element By(css selector, "specific css path") is not present. Message: expecting cart button

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

Having trouble launching the react app with npm start command

Attempting to launch a react app created by someone else. The instructions provided stated that in order to start it, I need to follow these steps To initiate the webpack dev script, execute npm start [appname]. The term [appname] corresponds to an appli ...

Preventing drag and drop functionality within the knockout js sortable feature

How can I selectively disable drag and drop on certain squares within a 5x5 grid while using the sortable feature in knockout js? Any suggestions or solutions for this specific use case? ...

Error encountered in 11ty: Invalid operation - eleventyConfig.addPassthroughCopy is not a recognized function

Attempting to integrate my CSS and JavaScript codes into 11ty has been a bit challenging for me. I recently discovered that 11ty utilizes something called .11ty.js, so I decided to utilize the addPassthroughCopy() function. Below is the script I tried: mo ...

Use jQuery to swap out two div classes within a table cell (TD) if they are

Although I'm making progress, I must confess that jQuery and CSS are not my strong suits. The objective: To create a dynamic div within a table data cell for a calendar feature. The content of the div varies based on the date range input. A filled d ...

Having trouble implementing new controllers in AngularJS UI-Router for nested states?

I'm currently facing an issue with nested states in the ui-router. My task involves rendering a page that includes regions, countries, and individuals per country. In the index.html file, there are three regions represented as links: EMEA, APAC, and ...

Looking up a destination with the Google Places API

My dilemma lies in dealing with an array of place names such as 'Hazrat Nizamuddin Railway Station, New Delhi, Delhi, India' and similar variations. These variations serve as alternative names for the same location, adding complexity to my task. ...

Changing the value of an input field based on a user's input

Looking to automatically format any input in an input field as currency: <input type="text" value="0,00 EUR" onChange={(e) => { e.target.value = convertToCurrency(e.target.value) }} /> const convertToCu ...

Building a matrix-esque table using d3.js reminiscent of HTML tables

I would like to generate a table resembling a matrix without numerical values. 1. Here is an example of my database table: | CODE | STIL | SUBSTIL | PRODUS | |------|-------|----------|---------| | R | stil1 | substil1 | produs1 | | R | stil1 | s ...

Adding AngularJS to Syncfusion grid or making the rows clickable and running AngularJS functions can be achieved by following these steps

I'm currently incorporating angularJs and Syncfusion to display data in a table using the Syncfusion grid (). However, I'm encountering difficulties in utilizing angularjs functions within this grid: <div class="table-responsive grid-tog ...

Using Javascript/React to filter an array by a specific value

{ "team_group": ["Alex Smith", "Jake Brown", "Sarah King"], "group_data": { "Alex Smith": { "status": "member" }, "Jake Brown": { "status": &qu ...

Unable to move cursor in contenteditable section

I am currently working on developing a rich text editor in React, but I have encountered an issue that has me stuck. The problem I am facing is that as I type each character, the insertion point does not update accordingly, causing the cursor to remain stu ...

PHP script to automatically update a table in a database upon the closure of a

I recently experimented with the following code snippet: <script> function myFunction() { return "You have not logged out of your account. Do you want to leave without logging out? "; } </script > <body onbeforeunload="return myFun ...

Generate 2 configurations for webpack

Currently, I am facing a challenge while building a webpack file. The issue arose when I needed to incorporate the 'node' target due to conflicts with an 'fs' function that reads certain files. Subsequently, I decided to split my config ...

Issue: [unresolved] Provider not recognized: $resourseProvider <- $resourse <- Phone Angular factory

I'm encountering an issue with injecting a resource. Error: [$injector:unpr] Unknown provider: $resourseProvider <- $resourse <- Phone Here is my code: index.html <script src="bower_components/angular/angular.js"></script> < ...

The Toggle Switch effectively removes the CSS class when set to false, but fails to reapply the class when set to true

Implementing a toggle switch using Bootstrap5 to control the visibility of grid lines. The setup includes adding a class to display grid lines when the toggle is true, and removing the class to hide the lines when the toggle is false. However, the issue ar ...

How can we universally detect and resolve the user's language within a React/Next.js application using an Apollo client HOC?

Currently, I am developing an I18n module utilizing the Next.js framework (v5). The challenge I am facing is determining the user's default language universally in order to display the UI in that language. While it is relatively simple to resolve th ...

What is the process of submitting a query request and then saving it as a variable in javascript?

As a beginner in SQL, JSON, and Fusion Table, I am looking to extract data from a Fusion Table and store it in a JavaScript variable, allowing me to display the data within a div element. This is the progress of my JavaScript code so far: var TopCity; To ...

JS causes the navigator to malfunction

UPDATE: Greetings! I have developed a navigation bar that loads various pages into a specific div. Here is the source code for the navigation bar: <div id="navBar"> <ul> <li><a href="#" onClick="document.getElementById('bott ...

Efficiently Minimize Bootstrap Components Upon Clicking the Link

I've successfully created a navigation menu that expands and collapses without using a dropdown feature. However, I'm encountering an issue where I can't seem to toggle the div when clicking on a menu link. I attempted to use JavaScript to c ...

What is the most efficient method to determine the most recent update to a MongoDB document?

Is it necessary for me to add lastActivity: new Date() @set every time I use it, or is there a more efficient method? ...