I am trying to write a Neustar WPM script to measure the time taken from clicking a button to the appearance of a button in a overlay that opens. The script looks something like below.
var webDriver = test.openBrowser();
var selenium = webDriver.getSelenium();
webDriver.get('https://www.mywebsite.com');
selenium.waitForPageToLoad(30000);
// Start logging HTTP traffic and timings
test.beginTransaction();
test.beginStep("Open SignUp");
selenium.click("link=Sign Up");
selenium.waitForElementPresent("name=nextStep");
test.endStep();
test.endTransaction();
The problem I am facing is that click does not return immediately and waits for the overlay to completely load. However I want to stop as soon as desired element is visible. How can I ensure that selenium.click return immediately instead of waiting till entire page is loaded.
you can try using this Java method,
public WebElement waitForVisibilityOfElementLocatedBy(final By locator) {
return waitFor(visibilityOfElementLocated(locator));
}
public static ExpectedCondition<WebElement> visibilityOfElementLocated(final By locator) {
return new ExpectedCondition<WebElement>() {
public WebElement apply(WebDriver driver) {
try {
return ExpectedConditions.elementIfVisible(ExpectedConditions.findElement(locator, driver));
} catch (StaleElementReferenceException var2) {
return null;
}
}
public String toString() {
return "visibility of element located by " + locator;
}
};
}`
Related
I have ts script with code to handle "unsaved" text inputs
Here is code of script
export class Unsave {
public static unsave_check(): void {
let unsaved = false;
$(":input").change(function(){
unsaved = true;
console.log(unsaved);
});
function unloadPage(){
if(unsaved){
return "You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?";
}
}
}
}
And then I use it in other script like this
`window.onbeforeunload = Unsave.unsave_check();`
But as I see, function unloadPage() is never hit, why so?
I see that unsaved is changing value to true. But when I go back, I get no alert message.
How I can fix this issue?
thank's for help
I think you should call Unsave.unsave_check() when the form has been initialized and bind the unloadPage on the window.onbeforeunload (and you can make it also static - or the other method to non-static and instantiate the object).
You should also move the value unsaved from the function scope, maybe to a private class field so both methods can access it
export class Unsave {
private unsaved: boolean = false;
public register() {
$(":input").change(() => {
this.unsaved = true;
console.log(this.unsaved);
});
}
public unloadPage() {
if (this.unsaved) {
return "You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?";
}
}
}
// call this after form init
const unsaveChecker = new Unsave();
unsaveChecker.register()
window.onbeforeunload = () => unsaveChecker.unloadPage()
You should call unloadPage in window.onbeforeunload with something like this :
export class Unsave {
private static unsaved: boolean = false;
public static unsave_check(): void {
Unsave.unsaved = false;
$(":input").change(function(){
Unsave.unsaved = true;
console.log(Unsave.unsaved);
});
}
public static unloadPage(): string {
if(Unsave.unsaved){
return "You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?";
}
}
}
Then
window.onbeforeunload = Unsave.unloadPage();
and somewhere else in your code you have to call unsave_check...
For instance:
document.addEventListener("DOMContentLoaded", function() {
Unsave.unsave_check();
});
Note: unloadPage and unsave_check are not consistent naming... one camel case, one snake case ?
I am trying to redirect a web page after a condition is returned as true but I can't seem to get it work. In theory this should, shouldn't it. What am I missing, is it even possible!
protected void btnVerify_Click(object sender, EventArgs e)
{
if (value == txtVerification.Text || txtVerification.Text == "****")
{
//defines a bool to tell if the popup window has been shown, this will only ever return true
bool PopupShown = doRedirect();
if(PopupShown)
{
Response.Redirect("somewebpage.aspx");
}
}
else
{
lblVerificationFailed.Visible = true;
}
}
//Opens the popup window to fire off the download and returns true
bool doRedirect()
{
string url = "GetDocs.aspx";
string s = "window.open('" + url + "', 'GetDocs', 'height=150,width=300,left=100,top=30,resizable=No,scrollbars=No,toolbar=no,menubar=no,location=no,directories=no, status=No');";
ClientScript.RegisterStartupScript(this.GetType(), "script", s, true);
return true;
}
You are trying to do in the server things that can be much more easily done on the client side.
You're using a server event to catch the click of a button on your view, launch a client popup and later redirect your page execution.
Try with something like this on javascript:
var btnVerify = document.getElementById("btnVerify");
btnVerify.addEventListener("click", function() {
window.open('GetDocs.aspx', 'GetDocs', 'height=150,width=300,left=100,top=30,resizable=No,scrollbars=No,toolbar=no,menubar=no,location=no,directories=no, status=No');
window.location.href = "somewebpage.aspx";
});
Sussed it, if I use window.location.replace instead of window.location it works exactly like I want it to. Many thanks all :)
I want to execute JavaScript code by using CefSharp in Windows Forms, but it does not work. The code is as following, and the message test is not shown. Did I miss something?
var browser = new ChromiumWebBrowser("http://localhost:50056/simple.aspx");
browser.Name = "Simple Page";
browser.Dock = DockStyle.Fill;
this.Controls.Add(browser);
browser.ExecuteScriptAsync("alert('test');");
You must wait for the browser to have sufficiently loaded before executing JavaScript. It's tempting to start trying to access the DOM in OnFrameLoadStart, whilst the V8Context will have been created and you will be able to execute a script the DOM will not have finished loading. If you need to access the DOM at its earliest possible point, subscribe to DOMContentLoaded.
Some examples of executing JavaScript are below.
browser.RenderProcessMessageHandler = new RenderProcessMessageHandler();
public class RenderProcessMessageHandler : IRenderProcessMessageHandler
{
// Wait for the underlying JavaScript Context to be created. This is only called for the main frame.
// If the page has no JavaScript, no context will be created.
void IRenderProcessMessageHandler.OnContextCreated(IWebBrowser browserControl, IBrowser browser, IFrame frame)
{
const string script = "document.addEventListener('DOMContentLoaded', function(){ alert('DomLoaded'); });";
frame.ExecuteJavaScriptAsync(script);
}
}
//Wait for the page to finish loading (all resources will have been loaded, rendering is likely still happening)
browser.LoadingStateChanged += (sender, args) =>
{
//Wait for the Page to finish loading
if (args.IsLoading == false)
{
browser.ExecuteJavaScriptAsync("alert('All Resources Have Loaded');");
}
}
//Wait for the MainFrame to finish loading
browser.FrameLoadEnd += (sender, args) =>
{
//Wait for the MainFrame to finish loading
if(args.Frame.IsMain)
{
args.Frame.ExecuteJavaScriptAsync("alert('MainFrame finished loading');");
}
};
I think, in the case of calling a JavaScript function that exists inside HTML, and passing input arguments, one can simply use the Browser.LoadingStateChanged event in the MainWindow constructor to make sure loading is initiated. This event will be called after the Browser_Loaded, where the HTML file is declared. Following is an example of the code:
public MainWindow()
{
InitializeComponent();
//Wait for the page to finish loading (all resources will have been loaded, rendering is likely still happening)
Browser.LoadingStateChanged += (sender, args) =>
{
//Wait for the Page to finish loading
if (args.IsLoading == false)
{
Browser.ExecuteScriptAsync("JavaScripFunctionName1", new object[] { arg1, arg2});
}
};
}
private void Browser_Loaded(object sender, RoutedEventArgs e)
{
Browser.LoadHtml(File.ReadAllText(GetFilePath("YourHTMLFileName.html")));
}
However, if you want to execute the JavaScript code and get results, you should use:
var result = await Browser.EvaluateScriptAsync("JavaScripFunctionName2", new object[] { });
MessageBox.Show(result.Result.ToString());
In HTML:
<html>
<body>
<script>
function JavaScripFunctionName1(arg1, arg2)
{
// something here
}
function JavaScripFunctionName2()
{
// something here
return result;
}
</script>
</body>
</html>
I want to deploy a script on C# which usually uses methods like:
ClientScript.RegisterStartupScript(GetType(), "script", "Details('" + hdnId.Value + "');", true);
However I wanted to make a class that runs that code:
public class WebUtilities
{
public static void CustomScript(Page objPage, string strScript)
{
objPage.ClientScript.RegisterStartupScript(objPage.GetType(), "script", strScript, true);
}
}
When I call WebUtilities.CustomScript, sometimes it works, but leaves a //]]> at the bottom of the page.
And there is one occasion that it does not work at all. I only noticed that the first method works, and the second one doesn't.
How can I make the class version to work properly?
I have this function, and it always works, try it
public static void callJavascriptFunction(string strScript)
{
if (HttpContext.Current == null && HttpContext.Current.Handler is Page) { return; }
Page currentPage = (Page)HttpContext.Current.Handler;
ScriptManager.RegisterStartupScript(currentPage,
currentPage.GetType(),
"Funct",
strScript,
true);
}
I am working on an application which fetches HTML content from the server and displays it to the user. The content fetched from the server is a complete HTML document. I have used UiBinder to specify UI for the view.
<g:HTMLPanel ui:field="mainPanel" styleName="ap-mainPanel">
</g:HTMLPanel>
In the view I have setViewerContent(String content) method and also a member panel for holding content[contentPanel]
public void setViewerContent(String content)
{
contentPanel = new HTMLPanel(content);
contentPanel.setStyleName("ap-mainPanel ap-scrollPanel"); //$NON-NLS-1$
contentPanel.addAttachHandler(new AttachEvent.Handler() {
#Override
public void onAttachOrDetach(AttachEvent event) {
if(event.isAttached())
{
System.out.println("<-- rendering complete -->");
isRenderComplete = true;
}
}
});
mainPanel.clear();
mainPanel.add(contentPanel);
addScrollHandler();
}
I add a scroll handler to the contentPanel which listens to the ScrollEvent and onScroll() calls the appropriate methods to fetch content from the server
based on whether scroll is at the top or bottom.
public void addScrollHandler() {
Event.sinkEvents(contentPanel.getElement(), Event.ONSCROLL);
contentPanel.addHandler(this, ScrollEvent.getType());
}
public void onScroll( ScrollEvent event )
{
if( HelperUtils.isScrollAtBottom( event.getSource() ) )
{
if(isRenderComplete)
{
System.out.println("<-- Process Down scroll START-->");
isRenderComplete = false;
getUiHandlers().reachedMaxVerticalScrollPostion();
System.out.println("<-- Process Down scroll END-->");
}
}
if( HelperUtils.isScrollAtTop( event.getSource() ) )
{
if(isRenderComplete)
{
System.out.println("<-- Process Up scroll START-->");
isRenderComplete = false;
getUiHandlers().reachedMinVerticalScrollPostion();
System.out.println("<-- Process Up scroll END -->");
}
}
}
The problem I was facing was as we render the content I see calls made to the server to fetch content continuously. New scroll events are being fired while the content fetched from the server is being rendered. We would not want this i.e while the content is being rendered we do not want the ScrollEvent to be fired. I tried the above code where I have attached AttachEvent.Handler() to contentPanel. A flag isRenderComplete is maintained which is turned true on contentPanel attach. This flag is used in the onScroll method before triggering any server call.This approach seems to work.
But I am not sure if this is the correct one. Does anyone has any better solution[s] ?
Also since we are creating new contentPanel everytime each fetch takes the scrollbar to the top. I tried to add a new HTMLPanel markerPanel with couple of line breaks to the contentPanel. Then in the onAttachOrDetach() of contentPanel tried to scroll to the markerPanel. This did not work.
public void setViewerContent(String content)
{
contentPanel = new HTMLPanel(content);
markerPanel = new HTMLPanel(" <br> <br> ");
contentPanel.setStyleName("ap-mainPanel ap-scrollPanel"); //$NON-NLS-1$
contentPanel.addAttachHandler(new AttachEvent.Handler() {
#Override
public void onAttachOrDetach(AttachEvent event) {
System.out.println("<-- rendering complete -->");
if(event.isAttached())
{
markerPanel.getElement().scrollIntoView();
isRenderComplete = true;
}
}
});
mainPanel.clear();
contentPanel.add(markerPanel);
mainPanel.add(contentPanel);
addScrollHandler();
}
Any suggestions ? we want the scroll to be at the bottom when we fetch new content and the scroll event should not be fired till the content fetched is rendered completely.
Add the scroll handler after content is rendered and remove it when the panel is detached
public void setViewerContent(String content)
{
contentPanel = new HTMLPanel(content);
markerPanel = new HTMLPanel(" <br> <br> ");
contentPanel.setStyleName("ap-mainPanel ap-scrollPanel"); //$NON-NLS-1$
contentPanel.addAttachHandler(new AttachEvent.Handler() {
#Override
public void onAttachOrDetach(AttachEvent event) {
System.out.println("<-- rendering complete -->");
if(event.isAttached())
{
markerPanel.getElement().scrollIntoView();
isRenderComplete = true;
addScrollHandler();
}
else
{
isRenderComplete = false;
removeScrollHandler();
}
}
});
mainPanel.clear();
contentPanel.add(markerPanel);
mainPanel.add(contentPanel);
}