2016-07-14 62 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。 –

相關問題