Wait until page is fully loaded in BackstopJS - puppeteer

I've a scenario where I need to search. The problem is that I need BackstopJS to wait until an animated gif is done, and after that take screenpicture. I've tried this:
{
"label": "My_search",
"cookiePath": "backstop_data/engine_scripts/cookies.json",
"url": "https://my.test.com/test/#/search",
"referenceUrl": "https://my.stage.test.com/test/#/search",
"clickSelector": "#page-wrap > search > div > ul > li:nth-child(2) > a > span",
"delay": 15000
}
Any idea how to solve this problem?

you can add the load eventListener to your page and then log a readyEvent String for BackstopJS
window.addEventListener('load', () => {
console.log('pageLoaded');
});
in your backstop scenario use "readyEvent": "pageLoaded",

Related

Switch to popup window with hotkey chrome extension

I have created a chrome extension that has a popup.js, background.js, content.js files (amongst others).
When I do some kind of hot key on the main browser page, I want to refocus/switch to my popup window.
I have tried a number of things. I am not sure where to put this.
I am using Chrome manifest v2.
I have the following in my manifest.json:
"commands": {
"popupWindow" : {
"suggested_key": {
"default": "Ctrl+Shift+P"
},
"description": "Switch to popup window"
}
}
I have the following in my background.js:
// Catch commands on the content page in the background script
chrome.commands.onCommand.addListener(function (command) {
if (command === "_execute_page_action") {
console.log("execute_browser_action");
} else if (command === "popupWindow") {
console.log("popupWindow");
}
});
At the moment, it's just a log. I have tried getting the id of the popup window, but I can't seem to.
Any help greatly appreciated.
You don't need anything in your background.js for this to work. Modify your manifest.json file to this:
{
...
...
"commands": {
"_execute_page_action" : {
"suggested_key": {
"default": "Ctrl+Shift+P",
"mac": "MacCtrl+Shift+F"
},
"description": "Switch to popup window"
}
...
}
You can get rid of the listener in background.js.

How to add cltr+tap listener to polymer element

I would like to create element that does something for ctrl+tap. How can I assign listener to it?
I have tried to use iron-a11y-keys-behavior https://elements.polymer-project.org/elements/iron-a11y-keys-behavior
and
keyBindings: {
'ctrl:tap': 'doSomething'
},
but it does not work.
Can I use somehow Polymer features like listeners or behaviors for it, or should I code it on my own using VanillaJS?
The only solution I have found is
listeners: {
'tap': '_elementTapped'
},
keyBindings: {
'ctrl+control:keydown': '_updatePressed',
'control:keyup': '_updatePressed'
},
_ctrlPressed: false,
_updatePressed: function(event) {
this._ctrlPressed = event.detail.ctrlKey;
},
_elementTapped: function(){
if(this._ctrlPressed){
this.doSomething();
}
}
For me it looks, like an overhead, as we have to add 2 more methods, 1 property and 1 listeners, comparing to 'ctrl:tap': 'doSomething'.
I would really appreciate cleaner solutions.

Anchor <a> tags not working in chrome when using #

Here is the code I am using on my page,
<li>Sound</li>
(in a menu which appears on all pages)
<a id="Sound"><a>
(on the page where i want to link to)
I have tried adding content to the tags with an id. But only in chrome the browser will not scroll down to the tag. These anchors work in IE&FF
Any ideas?
Turns out this was a bug in certain versions of chrome, posting workaround for anyone who needs it! :)
$(document).ready(function () {
var isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
if (window.location.hash && isChrome) {
setTimeout(function () {
var hash = window.location.hash;
window.location.hash = "";
window.location.hash = hash;
}, 300);
}
});
The workaround posted didn't work for me, however after days of searching this finally worked like a charm so I figured it was worth sharing:
$(function() {
$('a[href*="#"]:not([href="#"])').click(function() {
if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
if (target.length) {
$('html, body').animate({
scrollTop: target.offset().top
}, 1000);
return false;
}
}
});
});
If you somehow ended up here like me when finding out the anchor link to a SPA site doesn't work from an external site. Yep, the browser is just working too fast to load the skeleton of the page. And it couldn't find your anchor when it loads the page.
To work around this, just add in the lifecycle of your SPA (useEffect in React and mounted in Vue) some lines to check the url hash and do the scrolling yourself.
example using React
useEffect(()=> {
if(document.location.hash === '#some-anchor') {
setTimeout(()=> {
document
.querySelector("#some-anchor")
.scrollIntoView({ behavior: "smooth", block: "start" })
}, 300)
}
}, [])
I was having this problem as well (same page navigation using links) and the solution was very easy (though frustrating to figure out). I hope this helps - also I checked IE, Firefox, and Chrome and it worked across the board (as of 05-22-2019).
Your link should looks like this:
Word as link you want people to click
and your anchor should look like this:
<a name="#anchorname">Spot you want to appear at top of page once link is clicked</a>
Try using :
For menu page
<li>Sound</li>
in a menu which appears on all pages
<a id="#Sound"><a>
This works well in the all versions of Chrome!
I have tested it on my browser.
This answer is for someone who encountered same problem, but scripts didn't work. Try to remove loading='lazy' and decoding='async' from all images on the page or set width and height attributes to them.
It worked like a charm for me.
Here is my version of #Jake_ answer for Chrome / angular not scrolling to a correct anchor on initial page load up using ui-router (the original answer would throw my code into 'Transition superseeded' exceptions):
angular.module('myapp').run(function($transitions, $state, $document, $timeout) {
var finishHook = $transitions.onSuccess({}, function() { // Wait for the complete routing path to settle
$document.ready(function() { // On DOM ready - check whether we have an anchor and Chrome
var hash;
var params;
var isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
finishHook(); // Deregister the hook; the problem happens only on initial load
if ('#' in $state.params && isChrome) {
hash = $state.params['#']; // Save the anchor
params = _.omit($state.params, ['id', '#']);
$timeout(function() {
// Transition to the no-anchor state
$state.go('.', params, { reload: false, notify: false, location: 'replace' });
$timeout(function() {
// Transition back to anchor again
$state.go('.', _.assign($state.params, { '#': hash }), { reload: false, notify: false, location: 'replace' });
}, 0);
}, 0);
}
});
}, {invokeLimit: 1});
});
Not sure if this helps at all or not, but I realized my anchors in IE were working but not in Firefox or Chrome. I ended up adding ## to my anchors and this solved the issue.
example:
a href="##policy">Purpose and Policy Statement
instead of :
a href="#policy">Purpose and Policy Statement
<html>
<body>
<li>
Sound
</li>
<a id="Sound" href="www.google.com">I AM CALLED</a>
</body>
</html>
use this as your code it will call the anchor tag with id value sound
Simply change the call on your link to external.

