How to force phantomjs to finish navigating - c#

I have a problem that my phantomjs loads one site too slow, always at least 60 seconds though on other sites like google.com it takes less than 1 second.
PhantomJSDriverService service = PhantomJSDriverService.CreateDefaultService();
service.IgnoreSslErrors = true;
service.LoadImages = false;
service.ProxyType = "none";
service.HideCommandPromptWindow = true;
using (IWebDriver driver = new PhantomJSDriver(service ))
{
driver.Navigate().GoToUrl("http://abc.xyz"); //blocks too long
...
}
Is there any way to force it finish loading after reaching some point so the script will continue?

I see what you are asking now. You have a long loading page that you want to stop after the relevant stuff loads. I run into this same issue with some of the sites that we have at work but I have not tried a programmatic solution. Sorry, I don't know phantomjs but I found some links that I think would be helpful.
The way I would approach it is to wait for the DOMContentLoaded event to fire and then send an ESC to the page. At least that's what I do manually to stop the long loading files that I don't care about so that the execution can continue.
I found this question How can I wait for the page to be ready in PhantomJS? Here's the relevant part:
var page = require('webpage').create();
var system = require('system');
page.onInitialized = function() {
page.onCallback = function(data) {
console.log('Main page is loaded and ready');
//Do whatever here
};
page.evaluate(function() {
document.addEventListener('DOMContentLoaded', function() {
window.callPhantom();
}, false);
console.log("Added listener to wait for page ready");
});
};
page.open('https://www.google.com', function(status) {});
Once you detect DOMContentLoaded, use sendkeys() to send the ESC key. I honestly don't know if this will work but it's where I would start. Hopefully it will get you started.

I've just found out the reasons why the phantomjs load so slow because the target web has too many extensions, ads... so I switch to chrome and use adblock like Running Selenium WebDriver using Python with extensions (.crx files)

Related

JavaScript window.open returns null sometimes

