Cypress how to handle new tab without "target" and "href" attribute? - cypress

Note:
Cypress is a great tool for automating. I am new in Cypress world. I really like the way how we can take actions and make assertions on the same line of code.
However, I met a hard problem, that I am not able to process. I am sure that this is handled in some way, but after 2 days of researching (about 6 hours), I'm running out of energy.
Description:
I am trying (learning to use Cypress) to automate this example. I am not able to automate (button) "New Tab" functionality. I don't want to think about how can I solve this 'quest' and how can I automate the other two (buttons) "New WIndow" and "New WIndow Message" functionalities. Here is a screenshot of the HTML document:
My code:
I try to solve this by using the first answer from this topic.
/// <reference types="cypress" />
describe('Example shows how to work with browser windows.', () => {
it('Example shows how to work witn button that opens new tab without "target: _blank" and "href" attributes.', () => {
cy.visit('https://demoqa.com/browser-windows')
cy.window().then(win => {
cy.stub(win, 'open').as('open')
})
cy.xpath('//*[#id="tabButton"]').click()
cy.get('#open').should('have.been.calledOnceWithExactly', '/sample')
})
})
I am not sure what I miss.

Your example is not following the link's code you have provided. I have refactored your code, tested & it's working:
/// <reference types="cypress" />
describe('Example shows how to work with browser windows.', () => {
it('Example shows how to work witn button that opens new tab without "target: _blank" and "href" attributes.', () => {
cy.visit('https://demoqa.com/browser-windows', {
onBeforeLoad(win) {
cy.stub(win, 'open')
}
});
cy.get('#tabButton').click();
cy.window().its('open').should('be.called');
cy.get('#windowButton').click();
cy.window().its('open').should('be.called');
cy.get('#msgWindowButtonWrapper').click();
cy.window().its('open').should('be.called');
});
});
Results:

Related

Not able to access the element inside the DOM using cypress

I am testing a website i.e console.internetcomputerservices.com, please refer the below code:
/// <reference types="cypress" />
describe("Basic tests", () => {
before(() => {
cy.visit("https://console.internetcomputerservices.com", {
onBeforeLoad(win) {
win.localStorage.setItem(
"token",
"my-token"
);
},
});
});
it.only("should be able to run test 1", async () => {
cy.viewport(1280, 720)
//Clicks on Creat DApp
cy.contains('Create DApp').click()
//Clicks on Static website
cy.contains('Static Website').click()
//clicks on "Connect with github"
cy.contains('Connect with github').click()
//The origin is changed to github.com inside which following operation takes place
cy.origin('https://github.com', ()=>{
cy.get('input[name="login"]').type('my-email')
cy.get('input[name="password"]').type('my-password')
cy.get('[type="submit"]').click()
cy.get('[href="/settings/installations/29576211"]').click()
cy.contains('Only select repositories').click()
cy.contains('All repositories').click()
cy.get('.js-integrations-install-form-submit.btn-primary.btn.float-left.mr-2').click()
})
//Comes out of github.com back to console.internetcomputerservices.com
//(Expected) cypress will identify the placeholder and type "intro-2"
// but this doesn't happen, cypress doesn't identify any element inside the DOM
cy.get('input[placeholder="Search…"]').type('intro-2')
});
});
When we return back to our home website, i expect that the cypress identifies the placeholder and type in "intro-2", to check that was it particular to placeholder, i realised that cypress is not able to identify any element on DOM.
If you refer the Search bar, i want to access one with placeholder='Search...'
I apologies for poor choice of words, i am beginner in this and not familiar with jargon, I hope you understand my question.

Cypress: cannot find button in toolbar

