I have a process that create a quote divided in different test cases:
enter image description here
in the first IT I have the cy.visit which visit the login page of my page filling it with user and password
"the issue appears when I submit " I got a new URL generated and what I assumed is that it is not linking to the new url so the process stuck and cannot continue
enter image description here
so after that I got the error that the page cannot proceed, it stuck and get back to the login page and dont proceed with the other page generated automatically:
enter image description here
Well I am new in Cypress automation so I am not sure what is going on after I login on my page it get stuck in the process going back to the login page. So I am kind of sure it is not linking into the new URL that has the same domain so any person who has knowledge in Cypress can help me
It is the way Cypress works to stop one test contaminating the next one, and giving you a false pass.
The way you need to handle is with a session command to keep your login credential renewed for each test.
This is the pattern:
describe('before logged in', () => {
it("Login into the system", function () {
cy.visit(Cypress.env("ur146b"));
//login
login.getUser().type(this.data.user);
login.getPass().type(this.data.pass);
login.getLogin().click();
cy.wait(1000);
});
})
describe('when logged in', () => {
// now make such the login is renewed for each test
beforeEach(() => {
cy.session('login', () => {
cy.visit(Cypress.env("ur146b"));
//login
login.getUser().type(this.data.user);
login.getPass().type(this.data.pass);
login.getLogin().click();
})
})
it("Menu - full quote - get client", function () {
cy.visit('/homepage');
menu.getPolicy().click();
menu.getQuote().click();
menu.getClient().click();
cy.wait(1000);
});
it("fill client and address info", function () {
cy.visit('/homepage');
...
});
})
Read the complete details documentation page
Sorry I missed one step - it is mandatory to use cy.visit() in each test block after adding cy.session() to the login.
Otherwise you get the "blank page" problem you mention.
Ref session
Because the page is cleared at the beginning of each test by default, cy.visit() must be explicitly called at the beginning of each test.
enter image description here
I make the changes on my code also I added on cypress.config :experimentalSessionAndOrigin: true
enter image description here
I did my research and I got that the page is in blank and not showing the after login page
Related
I have a search input and result display area that are being handled by Ajax call. When user enter a keyword, Ajax call the backend and return HTML string. The JS handler then appends the response HTML into result display area.
Here my steps:
Search input: Vancouver (auto input by browser location)
Result: Welcome to Vancouver
Type into search input: Calgary
Expected: Welcome to Calgary
// Test case
Cypress.Commands.add('assessHeadingInfo', (options) => {
cy.fixture('selectors/index-page').then((selectors) => {
cy.xpath(selectors.head_info).then((heading) => {
cy.searchForArea('Calgary'); // Steps to input keyword and click search
cy.get(heading)
.children('h1')
.should('be.visible');
cy.get(heading)
.children('h1')
.invoke('text')
.should('equals', 'Welcome to Calgary');
});
});
});
Test error:
AssertionError
Timed out retrying after 4000ms: expected 'Welcome to Vancouver' to equal 'Welcome to Calgary'
However, the visual screenshot showed that the 'Welcome to Calgary' text was displayed while the test could not see.
I did follow the guide from Cypress app
Timed out retrying after 4000ms: cy.should() failed because this element is detached from the DOM.
...
You typically need to re-query for the element or add 'guards' which delay Cypress from running new commands. Learn more
I added 'a guard', cy.wait()...but nothing works.
Would you please teach me how to handle this issue?
Thank you.
UPDATE SOLUTION:
Thanks for #jhelguero helped me to find out.
Solution 1:
I added this and it worked well.
cy.contains('h1', 'Welcome to Calgary')
.should('be.visible');
Because I have put all the tests in block of
cy.xpath(selectors.head_info).then((heading) => {
...
});
So, when I do cy.get(heading) it caught the element before Ajax done. It was 'Welcome to Vancouver' instead.
Solution 2:
Then, I separated test steps like this.
cy.searchForArea('Calgary');
cy.xpath(selectors.head_info)
.children('h1')
.should('have.text', 'Welcome to Calgary');
and it was successful.
Summary:
Do this:
cy.xpath({selector}).should(have.text,'ABC');
cy.xpath({selector}).find('h1').should('have.text, '123');
DON'T do this:
cy.xpath({selector}).then((ele) => {
cy.get(ele).should(have.text, 'ABC');
cy.get(ele).find('h1').should('have.text, '123');
});
It looks like your DOM rerenders after the ajax call and thus the element('Welcome to') you were previously reference has been detached.
To fix this you will need to re query using the same selector after the ajax call is completed. You will not need cy.xpath(selectors.head_info).then().
Cypress.Commands.add('assessHeadingInfo', (options) => {
cy.fixture('selectors/index-page').then((selectors) => {
cy.searchForArea('Calgary'); // Steps to input keyword and click search
// use .contains() to search a selector with regex text
cy.contains(selectors.head_info, /Welcome to Calgary/)
.should('be.visible');
});
});
If you visually confirmed the text "Welcome to Calgary", the problem might be that .should('equals', 'Welcome to Calgary') is not retrying enough of preceding steps.
Try shortening the query.
You can also increase the timeout if you notice a lag before the text appears.
cy.get(`${heading} > h1`, {timeout:10_000})
.should('have.text', 'Welcome to Calgary')
Is there a way to disable a Resource route link while the resource is being generated and enabling it after that?
I have a PDF report that gets generated as soon as the user clicks on a Link. So I'm using a resource route that returns the PDF as a ReadableStream with a content-Disposition of attachment.
Here's a a code fragment example:
export const loader: LoaderFunction = async ({ params }) => {
invariant(params.recordID, "Record Id is required!");
let recordID = params.recordID;
let reportsService = createReportsService();
let reportFileStream = await reportsService.getReport(
recordID
);
return new Response(reportFileStream, {
headers: {
"Content-disposition": `attachment; filename=report.pdf`,
"Content-Type": "application/pdf",
},
});
};
I'm using the Link to the resource route this way:
<Link to={reportUrl} reloadDocument >
Get the Report
</Link>
I want the Link to get disabled as soon as the user clicks on it and then re enable it after the report is ready and the user has saved it (or discarded the "save" window).
I can't use useTransition hook because reloadDocument disables javascript behavior but I can't find out another way to disable and enable the link.
I can only disable it as soon as the user clicks on it (with a conditional pointer-events style controlled by useState) but I haven't found a way to detect when the report has been generated and the user has saved it (or discarded the "save" window) so I can re enable the link again.
So any help or hint to find a solution is very much appreciated!
Hi I am using the example application with navigation list but I want to create a login page on top of it in which once I click login button and after authentication i have to route the application to main page.
I tried below code but nothing happened.
oj.Router.rootInstance.go('login');
please help.
Application : Oracle JET distribution
Code:
function (oj, ko, app) { // this callback gets executed when all required modules are loaded
$(function() {
function init() {
oj.Router.sync().then(
function () {
// Bind your ViewModel for the content of the whole page body.
ko.applyBindings(app, document.getElementById('globalBody'));
// navigate the user to login or wherever you want them to be now
oj.Router.rootInstance.go('login');
},
function (error) {
oj.Logger.error('Error in root start: ' + error.message);
}
);
}
You'll want to move your router go() commands out of the main.js and into a viewModel that backs the login page and only runs if and when the user passes your authentication test by entering the right username/password.
If login is the default page you want them to see, change the router.configure and navData setup in appController.js to make that the default page:
self.router.configure({
'login': {label: 'Login', isDefault: true},
...
Have a look at the FixItFast sample code for an example of a login page and the structure that supports it. FixItFast is a much more involved example than the standard Starter templates because it assumes mobile-first, but the signin.html view and signin.js viewModel might give you good ideas.
First you make your login page as default page.
Then (in your login.html) on button click you can call a function (function in login.js) where validation of your username and password takes .
self.signIn = function()
{
//your validation
if (login==success)
{
oj.Router.rootInstance.go('dashboard');
}
else
{
alert("check your details");
}
};
Make sure that you have add your dashboard page in router config
self.router.configure({
'dashboard': {label: 'Dashboard'},
'login': {label: '',isDefault: true}
});
The below page code has a list of links that have no id and name to be used for click on it:
My casperjs code is problematic since it needs an id or name:
...
casper.then(function() {
test.assertTextExists("User Data", "Login ok");
test.clickLabel('Link_for_Data_1','a');
});
...
Also by using the xpath with href seems not to work:
this.click(x('//*[#href="#cookpot-home/data-cookpot"]/a[text()="Link_for_Data_1"]'));
Some more page code, maybe it helps (the dark blue in the below picture is the part which has the link, see the first picture):
After some investigation I realized that it may need some more time to load the next page after the login to this page.
I added a wait timer for 10s but it still didn't helped!
...
casper.then(function() {
casper.wait(10000, function() {
this.echo('should appear after 10s');
});
});
casper.then(function() {
console.log(this.getCurrentUrl());
casper.waitForText('Link_for_Data_1', function() {
this.echo('FOUND');
});
test.assertTextExists("Data page", "Login into Data");
...
The above code seems to work until it comes to the waitForText which never prints 'FOUND'.
Also the assertTextExists fails, but according to the getCurrentUrl it is in the correct page (the page shows the text "Data page")!!!
So all the above seems to be a step to the right way but it still didn't answers my main question.
I am able to run the test code and i am able to submit the form. I need the url of next page when submit button is click. I need to get url of next page when submit button is clicked. But i am getting curenturl of first page.
My code:
describe('Pmts app 5.0',function(){
var LoginPage = require("./LoginPO");
it('login test', function(){
LoginPage.setUserName('xyz#test.com');
LoginPage.setPassWord('test');
LoginPage.clickButton();
expect(browser.getCurrentUrl()).toEqual('https://localhost:1234/#/timesheet');
});
});
After submit button is clicked browser get closed immediately and it is not waiting for next page to load. Once the button is submitted it should wait until next page load and I need url of next page...
Put it in the following way:
LoginPage.clickButton().then(function(){ expect(browser.getCurrentUrl()).toEqual('https://localhost:1234/#/timesheet');
})
or you can put a explicit hard sleep:
browser.sleep(time in ms)
or you can put a browser.wait() to wait for certain element that appears on the next page:
browser.wait(function(){
return elem.isPresent()
},time in ms).then(function(){
expect(browser.getCurrentUrl())
.toEqual('https://localhost:1234/#/timesheet');
})
Please refrain from using browser.sleep(number), instead go for browser.waitForAngular() if your application is Angular.js based.
Using hard coded dependency is never a good idea.
I have noticed, that the time Protractor needs to load the whole page varies. Therefore, either use browser.waitForAngular() or set a high number in browser.sleep()
Try this :
describe('Pmts app 5.0',function(){
ptor = protractor.getInstance();
var LoginPage = require("./LoginPO");
it('login test', function(){
LoginPage.setUserName('xyz#test.com');
LoginPage.setPassWord('test');
LoginPage.clickButton();
ptor.sleep(1000);
expect(browser.getCurrentUrl()).toEqual('https://localhost:1234/#/timesheet');
});
});