Custom wait for selenium for angular7 application - java

We are automating an Angular 7 application using Selenium Webdriver. I need the custom waits using Javascript or JQuery that will wait for the page to render and wait for the $http response to get completed.
I've tried explicit waits but they are not working since the elements get loaded on the page but still loads and tried ng Webdriver but that is also failing.

These may be helpful for you. Before accessing any element check whether Jquery/Angular is done or not.
public static boolean isJQueryDone() {
Object jsResponse = tryJavascript("return jQuery.active;");
if (jsResponse instanceof Long) {
return ((Long) jsResponse) == 0;
} else if (jsResponse instanceof String) {
String response = (String) jsResponse;
return (response.startsWith("{\"hCode\"") || response.isEmpty());
} else {
return true;
}
}
public static boolean isAngularDone() {
Object jsResponse = tryJavascript("return window.getAllAngularTestabilities().filter(x=>!x.isStable()).length;");
if (jsResponse instanceof Long) {
return ((Long) jsResponse) == 0;
} else if (jsResponse instanceof String) {
String response = (String) jsResponse;
return response.isEmpty();
} else {
return true;
}
}
public static synchronized Object tryJavascript(String script, Object... args) {
try {
return execJavascript(script, args);
} catch (Exception ignore) {
return "";
}
}

Related

Java Call method with return type and method to be called

I have lots of calls against a REST API that i want handled the same way.
Perform call, check if not authenticated. Refresh Token call again or if we hit rate
limit despite rate limit function. Sleep and perform call again.
I would like to wrap this in a function that can be called in the way
ReturnType returnVal= handleIntegration(ReturnType , functionToBecCalled)
How can this be achieved?
For the example below something like
CustomersResponse customersReponse = handleIntegration(CustomersResponse , connection.customers.findCustomersResponse())
EmployeesReponse employeesRepsonse = handleIntegration(EmployeeResponse , connection.employees.findEmployeesResponse())
//Current Code
bucket.consume();
CustomersResponse customersResponse = null;
try {
customersResponse = connection.customers.findCustomersResponse();
} catch (IntegrationException e) {
if (e.getStatusCode() == 401) {
this.newAccessFromRefreshToken();
customersResponse = connection.customers.findCustomersResponse();
}else if (e.getStatusCode() == 429){
Thread.sleep(500);
customersResponse = connection.customers.findCustomersResponse();
}else
throw e;
}
bucket.consume();
EmployeeResponse employeeResponse = null;
try {
employeeResponse = connection.employees.findEmployeesResponse();
} catch (IntegrationException e) {
if (e.getStatusCode() == 401) {
this.newAccessFromRefreshToken();
employeeResponse = connection.employees.findEmployeesResponse();
}else if (e.getStatusCode() == 429){
Thread.sleep(500);
employeeResponse = connection.employees.findEmployeesResponse();
}else
throw e;
}
You could try something like the following with the help of Java 8+ Functional Interfaces and Generics:
public <T> T handleIntegration(Supplier<T> supplier) {
bucket.consume();
T result = null;
try {
result = supplier.get();
} catch (IntegrationException e) {
if (e.getStatusCode() == 401) {
this.newAccessFromRefreshToken();
result = supplier.get();
} else if (e.getStatusCode() == 429) {
Thread.sleep(500);
result = supplier.get();
} else
throw e;
}
return result;
}
Then you could call the method like this:
CustomersResponse returnVal = handleIntegration(connection.customers::findCustomersResponse)
If you are at least on Java 8 with lambdas, you can do it like this:
<T> T handleIntegration(Supplier<T> method) {
bucket.consume(); // I don't know how this fits - BEWARE!
T response = null;
try {
response = method.get();
} catch (IntegrationException e) {
if (e.getStatusCode() == 401) {
this.newAccessFromRefreshToken();
response = method.get();
} else if (e.getStatusCode() == 429){
Thread.sleep(500);
response = method.get();
} else
throw e;
}
}
// I don't know what you want to do with the response, returning it here for example
return response;
}
And use it e.g. as:
CustomersResponse customersReponse = handleIntegration(
CustomersResponse.class,
() -> connection.customers.findCustomersResponse()
);
Caveat: I assumed IntegrationException is an unchecked exception. If it is checked or in any case, e.g. connection.customers.findCustomersResponse() throws a checked exception, the provided java.util.function.Supplier will not do. You will have to provide a functional interface that throws the specific checked exception.
Unrelated Note: Thread.sleep() is easy, but you may want to consider a better way, because sleep blocks the thread.

How do I return boolean value from ExpectedCondition objects