I just started playing with cypress and I am trying to write down some tests in my sandbox application. In my first test user should click on a 'button' to make the toolbar to appear, then click on a button to activate the feature, then click a couple of times on a leaflet map to draw a line.
As you can see: click on 'Tools', then click on 'draw route' button and then click on map to draw.
This dummy app is wrapped inside a web component, here is the code:
And here is my test code:
describe('Draw geometries on map', ()=>{
beforeEach(() => {
cy.visit('http://192.168.49.2:30000/scouter/');
})
...
it('can draw after clicking draw button', ()=>{
cy.get('scouter-web').shadow().find('.scouter-tools-main-button').click()
cy.get('scouter-web').shadow().find('draw route').click()
console.log('new cy')
cy.get('scouter-web').shadow().get('scouter-web').shadow().find('#map')
.click(400, 400)
.click(400, 600)
.click(500, 600)
})
});
Problem is I, after clicking 'Tools', I can't 'find' the 'draw route' button. What am I missing? The whole stuff can be found here, subproject is scouter-web.
Instead of using the shadow() repeatedly, you can mention includeShadowDom: true once in your cypress.json file.
With find you can just use selector but I think you are using text. If you just want to use text, you can use contains.
cy.contains('draw route').click()
And if your application is throwing Uncaught Exceptions you can add to your cypress/support/index.js to globally turn off all uncaught exception handling. But a fair bit of warning, do this only when you are sure that the exceptions generated can be ignored.
Cypress.on('uncaught:exception', (err, runnable) => {
// returning false here prevents Cypress from
// failing the test
return false
})

Cypress - testing a contact form with google recaptcha

How can I test a contact form with google recaptcha ?
I want to test if "We will respond you soon." message appear.
I created my own Cypress command in order to test Google reCAPTCHA
Cypress.Commands.add('solveGoogleReCAPTCHA', () => {
// Wait until the iframe (Google reCAPTCHA) is totally loaded
cy.wait(500);
cy.get('#g-recaptcha *> iframe')
.then($iframe => {
const $body = $iframe.contents().find('body');
cy.wrap($body)
.find('.recaptcha-checkbox-border')
.should('be.visible')
.click();
});
});
I combined this command with the instructions given by Google:
https://developers.google.com/recaptcha/docs/faq#id-like-to-run-automated-tests-with-recaptcha.-what-should-i-do
So, I had to do minor changes to my source code:
export const RECAPTCHA_SITE_KEY: string = window.Cypress
? '6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI'
: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
After some attempts, I came up with this:
Cypress.Commands.add('confirmCaptcha', function () {
cy.get('iframe')
.first()
.then((recaptchaIframe) => {
const body = recaptchaIframe.contents()
cy.wrap(body).find('.recaptcha-checkbox-border').should('be.visible').click()
})
})
Also make sure you have this in your cypress.json file, otherwise iFrames cannot be accessed:
"chromeWebSecurity": false
This works for me, which has no need for a cy.wait(500) or other fixed amount of time, because it uses the cypress implicit wait in its for the iframe contents to load.
cy.get('iframe')
.first()
.its('0.contentDocument.body')
.should('not.be.undefined')
.and('not.be.empty')
.then(cy.wrap)
.find('#recaptcha-anchor')
.should('be.visible')
.click();
This can be added as a custom command as well. It is based off of this blog post: https://www.cypress.io/blog/2020/02/12/working-with-iframes-in-cypress/
Cypress has good suggestions on their best practice page: https://docs.cypress.io/guides/references/best-practices.html#Visiting-external-sites
Basically it comes down to this: if it is not your own application, just stub it. Trust the 3th party to test their own page.

Protractor : Check pdf document in a new tab

I am trying to automate a scenario where I click on a button and its opens up a pdf document in new tab. When the test fails, a json object is displayed instead of the pdf document.
I use this code :
element(by.id('MyButton')).click().then(function () {
browser.getAllWindowHandles().then(function (handles) {
newWindowHandle = handles[1]; // this is your new window
browser.switchTo().window(newWindowHandle).then(function () {
var EC = protractor.ExpectedConditions;
// Waits for the element is not present on the dom.
browser.wait(EC.stalenessOf($('#formattedJson')), 5000);
});
});
});
I can open the new tab but when I dont know how to check the content (pdf or json object).
Some advices would be appreciated.
For instance I have the error :
Failed: Error while waiting for Protractor to sync with the page: "both angularJS testability and angular testability are undefined. This could be either because this is a non-angular page or because your test involves client-side navigation, which can interfere with Protractor's bootstrapping. See http://git.io/v4gXM for details"
Thanks in advance.
;-)
Probably because the window that is rendering your pdf isn't an angular page. You can tell protractor not to wait for angular by using browser.waitForAngularEnabled(false). You should do this right before your call to switch window. Just remember to turn it back on when you close the window and switch back to your main app window. Check out this documentation for more info.
browser.getAllWindowHandles().then(function (handles) {
newWindowHandle = handles[1]; // this is your new window
browser.waitForAngularEnabled(false); //add this and it should work
browser.switchTo().window(newWindowHandle).then(function () {
var EC = protractor.ExpectedConditions;
// Waits for the element is not present on the dom.
browser.wait(EC.stalenessOf($('#formattedJson')), 5000);
});
}):

