So I have a for loop that goes through an array of urls, submits them to wave.webaim.org and makes a render of the page. Simple. However if after the loop I put an exit my images never render
for(x = 0; x < crawlarray.length; x++) {
uri = crawlarray[x];
encoded = encodeURIComponent(uri);
var webaim = "http://wave.webaim.org/report#/" + uri;
webpage.open(webaim, function(status) {
webpage.render(encoded + '.png');
});
}
phantom.exit(0);
If I remove the phantom.exit my images render.
How do I get these images to render and then exit?
I realized now that while render is blocking, open is not, since the render is inside open then I get the problem that render never gets run because the loop is finished before the webpage.open has a chance to finish.
Related
Ran into the issue, where the test code should click the button Process in the iframe. Used npm i cypress-iframe lib, but came up to nothing. Cypress could not find the button.
Tried cy.iframe('[class="resp-iframe"]').find('resp-iframe[id="submit"]')
HTML of the problem
Tried the other ways to click on iframe button:
cy.get('iframe[class="resp-iframe"]').then($element => {
const $body = $element.contents().find('body')
cy.wrap($body).find('resp-iframe[class="btn btn-block btn-primary"]').eq(0).click();
})
also
cy.get('[class="resp-iframe"]').then($element => {
const $body = $element.contents().find('body')
let stripe = cy.wrap($body)
stripe.find('[class="resp-iframe"]').click(150,150)
})
and
cy.iframe('#resp-iframe').find('[name="submitButton"]')
Error
Error 2
Updated FYI:
The first part of code - clicking the Google button in bottom-right:
const getIframeBody = () => {
// get the iframe > document > body
// and retry until the body element is not empty
return cy
.get('[id="popup-contentIframe"]')
.its('0.contentDocument.body')
// wraps "body" DOM element to allow
// chaining more Cypress commands, like ".find(...)"
// https://on.cypress.io/wrap
.then(cy.wrap)
}
getIframeBody().find('[id="payWithout3DS"]').click()
Then, waiting for secure payment preloader to finish up:
cy.wait(20000)
Then, trying to catch the Process button by suggestions:
cy.iframe('[name="AcsFrame"]').find('#submit').click()
or
cy.iframe('[class="resp-iframe"]').find('[id="submit"]')
whole code part looks:
const getIframeBody = () => {
// get the iframe > document > body
// and retry until the body element is not empty
return cy
.get('[id="popup-contentIframe"]')
.its('0.contentDocument.body')
// wraps "body" DOM element to allow
// chaining more Cypress commands, like ".find(...)"
// https://on.cypress.io/wrap
.then(cy.wrap)
}
getIframeBody().find('[id="payWithout3DS"]').click()
cy.wait(20000)
cy.iframe('[name="AcsFrame"]').find('#submit').click()
But still, getting:
Maybe anyone had something like that?
Thanks.
How about you try this:
cy.iframe('[name="AcsFrame"]').find('#submit').click()
You don't need to repeat the resp-iframe inside the .find().
The selector .find('resp-iframe[id="submit"]') means look for HTML like this: <resp-iframe id="submit"> but the element you want is <input id="submit">.
Everything else looks ok
cy.iframe('[class="resp-iframe"]').find('[id="submit"]')
I have this piece of code:
getText: (selector) => {
browser.waitUntil(function () {
return browser.isExisting(selector) === true;
},timeout,
'Could not find element after: ' + timeout,
pollingTime);
return browser.getText(selector);
}
And sometimes this function (getText(selector), but in deep browser.getText(selector)) returns undefined for the selector that looks like this:
article[data-product-id="test-00020"] li.product-entry__summary__item.is-price span
This doesn't happen every time test is run, but it happens occasionally. It is driving me nuts because the behavior is inconsistent. Sometimes it works and sometimes it doesn't.
Did anybody have similar problems? Please help! Thank you.
getText is dependent on the element being visible in the viewport of the page (so if it's scrolled off the page it will return an empty string)
Instead, you can use getHTML(false) to get the text content of an element (just ensure it's the inner-most element, otherwise you'll get HTML elements in the returned content)
If you use getHTML which I also did, you can strip out the HTML tags if they are not innerHTML:
var strArray = browser.getHTML("//div[myxpath]");
for(var i =0; i<strArray.length; i++){
strArray[i]=strArray[i].replace(/(<([^>]+)>)/ig, "");
strArray[i] = strArray[i].trim();
}
sorry for the Hungarian notation.
I am using the following code, which uses the imagesLoaded package with a callback to tell me when an element with a particular csspath has finished loading all of its images:
imagesLoadedScript = "imagesLoaded( '#{csspath}', { background: true }, function(message) { console.log('PHANTOM CLIENT REPORTING: #{csspath} Images Loaded'); return message; })"
imagesLoadedScript = imagesLoadedScript.strip.gsub(/\s+/,' ')
#session.evaluate_script(imagesLoadedScript)
The timing of the console.log statement, on inspection of PhantomJS logs with debug on, indicates that Capybara/Poltergiest is not waiting for the images to load, as expected, before it moves on to the next statement. I also cannot return a true (or false) value from inside the callback as I would like.
Capybara responds with
{"command_id":"678f1e2e-4820-4631-8cd6-413ce6f4b66f","response":"(cyclic structure)"}
Anyone have any ideas on how to return a value from inside a callback in a function executed via evaluate_script?
Many thanks.
TLDR; You can't
evaluate_script doesn't support asynchronous functions - you must return the result you want from the function passed in. One way to do what you want would be to execute the imagesLoaded script and have the callback set a global variable, and then loop on an evaluate_script fetching the result of the global until it's what you want - A very basic implementation would be something like
imagesLoadedScript = "window.allImagesLoaded = false; imagesLoaded( '#{csspath}', { background: true }, function() { window.my_images_loaded = true })"
#session.execute_script(imagesLoadedScript)
while !#session.evaluate_script('window.allImagesLoaded')
sleep 0.05
end
Obviously this could be made more flexible with a timeout ability, etc.
A second option would to write a custom capybara selector type for images with a loaded filter, although with the need for background image checking it would become pretty complicated and probably too slow to be useful.
Just in case someone finds this later.
I did roughly what Thomas Walpole suggested in his answer, in a more roundabout fashion, but taking advantage of Poltergeist's inherent waiting capabilities;
#to check that the target has loaded its images, run images loaded
#after a small timeout to allow the page to get the images
#append a marker div to the dom if the images have successfully loaded
imagesLoadedScript = "var item = document.querySelector('#{csspath}');
window.scroll(0, item.offsetTop);
function imagesDone(path, fn) {
imagesLoaded( path, function(instance) {
console.log('PHANTOM CLIENT REPORTING: ' + path + ' Images Loaded');
fn(true);
})
}
setTimeout(function(){
imagesDone('#{csspath}', function(done) {
var markerDiv = document.createElement('div');
markerDiv.id = 'ImagesLoadedMarker';
document.getElementsByTagName('html')[0].appendChild(markerDiv);
});
}, 1000)"
#then we strip the new lines and spaces that we added to make it readable
imagesLoadedScript = imagesLoadedScript.strip.gsub(/\s+/,' ')
#now we just execute the script as we do not need a return value
#session.execute_script(imagesLoadedScript)
#then we check for the marker, using capybara's inbuilt waiting time
if #session.has_xpath? "//*[#id ='ImagesLoadedMarker']"
Rails.logger.debug "!!!!! PhantomClient: Images Loaded Reporting: #{csspath} Images Loaded: Check Time #{Time.now} !!!!!"
#session.save_screenshot(file_path, :selector => csspath)
else
Rails.logger.debug "!!!!! PhantomClient: Images Loaded Reporting: #{csspath} Images NOT Loaded: Check Time #{Time.now} !!!!!"
#session.save_screenshot(file_path, :selector => csspath)
end
Why does Navigator.jumpTo require require the use of a route stack when Navigator.push does not?
I want to be able to jumpTo and back from any route/scene in my application.
Navigator.push and Navigator.pop work fine EXCEPT that I need to have my main scene remain mounted.
If I use Navigator.jumpTo and Navigator.jumpBack, the main scene remains mounted, but I have to use a route stack, which sometimes forces me to go back through multiple scenes to get back to my main scene.
The only solution I can think of is to dynamically manipulate the route stack before I jumpTo a new route, but this seems inelegant and unnecessary.
Or perhaps I'm missing something?
This is because of the jumpTo function have some problems,you can change it.
Open you-project\node_modules\react-native\Libraries\CustomComponents\Navigator\Navigator.js.
Change this code(In line 1031):
jumpTo: function(routeName) {
var destIndex = -1;
for (var i = 0; i < this.state.routeStack.length; i++) {
if (this.state.routeStack[i]["name"] === routeName) {
destIndex = i;
}
}
invariant(
destIndex !== -1,
'Cannot jump to route that is not in the route stack'
);
this._jumpN(destIndex - this.state.presentedIndex);
},
Now you can use jumpTo like navigator.jumpTo("Home").
When a script is injected in a safari extension it runs on page load, so that means when an extension is installed the injected javascript will only apply to newly-opened pages or pages which are reloaded afterwards. Does anyone know how to ensure the javascript is run without having to reload?
Alternatively, forcing users to load... this seems a bit dangerous though.
I've also tried to find a way to "execute" or "attach" a script on install. This is possible in Chrome and Firefox, without having to reload the page. Unfortunately in Safari I haven't found a way to do this without having to reload the page and let the normal addContentScript handlers take care of injecting the script.
To reload all Safari tabs directly after extension has been installed:
/* In glabal.js */
// Reloads all tabs
function reloadTabs() {
var browserWindows = safari.application.browserWindows;
for (var i = 0; i < browserWindows.length; i++) {
var tabs = browserWindows[i].tabs;
for (var j = 0; j < tabs.length; j++) {
tabs[j].url = tabs[j].url;
}
}
}
// Called on first run
function onInstall() {
reloadTabs();
}
var firstRun = localStorage['extensionHasPreviouslyRun'] === undefined ||
!JSON.parse(localStorage['extensionHasPreviouslyRun']);
if (firstRun) {
onInstall();
localStorage['extensionHasPreviouslyRun'] = JSON.stringify(true);
}