Security News
Combatting Alert Fatigue by Prioritizing Malicious Intent
In 2023, data breaches surged 78% from zero-day and supply chain attacks, but developers are still buried under alerts that are unable to prevent these threats.
@formidable-webview/ersatz
Advanced tools
🚀 Emulate and test WebView behaviors in node with jest and jsdom
:rocket: Emulate and test WebView
behaviors in node with
jest
and jsdom
(written in Typescript :blue_heart:)
The best use-case is when your application or library uses a
WebView
component with injected JavaScript. With Ersatz, you can mock theWebView
, perform assertions on the DOM, and verify that your JS to native communication is behaving as expected. Fundamentally, you can now-on consider code injected in aWebView
as part of the codebase and tested as deemed appropriate.
The easiest way to use Ersatz
is in combination with
jest
,
@formidable-webview/ersatz-testing
and
@testing-library/react-native
.
See examples
here. Because
there is no hard dependency on jest, You should be able to use Ersatz
with
any testing framework running on node, capable of mounting React components.
@formidable-webview/ersatz | react-native-webview |
---|---|
1.0.0 | ≥ 7.6.0 < 11 |
All the props in common with ScrollView
are supported.
Other props which can influence the DOM or the WebView and their support are listed bellow. If a prop is not listed, it is probably irrelevant (related to visual rendering) and will be ignored:
Prop | Support | Comments |
---|---|---|
source | :heavy_check_mark: | Both remote URI (including body, headers and method) and inline HTML are supported. Local files are not supported. |
javaScriptEnabled | :heavy_check_mark: | |
containerStyle | :heavy_check_mark: | Mapped to ScrollView contentContainerStyle . |
renderError | :heavy_check_mark: | |
renderLoading | :heavy_check_mark: | |
injectedJavaScript | :heavy_check_mark: | This code is evaluated in the DOM by jsdom. The code shouldn't be able to access scopes outside of the DOM, thanks to sandboxing. |
injectedJavaScriptBeforeContentLoaded | :heavy_check_mark: | Ibidem. |
userAgent | :heavy_check_mark: | |
injectedJavaScriptForMainFrameOnly | :warning: | Consider the behavior of Ersatz as if this prop was forced to true . |
injectedJavaScriptBeforeContentLoadedForMainFrameOnly | :warning: | Consider the behavior of Ersatz as if this prop was forced to true . |
incognito | :warning: | Technically, that is true because nothing is persisted between to jsdom instantiations! |
allowsFullscreenVideo | :warning: | There are no visual rendering in jsdom, so this prop cannot be emulated. |
cacheEnabled | :warning: | There is no cache implemented in jsdom. You can consider value false . |
javaScriptCanOpenWindowsAutomatically | :x: | Navigation is not (yet) supported. |
mediaPlaybackRequiresUserAction | :x: | |
originWhitelist | :x: | |
startInLoadingState | :x: | |
applicationNameForUserAgent | :x: |
To reproduce the logic behind the different event handlers, we based our
assumptions on the doc, the original source code and manual testing in Android,
at version 10.3.3 of react-native-webview
. If you find a divergence in
behaviors, you are welcome to open a bug report. Bellow is a list of event
handler props with a description of our understanding of when this handler will
be invoked.
Event Handler | Support | Behavior |
---|---|---|
onLoad | :heavy_check_mark: | Invoked when the WebView has finished the load operation with success. |
onLoadEnd | :heavy_check_mark: | Invoked when the WebView has finished the load operation, either with a success or failure |
onError | :heavy_check_mark: | Invoked when the WebView has finished the load operation with a failure. Failures cannot be reproduced though. |
onLoadStart | :heavy_check_mark: | Invoked when the WebView is starting to load from a source object. |
onLoadProgress | :heavy_check_mark: | Invoked multiple times when the WebView is loading. Although we support this, only one event will be fired at the end with progress: 1 . |
onHttpError | :heavy_check_mark: | Invoked when a HTTP request fetching the resource in source.uri fails. We do provide the description and httpStatus attributes of nativeEvent . |
onMessage | :heavy_check_mark: | Invoked when a script in the backend has posted a message with window.ReactNativeWebView.postMessage . We also provide the legacy window.postMessage . |
onNavigationStateChange | :warning: | Invoked when the WebView loading starts or ends. Special events such as formsubmit are not handled. Also, navigation to different URLs is not supported. |
onShouldStartLoadWithRequest | :x: | Unsupported. We don't have navigation right now. |
onFileDownload | :x: | Access to local filesystem is unsupported. |
Method | Support | Behavior |
---|---|---|
injectJavaScript | :heavy_check_mark: | Full support. |
reload | :heavy_check_mark: | Full support. |
stopLoading | :warning: | Method is present but does nothing. |
goBack | :warning: | Method is present but does nothing. Navigation is not supported. |
goForward | :warning: | Method is present but does nothing. Navigation is not supported. |
requestFocus | :warning: | Method is present but does nothing. |
Method | Behavior |
---|---|
getDocument | Return the Document instance loaded from the DOM. Prerequisite: the DOM must be loaded. |
getWindow | Return the Window instance loaded from the DOM. Prerequisite: the DOM must be loaded. |
As per the manual tests we performed, a load cycle appears to start:
source
prop;source
changes (a deep-equal don't trigger);reload
method is invoked;document.location.href
is changed (internal navigation);FETCHING (0) LOAD START (1) PROGRESS (2) LOAD END (3)
onHttpError -> onLoadStart -> onLoadProgress -> onLoadEnd
onNavigationStateChange onNavigationStateChange
onLoad (success)
onError (failure)
According to the documentation, injectedJavaScriptBeforeContentLoaded
and
injectedScript
are loaded between (1) and (3), but
injectedJavaScriptBeforeContentLoaded
is run right after document object
creation, while injectedScript
is run after
DOMContentLoaded
event. Our manual tests found out that both scripts have access to
window.ReactNativeWebView
.
Edge cases
source
prop, onLoadStart is triggered with loading: false
.source
prop, injectedJavaScript
and other scripts are still run.source.url
prop, url
in events is set to about:blank
.nativeEvent
attribute, their content is meaningless.FAQs
🚀 Emulate and test WebView behaviors in node with jest and jsdom
We found that @formidable-webview/ersatz demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
In 2023, data breaches surged 78% from zero-day and supply chain attacks, but developers are still buried under alerts that are unable to prevent these threats.
Security News
Solo open source maintainers face burnout and security challenges, with 60% unpaid and 60% considering quitting.
Security News
License exceptions modify the terms of open source licenses, impacting how software can be used, modified, and distributed. Developers should be aware of the legal implications of these exceptions.