-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Testing #158
base: webview
Are you sure you want to change the base?
Testing #158
Changes from 19 commits
ee10b26
6973b6b
efcf673
d6836d6
c2de65f
761ecf0
6db9c65
55a9608
3e2c009
d70a861
47f53af
f429a26
bc9ae5f
f0b47b9
5dc103e
2c773f8
403446f
77ff7e0
7185787
61c895e
66b3c49
da570e4
4323afe
aa3df09
6d218b7
f263800
42111ec
d42ded6
0d4fdf8
85d21b8
637fec3
2c83302
3a9d8fa
f8b0c11
be2899c
7c3b2c1
60105b6
e9e7a72
4934ed2
d7806ed
13d0b17
ce63069
fa60356
b4c6e58
35b902d
77350b7
00b047b
048851d
7f7152e
bbc334b
4528470
fa580f4
684f2ef
016ac01
c920025
e7bb953
84cea6b
5c447de
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
/* | ||
* Copyright (C) 2020 The Android Open Source Project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.android.samples.webviewdemo | ||
import android.content.Context | ||
import android.os.Handler | ||
import android.os.Looper | ||
import android.webkit.WebView | ||
import androidx.test.core.app.ApplicationProvider | ||
import androidx.test.espresso.web.assertion.WebViewAssertions.webMatches | ||
import androidx.test.espresso.web.model.Atoms.castOrDie | ||
import androidx.test.espresso.web.model.Atoms.script | ||
import androidx.test.espresso.web.sugar.Web.onWebView | ||
import androidx.test.espresso.web.webdriver.DriverAtoms.findElement | ||
import androidx.test.espresso.web.webdriver.DriverAtoms.getText | ||
import androidx.test.espresso.web.webdriver.DriverAtoms.webClick | ||
import androidx.test.espresso.web.webdriver.Locator | ||
import androidx.test.ext.junit.runners.AndroidJUnit4 | ||
import androidx.test.rule.ActivityTestRule | ||
import junit.framework.Assert.assertEquals | ||
import junit.framework.Assert.assertTrue | ||
import org.hamcrest.CoreMatchers.`is` | ||
import org.hamcrest.CoreMatchers.containsString | ||
import org.junit.Rule | ||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
|
||
|
||
/** | ||
* Launch, interact, and verify conditions in an activity that has a WebView instance. | ||
*/ | ||
@RunWith(AndroidJUnit4::class) | ||
|
||
|
||
class MainActivityTest { | ||
|
||
val context = ApplicationProvider.getApplicationContext<Context>() | ||
|
||
@Rule @JvmField | ||
val mainActivityRule = ActivityTestRule(MainActivity::class.java) | ||
fun afterActivityLaunched() { | ||
// Technically we do not need to do this - MainActivity has javascript turned on. | ||
// Other WebViews in your app may have javascript turned off, however since the only way | ||
// to automate WebViews is through javascript, it must be enabled. | ||
onWebView().forceJavascriptEnabled() | ||
} | ||
|
||
// Test to check that the drop down menu behaves as expected | ||
@Test | ||
fun dropDownMenu_SanFran() { | ||
mainActivityRule.getActivity() | ||
onWebView() | ||
.withElement(findElement(Locator.ID, "location")) | ||
.perform(webClick()) // Similar to perform(click()) | ||
.withElement(findElement(Locator.ID, "SF")) | ||
.perform(webClick()) // Similar to perform(click()) | ||
.withElement(findElement(Locator.ID, "title")) | ||
.check(webMatches(getText(), containsString("San Francisco"))) | ||
} | ||
|
||
// Test for checking createJsObject | ||
@Test | ||
fun jsObjectIsInjectedAndContainsPostMessage() { | ||
mainActivityRule.getActivity() | ||
onWebView() | ||
.check( | ||
webMatches( | ||
script("return jsObject && jsObject.postMessage != null;", castOrDie(Boolean::class.javaObjectType)), | ||
`is`(true) | ||
) | ||
) | ||
} | ||
|
||
@Test | ||
fun valueInCallback_compareValueInput_returnsTrue(){ | ||
mainActivityRule.getActivity() | ||
// Setup | ||
val jsObjName = "jsObject" | ||
val allowedOriginRules = setOf<String>("https://example.com") | ||
val message = "hello" | ||
// Get a handler that can be used to post to the main thread | ||
val mainHandler = Handler (Looper.getMainLooper()); | ||
val myRunnable = Runnable() { | ||
val webView = WebView(context) | ||
// Create JsObject | ||
createJsObject( | ||
webView, | ||
jsObjName, | ||
allowedOriginRules | ||
) { message -> //save message; call .set() | ||
} | ||
run() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All this should be inside the runnable's "run()" method. nit: there should be a way to rewrite this to be more like a lambda style: // This is how it would look in Java
mainHandler.post(() -> {
WebView webView = WebView(context);
createJsObject(webView, jsObjName, allowedOriginRules, () -> {
// ...
});
// ...
}); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I will move that and make the change to a lambda style. |
||
//Inject JsObject into Html | ||
webView.loadDataWithBaseURL("https://example.com","<html></html>", | ||
"text/html", "UTF-8","https://example.com") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok |
||
//Call js code to invoke callback | ||
webView.evaluateJavascript("${jsObjName}.postMessage(${message})", null) | ||
} | ||
} | ||
mainHandler.post(myRunnable) | ||
// evaluate what comes out -> it should be hello | ||
// *Note: //.get() is a place holder | ||
assertEquals("hello" | ||
, "//.get()" | ||
) | ||
} | ||
|
||
@Test | ||
// Checks that postMessage runs on the UI thread | ||
fun checkingThreadCallbackRunsOn() { | ||
mainActivityRule.getActivity() | ||
// Setup | ||
val jsObjName = "jsObject" | ||
val allowedOriginRules = setOf<String>("https://example.com") | ||
val message = "hello" | ||
// Get a handler that can be used to post to the main thread | ||
val mainHandler = Handler (Looper.getMainLooper()) | ||
// Start Interacting with webView on UI thread | ||
val myRunnable = Runnable() { | ||
run() { | ||
val webView = WebView(context) | ||
// Create JsObject | ||
createJsObject( | ||
webView, | ||
jsObjName, | ||
allowedOriginRules | ||
) { message -> assertTrue(isUiThread()) } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The next thing we'll want to do is to use a |
||
//Inject JsObject into Html | ||
webView.loadDataWithBaseURL("https://example.com","<html></html>", | ||
"text/html", "UTF-8","https://example.com") | ||
//Call js code to invoke callback | ||
webView.evaluateJavascript("${jsObjName}.postMessage(${message})", null) | ||
} | ||
} | ||
mainHandler.post(myRunnable) | ||
} | ||
|
||
/** | ||
* Returns true if the current thread is the UI thread based on the | ||
* Looper. | ||
*/ | ||
private fun isUiThread(): Boolean { | ||
return Looper.myLooper() == Looper.getMainLooper() | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
expectedMessage
would be better, not to be confused with the "actual message" (the one which comes from out of the callback)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. This made me think that we could also remove the message value in
checkingThreadCallbackRunsOn()
as it has no purpose there. Because we removedmessage
, I changed the value in thepostMessage()
call to be the string hello instead of${message}
.