Developing a modular login feature using Selenium WebDriver and Mocha framework

I am currently in the process of creating a login function specifically for mocha testing and selenium-webdriver to facilitate unit testing. I have numerous tasks that involve scenarios where "user logs in and...".

My attempt at the code below seems to be causing issues as when I run it, the console just displays:

Already registered user logs in and sees homepage
  1) should work (it's red text)

Login an existing user

After this display, nothing further happens, forcing me to exit the process using control-C. The code was functioning perfectly until I attempted to implement this modular login system, leading me to believe that is where the problem lies. Could there be something vital that I'm overlooking? Any feedback on my approach towards creating the login function would also be greatly appreciated considering my limited experience with webdriver.

Displayed below is all of the code, contained within a single JavaScript file.

var test = require('selenium-webdriver/testing'),
chai = require('chai');
chai.use(require('chai-string'));
chai.use(require('chai-as-promised'));
var expect = chai.expect,
webdriver = require('selenium-webdriver'),
By = webdriver.By;

// My aim is to create a reusable modular login function
function login(driver) {
    test.describe('Login an existing user', function() {
        test.it('should work', function() {
            this.timeout(0);

            var email = '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6f02160a020e06032f1b0a1c1b410c0002">[email protected]</a>';
            var password = 'password';

            driver.get('http://localhost:9000');

            driver.getTitle().then(function(title) {
                expect(title).to.equal('my title');
            })
            .then(function() {
                // do login stuff and click login button
            });
            .then(function() {
                return driver;
            });
        });
    });
}

// Example showcasing the usage of the login function
test.describe('Already registered user logs in and sees homepage', function() {
  test.it('should work', function() {

    this.timeout(0);
    var driver = new webdriver.Builder().
    withCapabilities(webdriver.Capabilities.chrome()).
    build();

    driver = login(driver)
    .then(function() {
        driver.findElement(By.xpath("relevant xpath")).click();
    })
  })
})

Answer №1

When you call login within test.it, it is essentially like calling describe inside it, which is against the rules of Mocha. Mocha does not allow invoking describe or it from within another it. This behavior can lead to unpredictable outcomes, as observed in your case. In rare instances, these unexpected behaviors may align with developer expectations purely by chance, not by design.

To fix this issue, simply remove the calls to test.describe and test.it from inside login, ensuring that you return a promise instead. While you can still use expect, avoid calling this.timeout(0) within login.

function login(driver) {
    var email = 'example@example.com';
    var password = 'password';

    driver.get('http://localhost:9000');

    return driver.getTitle().then(function(title) {
        expect(title).to.equal('my title');
    })
    .then(function() {
        // perform login actions and click login button
    })
    .then(function () {
        return driver;
    });
}

Update your calling code as follows:

var promise = login(driver)
.then(function(driver) {
    driver.findElement(By.xpath("relevant xpath")).click();
});

You have flexibility in how you handle the promise, but remember that driver is not a promise itself, so assigning it directly won't function properly.

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

Convert Roman Numerals with freecodecamp programming site

Why is it that the initial code snippet, which uses decimal numbers as keys and Roman numerals as values, fails the input-output test on freecodecamp.com for converting decimal numbers to Roman numerals? Conversely, the alternate code snippet, where the ke ...

What advantages do combined getter and setter methods offer?

In my experience, I have come across APIs that use combined getter and setter methods, particularly in scripting languages like Perl and JS used within our team. One example of this is seen in jQuery: //append something to element text var element = $(&ap ...

Invoking a function from a higher-level parent scope within multiple layers of nested directives

I am working with a data structure that is nested infinitely. There is a top-level object containing a collection of objects, and each of these objects can also have their own collection of objects. To iterate through this tree, I have implemented the fol ...

Is it considered beneficial to use Observable as a static class member?

Lately, I have been diving into a new Angular project and noticed that the common way to share state between unrelated components is by using rxjs Subject/BehaviorSubject as static members within the class. For instance: export class AbcService { privat ...

Creating a dynamic list that loads and renders content in real-time

I need to incorporate a unique list feature on my website that functions in the following manner: 1. On the homepage, a list should be displayed showing only the initial 12 items, followed by a "load more..." button. 2. Immediately after the page loads, ...

My type is slipping away with Typescript and text conversion to lowercase

Here is a simplified version of the issue I'm facing: const demo = { aaa: 'aaa', bbb: 'bbb', } const input = 'AAA' console.log(demo[input.toLowerCase()]) Playground While plain JS works fine by converting &apo ...

The error message "Uncaught (in promise) ReferenceError: dispatch is not defined" indicates that

Currently, I am utilizing vuex with index.js and auth.js stored in the store folder. My goal is to perform a basic sign-in operation within my signin.vue by calling an action from the store. However, I encountered the error 'Uncaught (in promise) Refe ...

In MongoDB and Node.js, encountered error: 'Unable to access property 'collection' as it is undefined'

I'm encountering a type error with my collection function that was previously functioning without any issues. This code was working perfectly in another project of mine. After reusing a lot of the code, I started experiencing this error. My MongoDB c ...

Asynchronous functions within the next context

Hello there! I am trying to send the client's IP address from the frontend in a Next.js application to the backend. To retrieve the IP, I am using the following function: async function getIP() { var clientIP = await publicIp.v4(); ...

The TypeScript inference feature is not functioning correctly

Consider the following definitions- I am confused why TypeScript fails to infer the types correctly. If you have a solution, please share! Important Notes: * Ensure that the "Strict Null Check" option is enabled. * The code includes c ...

How to use jQuery to select an element by using 'this' on a button

I have a total of 5 divs, each containing 5 different texts. <div class="text"> <%= theComment.text %> </div> I am working with node.js, MongoDB, and Mongoose. In addition to the divs, I also have a button labeled EDIT with a cl ...

"Utilizing VueJS XHR functionality within a versatile and reusable component

Seeking advice on best practices for improving the following scenario: I have a single global reusable component called <MainMenu>. Within this component, I am making an XHR request to fetch menu items. If I place <MainMenu> in both the heade ...

Trouble with bootstrap 5 nested accordions: panels won't collapse as expected

I've structured my page content using nested bootstrap accordions within Bootstrap 5. The primary accordion is organized by continents, with each panel containing a secondary accordion for individual countries. While the main accordion functions cor ...

What is the best way to create a sidebar that remains open without triggering a new sidebar every time it is clicked

I am looking to add a sidebar that opens a new view without navigating to a different page. The sidebar remains consistent and I want to avoid duplicating it on all pages. Check out this photo for an example. My goal is to provide additional content or fe ...

JavaScript - exploring techniques to alter the relationship between parents and children

I'm facing an issue with transforming the parent-child relationship in my data structure. Currently, it looks like this: { "id": 7, "name": "Folder 1", "parent_folder": null, "folders": ...

Controlling SVG elements within React

Just starting my programming journey and currently diving into building a surf app using React JS. For the landing page, I want to display location pins on an image of a coastline. These pins should be clickable, leading users to detailed information about ...

Interactive React Dropdown Component

As a relatively new React user, I am attempting to develop a custom component that will showcase a list of items within a select menu. The goal is to allow the user to make a selection from the menu and then click an "Add" button below it. Upon clicking th ...

Instructions for transferring an email attachment to a collaborative drive stored in a Google Sheets document

At the moment, I am utilizing a Google script that runs periodically on my Gmail account to retrieve all attachments labeled according to certain criteria. The issue arises when trying to access attachments within a folder located on a shared drive using t ...

Securing routes in Node.js using Passport.js

Within my express app, the main server code is contained in the server.js file. In this file, there is a route defined as app.get('/dashboard',require('./dashboard/dashboard.js'). The dashboard.js file contains multiple routes such as ...

Experimenting with the testing of two distinct functions

Hello, I am new to the world of testing and I would appreciate some guidance. I have two functions that I need help with. The first function is a bits-per-second converter that converts data into a more readable format. const convertBitrate = bitrate =&g ...