I am attempting maintenance on a system I did not write (and aren't we all?). It is written in C Sharp and JavaScript, with Telerik reports.
It has the following code included in JavaScript that runs when the user clicks a button to display a report in a separate window:
var oIframe = $("iframe id='idReportFrame' style='display:none' name='idReportFrame' src=''>");
oIframe.load(function() { parent.ViewReports(); });
oIframe.appendTo('body');
try
{
$('#idReportForm').attr('target', 'idReportFrame');
$('#idReportForm').submit();
}
catch (err) { // I did NOT write this
}
Then the load function:
function ViewReports()
{
var rptName = $("#ReportNameField").val();
if (rptName == '') { return false; }
var winOption = "fullscreen=no,height=" + $(window).height() + "left=0,directories=yes,titlebar=yes,toolbar=yes,location=yes,status=no,menubar=yes,scrollbars=no,resizable=no, top=0, width=" + $(window).width();
var win = window.open('#Url.Action("ReportView", "MyController")?pReportName=' + rptNameCode, 'Report', winOption);
win.focus();
return false;
}
When I execute this (in Chrome, at least), it does pop up the window and put the report in it. However, breakpoints in the c# code indicate that it is getting called 2 or 3 times. Breakpoints in the JavaScript and examination of the little log in the JavaScript debugging environment in Chrome show that the call to win.focus() fails once or twice before succeeding. It returns an undefined value, and then it appears that the first routine above is executed again.
I am inclined to think it some kind of timing issue, except that the window.open() call is supposed to be synchronous as far as I can tell, and I don't know why it would succeed sometimes and not others. There is a routine that gets executed on load of the window, perhaps that's somehow screwing up the return of the value from open().
I am not a JavaScript person much, as those of you that are can likely tell by this time. If there is something with the code I've put here that you can tell me is incorrect, that's great; what I'm more hopeful for is someone who can explain how the popup-report-in-frame is supposed to work. Hopefully I can do it without having to replace too much of the code I've got, as it is brittle and was not, shall we say, written with refactoring in mind.
From what I could find the window.open will return null when it fails to open. Something may be keeping the browser from opening additional windows a couple of times; maybe it is a popup blocker.
The actual loading of the url and creation of the window are done asynchronously.
https://developer.mozilla.org/en-US/docs/Web/API/Window.open
Popup blocking
In the past, evil sites abused popups a lot. A bad page could open
tons of popup windows with ads. So now most browsers try to block
popups and protect the user.
Most browsers block popups if they are called outside of
user-triggered event handlers like onclick.
For example:
// popup blocked
window.open('https://javascript.info');
// popup allowed
button.onclick = () => {
window.open('https://javascript.info');
};
Source: https://javascript.info/popup-windows
I just ran into this and it seems to be because I had a breakpoint on the line that calls window.open and was stepping through the code, in Chrome dev tools. This was extremely hit-and-miss and seemed to fail (return null, not open a window, whether one already existed or not) more times that it succeeded.
I read #Joshua's comment that the creation is done asynchronously, so I figured that forcing the code to 'stop' each time I step might be screwing things up somehow (though on a single line like var w = window.open(...) doesn't seem like this could happen).
So, I took out my breakpoint.. and everything started working perfectly!
I also took note of https://developer.mozilla.org/en-US/docs/Web/API/Window/open where they specify that if you are re-using a window variable and name (the second argumen to window.open) then a certain pattern of code is recommended. In my case, I am wanting to write HTML content to it, rather than give it a URL and let it async load the content over the network, and I may call the whole function repeatedly without regard for the user closing the window that pops up. So now I have something like this:
var win; // initialises to undefined
function openWindow() {
var head = '<html><head>...blahblah..</head>';
var content = '<h1>Amazing content<h1><p>Isn\'t it, though?</p>';
var footer = '</body></html>';
if (!win || win.closed) {
// window either never opened, or was open and has been closed.
win = window.open('about:blank', 'MyWindowName', 'width=100,height=100');
win.document.write(head + content + footer);
} else {
// window still exists from last time and has not been closed.
win.document.body.innerHTML = content;
}
}
I'm not convinced the write call should be given the full <html> header but this seems to work 100% for me.
[edit] I found that a Code Snippet on Stackoverflow has a some kind of security feature that prevents window.open, but this jsfiddle shows the code above working, with a tweak to show an incrementing counter to prove the content update is working as intended. https://jsfiddle.net/neekfenwick/h8em5kn6/3/
A bilt late but I think it's due to the window not beeing actually closed in js or maybe the memory pointer not being dereferenced.
I was having the same problem and I solved it by enclosing the call in a try finally block.
try {
if (!winRef || winRef.closed) {
winRef = window.open('', '', 'left=0,top=0,width=300,height=400,toolbar=0,scrollbars=0,status=0,dir=ltr');
} else {
winRef.focus();
}
winRef.document.open();
winRef.document.write(`
<html>
<head>
<link rel="stylesheet" href="/lib/bootstrap/dist/css/bootstrap.min.css">
</head>
<body>
${$(id).remove('.print-exclude').html()}
</body>
</html>
`);
winRef.document.close();
winRef.focus();
winRef.print();
} catch { }
finally {
if (winRef && !winRef.closed) winRef.close();
}

Selenium and Internet Explorer Driver

I'm trying to run some tests with C# and InternetExplorerDriver.
This code is executed on Windows Server 2012, 64 bit.
Right after navigation to a new URL, I'm calling a function that waits until a page loads\20 seconds timeout.
private bool waitForPageToLoad()
{
try
{
int timeout = int.Parse(ConfigurationManager.AppSettings["TimeoutForCustomExpression"]);
IWait<IWebDriver> wait = new OpenQA.Selenium.Support.UI.WebDriverWait(m_driver, TimeSpan.FromSeconds(timeout));
wait.Until(driver1 => ((IJavaScriptExecutor)m_driver).ExecuteScript("return document.readyState").Equals("complete"));
}
catch//(Exception e) //timeout
{
log(e.Message + e.StackTrace);
return false;
}
return true;
}
The function works great for every browser other than IE.
On IE, I the following error in my log:
JavaScript error (UnexpectedJavaScriptError) at
OpenQA.Selenium.Support.UI.DefaultWait1.PropagateExceptionIfNotIgnored(Exception
e) in
c:\Projects\WebDriver\trunk\dotnet\src\WebDriver.Support\UI\DefaultWait.cs:line
222 at OpenQA.Selenium.Support.UI.DefaultWait1.Until[TResult](Func`2
condition) in
c:\Projects\WebDriver\trunk\dotnet\src\WebDriver.Support\UI\DefaultWait.cs:line
180 at MainClass.waitForPageToLoad()
I have no idea why it happens.
Could somebody help me out here?
Sincerely,
Adam.
Without seeing all that extra information that Arran requested, it's hard to help you understand the error.
However if you're just looking for a quick fix that works in all browsers, I always just use
Thread.sleep(int milliseconds);
for my Selenium tests in C# that need to wait for a page to load or a certain element to render before continuing.

SignalR blocks chrome UI?

I'm having a problem with SignalR and so far can not understand why.
I've wrote a hub for long order processing operation and noticed, that it updates progress ok within FireFox, but has a problem with Chrome.
So, I've wrote simple test hub to check what is going on:
public class SimpleHub: Hub
{
public void LongProcess()
{
System.Threading.Thread.Sleep(2000);
Clients.Caller.AddProgress("Step 1 of 5 has completed.");
System.Threading.Thread.Sleep(2000);
Clients.Caller.AddProgress("Step 2 of 5 has completed.");
System.Threading.Thread.Sleep(3000);
Clients.Caller.AddProgress("Step 3 of 5 has completed.");
System.Threading.Thread.Sleep(1000);
Clients.Caller.AddProgress("Step 4 of 5 has completed.");
System.Threading.Thread.Sleep(4000);
Clients.Caller.AddProgress("Step 5 of 5 has completed.", true);
}
}
What it does, it adds progress every several seconds. It works as supposed in clean project in both browsers - every couple seconds appears new progress message in browser.
But when I try it on real project, with Firefox it works ok, but in Chrome it looks like it completely blocks UI(doesn't even repaint Chrome console) and only when LongProcess finishes, it adds all progress messages.
So question is, what could be cause of this - may be some jQuery setting? Any ideas what to check?
Btw, I've tried longPolling and serverSendEvents (this was chosen auto by signalR in Chrome), same result on both.
Update: added client code:
var hub = $.connection.SimpleHub;
hub.client.AddProgress = function (progress) {
$("#placeOrderProgress").append('<li><span>' + progress + '</span><i></i></li>');
};
$.connection.hub
.start()
.done(function () {
hub.server.longProcess($('#checkoutForm').toJSON());
});
Found the answer.
We had in couple places where jQuery remote validation is used this piece of code (to avoid racing conditions):
$.ajaxSetup({ async : false });
So when I removed it, SignalR started working fine on Chrome. Interestingly enough, on FireFox it does not have any influence - it works with or without this line of code.

WatiN seems to not find JavaScript alert

I have a web application that, under some conditions, pop up JavaScript alert()s that I need to react to in a WatiN test. Google pointed me at Handling alerts in WATIN from way back in 2007 that seemed promising, and I adapted the example code in that post into the following (anonymized):
private void MyAssert(IE browser, WatinHelper helper)
{
AlertDialogHandler alertDialogHandler = new AlertDialogHandler();
using (new UseDialogOnce(browser.DialogWatcher, alertDialogHandler))
{
// DoWrong() causes a JavaScript alert(); false means use nowait.
DoWrong(helper, false);
alertDialogHandler.WaitUntilExists(10 /*seconds*/);
if (!alertDialogHandler.Exists())
{
Assert.Fail("No JavaScript alert when it should have been there");
}
alertDialogHandler.OKButton.Click();
}
SecondAssert(browser);
}
However, while the alert is displayed virtually instantaneously (as it is supposed to) when DoWrong() is called, the call to alertDialogHandler.WaitUntilExists() eventually fails with a WatiNException: Dialog not available within 10 seconds... The only problem was that I could see that the dialog most definitely was up on the screen.
I'm probably missing something simple; can someone point me in the right direction please?
I have also tried the following two variants, and some variations of them, with no luck; I keep getting the same error.
AlertDialogHandler alertDialogHandler = new AlertDialogHandler();
DoWrong(helper, false);
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
do
{
}
while (!alertDialogHandler.Exists() && stopwatch.Elapsed.TotalMilliseconds < 3000);
Assert.IsTrue(alertDialogHandler.Exists(), "No JavaScript alert when it should have been there");
alertDialogHandler.OKButton.Click();
SecondAssert(browser);
and
AlertDialogHandler alertDialogHandler = new AlertDialogHandler();
browser.DialogWatcher.Add(alertDialogHandler);
DoWrong(helper, false);
alertDialogHandler.WaitUntilExists();
alertDialogHandler.OKButton.Click();
browser.WaitForComplete();
Assert.IsFalse(alertDialogHandler.Exists());
SecondAssert(browser);
Yes, I know that code is getting a bit ugly, but right now I'm mostly trying to get it to work at all. If it sits for a few seconds cooking the CPU at 100% utilization because of the tight loop in my second attempt, but only does what I need it to (plain and simple, dismiss that alert()), it's OK.
This is an issue with WatiN and IE8 and the way IE8 changed the way it creates popups. The issue is fixed in the current code available at the Sourceforge SVN repository for the project. Get it, compile it and your problem is solved.
A new release of WatiN will be available before the end of this year.
HTH,
Jeroen

How to fix "The requested resource is in use. (Exception from HRESULT: 0x800700AA)"

How can I solve this error?
"The requested resource is in use. (Exception from HRESULT: 0x800700AA)".
This appears while navigating to a different website using the WebBrowser control in C# .NET. Why?
The WebBrowser control is considered "in use" if either a navigation action is currently being processed, or any blocking dialog from the control is currently open (including context menu, Javascript alerts, NTLM login dialog, etc.). You can use the WebBrowser.IsBusy property to detect these states.
If due to a currently incomplete navigation action, you could try to stop the current navigation (if you indeed want to stop when the page is not completed loaded) or add the new navigation to a request queue and use a timer to wait until WebBrowser.IsBusy returns false.
If instead the busy state is due to one or more open blocking dialogs, you could do the same wait technique and perhaps Messagebox.Show() the user a message that pending navigation is delayed due to an open dialog window.
I had this same issue. Calling WebBrowser.Stop() did not help, and WebBrowser.IsBusy never became false.
It turns out that if the page creates any sort of dialog (alert() popups, javascript errors, NTLM login popups etc.) you can't navigate away from the page until the dialog is closed.
My solution was to prevent the dialogs from showing in the first place. Apparently preventing all of these popups is simple; just set
webBrowser.ScriptErrorsSuppressed = true;
bool go = false;
string SiteContent1 = string.Empty;
string SiteContent2 = string.Empty;
int index = 0;
WebBrowser wb = new WebBrowser();
void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
try
{
if (go)
{
SiteContent2 = wb.DocumentText;
// Code to compare to contents of the webbrowser
index++;
go = false;
steps = 1;
}
if (!go)
{
if (index >= TotalSiteCount)
{
Stop();
}
else if (steps == 1)
{
wb.Navigate(UrltocompareList[index].Url1);
}
else if (steps == 2)
{
SiteContent1 = wb.DocumentText;
wb.Navigate(UrltocompareList[index].Url2);
go = true;
}
steps++;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
UrltocompareList is a collection of 2 sites to compare.
TotalSiteCount is the number of items in UrltocompareList.
The form for this inherit IOleClientSite to remove media such as images, videos and no active X download to have a faster rendering time in webbrowser control.
I use this method instead of system.net.webclient to get the html of a webpage then compare them.
I got this error when it hits the wb.Navigate method.
An issue I ran into when running specflow tests with watin in windows 10 is that win10 by default uses MS Edge, so I had never opened IE, and when watin started it IE was stuck on the prompt for using default settings. Selecting options, closing browser and running tests again worked for me.
Just something to watch
This can be solved pretty easily.
This error occurs when the browser commits an action while he's already performing an action.
For example, you are navigating to some website while you rightclick in the web browser.
To solve this, I did the follow:
//if my webbrowser isn't performing any actions
if(!myWebBrowser.IsBusy)
{
//Navigate
myWebBrowser.Navigate("http://www.google.com");
}
First Try
1- Please Check Navigate URL's (if you check, please check again compiled folder)
2- Delete WebBrowser Control and Add New
Me forget copy original file App.Path + "\error.html" and see this problem.
Guarantee Method
I Fix This Error in VB6
Add WebBrowserControl wb(0) (Name wb , Index=0)
And Before Ever Navigate
For i = 1 To wb.UBound
Unload wb(i)
Next
Load wb(1)
wb(0).Visible = False
wb(1).Visible = true
wb(1).Navigate URL

Categories