From 6206c931bd39a55146b7f04c74fb1281260ccdd0 Mon Sep 17 00:00:00 2001 From: Felix Angelov Date: Mon, 14 Feb 2022 15:55:48 -0600 Subject: [PATCH] feat(platform_interface): create my_plugin_platform_interface (#1) --- .../my_plugin_platform_interface.yaml | 21 +++++++++++ .gitignore | 1 + src/my_plugin_platform_interface/CHANGELOG.md | 3 ++ src/my_plugin_platform_interface/LICENSE | 21 +++++++++++ src/my_plugin_platform_interface/README.md | 14 +++++++ .../analysis_options.yaml | 1 + .../lib/my_plugin_platform_interface.dart | 33 +++++++++++++++++ .../lib/src/method_channel_my_plugin.dart | 15 ++++++++ src/my_plugin_platform_interface/pubspec.yaml | 17 +++++++++ .../my_plugin_platform_interface_test.dart | 30 +++++++++++++++ .../src/method_channel_my_plugin_test.dart | 37 +++++++++++++++++++ 11 files changed, 193 insertions(+) create mode 100644 .github/workflows/my_plugin_platform_interface.yaml create mode 100644 src/my_plugin_platform_interface/CHANGELOG.md create mode 100644 src/my_plugin_platform_interface/LICENSE create mode 100644 src/my_plugin_platform_interface/README.md create mode 100644 src/my_plugin_platform_interface/analysis_options.yaml create mode 100644 src/my_plugin_platform_interface/lib/my_plugin_platform_interface.dart create mode 100644 src/my_plugin_platform_interface/lib/src/method_channel_my_plugin.dart create mode 100644 src/my_plugin_platform_interface/pubspec.yaml create mode 100644 src/my_plugin_platform_interface/test/my_plugin_platform_interface_test.dart create mode 100644 src/my_plugin_platform_interface/test/src/method_channel_my_plugin_test.dart diff --git a/.github/workflows/my_plugin_platform_interface.yaml b/.github/workflows/my_plugin_platform_interface.yaml new file mode 100644 index 0000000..fd1d4e5 --- /dev/null +++ b/.github/workflows/my_plugin_platform_interface.yaml @@ -0,0 +1,21 @@ +name: my_plugin_platform_interface + +on: + pull_request: + paths: + - ".github/workflows/my_plugin_platform_interface.yaml" + - "src/my_plugin_platform_interface/**" + push: + branches: + - main + paths: + - ".github/workflows/my_plugin_platform_interface.yaml" + - "src/my_plugin_platform_interface/**" + +jobs: + build: + uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/flutter_package.yml@v1 + with: + flutter_channel: stable + flutter_version: 2.10.1 + working_directory: src/my_plugin_platform_interface diff --git a/.gitignore b/.gitignore index cf0e373..4aa0df8 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ .dart_tool/ pubspec.lock flutter_export_environment.sh +coverage/ Podfile.lock Pods/ diff --git a/src/my_plugin_platform_interface/CHANGELOG.md b/src/my_plugin_platform_interface/CHANGELOG.md new file mode 100644 index 0000000..c1b1f39 --- /dev/null +++ b/src/my_plugin_platform_interface/CHANGELOG.md @@ -0,0 +1,3 @@ +# 0.1.0+1 + +* Initial release. diff --git a/src/my_plugin_platform_interface/LICENSE b/src/my_plugin_platform_interface/LICENSE new file mode 100644 index 0000000..bba8e50 --- /dev/null +++ b/src/my_plugin_platform_interface/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Very Good Ventures + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/my_plugin_platform_interface/README.md b/src/my_plugin_platform_interface/README.md new file mode 100644 index 0000000..9944842 --- /dev/null +++ b/src/my_plugin_platform_interface/README.md @@ -0,0 +1,14 @@ +# my_plugin_platform_interface + +[![style: very good analysis][very_good_analysis_badge]][very_good_analysis_link] + +A common platform interface for the `my_plugin` plugin. + +This interface allows platform-specific implementations of the `my_plugin` plugin, as well as the plugin itself, to ensure they are supporting the same interface. + +# Usage + +To implement a new platform-specific implementation of `my_plugin`, extend `MyPluginPlatform` with an implementation that performs the platform-specific behavior. + +[very_good_analysis_badge]: https://img.shields.io/badge/style-very_good_analysis-B22C89.svg +[very_good_analysis_link]: https://pub.dev/packages/very_good_analysis \ No newline at end of file diff --git a/src/my_plugin_platform_interface/analysis_options.yaml b/src/my_plugin_platform_interface/analysis_options.yaml new file mode 100644 index 0000000..44aef9a --- /dev/null +++ b/src/my_plugin_platform_interface/analysis_options.yaml @@ -0,0 +1 @@ +include: package:very_good_analysis/analysis_options.2.4.0.yaml diff --git a/src/my_plugin_platform_interface/lib/my_plugin_platform_interface.dart b/src/my_plugin_platform_interface/lib/my_plugin_platform_interface.dart new file mode 100644 index 0000000..1e57739 --- /dev/null +++ b/src/my_plugin_platform_interface/lib/my_plugin_platform_interface.dart @@ -0,0 +1,33 @@ +import 'package:my_plugin_platform_interface/src/method_channel_my_plugin.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +/// The interface that implementations of my_plugin must implement. +/// +/// Platform implementations should extend this class +/// rather than implement it as `MyPlugin`. +/// Extending this class (using `extends`) ensures that the subclass will get +/// the default implementation, while platform implementations that `implements` +/// this interface will be broken by newly added [MyPluginPlatform] methods. +abstract class MyPluginPlatform extends PlatformInterface { + /// Constructs a MyPluginPlatform. + MyPluginPlatform() : super(token: _token); + + static final Object _token = Object(); + + static MyPluginPlatform _instance = MethodChannelMyPlugin(); + + /// The default instance of [MyPluginPlatform] to use. + /// + /// Defaults to [MethodChannelMyPlugin]. + static MyPluginPlatform get instance => _instance; + + /// Platform-specific plugins should set this with their own platform-specific + /// class that extends [MyPluginPlatform] when they register themselves. + static set instance(MyPluginPlatform instance) { + PlatformInterface.verify(instance, _token); + _instance = instance; + } + + /// Return the current platform name. + Future getPlatformName(); +} diff --git a/src/my_plugin_platform_interface/lib/src/method_channel_my_plugin.dart b/src/my_plugin_platform_interface/lib/src/method_channel_my_plugin.dart new file mode 100644 index 0000000..adb01f2 --- /dev/null +++ b/src/my_plugin_platform_interface/lib/src/method_channel_my_plugin.dart @@ -0,0 +1,15 @@ +import 'package:flutter/foundation.dart' show visibleForTesting; +import 'package:flutter/services.dart'; +import 'package:my_plugin_platform_interface/my_plugin_platform_interface.dart'; + +/// An implementation of [MyPluginPlatform] that uses method channels. +class MethodChannelMyPlugin extends MyPluginPlatform { + /// The method channel used to interact with the native platform. + @visibleForTesting + final methodChannel = const MethodChannel('my_plugin'); + + @override + Future getPlatformName() { + return methodChannel.invokeMethod('getPlatformName'); + } +} diff --git a/src/my_plugin_platform_interface/pubspec.yaml b/src/my_plugin_platform_interface/pubspec.yaml new file mode 100644 index 0000000..69bb55c --- /dev/null +++ b/src/my_plugin_platform_interface/pubspec.yaml @@ -0,0 +1,17 @@ +name: my_plugin_platform_interface +description: A common platform interface for the my_plugin plugin. +version: 0.1.0+1 + +environment: + sdk: ">=2.12.0 <3.0.0" + flutter: ">=2.0.0" + +dependencies: + flutter: + sdk: flutter + plugin_platform_interface: ^2.1.0 + +dev_dependencies: + flutter_test: + sdk: flutter + very_good_analysis: ^2.4.0 diff --git a/src/my_plugin_platform_interface/test/my_plugin_platform_interface_test.dart b/src/my_plugin_platform_interface/test/my_plugin_platform_interface_test.dart new file mode 100644 index 0000000..bb05fc0 --- /dev/null +++ b/src/my_plugin_platform_interface/test/my_plugin_platform_interface_test.dart @@ -0,0 +1,30 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:my_plugin_platform_interface/my_plugin_platform_interface.dart'; + +class MyPluginMock extends MyPluginPlatform { + static const mockPlatformName = 'Mock'; + + @override + Future getPlatformName() async => mockPlatformName; +} + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + group('MyPluginPlatformInterface', () { + late MyPluginPlatform myPluginPlatform; + + setUp(() { + myPluginPlatform = MyPluginMock(); + MyPluginPlatform.instance = myPluginPlatform; + }); + + group('getPlatformName', () { + test('returns correct name', () async { + expect( + await MyPluginPlatform.instance.getPlatformName(), + equals(MyPluginMock.mockPlatformName), + ); + }); + }); + }); +} diff --git a/src/my_plugin_platform_interface/test/src/method_channel_my_plugin_test.dart b/src/my_plugin_platform_interface/test/src/method_channel_my_plugin_test.dart new file mode 100644 index 0000000..64f48e0 --- /dev/null +++ b/src/my_plugin_platform_interface/test/src/method_channel_my_plugin_test.dart @@ -0,0 +1,37 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:my_plugin_platform_interface/src/method_channel_my_plugin.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + const kPlatformName = 'platformName'; + + group('$MethodChannelMyPlugin', () { + late MethodChannelMyPlugin methodChannelMyPlugin; + final log = []; + + setUp(() async { + methodChannelMyPlugin = MethodChannelMyPlugin() + ..methodChannel.setMockMethodCallHandler((MethodCall methodCall) async { + log.add(methodCall); + switch (methodCall.method) { + case 'getPlatformName': + return kPlatformName; + default: + return null; + } + }); + }); + + tearDown(log.clear); + + test('getPlatformName', () async { + final platformName = await methodChannelMyPlugin.getPlatformName(); + expect( + log, + [isMethodCall('getPlatformName', arguments: null)], + ); + expect(platformName, equals(kPlatformName)); + }); + }); +}