I do have a method that waits for the JavaScript to load in the browser. From Selenium 3 (3.141.59), I have shifted to Selenium 4 (4.0.0-alpha-7)
This return code/statement doesnt work with Selenium 4
return wait.until(jQueryLoad) && wait.until(jsLoad);
What would be the correct return statement for this? I have tried several options but nothing worked. Please see the code structure for the method/function below. Your thoughts, ideas and answers will be highly appreaciated.
public static boolean waitForJStoLoad() {
WebDriverWait wait = new WebDriverWait(getDriver(), Duration.ofSeconds(30));
// wait for jQuery to load
ExpectedCondition<Boolean> jQueryLoad = new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver arg0) {
try {
Long state = (Long) ((JavascriptExecutor) arg0).executeScript("return jQuery.active");
return (state == 0);
} catch (Exception e) {
return true;
}
}
};
// wait for Javascript to load
ExpectedCondition<Boolean> jsLoad = new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver arg0) {
String state = (String) ((JavascriptExecutor) arg0).executeScript("return document.readyState;");
return state.equalsIgnoreCase("complete");
}
};
return wait.until(jQueryLoad) && wait.until(jsLoad);
}
Well, I'm using standard Selenium 3 and not checking JavaScripts, but I do have several simple methods validating some conditions with the Expected Conditons and returning Boolean.
Something like this:
public boolean waitForElementToDisappear(By element){
try {
wait.until((ExpectedConditions.invisibilityOfElementLocated(element)));
return true;
}catch (Throwable t){
return false;
}
}

Are expected values for Eclipse RCP property testers always String?

In the eclipse documentation I've seen the following snippet (http://help.eclipse.org/neon/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fcore%2Fexpressions%2FPropertyTester.html):
<propertyTester
namespace="org.eclipse.jdt.core"
id="org.eclipse.jdt.core.IPackageFragmentTester"
properties="isDefaultPackage"
type="org.eclipse.jdt.core.IPackageFragment"
class="org.eclipse.demo.MyPackageFragmentTester">
</propertyTester>
with the following property tester implementation:
public class MyPackageFragmentTester extends PropertyTester {
public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
IPackageFragment fragment= (IPackageFragment)receiver;
if ("isDefaultPackage".equals(property)) {
return expectedValue == null
? fragment.isDefaultPackage()
: fragment.isDefaultPackage() == ((Boolean)expectedValue).booleanValue();
}
Assert.isTrue(false);
return false;
}
}
I'm a bit wondering about the ((Boolean)expectedValue) part - because the expected value is give in the <test property="..."/> tag as string:
<test property="org.eclipse.jdt.core.isDefaultPackage" value="true" />
And whenever I implemented a property tester the value was given as a String.
So my question is: Is it possible to have an expected value that is not a String? According to the Eclipse RCP documentation it should be... but how!?
It is not made very clear but the expected value can be a String or a Boolean, Float (!) or Integer.
The code that works out which is in org.eclipse.core.internal.expressions.Expressions:
public static Object convertArgument(String arg) throws CoreException {
if (arg == null) {
return null;
} else if (arg.length() == 0) {
return arg;
} else if (arg.charAt(0) == '\'' && arg.charAt(arg.length() - 1) == '\'') {
return unEscapeString(arg.substring(1, arg.length() - 1));
} else if ("true".equals(arg)) { //$NON-NLS-1$
return Boolean.TRUE;
} else if ("false".equals(arg)) { //$NON-NLS-1$
return Boolean.FALSE;
} else if (arg.indexOf('.') != -1) {
try {
return Float.valueOf(arg);
} catch (NumberFormatException e) {
return arg;
}
} else {
try {
return Integer.valueOf(arg);
} catch (NumberFormatException e) {
return arg;
}
}
}
So it is a String unless it is true, false or a number.

Java - synchronous callback