Creating Chrome extensions to hide DIV display:none; on a specific page

I'm trying to create my first Chrome extension.
It's basically an adblocker for specific elements, in this case - the Facebook comments section.
It works with the all_urls but not with that specific domain.
Manifest file:
{
"name": "My extension",
"version": "1.0",
"manifest_version": 2,
"content_scripts": [
{
"matches": ["http://visir.is/*"], //where your script should be injected
"css": ["style.css"] //the name of the file to be injected
}
]
}
style.css file:
.fbcomment {
display: none;
}
Any ideas how to correct "matches"?
I have tried *://visir.is/* as specified in https://developer.chrome.com/extensions/match_patterns but it only works with all_urls
Viktor,
You are on the wrong way. Your extension should work on Facebook site, and so the matches statement in the manifest must be exactly as the following:
"matches": ["https://www.facebook.com/*"]
Than you need to find all the comments in the timeline (most probably by css class), detect the presence of the target site address (//visir.is/) and then hide these comments.
Because the timeline dynamically load more posts you will also need to observe the new nodes and apply your function on them too (see the example from my Chrome extension below):
var obs = new MutationObserver(function (mutations, observer) {
for (var i = 0; i < mutations[0].addedNodes.length; i++) {
if (mutations[0].addedNodes[i].nodeType == 1) {
$(mutations[0].addedNodes[i]).find(".userContentWrapper").each(function () {
injectFBMButton($(this));
});
}
}
injectMainButton();
});
obs.observe(document.body, { childList: true, subtree: true, attributes: false, characterData: false });

Does body.onload wait for IFrames?

I know that onload event waits for page resources to load before firing - images, stylesheets, etc.
But does this include IFrames inside the page? In other words, is it guaranteed that all the child Frames' onloads will always fire before the parent's does?
Also, please let me know if behavior varies between browsers.
No, it doesn't. If you want to do something like that, you'll need to add an onload handler for the iframe. You can do this nicely with jQuery:
<iframe src="http://digg.com"></iframe>
<script>
var count = $('iframe').length;
$(function() {
// alert('loaded'); // will show you when the regular body loads
$('iframe').load(function() {
count--;
if (count == 0)
alert('all frames loaded');
});
});
</script>
This would alert when all the frames are loaded.
See the example:
http://jsbin.com/azilo
Or plain javascript should work..
function checkIframes() {
if(!i) { i = 0; }
if(document.getElementsByTagName('iframe')[i]) {
document.getElementsByTagName('iframe')[i].onload = function () { i++; checkIframes(); }
}
else { yourFunctionInHere(); }
}
haven't really tested this, but should work... than refer to it with document.onload = function() { checkIframes(); }
I don't really like libraries like jQuery, because so far I found I can achieve more with less code, with regular javascript.
As I see on my pages, each iframe got independent onload, and top-frame onload doesn't wait for iframes to fire.
I got gif/png banners on my site that sometimes loads very slowly, so I put them into iframe and that made whole site and onload event to work faster.