toggle between utilizing the page object API and the primary Nightwatch API

Currently, I am incorporating the page object model alongside nightwatch for my testing procedures. Encountering challenges while trying to interact with an element led me to execute some jquery. However, the 'execute' command is not featured in the available subset of commands within the page object api. To utilize it, I am required to invoke the complete nightwatch command api. For further information on this matter, please refer to https://github.com/nightwatchjs/nightwatch/wiki/Page-Object-API. My query is how can I revert back to the page object api after executing my jquery statement.

Here is an outline of my page object:

elements: {
  nameInput: 'input[name="name"]',
  billingEmail: 'input[name="billingEmail"]',
  licenseNumber: 'input[name="licenses.total"]',
  licensePrice: 'input[name="subscription.price"]',
  hardwareModel: 'input[name="model"]',
  hardwareQuantity: 'input[name="quantity"]',
  hardwarePrice: 'input[name="price"]',
  customerEmail: 'input[name="customerEmail"]',
  createButton: 'button[name="createAccount"]',
  cancelButton: 'button[name="cancel"]',
},


inputClientDetails (name, email) {
    this
      .waitForElementVisible('body', 10000)
      .setValue('@nameInput', name)
      .setValue('@billingEmail', email)
      .setValue('@licenseNumber', '10')
      .setValue('@licensePrice', '9.99')
      .api.execute(function () {
          $('.datepicker--wrapper').find('input[type=text]').val('2017-08-30').trigger($.Event("keydown", {keyCode: 40}));
      })
      .setValue('@hardwareModel', 'Test model')
      .setValue('@hardwarePrice', '9.99')
      .setValue('@hardwareQuantity', '10')
      .setValue('@customerEmail', email)
      .click('@createButton')
    return this.api;
},

While executing the test, I encounter the following error: ERROR: Unable to locate element: "@hardwareModel" using: css selector

Interestingly, when the 'execute' statement is absent from the page object, no issue arises. Hence, I am curious if there is a way to revert to the page object api after engaging with the primary nightwatch api. I attempted to incorporate a return statement within the function, but it proved to be ineffective.

Answer №1

When you invoke .api.whatever(), the function that follows in the chain also utilizes the .api (which represents the browser).

An alternative approach is to divide your function into two parts instead of chaining the entire sequence.

inputClientDetails (name, email) {
var client=this.api;
this
  .waitForElementVisible('body', 10000)
  .setValue('@nameInput', name)
  .setValue('@billingEmail', email)
  .setValue('@licenseNumber', '10')
  .setValue('@licensePrice', '9.99')
//perform operations using client-browser
client.execute(function () {
      $('.datepicker--wrapper').find('input[type=text]').val('2017-08-30').trigger($.Event("keydown", {keyCode: 40}));
  })
//Resume page object operations
this.setValue('@hardwareModel', 'Test model')
  .setValue('@hardwarePrice', '9.99')
  .setValue('@hardwareQuantity', '10')
  .setValue('@customerEmail', email)
  .click('@createButton')
return this.api;
//Use either this.api or this, but prefer this.api if there are additional chained functions reliant on the browser.
}

Answer №2

There are two options available to address this particular issue:

Option 1: When using the api, it will now return this.api instead of just this for the page-object, allowing us to call this page object using page.

