Skip to content

Commit

Permalink
Revise vacation stategy to capture stack trace (#217)
Browse files Browse the repository at this point in the history
  • Loading branch information
sbabcoc authored May 15, 2022
1 parent 92f19e8 commit 5ba075b
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 60 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ repositories {

dependencies {
constraints {
api 'com.nordstrom.tools:java-utils:2.1.0'
api 'com.nordstrom.tools:java-utils:2.2.0'
api 'com.nordstrom.tools:settings:2.3.10'
api 'com.nordstrom.tools:junit-foundation:16.0.2'
api 'com.github.sbabcoc:logback-testng:1.3.4'
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
<revision>@projectVersion@</revision>
<timestamp>@projectTimestamp@</timestamp>
<selenium-api>@seleniumApi@</selenium-api>
<java-utils.version>2.1.0</java-utils.version>
<java-utils.version>2.2.0</java-utils.version>
<compiler-plugin.version>3.8.1</compiler-plugin.version>
<surefire-plugin.version>3.0.0-M5</surefire-plugin.version>
<source-plugin.version>3.2.1</source-plugin.version>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,48 +1,14 @@
package com.nordstrom.automation.selenium.exceptions;

import java.lang.reflect.Method;

import com.nordstrom.automation.selenium.utility.ReflectUtil;

/**
* This exception is thrown when a client calls a method of a container object that's no longer valid.
*/
public class ContainerVacatedException extends RuntimeException {

private static final long serialVersionUID = 2043877560841903084L;

private final transient Method vacater;
private static final String PREAMBLE = "Container object was vacated by invocation of method: ";

/**
* Constructs a new {@code container vacated} exception with the specified vacater.
*
* @param vacater method that caused the container to be vacated
*/
public ContainerVacatedException(final Method vacater) {
super(getMessage(vacater));
this.vacater = vacater;
}
private static final long serialVersionUID = -7653982501901130765L;

/**
* Get the method that caused the affected container object to be vacated.
*
* @return method that vacated the target object
*/
public Method getVacater() {
return vacater;
public ContainerVacatedException(VacationStackTrace stackTrace) {
super(stackTrace);
}

/**
* Assemble the message for this exception.
*
* @param method method that vacated the target object.
* @return message for this exception
*/
private static String getMessage(final Method method) {
String className = method.getDeclaringClass().getSimpleName();
String signature = ReflectUtil.getSignature(method);
return PREAMBLE + className + ":" + signature;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.nordstrom.automation.selenium.exceptions;

import java.lang.reflect.Method;

import com.nordstrom.automation.selenium.utility.ReflectUtil;
import com.nordstrom.common.base.StackTrace;

public class VacationStackTrace extends StackTrace {

private static final long serialVersionUID = -512001372372827847L;

private final transient Method vacater;
private final transient String reason;
private static final String PREAMBLE = "Container object was vacated by invocation of method: ";

/**
* Constructs a new {@code container vacated} exception with the specified vacater.
*
* @param vacater method that caused the container to be vacated
*/
public VacationStackTrace(final Method vacater) {
this(vacater, null);
}

/**
* Constructs a new {@code container vacated} exception with the specified vacater.
*
* @param vacater method that caused the container to be vacated
* @param reason for vacating the target object
*/
public VacationStackTrace(final Method vacater, final String reason) {
super(getMessage(vacater, reason));
this.vacater = vacater;
this.reason = reason;
}

/**
* Get the reason that the affected container object to be vacated.
*
* @return reason for vacating the target object
*/
public String getReason() {
return reason;
}

/**
* Get the method that caused the affected container object to be vacated.
*
* @return method that vacated the target object
*/
public Method getVacater() {
return vacater;
}

/**
* Assemble the message for this exception.
*
* @param method method that vacated the target object.
* @param reason for vacating the target object
* @return message for this exception
*/
private static String getMessage(final Method method, final String reason) {
String className = method.getDeclaringClass().getSimpleName();
String signature = ReflectUtil.getSignature(method);
String suffix = (reason != null) ? "\n" + reason : "";
return PREAMBLE + className + ":" + signature + suffix;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
import com.nordstrom.automation.selenium.SeleniumConfig;
import com.nordstrom.automation.selenium.annotations.PageUrl;
import com.nordstrom.automation.selenium.core.WebDriverUtils;
import com.nordstrom.automation.selenium.exceptions.ContainerVacatedException;
import com.nordstrom.automation.selenium.exceptions.LandingPageMismatchException;
import com.nordstrom.automation.selenium.exceptions.PageNotLoadedException;
import com.nordstrom.automation.selenium.exceptions.VacationStackTrace;
import com.nordstrom.automation.selenium.interfaces.WrapsContext;
import com.nordstrom.automation.selenium.model.Page.WindowState;
import com.nordstrom.automation.selenium.support.Coordinator;
Expand Down Expand Up @@ -66,7 +66,7 @@ public interface ByEnum {
protected WebDriver driver;
protected SearchContext context;
protected ComponentContainer parent;
protected ContainerVacatedException vacated;
protected VacationStackTrace vacated;
protected SearchContextWait wait;
private List<Class<?>> bypassClasses;
private List<String> bypassMethods;
Expand All @@ -75,9 +75,9 @@ public interface ByEnum {
private static final String PLACEHOLDER = "{}";
private static final Class<?>[] BYPASS_CLASSES = {WrapsContext.class};
private static final String[] BYPASS_METHODS = {"validateParent", "getDriver", "getContext", "getParent",
"getParentPage", "getWait", "switchTo", "switchToContext", "getVacated", "setVacated", "getArgumentTypes",
"getArguments", "enhanceContainer", "myBypassClasses", "myBypassMethods", "getLogger", "hashCode",
"equals"};
"getParentPage", "getWait", "switchTo", "switchToContext", "getVacated", "setVacated", "isVacated",
"getArgumentTypes", "getArguments", "enhanceContainer", "myBypassClasses", "myBypassMethods",
"getLogger", "hashCode", "equals"};

private static final Class<?>[] ARG_TYPES = {SearchContext.class, ComponentContainer.class};
private static final Class<?>[] COLLECTIBLE_ARGS = {RobustWebElement.class, ComponentContainer.class};
Expand Down Expand Up @@ -269,9 +269,9 @@ public String toString() {
/**
* Get validity indication for this container and its ancestors.
*
* @return {@link ContainerVacatedException} for vacated container; 'null' if container is still valid
* @return {@link VacationStackTrace} for vacated container; 'null' if container is still valid
*/
ContainerVacatedException getVacated() {
VacationStackTrace getVacated() {
// if child container looks valid
if ((vacated == null) && (parent != null)) {
// propagate ancestor validity
Expand All @@ -281,11 +281,11 @@ ContainerVacatedException getVacated() {
}

/**
* Set the method that caused this container to be vacated.
* Save the flow of execution that caused this container to be vacated.
*
* @param vacated {@link ContainerVacatedException} for vacated container
* @param vacated {@link VacationStackTrace} for vacated container
*/
void setVacated(final ContainerVacatedException vacated) {
void setVacated(final VacationStackTrace vacated) {
this.vacated = vacated;
// if has ancestor
if (parent != null) {
Expand All @@ -294,6 +294,15 @@ void setVacated(final ContainerVacatedException vacated) {
}
}

/**
* Determine if this container has been vacated.
*
* @return 'true' if container has been vacated; otherwise 'false'
*/
boolean isVacated() {
return (null != getVacated());
}

/**
* Find all elements within the current context using the given locator constant.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.nordstrom.automation.selenium.exceptions.PageLoadRendererTimeoutException;
import com.nordstrom.automation.selenium.exceptions.PageNotLoadedException;
import com.nordstrom.automation.selenium.exceptions.TransitionErrorException;
import com.nordstrom.automation.selenium.exceptions.VacationStackTrace;
import com.nordstrom.automation.selenium.interfaces.DetectsLoadCompletion;
import com.nordstrom.automation.selenium.interfaces.TransitionErrorDetector;
import com.nordstrom.automation.selenium.model.Page.WindowState;
Expand Down Expand Up @@ -94,16 +95,10 @@ public Object intercept(@This final Object obj, @Origin final Method method, @Al
increaseDepth();
long initialTime = System.currentTimeMillis();
ComponentContainer container = (ComponentContainer) obj;
ContainerVacatedException vacated = container.getVacated();

try {
// if container valid
if (vacated == null) {
// build exception for potential vacation
vacated = new ContainerVacatedException(method);
} else {
// INVALID!
throw vacated;
if (container.isVacated()) {
throw new ContainerVacatedException(container.getVacated());
}

WebDriver driver = container.getWrappedDriver();
Expand Down Expand Up @@ -145,7 +140,7 @@ public Object intercept(@This final Object obj, @Origin final Method method, @Al
driver.switchTo().window(windowHandle);
TARGET.set(null);
}
container.setVacated(vacated);
container.setVacated(new VacationStackTrace(method, "Target window for this container has closed."));
reference = null;
}

Expand All @@ -163,7 +158,8 @@ public Object intercept(@This final Object obj, @Origin final Method method, @Al
reference = null;
} else {
newHandle = driver.getWindowHandle();
container.setVacated(vacated);
container.setVacated(
new VacationStackTrace(method, "This page object no longer owns its target window."));
}
}

Expand Down

0 comments on commit 5ba075b

Please sign in to comment.