Cypress before hook repeats after each it statement - javascript

I am new to cypress when go to a url using a before hook it completes the first it statement, then it executes the before hook again and does the 2nd it statement, it should execute the before hook once execute the it statements and stop. However that is not what is happening and i need help please to see what i am doing wrong. My code is below:
import { expect, assert, should } from 'chai';
import LoginPage from '../page-objects/LoginPage.spec'
import BeHomePage from '../page-objects/BeHomePage.spec'
describe('create, edit, delete Survey', () => {
before(function() {
cy.visit(''); // see config json for base url
})
it('user can login to boardeffect', () => {
LoginPage.getLoginUserName().type(Cypress.env('username'));
LoginPage.getLoginUserPassword().type(Cypress.env('password'));
LoginPage.getSigninButton().click();
})
it('user can navigate to collaborate', () => {
BeHomePage.getAutoBeWorkroom().should('be.visible');
BeHomePage.getAutoBeWorkroom().click();
BeHomePage.getCollaborate().should('be.visible');
BeHomePage.getCollaborate().click();
cy.wait(10000)
})
})
{
"baseUrl": "https://automation-ozzie.boardeffect.com/login",
"defaultCommandTimeout": 15000,
"env": {
"username": "steveSystem",
"password": "Passw0rd"
}
}
class BeHomePage {
getAutoBeWorkroom() {
return cy.get(':nth-child(7) > a')
}
getCollaborate(){
return cy.get('.workroom-buttons > :nth-child(4) > a')
}
getNewSurvey(){
return cy.get('btn btn-success')
}
}
export default new BeHomePage();
As picture below shows all code in one (it) block passes as seen in picture however code in 2 it blocks fails as seen above.
enter image description here

The extra step you need is discussed in this section of the docs Cookies - Preserve Once.
Cypress auto-clears cookies between each it(), but if you add
it('user can login to boardeffect', () => {
LoginPage.getLoginUserName().type(Cypress.env('username'));
LoginPage.getLoginUserPassword().type(Cypress.env('password'));
LoginPage.getSigninButton().click();
// preserve the cookie set above for the next test
Cypress.Cookies.preserveOnce('_boardeffect_session');
})
it will keep that cookie value during subsequent it() sections.
Open the browser dev-tools, go to Application, Cookies, https://automation-ozzie.boardeffect.com and observe that without preserveOnce() the cookie value is cleared.

Related

Cypress won't open the specified URL

