Tengo una clase con un método que realiza el inicio de sesión.
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;Tengo otro archivo de especificaciones para probar:
login.spec.js
import {fillCredentials,clickLogin} from '../../support/PageObjects/loginPage' describe('User Onboarding Emails', () => { it('Verification email', () => { cy.visit('/') fillCredentials('username','password') clickLogin() }); });Sin embargo, está dando un error de
(0 , _loginPage.fillCredentials) is not a functionSé que es una forma incorrecta de llamar a un método. ¿Hay alguna forma en que pueda usar los métodos sin crear una instancia de clase para acceder a los métodos?
Puede hacerlo si hace que los métodos sean estáticos .
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() }); }); Con los métodos estáticos, pierde this que se refiere a la instancia de clase y, por lo tanto, pierde la capacidad de encadenar métodos,
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 }); });Como funciones en lugar de una clase, este es el patrón.
// LoginPage.js export const fillCredentials = (username, password) => { cy.get('[id=username]').type(username); cy.get('[id=password]').type(password); return this; } export const clickLogin = () => { cy.contains("Login").click(); } // login.spec (same as you have above) import { fillCredentials, clickLogin } from '../../support/PageObjects/loginPage' describe('User Onboarding Emails', () => { it('Verification email', () => { cy.visit('/') fillCredentials('username','password') clickLogin() }); })Tenga cuidado al encapsular el código de prueba en los objetos de la página, ya que puede generar un código demasiado complicado.
Por ejemplo, si ahora desea probar qué sucede si no se ingresa la contraseña, no puede usar fillCredentials porque no puede omitir el parámetro de contraseña. Entonces, ¿agrega una función fillCredentialsWithoutPassword ? ¿Modificas fillCredentials para probar si password no está definida?
Entonces, lo que sucede es que está mezclando la estructura del módulo definida por Closures con el patrón de instancia de clase.
Para este escenario (que es una instancia de clase), las funciones NO son parte del objeto en sí, sino de su PROTOTIPO .
Entonces, para obtener esa función, debe acceder a su prototipo.
//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 //ƒ (){}Pruébalo : )
Las otras respuestas dadas funcionarán y resolverán su pregunta exacta, pero me temo que hacer que las funciones sean estáticas es un antipatrón para el Modelo de objetos de página.Consulte este artículo sobre cómo configurar un POM para Cypress. Le recomiendo encarecidamente que cree una instancia de la clase, similar a la siguiente.
//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() }); }); También podría usar un bloque beforeEach() para instanciar la variable antes de cada prueba.
describe('User Onboarding Emails', () => { let loginPage: LoginPage; beforeEach(() => { loginPage = new LoginPage(); }); it('Verification email', () => { ... }); }) Aparte, por lo general se prefiere nombrar las clases que comienzan con mayúsculas ( LoginPage frente a página de inicio de loginPage ). Al nombrar una clase de esta manera, puede diferenciar fácilmente la clase frente a la variable instanciada.