inputClientDetails (name, email) {
this
  .waitForElementVisible('body', 10000)
  .setValue('@nameInput', name)
  .setValue('@billingEmail', email)
  .setValue('@licenseNumber', '10')
  .setValue('@licensePrice', '9.99')
  .api.execute(function () {
      $('.datepicker--wrapper').find('input[type=text]').val('2017-08-30').trigger($.Event("keydown", {keyCode: 40}));
  })
  .page.yourPage().setValue('@hardwareModel', 'Test model') 
  .page.yourPage().setValue('@hardwarePrice', '9.99')
  .page.yourPage().setValue('@hardwareQuantity', '10')
  .page.yourPage().setValue('@customerEmail', email)
  .page.yourPage().click('@createButton')
return this.api;

Option 2: You can choose to divide your function into smaller functions, where the smaller function will return this for the page object instead of this.api.

inputClientDetails (name, email) {
    this
      .waitForElementVisible('body', 10000)
      .setValue('@nameInput', name)
      .setValue('@billingEmail', email)
      .setValue('@licenseNumber', '10')
      .setValue('@licensePrice', '9.99')
      .callExecute()
      .setValue('@hardwareModel', 'Test model')
      .setValue('@hardwarePrice', '9.99')
      .setValue('@hardwareQuantity', '10')
      .setValue('@customerEmail', email)
      .click('@createButton')
    return this.api;
},

callExecute(){
      this.api.execute(function () {
          $('.datepicker--wrapper').find('input[type=text]').val('2017-08-30').trigger($.Event("keydown", {keyCode: 40}));
      });
     return this;
}

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

My Python script using selenium isn't functioning properly - what could be the issue?

Here is a code snippet: from selenium import webdriver driver = webdriver.Chrome(executable\_path=**"C:\\\\browserdrivers\\\\chromedriver.exe") driver.get("https://www.aliexpress.com/item/1005 ...

Node.js version 12.7 does not have the ability to support dynamic keys within objects

According to what I've read about ecma6, it should allow for dynamic key objects. I recently upgraded my node to version 0.12.7, but I'm still encountering an error. node /var/www/games/node_modules/app.js /var/www/games/node_modules/app.js ...

Code for a regular expression that permits either letters or numbers with symbols

Here is the code snippet I am using for data validation in jQuery: return /^(?=.*[A-Za-z0-9/\$#.-_])[A-Za-z0-9/\$#.-_]$/i.test(value) The requirement is that the value should begin with letters or numbers, or a combination of both. Afterwards, ...

Adding clickable padding to a Draft.js editor can enhance the user experience and make the editing process

Is there a way to apply padding to the Draft.js Editor so that clicking on the padding area selects the Editor? If I add padding directly to the container div of the Editor, the padding displays properly but clicking on it does not enable writing in the E ...

"Utilizing the power of Node.js to perform SQL queries with

I'm having trouble with this SQL query that uses INNER JOIN. The query is returning an error. connection.query("SELECT caracavis.caracname FROM caracavis WHERE firstcaturl ='" + req.body[0].firstcatname + "' AND secondcaturl = '" + r ...

Ways to allocate space evenly between components of the same size in React Native

As a beginner in Javascript and React-native, I have been experimenting with the technology to assess its viability for potential use in my current workplace. However, I have encountered some challenges with the user interface. To enhance my understanding ...

Starting http-server in the background using an npm script

Is there a way to run http-server in the background using an npm script, allowing another npm script, like a Mocha test with jsdom, to make HTTP requests to http-server? To install the http-server package, use: npm install http-server --save-dev In your ...

Verify modifications prior to navigating in React or Next.js

I have a simple Next JS application with two pages. -> Home page import Header from "../components/header"; const handleForm = () => { console.log("trigger"); }; export default () => ( <> <Header /> & ...

Utilizing a React Hook to set data by creating a pure function that incorporates previous data using a thorough deep comparison methodology

I have come across the following code snippet: export function CurrentUserProvider({ children }) { const [data, setData] = useState(undefined); return ( <CurrentUserContext.Provider value={{ data, setData, }} & ...

Implement a sequence of animations within a div using jQuery

My goal is to create an animation effect for each div element within a row when the user scrolls down to that specific point on the page. The layout consists of three <div> elements in the same row. The structure of the HTML code is as shown below: ...

What is causing my array of objects to constantly accumulate undefined elements?

My quick sort function implementation for the object users_total_likes is behaving unexpectedly. When compiled and run in the terminal or browser, it adds undefined values causing a TypeError: if(users[i][key] >= users[hi][key] && users[j][key] ...

Storing data values from a specific object key into an array in Vue: Step-by-step guide

Just dipping my toes into the world of Vue framework here. I managed to create a selectable table that stores data in an object. I want this function to run in the background, so I figured it should be in the computed section. The object structure is as fo ...

Using TypeScript with Node.js and Sequelize - the process of converting a value to a number and then back to a string within a map function using the OR

Currently, I am facing a challenge in performing addition on currency prices stored as an array of objects. The issue arises from the fact that the currency type can vary among 3 different types within the array of objects. The main hurdle I encounter is ...

Unexpected error arises in Typescript despite code functioning properly

As part of a practice project where I'm focusing on using webpack, ES6, npm and Typescript implementation, I have successfully set up loaders for 'awesome-typescript-loader' and 'babel-loader', which are bundling the code properly. ...

Develop a PHP polling system with a limit of one vote allowed per unique IP address

My website features an Ajax Poll where users can vote multiple times after refreshing the page, with results being recorded. However, I want to restrict voting to once per IP address and show the results upon page refresh. Below is the code: The HTML Pag ...

Display additional javascript code for expanding a marquee

Currently, I am working on a stock ticker project using JavaScript. It's progressing well, and now I am focusing on adding a "show more" button to style the ticker. The button should be placed outside of the marquee. When clicked, it will expand the m ...

Passing JSON data dynamically to create a chart with chartjs

I have also developed this project on codesandbox: https://codesandbox.io/s/bar-graph-9nr8u?file=/src/App.js:2394-3036 I possess JSON data and a Pie graph with labels including car, bikes, motor, and trucks. My goal is to display the total number of users ...

What is the best way to use jQuery to set the height of one div equal to another div

Edited: I am facing a situation with a 3-column layout - Column A, Column B, Column C. The height of Column A is dynamic and I need to set the same height for both Column B and C. For instance, Column A contains a tabbed panel with varying heights based ...

Loading a unique shape using JSON within the KineticJS framework

Is there a way to load a unique custom shape using a Json file in Kinetic JS? The documentation I found only covers loading normal shapes. ...

Changing a single variable into an array that holds the variable in JavaScript

Is there a way to change 5 into [5] using JavaScript? I need this functionality for a method that utilizes jQuery's $.inArray. It should be able to handle both scalar variables and arrays, converting scalars into arrays with a single element. ...