Skip to content

Commit

Permalink
refine the code for handling JavaScript.
Browse files Browse the repository at this point in the history
  • Loading branch information
vmi committed Dec 19, 2016
1 parent 119c09b commit bf3b618
Show file tree
Hide file tree
Showing 15 changed files with 197 additions and 236 deletions.
21 changes: 8 additions & 13 deletions src/main/java/jp/vmi/selenium/selenese/Eval.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
import java.util.List;
import java.util.Map;

import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;

import com.google.gson.Gson;

import jp.vmi.selenium.selenese.mutator.SeleneseRunnerMutator;
Expand All @@ -16,38 +13,36 @@
public class Eval {

private final SeleneseRunnerMutator mutator;
private final Context context;

/**
* Constructor.
*
* @param context Selenese Runner context.
*/
public Eval(Context context) {
this.mutator = new SeleneseRunnerMutator(context);
this.context = context;
this.mutator = new SeleneseRunnerMutator();
}

/**
* Evaluate script including "storedVars" variable.
*
* @param driver WebDriver instance.
* @param context Selenese Runner context.
* @param script JavaScript code.
* @return result of evaluating script.
*/
public Object eval(WebDriver driver, String script) {
return eval(driver, script, null);
public Object eval(Context context, String script) {
return eval(context, script, null);
}

/**
* Evaluate script including "storedVars" variable.
*
* @param driver WebDriver instance.
* @param context Selenese Runner context.
* @param script JavaScript code.
* @param cast cast type.
* @return result of evaluating script.
*/
public Object eval(WebDriver driver, String script, String cast) {
public Object eval(Context context, String script, String cast) {
VarsMap varsMap = context.getVarsMap();
boolean hasStoredVars = script.matches(".*\\bstoredVars\\b.*");
StringBuilder writer = new StringBuilder();
Expand All @@ -60,13 +55,13 @@ public Object eval(WebDriver driver, String script, String cast) {
if (cast != null)
writer.append(cast);
writer.append("((function(){");
mutator.mutate(script, writer);
mutator.mutate(context, script, writer);
writer.append("})())");
if (hasStoredVars)
writer.append(", storedVars];})();");
else
writer.append("];");
Object result = ((JavascriptExecutor) driver).executeScript(writer.toString());
Object result = context.executeScript(writer.toString());
if (!(result instanceof List))
throw new SeleneseRunnerRuntimeException(result.toString());
List<?> list = (List<?>) result;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/jp/vmi/selenium/selenese/Runner.java
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ public Result execute(Selenese selenese) {

@Override
public boolean isTrue(String expr) {
return (Boolean) eval.eval(driver, varsMap.replaceVars(expr), "Boolean");
return (Boolean) eval.eval(this, varsMap.replaceVars(expr), "Boolean");
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ protected void evalCurArgs(Context context, String[] curArgs) {
for (int i = 0; i < curArgs.length; i++) {
Matcher matcher = JS_BLOCK_RE.matcher(curArgs[i]);
if (matcher.matches()) {
Object value = context.getEval().eval(context.getWrappedDriver(), matcher.group(1));
Object value = context.getEval().eval(context, matcher.group(1));
if (value == null)
value = "";
curArgs[i] = value.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class OpenWindow extends AbstractCommand {
@Override
protected Result executeImpl(Context context, String... curArgs) {
String script = String.format("window.open('%s', '%s'); null;", curArgs[ARG_URL], curArgs[ARG_WINDOW_ID]);
context.getEval().eval(context.getWrappedDriver(), script);
context.getEval().eval(context, script);
return SUCCESS;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class RunScript extends AbstractCommand {

@Override
protected Result executeImpl(Context context, String... curArgs) {
context.getEval().eval(context.getWrappedDriver(), curArgs[ARG_SCRIPT]);
context.getEval().eval(context, curArgs[ARG_SCRIPT]);
return SUCCESS;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ protected Result executeImpl(final Context context, String... curArgs) {
boolean waitResult = Wait.defaultInterval.wait(startTime, timeout, new StopCondition() {
@Override
public boolean isSatisfied() {
Object result = context.getEval().eval(context.getWrappedDriver(), script);
Object result = context.getEval().eval(context, script);
if (result == null)
return false;
else if (result instanceof String)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,14 @@

import java.util.regex.Pattern;

import jp.vmi.selenium.selenese.Context;

/**
* Models a function declaration. That is, it provides an implementation of a particular Javascript
* function.
*/
public class FunctionDeclaration implements ScriptMutator {

private final Pattern pattern;
private final String function;

Expand All @@ -40,20 +43,13 @@ public class FunctionDeclaration implements ScriptMutator {
* @param result The body of the function implementation.
*/
public FunctionDeclaration(String raw, String result) {
String base = raw.replace(".", "\\s*\\.\\s*");

pattern = Pattern.compile(".*" + base + "\\s*\\(\\s*\\).*");

function = raw + " = function() { " + result + " }; ";
pattern = MutatorUtils.generatePatternForCodePresence(raw + "()");
function = raw + " = function() { " + result + " };";
}

@Override
public void mutate(String script, StringBuilder outputTo) {
if (!pattern.matcher(script).matches()) {
return;
}

outputTo.append(function);
public void mutate(Context context, String script, StringBuilder outputTo) {
if (pattern.matcher(script).find())
outputTo.append(function);
}

}
37 changes: 37 additions & 0 deletions src/main/java/jp/vmi/selenium/selenese/mutator/MutatorUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package jp.vmi.selenium.selenese.mutator;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Utilities for mutator.
*/
public final class MutatorUtils {

private MutatorUtils() {
// no operation.
}

private static final Pattern RE = Pattern.compile("\\G\\s*(?:(\\w+)|(\\W))");

/**
* Generate the pattern for testing presence of the code.
*
* @param code code.
* @return pattern for testing.
*/
public static Pattern generatePatternForCodePresence(String code) {
StringBuilder pattern = new StringBuilder(code.length() * 2);
Matcher matcher = RE.matcher(code);
while (matcher.find()) {
if (pattern.length() != 0)
pattern.append("\\s*");
String symbol = matcher.group(1);
if (symbol != null)
pattern.append(symbol);
else
pattern.append(Pattern.quote(matcher.group(2)));
}
return Pattern.compile(pattern.toString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,22 @@

package jp.vmi.selenium.selenese.mutator;

import jp.vmi.selenium.selenese.Context;

/**
* A mechanism for taking a single method from a script meant for Selenium Core and converting to
* something that webdriver can evaluate.
*/
public interface ScriptMutator {

/**
* Mutate a script. The original, unmodified script is used to generate a script on the
* StringBuilder, the "toString" method of which should be used to get the result. We make use of
* a StringBuilder rather than a normal String so that we can efficiently chain mutators.
*
* @param context SeleneseRunner context.
* @param script The original script.
* @param outputTo The mutated script.
*/
void mutate(String script, StringBuilder outputTo);
void mutate(Context context, String script, StringBuilder outputTo);
}
Loading

0 comments on commit bf3b618

Please sign in to comment.