flutter_inappwebview
flutter_inappwebview copied to clipboard
Add testing example to docs
Environment
Flutter version: 3.7.12 Plugin version: 6.0.0
Description
Hello! After upgrading the package version from 5.8.0 to 6.0.0 my tests started failing, I've spent some time taking a look at the documentation and searching through Google and Stack Overflow but nothing seems to work for me
The logs mention this:
A platform implementation for
flutter_inappwebview
has not been set. Please ensure that an implementation ofInAppWebViewPlatform
has been set toWebViewPlatform.instance
before use. For unit testing,WebViewPlatform.instance
can be set with your own test implementation.
What you'd like to happen:
Could you please provide a minimal reproducible test scenario for this to work? Would be really appreciated!
👋 @GonzaloAldana
NOTE: This comment is auto-generated.
Are you sure you have already searched for the same problem?
Some people open new issues but they didn't search for something similar or for the same issue. Please, search for it using the GitHub issue search box or on the official inappwebview.dev website, or, also, using Google, StackOverflow, etc. before posting a new one. You may already find an answer to your problem!
If this is really a new issue, then thank you for raising it. I will investigate it and get back to you as soon as possible. Please, make sure you have given me as much context as possible! Also, if you didn't already, post a code example that can replicate this issue.
In the meantime, you can already search for some possible solutions online! Because this plugin uses native WebView, you can search online for the same issue adding android WebView [MY ERROR HERE]
or ios WKWebView [MY ERROR HERE]
keywords.
Following these steps can save you, me, and other people a lot of time, thanks!
Facing same issue any update related this ?
This worked
class MockWebViewPlatform extends Mock
with MockPlatformInterfaceMixin
implements InAppWebViewPlatform {}
class MockPlatformCookieManager extends Mock
with MockPlatformInterfaceMixin
implements PlatformCookieManager {}
class MockWebViewWidget extends Mock
with MockPlatformInterfaceMixin
implements PlatformInAppWebViewWidget {}
class FakeCookieParams extends Fake
implements PlatformCookieManagerCreationParams {}
class FakeWebUri extends Fake implements WebUri {}
class FakeWidgetParams extends Fake
implements PlatformInAppWebViewWidgetCreationParams {}
class MockWebViewDependencies {
static const MethodChannel channel = MethodChannel('fk_user_agent');
Future<void> init() async {
registerFallbackValue(FakeCookieParams());
registerFallbackValue(FakeWebUri());
registerFallbackValue(FakeWidgetParams());
// Mock webview widget
final mockWidget = MockWebViewWidget();
when(() => mockWidget.build(any())).thenReturn(const SizedBox.shrink());
// Mock cookie manager
final mockCookieManager = MockPlatformCookieManager();
when(() => mockCookieManager.deleteAllCookies())
.thenAnswer((_) => Future.value(true));
when(() => mockCookieManager.setCookie(
url: any(named: 'url'),
name: any(named: 'name'),
value: any(named: 'value'),
path: any(named: 'path'),
domain: any(named: 'domain'),
expiresDate: any(named: 'expiresDate'),
maxAge: any(named: 'maxAge'),
isSecure: any(named: 'isSecure'),
isHttpOnly: any(named: 'isHttpOnly'),
sameSite: any(named: 'sameSite'),
// ignore: deprecated_member_use
iosBelow11WebViewController:
any(named: 'iosBelow11WebViewController'),
webViewController: any(named: 'webViewController'),
)).thenAnswer((_) => Future.value(true));
// Mock webview platform
final mockPlatform = MockWebViewPlatform();
when(() => mockPlatform.createPlatformInAppWebViewWidget(any()))
.thenReturn(mockWidget);
when(() => mockPlatform.createPlatformCookieManager(any()))
.thenReturn(mockCookieManager);
// Use mock
InAppWebViewPlatform.instance = mockPlatform;
// Mock user agent in setUp or setUpAll
channel.setMockMethodCallHandler((MethodCall methodCall) async {
return {'webViewUserAgent': 'userAgent'};
});
FkUserAgent.init();
}
void tearDown() {
channel.setMockMethodCallHandler(null);
}
/// This double pump is needed for triggering the build of the webview
/// otherwise it will fail
Future<void> doublePump(WidgetTester tester) async {
await tester.pump();
await tester.pump();
}
}
And add these to the tests
void main() {
final mockWebViewDependencies = MockWebViewDependencies();
setUp(() {
mockWebViewDependencies.init();
});
tearDown(() {
mockWebViewDependencies.tearDown();
});
.
.
.
I do Just like @GonzaloAldana said,
but I have some error.
Bad state: A test tried to use
any
orcaptureAny
on a parameter of typeBuildContext
, but registerFallbackValue was not previously called to register a fallback value forBuildContext
.
So I try to add those code:
class FakeBuildContext extends Fake implements BuildContext {}
registerFallbackValue(FakeBuildContext());
And change setup callback to async function like this:
setUp(() async {
await mockWebViewDependencies.init();
});
Its worked!
Environment
Flutter version: 3.19.3 Plugin version: 6.0.0
Great thread!
I am trying to test a situation where onLoadStart is called again when a redirect url is called, I am mocking a lot of stuff but I am not able to trigger onLoadStart in widget tests, any ideas?
This worked
class MockWebViewPlatform extends Mock with MockPlatformInterfaceMixin implements InAppWebViewPlatform {} class MockPlatformCookieManager extends Mock with MockPlatformInterfaceMixin implements PlatformCookieManager {} class MockWebViewWidget extends Mock with MockPlatformInterfaceMixin implements PlatformInAppWebViewWidget {} class FakeCookieParams extends Fake implements PlatformCookieManagerCreationParams {} class FakeWebUri extends Fake implements WebUri {} class FakeWidgetParams extends Fake implements PlatformInAppWebViewWidgetCreationParams {} class MockWebViewDependencies { static const MethodChannel channel = MethodChannel('fk_user_agent'); Future<void> init() async { registerFallbackValue(FakeCookieParams()); registerFallbackValue(FakeWebUri()); registerFallbackValue(FakeWidgetParams()); // Mock webview widget final mockWidget = MockWebViewWidget(); when(() => mockWidget.build(any())).thenReturn(const SizedBox.shrink()); // Mock cookie manager final mockCookieManager = MockPlatformCookieManager(); when(() => mockCookieManager.deleteAllCookies()) .thenAnswer((_) => Future.value(true)); when(() => mockCookieManager.setCookie( url: any(named: 'url'), name: any(named: 'name'), value: any(named: 'value'), path: any(named: 'path'), domain: any(named: 'domain'), expiresDate: any(named: 'expiresDate'), maxAge: any(named: 'maxAge'), isSecure: any(named: 'isSecure'), isHttpOnly: any(named: 'isHttpOnly'), sameSite: any(named: 'sameSite'), // ignore: deprecated_member_use iosBelow11WebViewController: any(named: 'iosBelow11WebViewController'), webViewController: any(named: 'webViewController'), )).thenAnswer((_) => Future.value(true)); // Mock webview platform final mockPlatform = MockWebViewPlatform(); when(() => mockPlatform.createPlatformInAppWebViewWidget(any())) .thenReturn(mockWidget); when(() => mockPlatform.createPlatformCookieManager(any())) .thenReturn(mockCookieManager); // Use mock InAppWebViewPlatform.instance = mockPlatform; // Mock user agent in setUp or setUpAll channel.setMockMethodCallHandler((MethodCall methodCall) async { return {'webViewUserAgent': 'userAgent'}; }); FkUserAgent.init(); } void tearDown() { channel.setMockMethodCallHandler(null); } /// This double pump is needed for triggering the build of the webview /// otherwise it will fail Future<void> doublePump(WidgetTester tester) async { await tester.pump(); await tester.pump(); } }
And add these to the tests
void main() { final mockWebViewDependencies = MockWebViewDependencies(); setUp(() { mockWebViewDependencies.init(); }); tearDown(() { mockWebViewDependencies.tearDown(); }); . . .
Can you please add full example
I use mockito
so the above example didn't work out of the box.
but I was able to get it to work with this code below:
class MockWebViewPlatform extends InAppWebViewPlatform
with MockPlatformInterfaceMixin {
@override
PlatformInAppWebViewWidget createPlatformInAppWebViewWidget(
PlatformInAppWebViewWidgetCreationParams params,
) {
return MockWebViewWidget.implementation(params);
}
@override
PlatformCookieManager createPlatformCookieManager(
PlatformCookieManagerCreationParams params,
) {
return MockPlatformCookieManager();
}
}
class MockPlatformCookieManager extends Fake implements PlatformCookieManager {
@override
Future<bool> deleteAllCookies() async {
return true;
}
@override
Future<bool> setCookie({
required WebUri url,
required String name,
required String value,
String path = '/',
String? domain,
int? expiresDate,
int? maxAge,
bool? isSecure,
bool? isHttpOnly,
HTTPCookieSameSitePolicy? sameSite,
PlatformInAppWebViewController? iosBelow11WebViewController,
PlatformInAppWebViewController? webViewController,
}) async {
return true;
}
}
class MockWebViewWidget extends PlatformInAppWebViewWidget {
MockWebViewWidget.implementation(super.params) : super.implementation();
@override
Widget build(BuildContext context) {
return const SizedBox.shrink();
}
@override
T controllerFromPlatform<T>(PlatformInAppWebViewController controller) {
// TODO: implement controllerFromPlatform
throw UnimplementedError();
}
@override
void dispose() {
// TODO: implement dispose
}
@override
// TODO: implement params
PlatformInAppWebViewWidgetCreationParams get params =>
throw UnimplementedError();
}
class MockWebViewDependencies {
Future<void> init() async {
// Mock webview platform
final InAppWebViewPlatform mockPlatform = MockWebViewPlatform();
// Use mock
InAppWebViewPlatform.instance = mockPlatform;
}
}
@mike-edify Thank you! Thanks to this I was also able to test InAppBrowser!
It would be nice if the documentation describes how to write these tests!
@ShuheiSuzuki-07 You're welcome. Glad it helped someone. :D
Thanks @L4rue @GonzaloAldana You're lifesavers!!! I am new to widget testing, and the issue was like the final boss to me haha, I learned a lot from your solutions. 🙏
we are getting this issue in Plugin version: 6.0.0 if I use 5.8.0 then there is no error
Can anyone give me an complete example for InAppWebView @mike-edify @ShuheiSuzuki-07