Home > Mobile >  How to call a method in another module JavaScript?
How to call a method in another module JavaScript?

Time:01-22

I have a class with method performing login

LoginPage.js

class loginPage {
  fillCredentials(username, password) {
    cy.get('[id=username]').type(username);
    cy.get('[id=password]').type(password);
    return this;
  }

  clickLogin() {
    cy.contains("Login").click();
  }
}
export default loginPage;

I have another spec file for testing:

login.spec.js

import {fillCredentials,clickLogin} from '../../support/PageObjects/loginPage'

describe('User Onboarding Emails', () => {
  it('Verification email', () => {
    cy.visit('/')
    fillCredentials('username','password')
    clickLogin()
  });
});

However, it is giving an error of

(0 , _loginPage.fillCredentials) is not a function

I know its a wrong way of calling a method. Is there any way I can use the methods without creating an instance of class to access methods

CodePudding user response:

So, what's going on is that you are mixing up the module structure with is defined by Closures with the class-instance pattern.

For this scenario (which is class-instance) the functions are NOT part of the object itself, but of it's PROTOTYPE.

So in order to get that function you should access it's prototype.

//create a class (class syntax and this one is pretty much the same)
function xx (){}
//this is what class syntax makes to create a method for the class
xx.prototype.theFunctionIwant = function (){}

//create an instance
var example = new xx()

//this is how you can spy that function in the test
xx.prototype.theFunctionIwant
//ƒ (){}

Try it out : )

CodePudding user response:

You can do so if you make the methods static

class loginPage {

  static fillCredentials(username, password) {
    cy.get('[id=username]').type(username);
    cy.get('[id=password]').type(password);
    //return this;  // you can't return "this" because there is no this for static methods
  }

  static clickLogin() {
    cy.contains("Login").click();
  }
}
export default loginPage;
import {fillCredentials,clickLogin} from '../../support/PageObjects/loginPage'

describe('User Onboarding Emails', () => {
  it('Verification email', () => {
    cy.visit('/')
    fillCredentials('username','password')
    clickLogin()
  });
});

With static methods you lose this which refers to the class instance, and therefore lose the ability to chain methods,

import {fillCredentials,clickLogin} from '../../support/PageObjects/loginPage'

describe('User Onboarding Emails', () => {
  it('Verification email', () => {
    cy.visit('/')
    fillCredentials('username','password').clickLogin()  // can't do this with static
  });
});

CodePudding user response:

The other answers given will work, but if you are trying to implement something like the Page-Object model, they are missing the mark. Instead of marking the functions as static, you'll want to instantiate the class before calling the functions.

//LoginPage.js
export class LoginPage { ... }

//login.spec.js
import { LoginPage } from '../../support/PageObjects/loginPage';

describe('User Onboarding Emails', () => {
  it('Verification email', () => {
    const loginPage = new LoginPage()
    cy.visit('/')
    loginPage.fillCredentials('username','password')
    loginPage.clickLogin()
  });
});

You could also use a beforeEach() block to instantiate the variable before each test.

describe('User Onboarding Emails', () => {
  let loginPage: LoginPage;
  beforeEach(() => {
    loginPage = new LoginPage();
  });
  it('Verification email', () => {
    ...
  });
})

As an aside, it is usually preferred to name classes beginning with an uppercase (LoginPage vs. loginPage). When naming a class this way, you can easily differentiate the class vs. the instantiated variable.

  •  Tags:  
  • Related