When I run the test, the specified URL does not open, even though it is entered correctly and set in BaseUrl in cypress.config.js:
> module.exports = defineConfig({ e2e: {
> "projectId": "fi4fhz",
> "viewportHeight": 1080,
> "viewportWidth": 1920,
> specPattern: 'cypress/e2e/**/*.{js,jsx,ts,tsx}',
> baseUrl: 'https://pha.mm.int:6001/',
>
> setupNodeEvents(on, config) {
>
> }, },
In every test file I have this:
beforeEach(() => {
cy.runInWeb();
});
and in commands.js I have:
Cypress.Commands.add("runInWeb", () => { cy.visit(Cypress.e2e().projectUrl) });
and in cypress.config.js I have:
"projectUrl": "https://pha.mm.int:6001/"
but it's not functioning. Where is the problem?
The baseUrl value https://pha.mm.int:6001/ shows up in the browser address bar because Cypress uses it to configure set up the runner.
But the <iframe> containing the web page under test isn't changed until you perform
the first cy.visit('/').
This is to allow you to execute code before the page load occurs, like cy.intercept() and cy.fixture().
Yes you visit() but not in the right way, if you store your url in env variable you get it out like this:
Cypress.Commands.add("runInWeb", () => { cy.visit(Cypress.env('projectUrl')) });
and you store the default like this:
// cypress.config.js
const { defineConfig } = require("cypress");
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
specPattern: 'cypress/e2e/**/*.cy.{js,jsx,ts,tsx}'
},
env: {
projectUrl: 'https://pha.mm.int:6001/',
},
})
or cypress.env.json
{
"projectUrl": "https://pha.mm.int:6001/"
}
Ensure that you have this beforeEach prior to running your it test blocks. You need to use cy.visit('/') before each of your tests.
beforeEach(() => {
//cy.session(id, setup); Use is if you want to stay logged into your application
cy.visit('/);
cy.wait(100);
});
If you're interested in using a session, visit the cypress docs here:
Based on the information in the question, I assume that you did not include a cy.visit() command. Without that command, Cypress does not know to open a webpage.

How pass a login form with CYPRESS?

I manage to run CYPRESS without any worries on a site without authentication.
But on an intranet, I can't identify myself. I must to log in before.
Here is my code:
describe('home', () => {
it('home accessible', () => {
cy.visit('/')
})
//We fill the login FORM
it('User Field', () => {
cy.get('input#user')
.type('login')
})
it('User pass', () => {
cy.get('input#pass')
.type('mot de passe')
})
it('check consent', () => {
cy.get('input#permalogin')
.click({ force: true })
})
it('submit', () => {
cy.get('input.btn.btn-primary')
.click()
})
//the form is submit, we can visit a page
it('autre page!!', () => {
cy.visit('/luniversite/page-2',{ timeout: 30000 })
})
//We check the title of the page, we should be on the page 2
it('titre page 2', () => {
cy.title().should('eq', 'page 2: INTRANET)
})
CYPRESS and the CYPRESS video show me that I am blocked on the authentication page.
The test on the title of the page is not correct, I don't access page-2. I stay on the first page for log in.
First thing's first: This appears to be one test, but you are specifying multiple it() functions, which is breaking it up into multiple tests, which is not what you want. You will want to restructure your test like this:
describe("home", () => {
it("home accessible", () => {
cy.visit("/");
//We fill the login FORM
cy.get("input#user").type("login");
cy.get("input#pass").type("mot de passe");
cy.get("input#permalogin").click({ force: true });
cy.get("input.btn.btn-primary").click();
cy.visit("/luniversite/page-2", { timeout: 30000 });
cy.title().should("eq", "page 2: INTRANET");
});
});
With that out of the way, it's hard to know what your application is doing without more details:
1/ When executed manually, is your application authenticating properly with the provided credentials? Do you have console errors? Have you determined that the element locators you're using are actually interacting with the elements in the manner you expect?
2/ Is your test attempting to navigate to /luniversite/page-2 before authentication is complete? If so, you may want to use intercept your authentication call and wait for it to complete:
// get your authentication POST request from network tab of devtools and use that in the cy.intercept call
cy.intercept('POST', '/yourAuthenticationCallUrl').as("#authenticationCall")
// YOUR LOGIN STEPS HERE
cy.wait("#authenticationCall") //waits for the authentication call to complete before moving to the next step
cy.visit("/luniversite/page-2", { timeout: 30000 });

Cypress not intercepting request with render function vue

I'm trying to do a pretty simple intercept in Cypress using a Vue's application. My component has a setup method using render function as such:
setup() {
useInfiniteLoading({ runner: ... })
}
Then on my tests I do the following:
describe("List todo resource", () => {
it("Checks it loads more todos when scrolling to the bottom", function () {
cy.intercept('/todo').as('getTodos');
cy.visit("/todos");
cy.wait("#getTodos").then(({response}) => {
console.log(response);
})
})
})
When running the test I see that the intercept is not stubbing the response.
As you can see from the image the request makes a request to my actual server running locally and the response is stubed. The weird part is that in a previous test I have:
it("Checks the todo list gets updated when clicking on to resolve it (from true to false)", function () {
cy.visit("/todos");
const resolved = false;
const shouldHaveClass = resolved
? "mdi-checkbox-marked-outline"
: "mdi-checkbox-blank-outline";
cy.intercept("GET", "todo", {
fixture: "resources/todo/list.todo.json",
}).as("getTodos");
cy.intercept("PUT", "todo", {
body: { data: { ...this.updateTodoFixture.data, resolved } },
}).as("updateTodo");
cy.get(".todo-list-item__resolve")
.first()
.each((btn) => {
btn.click();
});
cy.get(".todo-list-item__resolve")
.first()
.should("satisfy", ($el) => {
const classList = Array.from($el[0].classList);
return classList.includes(shouldHaveClass);
});
});
And the response is stubbed using intercept as you can see from the previous screenshot. Is it possible that the previous test is affecting the next test? I have tried taking a look into "Intercept too soon" but no luck on trying to apply the fix described in the page.
Any idea on what could be causing the stub not to happen?

Looking for alternatives to cy.wait() on a flaky test in Cypress

So I have a flaky test case right now in Cypress. When the modal loads, it skips the filling out the name part but fills out everything else. Therefore, causing it to fail the first time, but on the retry, it passes. I tried adding an assertion (see below), but it does not work. I am trying to avoid adding using a wait command, but wanted to see if there are any other alternatives out there to cy.wait().
describe("Coach dealing with forms" () => {
beforeEach(() => {
loginfile.login(users.coach)
});
it("Can fill out form and submit", () => {
cy.get("#modal-button").click()
cy.get("#modal-form").should("exist")
cy.get("#form-name").type("Mike Johnson")
cy.get("#form-age").type("33")
cy.get("#form-email").type("mj09#yahoo.com)
cy.get("#submit-button").click()
}
}
There a number of ways to approach flaky tests. You can try these and check what suits best for your use case:
1.Test Retires easy and effective, just retry the execution automatically it something fails. Can be applied, globally using cypress.json or to a describe block or to a it block as well.
For it block:
// `it` test block with custom configuration
it('allows user to login', {
retries: {
runMode: 2,
openMode: 2
}
}, () => {
// ...
})
For describe block:
// Customizing retry attempts for a suite of tests
describe('User bank accounts', {
retries: {
runMode: 2,
openMode: 2,
}
}, () => {
// The per-suite configuration is applied to each test
// If a test fails, it will be retried
it('allows a user to view their transactions', () => {
// ...
}
it('allows a user to edit their transactions', () => {
// ...
}
})
2.Adding .visible and click() before writing into the name field
it("Can fill out form and submit", () => {
cy.get("#modal-button").click()
cy.get("#modal-form").should("exist")
cy.get("#form-name").should('be.visible') //making sure the name field is visible
cy.get("#form-name").click() //clicking on the name field
cy.get("#form-name").type("Mike Johnson")
cy.get("#form-age").type("33")
cy.get("#form-email").type("mj09#yahoo.com")
cy.get("#submit-button").click()
})
3.Use timeouts instead of waits
cy.get("#form-name", {timeout: 10000}).type("Mike Johnson")
4.Use cy.intercept() to wait for the XHR request to finish execution. Here I am assuming that there is some unfinished XHR request after clicking the modal button that is causing the issue. If that is not the case, you can debug your tests to find out and apply intercept accordingly.
it("Can fill out form and submit", () => {
cy.intercept('http://example.com/settings').as('getSettings') //Intercept the url that is triggered after clicking the modal button
cy.get("#modal-button").click()
cy.wait('#getSettings') //Wait till that request has finished execution
cy.get("#modal-form").should("exist")
cy.get("#form-name").type("Mike Johnson")
cy.get("#form-age").type("33")
cy.get("#form-email").type("mj09#yahoo.com")
cy.get("#submit-button").click()
})
You should add a timeout to the type() command (not to the get() command) and follow it with a should() to confirm the value has been entered.
type() and should() will both retry until they succeed.
it("Can fill out form and submit", () => {
cy.get("#modal-button").click()
cy.get("#modal-form") // .should("exist") - don't need as cy.get() does that already
cy.get("#form-name").type("Mike Johnson", {timeout: 10000}) // wait for actionability
.should('have.value', 'Mike Johnson');
cy.get("#form-age").type("33")
cy.get("#form-email").type("mj09#yahoo.com")
cy.get("#submit-button").click()
})

Jest: Trying to mock nested functions and redirects in jest, but no avail

We are using a javascript framework(Not react) to render the ui.
main.js
function logout(){
someObj.lock($('#container'), 'Logging out', true);
document.location = app.context + `/${appName}/signout.action?name=${appName}`;
}
function action(event){
switch(event.target){
case 'user:logout':
logout();
break;
case 'user:application':
document.location = app.context + "/";
break;
}
}
module.exports = {
action: action,
logout: logout
}
main.js along with another js file renders a navbar and a dropdown. My intention is to check whether title, dropdown in the navbar is rendered. Also I
am testing whether the browser redirect takes place in the right way.
action method takes an event object and based on its type, either performs signout('user:logout') or redirects to application page('user:application').
tests/main.js
import main from '../main';
describe("some title", () => {
it("some behavior", () => {
let event = {
target: 'user:logout'
}
let app = {
context: ''
}
let appName = 'Some app';
main.logout = jest.fn();
someObj = jest.fn();
someObj.lock = jest.fn();
document.location.assign = jest.fn();
main.action(event);
expect(main.logout).toHaveBeenCalled();
expect(document.location.assign).toBeCalledWith(app.context + `/${appName}/signout.action?name=${appName}`);
})
});
In the test file, I am trying to mock logout function. However it is executing someObj.lock function. someObj is not availabe to tests/main.js
and I am mocking it as well. I'm not sure whether I have to use spyOn instead. I'm using document.location.assign to test for browser redirects.
This test is not working and the terminal is displaying TypeError: Could not parse "/application name/signout.action?name=application name" as URL.
I have spent an entire day testing this feature but to no avail. I need some advice on the best way to test this feature.
Links explored: Intercept navigation change with jest.js (or how to override and restore location.href)
jest documentation

Categories

Resources