This is more of an open ended question. Apologies for asking, however, I cant seem to find a good explanation in online searches, and this community has been one of the important learning resources.
I am writing end to end tests for a complex web application. In a nutshell, it involves...
- Creating an application by giving specific inputs
- Filling out a series of forms, which differ according to the input given during application creation.
Since the main concept of Cypress is to keep the spec file clean and add all the code in a custom command, and call the custom command in the spec file, I have been writing a lot of if-else conditional statements. For example...
//spec
describe("Test scenario 1", () => {
it("test case 1", function () {
cy.CustomCommand1(arg1,arg2) //arguments are fetched from a fixture file, which acts like input data. Fixture file changes for various test to cover multiple scenario.
})
})
//CustomCommand1
Cypress.Commands.Add('CustomCommand1',(arg1,arg2) => {
if(arg1==xyz || arg2==abc){
//fill some fields
//assert on things in the form and so on...
}
else{
//do something else
//assert on something else and so on...
}
})
This is how I have been using a single command for a single page on my web app, and adding logic for the appearance of various form fields and check boxes etc, filling them and asserting.
I have multiple pages and each displaying different set of fields on the basis of the input data while creation of application. Every page has its own custom command and there is hell of a logic built in there. A real custom command from my project looks like this...
Cypress.Commands.add('addEmployers', (employer) => {
cy.location('pathname').should('eq', '/welcome/employers')
cy.get('[data-testid="add-employer"]').click()
cy.get('#company_name').type(employer.company)
cy.get('#position').type(employer.position)
cy.get('#current').click()
cy.get(`[data-testid="${employer.type}"]`).click()
cy.get('#start_date').parent().type(`${employer.sdate}{enter}`)
if (employer.type == 'not_current') {
cy.get('#end_date').parent().type(`${employer.edate}{enter}`)
}
cy.get('[data-testid="street_address"]').type(employer.addr.street)
cy.selectCountry('#country',employer.addr.country)
if ((['Canada','United States'].includes(employer.addr.country))) {
cy.dropdownWithText('#province_state',employer.addr.province)
}
else {
cy.selectOTProvince('#other_province_state',employer.addr)
}
cy.get('#city').type(employer.addr.city)
cy.get('#postal_code').type(employer.addr.postal)
if(employer.type == 'yes_current' && employer.empcontact == 'Y') {
cy.get('#can_contact').click()
cy.get('[data-testid="can_contact_employer"]').click()
}
if(employer.type == 'yes_current' && employer.empcontact == 'N') {
cy.get('#can_contact').click()
cy.get('[data-testid="cannot_contact_employer"]').click()
}
if(employer.type == 'not_current' || (employer.type == 'yes_current' && employer.empcontact == 'Y')){
cy.ClickNext()
cy.get('#contact_first_name').type(employer.emp.fname)
cy.get('#contact_last_name').type(employer.emp.lname)
cy.EmailGen('employer').then(email => {
cy.wrap(email).as('employerEmail')
})
cy.get('@employerEmail').then(email =>{
cy.get('#contact_email').type(`${email}`)
cy.wrap(email).as('empemail')
})
})
}
})
And then I get to know that if we have conditional statements in a test, they would require tests too. (Test of Tests :shrug:)
Is there something fundamentally wrong in my approach. If yes, what changes should I bring to my approach to keep spec files clean and do bulk of the jobs in custom command?
Do let me know if any more details are required!