I have the following code which is executed asynchronously. I would like to make it synchronous in order to follow some logical flow but I cannot work out how.
You will see that scanning is set to true to indicate that the method is still working, at the beginning - I then initiate a findPrinters(...) command - this contains a DiscoveryHandler which runs asynchronously - foundPrinter() is called each time an item is discovered. discoveryFinished() is when the discovery process is successfully completed, and discoveryError(...) is called whenever an error occurs.
I rely on something being set in my DiscoveryHandler before I would like to return from this method. Hence why I have while (scanning) underneath it. But this feels like a hack to me, and not the correct way of doing things. I cannot get wait() and notify() working. Can someone tell me what the correct way to do this is please?
private boolean findPrinter(final Context ctx) {
try {
scanning = true;
BluetoothDiscoverer.findPrinters(ctx, new DiscoveryHandler() {
public void foundPrinter(DiscoveredPrinter device) {
if (device instanceof DiscoveredPrinterBluetooth) {
DiscoveredPrinterBluetooth btDevice = (DiscoveredPrinterBluetooth) device;
if (btDevice.friendlyName.startsWith("XXXX")) {
try {
connection = new BluetoothConnection(btDevice.address);
connection.open();
if (connection.isConnected()) {
address = btDevice.address;
}
} catch (Exception ex) {
}
}
}
}
public void discoveryFinished() {
scanning = false;
}
public void discoveryError(String arg0) {
scanning = false;
}
});
} catch (Exception ex) {
}
while (scanning) {}
return false;
}
You could do this with CountDownLatch, which might be the lightest synchronization primitive in java.util.concurrent:
private boolean findPrinter(final Context ctx) {
final CountDownLatch latch = new CountDownLatch(1);
final boolean[] result = {false};
...
BluetoothDiscoverer.findPrinters(ctx, new DiscoveryHandler() {
...
public void discoveryFinished() {
result[0] = true;
latch.countDown();
}
public void discoveryError(String arg0) {
result[0] = false;
latch.countDown();
}
...
}
// before final return
// wait for 10 seconds for the response
latch.await(10, TimeUnit.SECONDS);
//return the result, it will return false when there is timeout
return result[0];
}
There are a bunch of ways you can do this and wait()/notify() is probably not the best since you probably want to return something from your async method. As such I suggest using something like a BlockingQueue. Here is a simplified example of how you can do this:
private boolean findPrinter(final Context ctx) {
final BlockingQueue<?> asyncResult = new SynchronousQueue<?>();
try {
BluetoothDiscoverer.findPrinters(ctx, new DiscoveryHandler() {
public void foundPrinter(DiscoveredPrinter device) {
if (device instanceof DiscoveredPrinterBluetooth) {
DiscoveredPrinterBluetooth btDevice = (DiscoveredPrinterBluetooth) device;
if (btDevice.friendlyName.startsWith("XXXX")) {
try {
connection = new BluetoothConnection(btDevice.address);
connection.open();
if (connection.isConnected()) {
address = btDevice.address;
}
} catch (Exception ex) {
}
}
}
}
public void discoveryFinished() {
asyncResult.put(true);
}
public void discoveryError(String arg0) {
asyncResult.put(arg0);
}
});
} catch (Exception ex) {
}
Object result = asyncResult.take();
if (result instanceof Boolean) {
return (Boolean) result;
} else if (result instanceof String) {
logError((String) result);
}
return false;
}
One problem with using SynchronousQueue here though is that if discoveryFinished()/discoveryError() is called more than once, then the thread executing the code asynchronously will block forever since the SynchronousQueue assumes there will be exactly one take() per every put() and will block if a put() is made without a corresponding take() or vice versa. So if in your case those methods can be called more than once you would probably use a different kind of BlockingQueue instead (see documentation).

Browser Java Plugin Detection

What is the preferred method to determine if the Sun Java Plugin is installed in the browser?
java deployment toolkit
script src="http://java.com/js/deployJava.js"
if (deployJava.versionCheck('1.6'))
{
alert("1.6 installed")
}
You may also consider PluginDetect script.
This isn't an answer for your exact question but is offered as a solution for determining the browser itself. Don't be too harsh, this is really old code that I wrote some time ago.
import java.applet.*;
public class BrowserDetector extends Applet {
public void init() {
if (isNetscape()) {
System.out.println("This browser is a Netscape Browser.");
}
if (isMicrosoft()) {
System.out.println("This browser is a Microsoft Browser.");
}
System.out.println("VM Type: " + getVMType());
}
public static boolean isNetscape() {
try {
Class.forName("netscape.applet.MozillaAppletContext");
} catch (ClassNotFoundException e) {
System.out.println("This browser is not a Netscape Browser.");
return false;
}
return true;
}
public static boolean isMicrosoft() {
try {
Class.forName("com.ms.applet.GenericAppletContext");
} catch (ClassNotFoundException e) {
System.out.println("This browser is not a Microsoft Browser.");
return false;
}
return true;
}
public String getVMType() {
String theBrowser = "No VM";
String appletContext = getAppletContext().toString();
if (appletContext.startsWith("sun.applet.AppletViewer"))
theBrowser = "APPLETVIEWER";
else if (appletContext.startsWith("netscape.applet."))
theBrowser = "NETSCAPE";
else if (appletContext.startsWith("com.ms.applet."))
theBrowser = "MICROSOFT";
else if (appletContext.startsWith("sunw.hotjava.tags.TagAppletPanel"))
theBrowser = "HOTJAVA";
else if (appletContext.startsWith( "sun.plugin.navig.win32.AppletPlugin"))
theBrowser = "NETSCAPEPLUGIN";
else if (appletContext.startsWith( "sun.plugin.ocx.ActiveXApplet"))
theBrowser = "MICROSOFTPLUGIN";
else if (appletContext.startsWith( "sun.plugin.viewer.context.IExplorerAppletContext"))
theBrowser = "MICROSOFTPLUGINJRE1.4";
return theBrowser;
}
}

Categories