CasperJS form fill sometimes stays on the current page

I have a simple casperjs test to submit a search form on my homepage. Then I assert that the title on the landing page is correct.
Works fine on my computer (OSX 10.9.2) but on my colleague's laptops (a Win 7 and Win 8), the test fails randomly because casper "thinks" it is still on the search page.
casper.test.begin('Search', function(test) {
casper.start("http://localhost:8080/site", function() {
this.fill(searchForm, { query: goodQuery }, true);
});
casper.then(function() {
// sometimes fails, says it's "My Project" main title
test.assertTitle('Search Result', 'Search result title is ok');
});
}
Introducing a casper.waitFor(3000) before checking the page title does not change the outcome. I've also tried to replace the then step by a waitForUrl, but it fails after 5 secs, saying it is still on the current page.
Plenty of other tests work fine on all computers but it's the only one with form submition.
Any hints on how to solve or properly work around this? I'd rather not simulate a click on the submit button (more coupling to the form internals) if possible (but it would be okay I guess).
Thanks
$ casperjs --version
1.1.0-beta3
$ phantomjs --version
1.9.7
EDIT: submitting the form and waitForUrldid not help. I found out that the test actually runs fine on its own, even on the Windows 7 machine. But when I run two tests:
01 search.js (the one described above)
02 menu.js (a simple one, merely containing assertExists)
'search.js' fails most of the time... and sometimes 'menu.js' fails instead! I suspect some mishandled concurrent access, although it consistently works on OSX. I must be doing something wrong. Both tests have the same structure:
casper.test.begin('Some test', function(test) {
casper.start(someUrl, function() {
// some test
});
casper.run(function() {
test.done();
});
});
Any clue?
Try :
casper.test.begin('Search', function(test) {
casper.start("http://localhost:8080/site", function() {
this.fill(searchForm, {
query: goodQuery
},false);
this.click("your selector for submit button");
});
casper.then(function() {//you should use waitForUrl/Selector/Text() instead
// sometimes fails, says it's "My Project" main title
test.assertTitle('Search Result', 'Search result title is ok');
});
casper.run(function() {
this.test.comment('------ Tests over ----\n');
test.done();
});
});
It's better to submit the form by clicking. Sometimes (often) it doesn't pass putting the fill arg at true. Just put the correct selector for the submit button.
You should wait for an item to appear on the following page. I would change your code to the following:
casper.test.begin('Search', function(test) {
casper.start("http://localhost:8080/site", function() {
this.fill(searchForm, { query: goodQuery }, true);
});
casper.waitForSelector('#someSelectorOnNextPage', function() {
test.assertTitle('Search Result', 'Search result title is ok');
});
}
I also experience same issue. Suprisingly adding empty then() handler fixes that in v1.1.0-beta3. I don't think this is expected behavior though:
casper.test.begin('Search', function(test) {
casper.start("http://localhost:8080/site", function() {
this.fill(searchForm, { query: goodQuery }, true);
});
// Do nothing here, just call it as a placeholder
// Here http://localhost:8080/site sends us to the next endpoint
casper.then(function() {});
// Now this is the final page we actually want to assert
casper.then(function() {
test.assertTitle('Search Result', 'Search result title is ok');
});
}
EDIT:
Although question author says casper.waitForUrl() didn't work for them, it did work for me as an alternative solution.
What does look strange is that in verbose mode whatever returns a 301 status code along with Location Header is recognized as HTTP 200 response by Casper.
EDIT 2:
Well obviously it doesn't happen every time, but what I noticed is that Casper sometimes doubles the previous response (that's why I thought it recognizes some specific HTTP codes as 200 mistakenly and that's why author's code functioned as if it stayed on same page after form submission) and sometimes not.
waitForUrl() fixes that obviously but there is still some underneath issue in Casper which scares me a bit and I hope I will find some time to report it with all the dumps to Casper issue tracker.

Resources