2016-07-14 113 views
3

我想要获取WebView的实例,以便我可以在其上调用evaluateJavascript()。 我写了一个自定义的匹配,然后试图将WebView分配给一个静态变量如下:Espresso:如何在WebView上调用evaluateJavascript()

public static WebView view1; 

public static Matcher<View> isJavascriptEnabled1() { 
    return new BoundedMatcher<View, WebView>(WebView.class) { 
     @Override 
     public void describeTo(Description description) { 
      description.appendText("WebView with JS enabled"); 
     } 
     @Override 
     public boolean matchesSafely(WebView webView) { 
      view1 =webView; 
      return webView.getSettings().getJavaScriptEnabled(); 
     } 
    }; 
} 

而在我的测试类我称之为:

CustomMatcher.isJavascriptEnabled1(); 
CustomMatcher.view1.evaluateJavascript("$('.status dl  dd').get(0).innerText.replace('pts.', '').replace(',', '').trim()\"]",new ValueCallback<String>() { 
    @Override 
    public void onReceiveValue(String s) { 
     Log.d("LogName", s); // Prints asd 
    } 

}); java.lang.NullPointerException: Attempt to invoke virtual method 'void android.webkit.WebView.evaluateJavascript(java.lang.String, android.webkit.ValueCallback)' on a null object reference

回答

3

您没有使用Matcher匹配一个观点:

我得到的错误。这不起作用,因为调用isJavascriptEnabled1()只会创建一个新的自定义实例Matcher。但例如​​永远不会执行,这就是为什么CustomMatcher.view1null。 为了使你的代码的工作,你必须与你一起Matcher使用Espresso.onView()

// Use onView and the matcher to find a web view with enabled java script 
Espresso.onView(CustomMatcher.isJavascriptEnabled1()); 

// Now CustomMatcher.view1 should not be null (if there is a web view) 
CustomMatcher.view1.evaluateJavascript("$('.status dl  dd').get(0).innerText.replace('pts.', '').replace(',', '').trim()\"]",new ValueCallback<String>() { 
    @Override 
    public void onReceiveValue(String s) { 
     Log.d("LogName", s); // Prints asd 
    } 
}); 

但是那还是不正确的。方法evaluateJavascript()是异步的,Espresso不会等待调用回调(onReceiveValue())。因此,在调用onReceive()之前,测试很可能会结束。

还有Espresso Web用于测试WebViews。根据您的目标,您可能会发现它很有用。 Espresso Web也在幕后执行Java脚本。

如果不使用Espresso Web,我会建议编写自定义ViewAction,这将在匹配的WebView上执行。这个动作可以使用WebView评估Java脚本:

/** 
* {@link ViewAction} that evaluates javascript in a {@link WebView}. 
*/ 
public class EvaluateJsAction implements ViewAction, ValueCallback<String> { 

    private static final long TIME_OUT = 5000; 
    private final String mJsString; 
    private final AtomicBoolean mEvaluateFinished = new AtomicBoolean(false); 

    public EvaluateJsAction(final String javaScriptString) { 
     mJsString = javaScriptString; 
    } 

    @Override 
    public Matcher<View> getConstraints() { 
     return isAssignableFrom(WebView.class); 
    } 

    @Override 
    public String getDescription() { 
     return "evaluate '" + mJsString + "' on webview"; 
    } 

    @Override 
    public void perform(UiController uiController, View view) { 
     uiController.loopMainThreadUntilIdle(); 

     final WebView webView = (WebView) view; 
     webView.evaluateJavascript(mJsString, this); 

     final long timeOut = System.currentTimeMillis() + TIME_OUT; 
     while (!mEvaluateFinished.get()) { 
      if (timeOut < System.currentTimeMillis()) { 
       throw new PerformException.Builder() 
         .withActionDescription(this.getDescription()) 
         .withViewDescription(HumanReadables.describe(view)) 
         .withCause(new RuntimeException(String.format(Locale.US, 
           "Evaluating java script did not finish after %d ms of waiting.", TIME_OUT))) 
         .build(); 
      } 
      uiController.loopMainThreadForAtLeast(50); 
     } 
    } 

    @Override 
    public void onReceiveValue(String value) { 
     mEvaluateFinished.set(true); 
    } 
} 

然后用这个动作:

onView(withJavaScriptEnabled()).perform(new EvaluateJsAction(theJavaScriptString)); 
+0

非常感谢您的时间来回答这个问题,真的helpful.Thanks。 –

相关问题