For UI Testing purpose I would like to take a screenshot of my application's favicon , I am using cy.screenshot('Application', { capture: 'fullPage' }) but it is not capturing the favicon
You can assert the favicon is available like so:
it('assert favicon', () => {
cy.visit('www.reactjs.org').document().its('head').find('link[rel="icon"]').should('have.attr', 'href').should('eq', '/favicon.ico')
});
The example above is using React's official webpage for the assertion, but you can customize the code for your use case.
Most probably it seems that cypress is executing the screenshot before favicon has been loaded.
Have you tried just using a timeout before screenshot?
cy.wait(2500).then(cy.screenshot('Application', { capture: 'fullPage' }));
Related
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.
I am now write some tests with electron-spectron.
After spectrum start my app, I want to check if my video is stopped or not
the code is like
element
<video muted autoplay id='videoContainer' class='video'></video>
test code
.given("",function(){
//do something
})
.when("",function(){
//do something
})
.then("the player should stop the program", function() {
return app.client.someFuncton('//*[#id="videoContainer"]')
.then(result=>{
console.log(result) // suppose to get my video source
})
})
It seems that webdriverIO doesn't have an API like getElementById that I can use to find my video tag's source.
Do someone have any good idea?
Here is the documentation for selector in WEBDRIVERIO.
If you want to select an object with id or classname you need to use your selector parameters like below.
'#' means you are looking for element with id.
app.client.someFunction('#yourElementsId')
'.' means you are looking for element with class.
app.client.someFunction('.yourElementsClassname')
I have written multiple spec files for unit testing various modules on the webpage. If i run them individually, one at a time they work fine. But when i try to run all the files in a sequence, only the first file in the spec folder works while all other tests fail. Any help would be appreciated.
Every spec file loads a static page using requirejs and renders them on the page. Once the page is rendered i check whether the title, text etc is proper or not. The spec files looks like this.
AboutSpec.js-->
require(["views/About", "nls/messages"], function (About, messages) {
beforeEach(function(){
var temp = new About();
temp.render();
});
describe("Test for About Page", function () {
it("Check For About Title", function () {
var aboutTitleText = $('.eight.columns h2').text();
expect(aboutTitleText).toEqual(messages["about_title"]);
});
});
});
FooterSpec.js-->
require(["views/Footer", "nls/messages"], function (Footer, messages) {
beforeEach(function(){
var temp = new Footer();
temp.render();
});
describe("Test for Footer Page", function () {
it("Check For Footer Content", function () {
var footerText = $('.five.columns h2').text();
expect(footerText).toEqual(messages["footer_content"]);
});
});
});
jstestDriver.conf-->
load:
- jasmine/lib/jasmine-1.3.1/jasmine.js
- jasmine/lib/adapter/JasmineAdapter.js
- js-src/javaScript/require.js
- js-src/javaScript/default.js
test:
- js-test/AboutSpec.js
- js-test/FooterSpec.js
When i run this setup, the About page does not render. Only the Footer page renders due to which all the test cases of about page fails.
We're facing the exact same problem, and I've spent--how many hours, now? Oh yeah, too many!-- trying to solve this problem.
Today I discovered Karma, a JsTD replacement from Google which runs every test in a fresh iframe. It also integrates with Jenkins. I'm in the process of installing it now and will report back on how it went.
These are my first steps with the Firefox AddOn SDK. What I'm trying to create is a simple 'settings dialogue'. I thought about a html page containing forms for the values and a submit button. Following the first mozilla tutorials I created a widget:
var widget = require('widget').Widget({
label: 'Settings',
id: 'settings',
//panel: text_entry
contentURL: data.url('images/stgfavicon.ico'),
contentScriptFile: data.url('scripts/submit.js'),
onClick: function() {
tabs.open(data.url('forms/settings.html'));
}
});
But since settings.js is not the contentScriptFile I got no communication between settings.html and settings.js. Is it possible to get this done without some (complex looking) messaging system? And how to save the values best? A JSON file?
Some links/examples/API names would help me a lot. :)
That's because you're trying to attach your script to the widget (which is not an HTML file). You need to attach it to the actual html file after the tab opens.
tabs.open({
url: data.url('forms/settings.html'),
onOpen: function onOpen(tab) {
tab.attach({ contentScriptFile: data.url('scripts/submit.js'); });
}
});
I haven't tested that out so there may be an error.
You should also look at the simple-prefs module if these are settings that aren't going to be adjusted frequently.
I have protocol (like http) with scheme managed with 3rd party App registered in Mac OS X.
I.e, x-someapp://someaction or something like that.
How can I open this URL with Google Chrome?
By default, Chrome starts searching in Google engine instead launching App and passing URL handling to it...
Safari launches some registered App. And it is right thing.
Firefox and Opera asks what to do... and I can launch App also.
But Chrome... Doesn't ask.
I even tried to write some HTML page with JavaScript inside to send XHttpRequest:
function _httpExecuteCallback()
{
if (httpRequestCallbackFunction != null) {
if (httpRequest.readyState == 4) {
if (httpRequest.status == 200) {
httpRequestCallbackFunction();
httpRequestCallbackFunction = null;
}
}
}
}
function _httpGet(url, callbackFunction)
{
httpRequest = false;
httpRequestCallbackFunction = callbackFunction;
httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = _httpExecuteCallback;
httpRequest.open('GET', url, true);
httpRequest.send(null);
}
_httpGet('x-someapp://test',function(){})
No results also...
The current accepted solution has a problem with Chrome for SSL https. Watching the console log, Chrome blocks the request because it thinks the custom url protocol is not secure:
[blocked] The page at reports blah blah ran insecure content from customproto//blah blah
Here is a solution (this took me a few days to research):
<input type='button' value='Test Custom Url' onclick='exec()'>
<script>
function submitRequest(buttonId) {
var d = (window.parent)?window.parent.document:window.document
if (d.getElementById(buttonId) == null || d.getElementById(buttonId) == undefined) return;
if (d.getElementById(buttonId).dispatchEvent) {
var e = d.createEvent("MouseEvents");
e.initEvent("click", true, true);
d.getElementById(buttonId).dispatchEvent(e);
}
else {
d.getElementById(buttonId).click();
}
}
function exec(){
var d = (window.parent)?window.parent.document:window.document
var f = d.getElementById('customUrlLink')
if (f ) {f.parentNode.removeChild(f);}
var a = d.createElement('a');
a.href = 'mycustomproto://arg1';
a.innerHTML = "Link"
a.setAttribute('id', 'customUrlLink');
a.setAttribute("style", "display:none; ");
d.body.appendChild(a);
submitRequest("customUrlLink");
}
</script>
This code will not work for IE. I've found using this technique IE limits the argument of the custom protocol to less than 1000 where as using the iFrame technique IE will allow 2083 chars.
The only way to overcome the url limit in javascript is chuck the data and call multiple times. If anyone wants to take a stab at that, please let me know how it goes. I would like to use it.
To handle long urls in the executing app, pass a token into the app and have it go get the data from a url GET.
So for right now I am using one function for Chrome/FF and another function for IE.
These links helped me develop this solution:
https://superuser.com/questions/655405/custom-protocol-handler-not-working-in-chrome-on-ssl-page
Simulating a click in jQuery/JavaScript on a link
(wish I had known this a few days ago....hope this helps someone)
==================================================
Update: (8hr later)
==================================================
Jake posted a great solution for chrome: https://superuser.com/questions/655405/custom-protocol-handler-not-working-in-chrome-on-ssl-page
This works in chrome only:
window.location.assign("customprotocol://");
It will fail in an iframe so this is working:
var w = (window.parent)?window.parent:window
w.location.assign(service + '://' + data)
==================================================
Update: (weeks later)
==================================================
All of the examples of opening the custom protocol, including my own, have a "://" in the url. And this is what is causing the SSL warnings.
Turns out the solution is to change "://" to ":"
so do this:
src="x-myproto:query" .....
and the SSL warnings will go away.
==================================================
Follow: (after months of production use)
==================================================
This has been working well for chorme. Detect the browser and if chrome do this:
var w = (window.parent)?window.parent:window
w.location.assign('myproto://xyzabcdefetc')
For IE and other browsers I do something slightly different.
Note that browsers do impose a limit on how much data you can put in custom url protocol. As long as your string is under 800 chars this seems to be the magic number for which works in all browsers.
It looks like it's Google's locationbar parsing which is getting in the way.
The browser, however, does seem to handle custom URL schemes properly. Try this in your locationbar:
javascript:document.location = 'myscheme://whatever'
Any link on your page that uses the custom scheme should also do the right thing.
I found the solution that works with Chrome.
I use the IFRAME-way.
Example (with JQuery):
$("body").append('<span id="__protoProxy"></span>');
function queryWord(aWord)
{
var protoProxy = document.getElementById('__protoProxy');
if (protoProxy)
{
var word = aWord.replace('"','\"');
protoProxy.innerHTML = '<div style="display:none;"><iframe src="x-myproto://query?' + word + '"></iframe></div>';
}
}
queryWord('hello');
Here's a solution that also includes a redirect to the App Store / Play Store if the user doesn't have the app. It uses a setTimeout for this. It also makes use of an iframe to support more browsers. So this works on Chrome, and any other mobile browser. We use this as my company, Branch. Just modify the two links below to correspond to your URI and App Store link.
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
window.onload = function() {
// Deep link to your app goes here
document.getElementById("l").src = "my_app://somepath";
setTimeout(function() {
// Link to the App Store should go here -- only fires if deep link fails
window.location = "https://itunes.apple.com/us/app/myapp/id123456789?ls=1&mt=8";
}, 500);
};
</script>
<iframe id="l" width="1" height="1" style="visibility:hidden"></iframe>
</body>
</html>
Again, this should work on any browser, thanks to the iframe.
If Chrome does not recognize the URL scheme, it defaults to a search.
This is what I see in Safari:
alt text http://img62.imageshack.us/img62/6792/clipboard02oh.jpg
and in Firefox:
alt text http://img138.imageshack.us/img138/9986/clipboard04xk.jpg
I believe the reason why Chrome defaults to search is that there are special google searches that use the colon.
E.g:
define: dictionary
filetype:pdf google chromium
This is one of the annoyances I have with Firefox, I have to jump to the "search box" rather than the address bar to execute these types of searches. Since Chrome does not have a separate search box like Firefox, IE and Safari have, this functionality is required.
Ajax requests won't get you around this.
Some weeks later ....
Looks like window.location.replace('myscheme://whatever') has full cross-browser support , works with chrome,firefox,safari,edge,opera see https://developer.mozilla.org/en-US/docs/Web/API/Location/replace